diff options
author | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-06 18:02:41 +0000 |
---|---|---|
committer | erg@google.com <erg@google.com@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-04-06 18:02:41 +0000 |
commit | a0b60cfd11d0bcccb80c703a1030e083b9e0a3ca (patch) | |
tree | 756890f4dbf9aeac0963ea64fd15dd98b25ec167 /chrome/browser | |
parent | 862829ebd7c09e5fb888996eead25b86325eaa67 (diff) | |
download | chromium_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/browser')
-rw-r--r-- | chrome/browser/shell_integration.h | 7 | ||||
-rw-r--r-- | chrome/browser/shell_integration_linux.cc | 27 | ||||
-rw-r--r-- | chrome/browser/shell_integration_unittest.cc | 26 | ||||
-rw-r--r-- | chrome/browser/ui/gtk/browser_window_gtk.cc | 13 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app.cc | 31 | ||||
-rw-r--r-- | chrome/browser/web_applications/web_app.h | 11 |
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) |