blob: 7179cbcf903d91e417d109ed279082028a6ca9df [file] [log] [blame]
[email protected]8806d3b2012-04-13 06:46:341// Copyright (c) 2012 The Chromium Authors. All rights reserved.
[email protected]b96aa932009-08-12 21:34:492// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/shell_integration.h"
6
[email protected]af71d642010-03-12 10:29:047#include <map>
8
[email protected]b96aa932009-08-12 21:34:499#include "base/file_path.h"
[email protected]af71d642010-03-12 10:29:0410#include "base/file_util.h"
[email protected]ea1a3f62012-11-16 20:34:2311#include "base/files/scoped_temp_dir.h"
[email protected]af71d642010-03-12 10:29:0412#include "base/message_loop.h"
[email protected]7286e3fc2011-07-19 22:13:2413#include "base/stl_util.h"
[email protected]b96aa932009-08-12 21:34:4914#include "base/string_util.h"
[email protected]be1ce6a72010-08-03 14:35:2215#include "base/utf_string_conversions.h"
[email protected]a0b60cfd2011-04-06 18:02:4116#include "chrome/browser/web_applications/web_app.h"
[email protected]42896802009-08-28 23:39:4417#include "chrome/common/chrome_constants.h"
[email protected]e97882f2012-06-04 02:23:1718#include "content/public/test/test_browser_thread.h"
[email protected]b96aa932009-08-12 21:34:4919#include "googleurl/src/gurl.h"
20#include "testing/gtest/include/gtest/gtest.h"
21
[email protected]8ea8f1ef2013-01-06 18:39:0322#if defined(OS_POSIX) && !defined(OS_MACOSX)
[email protected]76b90d312010-08-03 03:00:5023#include "base/environment.h"
[email protected]98566d7a2012-04-17 00:28:5624#include "chrome/browser/shell_integration_linux.h"
[email protected]1fd5302c2011-05-28 04:06:4325#endif
[email protected]3bc60432010-03-12 11:15:1326
[email protected]b96aa932009-08-12 21:34:4927#define FPL FILE_PATH_LITERAL
28
[email protected]631bb742011-11-02 11:29:3929using content::BrowserThread;
30
[email protected]1fd5302c2011-05-28 04:06:4331#if defined(OS_POSIX) && !defined(OS_MACOSX)
[email protected]af71d642010-03-12 10:29:0432namespace {
33
34// Provides mock environment variables values based on a stored map.
[email protected]76b90d312010-08-03 03:00:5035class MockEnvironment : public base::Environment {
[email protected]af71d642010-03-12 10:29:0436 public:
[email protected]76b90d312010-08-03 03:00:5037 MockEnvironment() {}
[email protected]af71d642010-03-12 10:29:0438
39 void Set(const std::string& name, const std::string& value) {
40 variables_[name] = value;
41 }
42
[email protected]3ba7e082010-08-07 02:57:5943 virtual bool GetVar(const char* variable_name, std::string* result) {
[email protected]af71d642010-03-12 10:29:0444 if (ContainsKey(variables_, variable_name)) {
45 *result = variables_[variable_name];
46 return true;
47 }
48
49 return false;
50 }
51
[email protected]c87bcf002010-08-06 01:03:3752 virtual bool SetVar(const char* variable_name, const std::string& new_value) {
[email protected]fc586c72010-07-31 16:55:4053 ADD_FAILURE();
54 return false;
55 }
56
[email protected]4fae3162010-08-04 02:13:3457 virtual bool UnSetVar(const char* variable_name) {
[email protected]fc586c72010-07-31 16:55:4058 ADD_FAILURE();
[email protected]e9032c62010-07-16 03:34:2559 return false;
[email protected]ac7264c2010-07-08 13:32:5160 }
61
[email protected]af71d642010-03-12 10:29:0462 private:
63 std::map<std::string, std::string> variables_;
64
[email protected]76b90d312010-08-03 03:00:5065 DISALLOW_COPY_AND_ASSIGN(MockEnvironment);
[email protected]af71d642010-03-12 10:29:0466};
67
68} // namespace
69
70TEST(ShellIntegrationTest, GetDesktopShortcutTemplate) {
71#if defined(GOOGLE_CHROME_BUILD)
72 const char kTemplateFilename[] = "google-chrome.desktop";
73#else // CHROMIUM_BUILD
74 const char kTemplateFilename[] = "chromium-browser.desktop";
75#endif
76
77 const char kTestData1[] = "a magical testing string";
78 const char kTestData2[] = "a different testing string";
79
80 MessageLoop message_loop;
[email protected]c38831a12011-10-28 12:44:4981 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
[email protected]af71d642010-03-12 10:29:0482
83 {
[email protected]ea1a3f62012-11-16 20:34:2384 base::ScopedTempDir temp_dir;
[email protected]af71d642010-03-12 10:29:0485 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
86
[email protected]76b90d312010-08-03 03:00:5087 MockEnvironment env;
88 env.Set("XDG_DATA_HOME", temp_dir.path().value());
[email protected]af71d642010-03-12 10:29:0489 ASSERT_TRUE(file_util::WriteFile(
90 temp_dir.path().AppendASCII(kTemplateFilename),
91 kTestData1, strlen(kTestData1)));
92 std::string contents;
[email protected]98566d7a2012-04-17 00:28:5693 ASSERT_TRUE(ShellIntegrationLinux::GetDesktopShortcutTemplate(&env,
94 &contents));
[email protected]af71d642010-03-12 10:29:0495 EXPECT_EQ(kTestData1, contents);
96 }
97
98 {
[email protected]ea1a3f62012-11-16 20:34:2399 base::ScopedTempDir temp_dir;
[email protected]af71d642010-03-12 10:29:04100 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
101
[email protected]76b90d312010-08-03 03:00:50102 MockEnvironment env;
103 env.Set("XDG_DATA_DIRS", temp_dir.path().value());
[email protected]af71d642010-03-12 10:29:04104 ASSERT_TRUE(file_util::CreateDirectory(
105 temp_dir.path().AppendASCII("applications")));
106 ASSERT_TRUE(file_util::WriteFile(
107 temp_dir.path().AppendASCII("applications")
108 .AppendASCII(kTemplateFilename),
109 kTestData2, strlen(kTestData2)));
110 std::string contents;
[email protected]98566d7a2012-04-17 00:28:56111 ASSERT_TRUE(ShellIntegrationLinux::GetDesktopShortcutTemplate(&env,
112 &contents));
[email protected]af71d642010-03-12 10:29:04113 EXPECT_EQ(kTestData2, contents);
114 }
115
116 {
[email protected]ea1a3f62012-11-16 20:34:23117 base::ScopedTempDir temp_dir;
[email protected]af71d642010-03-12 10:29:04118 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
119
[email protected]76b90d312010-08-03 03:00:50120 MockEnvironment env;
121 env.Set("XDG_DATA_DIRS", temp_dir.path().value() + ":" +
[email protected]af71d642010-03-12 10:29:04122 temp_dir.path().AppendASCII("applications").value());
123 ASSERT_TRUE(file_util::CreateDirectory(
124 temp_dir.path().AppendASCII("applications")));
125 ASSERT_TRUE(file_util::WriteFile(
126 temp_dir.path().AppendASCII(kTemplateFilename),
127 kTestData1, strlen(kTestData1)));
128 ASSERT_TRUE(file_util::WriteFile(
129 temp_dir.path().AppendASCII("applications")
130 .AppendASCII(kTemplateFilename),
131 kTestData2, strlen(kTestData2)));
132 std::string contents;
[email protected]98566d7a2012-04-17 00:28:56133 ASSERT_TRUE(ShellIntegrationLinux::GetDesktopShortcutTemplate(&env,
134 &contents));
[email protected]af71d642010-03-12 10:29:04135 EXPECT_EQ(kTestData1, contents);
136 }
137}
138
[email protected]0b7df36d2012-07-11 09:50:47139TEST(ShellIntegrationTest, GetWebShortcutFilename) {
[email protected]b96aa932009-08-12 21:34:49140 const struct {
141 const FilePath::CharType* path;
142 const char* url;
143 } test_cases[] = {
144 { FPL("http___foo_.desktop"), "http://foo" },
145 { FPL("http___foo_bar_.desktop"), "http://foo/bar/" },
146 { FPL("http___foo_bar_a=b&c=d.desktop"), "http://foo/bar?a=b&c=d" },
147
148 // Now we're starting to be more evil...
149 { FPL("http___foo_.desktop"), "http://foo/bar/baz/../../../../../" },
150 { FPL("http___foo_.desktop"), "http://foo/bar/././../baz/././../" },
151 { FPL("http___.._.desktop"), "http://../../../../" },
152 };
153 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) {
[email protected]4f260d02010-12-23 18:35:42154 EXPECT_EQ(std::string(chrome::kBrowserProcessExecutableName) + "-" +
[email protected]42896802009-08-28 23:39:44155 test_cases[i].path,
[email protected]0b7df36d2012-07-11 09:50:47156 ShellIntegrationLinux::GetWebShortcutFilename(
[email protected]42896802009-08-28 23:39:44157 GURL(test_cases[i].url)).value()) <<
158 " while testing " << test_cases[i].url;
[email protected]b96aa932009-08-12 21:34:49159 }
160}
161
[email protected]a2778d32011-12-01 07:49:34162TEST(ShellIntegrationTest, GetDesktopFileContents) {
[email protected]b96aa932009-08-12 21:34:49163 const struct {
164 const char* url;
165 const char* title;
[email protected]0b303cc2009-09-28 22:35:15166 const char* icon_name;
[email protected]b96aa932009-08-12 21:34:49167 const char* template_contents;
168 const char* expected_output;
169 } test_cases[] = {
170 // Dumb case.
[email protected]0b303cc2009-09-28 22:35:15171 { "ignored", "ignored", "ignored", "", "#!/usr/bin/env xdg-open\n" },
[email protected]b96aa932009-08-12 21:34:49172
173 // Real-world case.
174 { "http://gmail.com",
175 "GMail",
[email protected]0b303cc2009-09-28 22:35:15176 "chrome-http__gmail.com",
[email protected]b96aa932009-08-12 21:34:49177
178 "[Desktop Entry]\n"
179 "Version=1.0\n"
180 "Encoding=UTF-8\n"
181 "Name=Google Chrome\n"
182 "Comment=The web browser from Google\n"
183 "Exec=/opt/google/chrome/google-chrome %U\n"
184 "Terminal=false\n"
185 "Icon=/opt/google/chrome/product_logo_48.png\n"
186 "Type=Application\n"
187 "Categories=Application;Network;WebBrowser;\n"
[email protected]0a96c3f2011-05-11 22:10:20188 "MimeType=text/html;text/xml;application/xhtml_xml;\n"
189 "X-Ayatana-Desktop-Shortcuts=NewWindow;\n"
190 "\n"
191 "[NewWindow Shortcut Group]\n"
192 "Name=Open New Window\n"
193 "Exec=/opt/google/chrome/google-chrome\n"
194 "TargetEnvironment=Unity\n",
[email protected]b96aa932009-08-12 21:34:49195
[email protected]82810fe12009-09-25 16:21:57196 "#!/usr/bin/env xdg-open\n"
[email protected]b96aa932009-08-12 21:34:49197 "[Desktop Entry]\n"
198 "Version=1.0\n"
199 "Encoding=UTF-8\n"
200 "Name=GMail\n"
[email protected]b10392932011-03-08 21:28:14201 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
[email protected]b96aa932009-08-12 21:34:49202 "Terminal=false\n"
[email protected]0b303cc2009-09-28 22:35:15203 "Icon=chrome-http__gmail.com\n"
[email protected]b96aa932009-08-12 21:34:49204 "Type=Application\n"
205 "Categories=Application;Network;WebBrowser;\n"
[email protected]a2778d32011-12-01 07:49:34206#if !defined(USE_AURA)
207 // Aura Chrome creates browser window in a single X11 window, so
208 // WMClass does not matter.
[email protected]a0b60cfd2011-04-06 18:02:41209 "StartupWMClass=gmail.com\n"
[email protected]a2778d32011-12-01 07:49:34210#endif
[email protected]b96aa932009-08-12 21:34:49211 },
212
[email protected]82810fe12009-09-25 16:21:57213 // Make sure we don't insert duplicate shebangs.
214 { "http://gmail.com",
215 "GMail",
[email protected]0b303cc2009-09-28 22:35:15216 "chrome-http__gmail.com",
[email protected]82810fe12009-09-25 16:21:57217
218 "#!/some/shebang\n"
[email protected]0a96c3f2011-05-11 22:10:20219 "[Desktop Entry]\n"
[email protected]82810fe12009-09-25 16:21:57220 "Name=Google Chrome\n"
221 "Exec=/opt/google/chrome/google-chrome %U\n",
222
223 "#!/usr/bin/env xdg-open\n"
[email protected]0a96c3f2011-05-11 22:10:20224 "[Desktop Entry]\n"
[email protected]82810fe12009-09-25 16:21:57225 "Name=GMail\n"
[email protected]b10392932011-03-08 21:28:14226 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
[email protected]0a96c3f2011-05-11 22:10:20227 "Icon=chrome-http__gmail.com\n"
[email protected]a2778d32011-12-01 07:49:34228#if !defined(USE_AURA)
229 // Aura Chrome creates browser window in a single X11 window, so
230 // WMClass does not matter.
[email protected]a0b60cfd2011-04-06 18:02:41231 "StartupWMClass=gmail.com\n"
[email protected]a2778d32011-12-01 07:49:34232#endif
[email protected]82810fe12009-09-25 16:21:57233 },
234
235 // Make sure i18n-ed comments are removed.
236 { "http://gmail.com",
237 "GMail",
[email protected]0b303cc2009-09-28 22:35:15238 "chrome-http__gmail.com",
[email protected]82810fe12009-09-25 16:21:57239
[email protected]0a96c3f2011-05-11 22:10:20240 "[Desktop Entry]\n"
[email protected]82810fe12009-09-25 16:21:57241 "Name=Google Chrome\n"
242 "Exec=/opt/google/chrome/google-chrome %U\n"
243 "Comment[pl]=Jakis komentarz.\n",
244
245 "#!/usr/bin/env xdg-open\n"
[email protected]0a96c3f2011-05-11 22:10:20246 "[Desktop Entry]\n"
[email protected]82810fe12009-09-25 16:21:57247 "Name=GMail\n"
[email protected]b10392932011-03-08 21:28:14248 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
[email protected]0a96c3f2011-05-11 22:10:20249 "Icon=chrome-http__gmail.com\n"
[email protected]a2778d32011-12-01 07:49:34250#if !defined(USE_AURA)
251 // Aura Chrome creates browser window in a single X11 window, so
252 // WMClass does not matter.
[email protected]a0b60cfd2011-04-06 18:02:41253 "StartupWMClass=gmail.com\n"
[email protected]a2778d32011-12-01 07:49:34254#endif
[email protected]82810fe12009-09-25 16:21:57255 },
256
[email protected]0b303cc2009-09-28 22:35:15257 // Make sure that empty icons are replaced by the chrome icon.
258 { "http://gmail.com",
259 "GMail",
260 "",
261
[email protected]0a96c3f2011-05-11 22:10:20262 "[Desktop Entry]\n"
[email protected]0b303cc2009-09-28 22:35:15263 "Name=Google Chrome\n"
264 "Exec=/opt/google/chrome/google-chrome %U\n"
265 "Comment[pl]=Jakis komentarz.\n"
266 "Icon=/opt/google/chrome/product_logo_48.png\n",
267
268 "#!/usr/bin/env xdg-open\n"
[email protected]0a96c3f2011-05-11 22:10:20269 "[Desktop Entry]\n"
[email protected]0b303cc2009-09-28 22:35:15270 "Name=GMail\n"
[email protected]b10392932011-03-08 21:28:14271 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
[email protected]0b303cc2009-09-28 22:35:15272 "Icon=/opt/google/chrome/product_logo_48.png\n"
[email protected]a2778d32011-12-01 07:49:34273#if !defined(USE_AURA)
274 // Aura Chrome creates browser window in a single X11 window, so
275 // WMClass does not matter.
[email protected]a0b60cfd2011-04-06 18:02:41276 "StartupWMClass=gmail.com\n"
[email protected]a2778d32011-12-01 07:49:34277#endif
[email protected]0b303cc2009-09-28 22:35:15278 },
279
[email protected]b96aa932009-08-12 21:34:49280 // Now we're starting to be more evil...
281 { "http://evil.com/evil --join-the-b0tnet",
282 "Ownz0red\nExec=rm -rf /",
[email protected]0b303cc2009-09-28 22:35:15283 "chrome-http__evil.com_evil",
[email protected]b96aa932009-08-12 21:34:49284
[email protected]0a96c3f2011-05-11 22:10:20285 "[Desktop Entry]\n"
[email protected]b96aa932009-08-12 21:34:49286 "Name=Google Chrome\n"
287 "Exec=/opt/google/chrome/google-chrome %U\n",
288
[email protected]82810fe12009-09-25 16:21:57289 "#!/usr/bin/env xdg-open\n"
[email protected]0a96c3f2011-05-11 22:10:20290 "[Desktop Entry]\n"
[email protected]b96aa932009-08-12 21:34:49291 "Name=http://evil.com/evil%20--join-the-b0tnet\n"
292 "Exec=/opt/google/chrome/google-chrome "
[email protected]b10392932011-03-08 21:28:14293 "--app=http://evil.com/evil%20--join-the-b0tnet\n"
[email protected]0a96c3f2011-05-11 22:10:20294 "Icon=chrome-http__evil.com_evil\n"
[email protected]a2778d32011-12-01 07:49:34295#if !defined(USE_AURA)
296 // Aura Chrome creates browser window in a single X11 window, so
297 // WMClass does not matter.
[email protected]a0b60cfd2011-04-06 18:02:41298 "StartupWMClass=evil.com__evil%20--join-the-b0tnet\n"
[email protected]a2778d32011-12-01 07:49:34299#endif
[email protected]b96aa932009-08-12 21:34:49300 },
[email protected]82810fe12009-09-25 16:21:57301 { "http://evil.com/evil; rm -rf /; \"; rm -rf $HOME >ownz0red",
302 "Innocent Title",
[email protected]0b303cc2009-09-28 22:35:15303 "chrome-http__evil.com_evil",
[email protected]82810fe12009-09-25 16:21:57304
[email protected]0a96c3f2011-05-11 22:10:20305 "[Desktop Entry]\n"
[email protected]82810fe12009-09-25 16:21:57306 "Name=Google Chrome\n"
307 "Exec=/opt/google/chrome/google-chrome %U\n",
308
309 "#!/usr/bin/env xdg-open\n"
[email protected]0a96c3f2011-05-11 22:10:20310 "[Desktop Entry]\n"
[email protected]82810fe12009-09-25 16:21:57311 "Name=Innocent Title\n"
312 "Exec=/opt/google/chrome/google-chrome "
[email protected]b10392932011-03-08 21:28:14313 "\"--app=http://evil.com/evil;%20rm%20-rf%20/;%20%22;%20rm%20"
314 // Note: $ is escaped as \$ within an arg to Exec, and then
315 // the \ is escaped as \\ as all strings in a Desktop file should
316 // be; finally, \\ becomes \\\\ when represented in a C++ string!
317 "-rf%20\\\\$HOME%20%3Eownz0red\"\n"
[email protected]0a96c3f2011-05-11 22:10:20318 "Icon=chrome-http__evil.com_evil\n"
[email protected]a2778d32011-12-01 07:49:34319#if !defined(USE_AURA)
320 // Aura Chrome creates browser window in a single X11 window, so
321 // WMClass does not matter.
[email protected]a0b60cfd2011-04-06 18:02:41322 "StartupWMClass=evil.com__evil;%20rm%20-rf%20_;%20%22;%20"
323 "rm%20-rf%20$HOME%20%3Eownz0red\n"
[email protected]a2778d32011-12-01 07:49:34324#endif
[email protected]82810fe12009-09-25 16:21:57325 },
[email protected]790613c2009-12-30 14:49:41326 { "http://evil.com/evil | cat `echo ownz0red` >/dev/null",
[email protected]82810fe12009-09-25 16:21:57327 "Innocent Title",
[email protected]0b303cc2009-09-28 22:35:15328 "chrome-http__evil.com_evil",
[email protected]82810fe12009-09-25 16:21:57329
[email protected]0a96c3f2011-05-11 22:10:20330 "[Desktop Entry]\n"
[email protected]82810fe12009-09-25 16:21:57331 "Name=Google Chrome\n"
332 "Exec=/opt/google/chrome/google-chrome %U\n",
333
334 "#!/usr/bin/env xdg-open\n"
[email protected]0a96c3f2011-05-11 22:10:20335 "[Desktop Entry]\n"
[email protected]82810fe12009-09-25 16:21:57336 "Name=Innocent Title\n"
337 "Exec=/opt/google/chrome/google-chrome "
[email protected]b10392932011-03-08 21:28:14338 "--app=http://evil.com/evil%20%7C%20cat%20%60echo%20ownz0red"
339 "%60%20%3E/dev/null\n"
[email protected]0a96c3f2011-05-11 22:10:20340 "Icon=chrome-http__evil.com_evil\n"
[email protected]a2778d32011-12-01 07:49:34341#if !defined(USE_AURA)
342 // Aura Chrome creates browser window in a single X11 window, so
343 // WMClass does not matter.
[email protected]a0b60cfd2011-04-06 18:02:41344 "StartupWMClass=evil.com__evil%20%7C%20cat%20%60echo%20ownz0red"
345 "%60%20%3E_dev_null\n"
[email protected]a2778d32011-12-01 07:49:34346#endif
[email protected]82810fe12009-09-25 16:21:57347 },
[email protected]b96aa932009-08-12 21:34:49348 };
349 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) {
[email protected]b10392932011-03-08 21:28:14350 SCOPED_TRACE(i);
[email protected]a0b60cfd2011-04-06 18:02:41351 EXPECT_EQ(
352 test_cases[i].expected_output,
[email protected]98566d7a2012-04-17 00:28:56353 ShellIntegrationLinux::GetDesktopFileContents(
[email protected]a0b60cfd2011-04-06 18:02:41354 test_cases[i].template_contents,
355 web_app::GenerateApplicationNameFromURL(GURL(test_cases[i].url)),
356 GURL(test_cases[i].url),
357 "",
[email protected]8806d3b2012-04-13 06:46:34358 FilePath(),
[email protected]a0b60cfd2011-04-06 18:02:41359 ASCIIToUTF16(test_cases[i].title),
[email protected]5951c852012-06-20 00:12:53360 test_cases[i].icon_name,
361 FilePath()));
[email protected]b96aa932009-08-12 21:34:49362 }
363}
[email protected]12f520c2010-01-06 18:11:15364#endif