summaryrefslogtreecommitdiffstats
path: root/chrome
diff options
context:
space:
mode:
authorerg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-06 18:02:41 +0000
committererg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98>2011-04-06 18:02:41 +0000
commita0b60cfd11d0bcccb80c703a1030e083b9e0a3ca (patch)
tree756890f4dbf9aeac0963ea64fd15dd98b25ec167 /chrome
parent862829ebd7c09e5fb888996eead25b86325eaa67 (diff)
downloadchromium_src-a0b60cfd11d0bcccb80c703a1030e083b9e0a3ca.zip
chromium_src-a0b60cfd11d0bcccb80c703a1030e083b9e0a3ca.tar.gz
chromium_src-a0b60cfd11d0bcccb80c703a1030e083b9e0a3ca.tar.bz2
Add the calculated WMClass to generated .desktop files.
(Also modifies it so that we only modify the wmclass_name, and not the wmclass_class because the internal application names aren't meant for display and are very ugly.) BUG=20587 TEST=Verify with xprop that the WM_CLASS of application desktop links mmatches the StartupWMClass key in the desktop file. Review URL: http://codereview.chromium.org/6759076 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@80656 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome')
-rw-r--r--chrome/browser/shell_integration.h7
-rw-r--r--chrome/browser/shell_integration_linux.cc27
-rw-r--r--chrome/browser/shell_integration_unittest.cc26
-rw-r--r--chrome/browser/ui/gtk/browser_window_gtk.cc13
-rw-r--r--chrome/browser/web_applications/web_app.cc31
-rw-r--r--chrome/browser/web_applications/web_app.h11
6 files changed, 88 insertions, 27 deletions
diff --git a/chrome/browser/shell_integration.h b/chrome/browser/shell_integration.h
index cdce891..575575e 100644
--- a/chrome/browser/shell_integration.h
+++ b/chrome/browser/shell_integration.h
@@ -96,8 +96,11 @@ class ShellIntegration {
// and |title|. The |template_contents| should be contents of .desktop file
// used to launch Chrome.
static std::string GetDesktopFileContents(
- const std::string& template_contents, const GURL& url,
- const std::string& extension_id, const string16& title,
+ const std::string& template_contents,
+ const std::string& app_name,
+ const GURL& url,
+ const std::string& extension_id,
+ const string16& title,
const std::string& icon_name);
static void CreateDesktopShortcut(const ShortcutInfo& shortcut_info,
diff --git a/chrome/browser/shell_integration_linux.cc b/chrome/browser/shell_integration_linux.cc
index b6bd6a6..1c67825 100644
--- a/chrome/browser/shell_integration_linux.cc
+++ b/chrome/browser/shell_integration_linux.cc
@@ -29,6 +29,7 @@
#include "base/task.h"
#include "base/threading/thread.h"
#include "base/utf_string_conversions.h"
+#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths.h"
#include "content/browser/browser_thread.h"
@@ -360,8 +361,11 @@ FilePath ShellIntegration::GetDesktopShortcutFilename(const GURL& url) {
// static
std::string ShellIntegration::GetDesktopFileContents(
- const std::string& template_contents, const GURL& url,
- const std::string& extension_id, const string16& title,
+ const std::string& template_contents,
+ const std::string& app_name,
+ const GURL& url,
+ const std::string& extension_id,
+ const string16& title,
const std::string& icon_name) {
// See http://standards.freedesktop.org/desktop-entry-spec/latest/
// Although not required by the spec, Nautilus on Ubuntu Karmic creates its
@@ -410,6 +414,9 @@ std::string ShellIntegration::GetDesktopFileContents(
} else if (tokenizer.token().substr(0, 9) == "MimeType=") {
// Skip MimeType lines, they are only relevant for a web browser
// shortcut, not a web application shortcut.
+ } else if (tokenizer.token().substr(0, 15) == "StartupWMClass=") {
+ // Skip StartupWMClass; it will certainly be wrong since we emit a
+ // different one based on the app name below.
} else if (tokenizer.token().substr(0, 5) == "Icon=" &&
!icon_name.empty()) {
output_buffer += StringPrintf("Icon=%s\n", icon_name.c_str());
@@ -417,6 +424,12 @@ std::string ShellIntegration::GetDesktopFileContents(
output_buffer += tokenizer.token() + "\n";
}
}
+
+ std::string wmclass = web_app::GetWMClassFromAppName(app_name);
+ if (!wmclass.empty()) {
+ output_buffer += StringPrintf("StartupWMClass=%s\n", wmclass.c_str());
+ }
+
return output_buffer;
}
@@ -433,9 +446,15 @@ void ShellIntegration::CreateDesktopShortcut(
std::string icon_name = CreateShortcutIcon(shortcut_info, shortcut_filename);
+ std::string app_name =
+ web_app::GenerateApplicationNameFromInfo(shortcut_info);
std::string contents = GetDesktopFileContents(
- shortcut_template, shortcut_info.url, shortcut_info.extension_id,
- shortcut_info.title, icon_name);
+ shortcut_template,
+ app_name,
+ shortcut_info.url,
+ shortcut_info.extension_id,
+ shortcut_info.title,
+ icon_name);
if (shortcut_info.create_on_desktop)
CreateShortcutOnDesktop(shortcut_filename, contents);
diff --git a/chrome/browser/shell_integration_unittest.cc b/chrome/browser/shell_integration_unittest.cc
index 714cbf3..2c4aa8b 100644
--- a/chrome/browser/shell_integration_unittest.cc
+++ b/chrome/browser/shell_integration_unittest.cc
@@ -13,6 +13,7 @@
#include "base/stl_util-inl.h"
#include "base/string_util.h"
#include "base/utf_string_conversions.h"
+#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/common/chrome_paths_internal.h"
#include "content/browser/browser_thread.h"
@@ -196,6 +197,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
"Icon=chrome-http__gmail.com\n"
"Type=Application\n"
"Categories=Application;Network;WebBrowser;\n"
+ "StartupWMClass=gmail.com\n"
},
// Make sure we don't insert duplicate shebangs.
@@ -210,6 +212,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
"#!/usr/bin/env xdg-open\n"
"Name=GMail\n"
"Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
+ "StartupWMClass=gmail.com\n"
},
// Make sure i18n-ed comments are removed.
@@ -224,6 +227,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
"#!/usr/bin/env xdg-open\n"
"Name=GMail\n"
"Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
+ "StartupWMClass=gmail.com\n"
},
// Make sure that empty icons are replaced by the chrome icon.
@@ -240,6 +244,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
"Name=GMail\n"
"Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
"Icon=/opt/google/chrome/product_logo_48.png\n"
+ "StartupWMClass=gmail.com\n"
},
// Now we're starting to be more evil...
@@ -254,6 +259,7 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
"Name=http://evil.com/evil%20--join-the-b0tnet\n"
"Exec=/opt/google/chrome/google-chrome "
"--app=http://evil.com/evil%20--join-the-b0tnet\n"
+ "StartupWMClass=evil.com__evil%20--join-the-b0tnet\n"
},
{ "http://evil.com/evil; rm -rf /; \"; rm -rf $HOME >ownz0red",
"Innocent Title",
@@ -270,6 +276,8 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
// the \ is escaped as \\ as all strings in a Desktop file should
// be; finally, \\ becomes \\\\ when represented in a C++ string!
"-rf%20\\\\$HOME%20%3Eownz0red\"\n"
+ "StartupWMClass=evil.com__evil;%20rm%20-rf%20_;%20%22;%20"
+ "rm%20-rf%20$HOME%20%3Eownz0red\n"
},
{ "http://evil.com/evil | cat `echo ownz0red` >/dev/null",
"Innocent Title",
@@ -283,17 +291,21 @@ TEST(ShellIntegrationTest, GetDesktopFileContents) {
"Exec=/opt/google/chrome/google-chrome "
"--app=http://evil.com/evil%20%7C%20cat%20%60echo%20ownz0red"
"%60%20%3E/dev/null\n"
+ "StartupWMClass=evil.com__evil%20%7C%20cat%20%60echo%20ownz0red"
+ "%60%20%3E_dev_null\n"
},
};
for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) {
SCOPED_TRACE(i);
- EXPECT_EQ(test_cases[i].expected_output,
- ShellIntegration::GetDesktopFileContents(
- test_cases[i].template_contents,
- GURL(test_cases[i].url),
- "",
- ASCIIToUTF16(test_cases[i].title),
- test_cases[i].icon_name));
+ EXPECT_EQ(
+ test_cases[i].expected_output,
+ ShellIntegration::GetDesktopFileContents(
+ test_cases[i].template_contents,
+ web_app::GenerateApplicationNameFromURL(GURL(test_cases[i].url)),
+ GURL(test_cases[i].url),
+ "",
+ ASCIIToUTF16(test_cases[i].title),
+ test_cases[i].icon_name));
}
}
#elif defined(OS_WIN)
diff --git a/chrome/browser/ui/gtk/browser_window_gtk.cc b/chrome/browser/ui/gtk/browser_window_gtk.cc
index 3d66b024..59eaf65 100644
--- a/chrome/browser/ui/gtk/browser_window_gtk.cc
+++ b/chrome/browser/ui/gtk/browser_window_gtk.cc
@@ -71,6 +71,7 @@
#include "chrome/browser/ui/tab_contents/tab_contents_wrapper.h"
#include "chrome/browser/ui/webui/bug_report_ui.h"
#include "chrome/browser/ui/window_sizer.h"
+#include "chrome/browser/web_applications/web_app.h"
#include "chrome/common/chrome_switches.h"
#include "chrome/common/pref_names.h"
#include "content/browser/renderer_host/render_widget_host_view.h"
@@ -294,12 +295,12 @@ void BrowserWindowGtk::Init() {
g_object_unref(gtk_window_get_group(window_));
if (browser_->type() & Browser::TYPE_APP) {
- std::string wmclassname = browser_->app_name();
- if (wmclassname != DevToolsWindow::kDevToolsApp) {
- file_util::ReplaceIllegalCharactersInPath(&wmclassname, '_');
- TrimString(wmclassname, "_", &wmclassname);
- gtk_window_set_wmclass(window_, wmclassname.c_str(),
- wmclassname.c_str());
+ std::string app_name = browser_->app_name();
+ if (app_name != DevToolsWindow::kDevToolsApp) {
+ std::string wmclassname = web_app::GetWMClassFromAppName(app_name);
+ gtk_window_set_wmclass(window_,
+ wmclassname.c_str(),
+ gdk_get_program_class());
}
}
diff --git a/chrome/browser/web_applications/web_app.cc b/chrome/browser/web_applications/web_app.cc
index c4046c8..90e4071 100644
--- a/chrome/browser/web_applications/web_app.cc
+++ b/chrome/browser/web_applications/web_app.cc
@@ -10,8 +10,10 @@
#include "base/command_line.h"
#include "base/file_util.h"
+#include "base/i18n/file_util_icu.h"
#include "base/md5.h"
#include "base/path_service.h"
+#include "base/string_util.h"
#include "base/threading/thread.h"
#include "base/utf_string_conversions.h"
#include "base/win/windows_version.h"
@@ -339,14 +341,8 @@ bool CreateShortcutTask::CreateShortcut() {
shortcut_info_.description.resize(MAX_PATH - 1);
// Generates app id from web app url and profile path.
- std::string app_name;
- if (!shortcut_info_.extension_id.empty()) {
- app_name = web_app::GenerateApplicationNameFromExtensionId(
- shortcut_info_.extension_id);
- } else {
- app_name = web_app::GenerateApplicationNameFromURL(
- shortcut_info_.url);
- }
+ std::string app_name =
+ web_app::GenerateApplicationNameFromInfo(shortcut_info_);
std::wstring app_id = ShellIntegration::GetAppId(
UTF8ToWide(app_name), profile_path_);
@@ -454,6 +450,17 @@ FilePath GetWebAppDataDirectory(const FilePath& root_dir,
} // namespace internals
+std::string GenerateApplicationNameFromInfo(
+ const ShellIntegration::ShortcutInfo& shortcut_info) {
+ if (!shortcut_info.extension_id.empty()) {
+ return web_app::GenerateApplicationNameFromExtensionId(
+ shortcut_info.extension_id);
+ } else {
+ return web_app::GenerateApplicationNameFromURL(
+ shortcut_info.url);
+ }
+}
+
std::string GenerateApplicationNameFromURL(const GURL& url) {
std::string t;
t.append(url.host());
@@ -514,4 +521,12 @@ void GetIconsInfo(const WebApplicationInfo& app_info,
}
#endif
+#if defined(TOOLKIT_GTK)
+std::string GetWMClassFromAppName(std::string app_name) {
+ file_util::ReplaceIllegalCharactersInPath(&app_name, '_');
+ TrimString(app_name, "_", &app_name);
+ return app_name;
+}
+#endif
+
} // namespace web_app
diff --git a/chrome/browser/web_applications/web_app.h b/chrome/browser/web_applications/web_app.h
index 7ccb33f..a0727e9 100644
--- a/chrome/browser/web_applications/web_app.h
+++ b/chrome/browser/web_applications/web_app.h
@@ -18,6 +18,10 @@ class Profile;
namespace web_app {
+// Compute a deterministic name based on data in the shortcut_info.
+std::string GenerateApplicationNameFromInfo(
+ const ShellIntegration::ShortcutInfo& shortcut_info);
+
// Compute a deterministic name based on the URL. We use this pseudo name
// as a key to store window location per application URLs in Browser and
// as app id for BrowserWindow, shortcut and jump list.
@@ -54,6 +58,13 @@ void GetIconsInfo(const WebApplicationInfo& app_info,
IconInfoList* icons);
#endif
+#if defined(TOOLKIT_GTK)
+// GTK+ 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);
+#endif
+
namespace internals {
#if defined(OS_WIN)