blob: 1a6b97956f450856addc557ddeceaa5a002717c9 [file] [log] [blame]
[email protected]9bc8cff2010-04-03 01:05:391// Copyright (c) 2010 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]af71d642010-03-12 10:29:0411#include "base/message_loop.h"
12#include "base/scoped_temp_dir.h"
13#include "base/stl_util-inl.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]42896802009-08-28 23:39:4416#include "chrome/common/chrome_constants.h"
[email protected]12f520c2010-01-06 18:11:1517#include "chrome/common/chrome_paths_internal.h"
[email protected]1bda97552011-03-01 20:11:5218#include "content/browser/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]1caa92612010-06-11 00:13:5622#if defined(OS_WIN)
23#include "chrome/installer/util/browser_distribution.h"
24#elif defined(OS_LINUX)
[email protected]76b90d312010-08-03 03:00:5025#include "base/environment.h"
[email protected]3bc60432010-03-12 11:15:1326#endif // defined(OS_LINUX)
27
[email protected]b96aa932009-08-12 21:34:4928#define FPL FILE_PATH_LITERAL
29
30#if defined(OS_LINUX)
[email protected]af71d642010-03-12 10:29:0431namespace {
32
33// Provides mock environment variables values based on a stored map.
[email protected]76b90d312010-08-03 03:00:5034class MockEnvironment : public base::Environment {
[email protected]af71d642010-03-12 10:29:0435 public:
[email protected]76b90d312010-08-03 03:00:5036 MockEnvironment() {}
[email protected]af71d642010-03-12 10:29:0437
38 void Set(const std::string& name, const std::string& value) {
39 variables_[name] = value;
40 }
41
[email protected]3ba7e082010-08-07 02:57:5942 virtual bool GetVar(const char* variable_name, std::string* result) {
[email protected]af71d642010-03-12 10:29:0443 if (ContainsKey(variables_, variable_name)) {
44 *result = variables_[variable_name];
45 return true;
46 }
47
48 return false;
49 }
50
[email protected]c87bcf002010-08-06 01:03:3751 virtual bool SetVar(const char* variable_name, const std::string& new_value) {
[email protected]fc586c72010-07-31 16:55:4052 ADD_FAILURE();
53 return false;
54 }
55
[email protected]4fae3162010-08-04 02:13:3456 virtual bool UnSetVar(const char* variable_name) {
[email protected]fc586c72010-07-31 16:55:4057 ADD_FAILURE();
[email protected]e9032c62010-07-16 03:34:2558 return false;
[email protected]ac7264c2010-07-08 13:32:5159 }
60
[email protected]af71d642010-03-12 10:29:0461 private:
62 std::map<std::string, std::string> variables_;
63
[email protected]76b90d312010-08-03 03:00:5064 DISALLOW_COPY_AND_ASSIGN(MockEnvironment);
[email protected]af71d642010-03-12 10:29:0465};
66
67} // namespace
68
69TEST(ShellIntegrationTest, GetDesktopShortcutTemplate) {
70#if defined(GOOGLE_CHROME_BUILD)
71 const char kTemplateFilename[] = "google-chrome.desktop";
72#else // CHROMIUM_BUILD
73 const char kTemplateFilename[] = "chromium-browser.desktop";
74#endif
75
76 const char kTestData1[] = "a magical testing string";
77 const char kTestData2[] = "a different testing string";
78
79 MessageLoop message_loop;
[email protected]0c7d74f2010-10-11 11:55:2680 BrowserThread file_thread(BrowserThread::FILE, &message_loop);
[email protected]af71d642010-03-12 10:29:0481
82 {
83 ScopedTempDir temp_dir;
84 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
85
[email protected]76b90d312010-08-03 03:00:5086 MockEnvironment env;
87 env.Set("XDG_DATA_HOME", temp_dir.path().value());
[email protected]af71d642010-03-12 10:29:0488 ASSERT_TRUE(file_util::WriteFile(
89 temp_dir.path().AppendASCII(kTemplateFilename),
90 kTestData1, strlen(kTestData1)));
91 std::string contents;
[email protected]76b90d312010-08-03 03:00:5092 ASSERT_TRUE(ShellIntegration::GetDesktopShortcutTemplate(&env,
[email protected]af71d642010-03-12 10:29:0493 &contents));
94 EXPECT_EQ(kTestData1, contents);
95 }
96
97 {
98 ScopedTempDir temp_dir;
99 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
100
[email protected]76b90d312010-08-03 03:00:50101 MockEnvironment env;
102 env.Set("XDG_DATA_DIRS", temp_dir.path().value());
[email protected]af71d642010-03-12 10:29:04103 ASSERT_TRUE(file_util::CreateDirectory(
104 temp_dir.path().AppendASCII("applications")));
105 ASSERT_TRUE(file_util::WriteFile(
106 temp_dir.path().AppendASCII("applications")
107 .AppendASCII(kTemplateFilename),
108 kTestData2, strlen(kTestData2)));
109 std::string contents;
[email protected]76b90d312010-08-03 03:00:50110 ASSERT_TRUE(ShellIntegration::GetDesktopShortcutTemplate(&env,
[email protected]af71d642010-03-12 10:29:04111 &contents));
112 EXPECT_EQ(kTestData2, contents);
113 }
114
115 {
116 ScopedTempDir temp_dir;
117 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
118
[email protected]76b90d312010-08-03 03:00:50119 MockEnvironment env;
120 env.Set("XDG_DATA_DIRS", temp_dir.path().value() + ":" +
[email protected]af71d642010-03-12 10:29:04121 temp_dir.path().AppendASCII("applications").value());
122 ASSERT_TRUE(file_util::CreateDirectory(
123 temp_dir.path().AppendASCII("applications")));
124 ASSERT_TRUE(file_util::WriteFile(
125 temp_dir.path().AppendASCII(kTemplateFilename),
126 kTestData1, strlen(kTestData1)));
127 ASSERT_TRUE(file_util::WriteFile(
128 temp_dir.path().AppendASCII("applications")
129 .AppendASCII(kTemplateFilename),
130 kTestData2, strlen(kTestData2)));
131 std::string contents;
[email protected]76b90d312010-08-03 03:00:50132 ASSERT_TRUE(ShellIntegration::GetDesktopShortcutTemplate(&env,
[email protected]af71d642010-03-12 10:29:04133 &contents));
134 EXPECT_EQ(kTestData1, contents);
135 }
136}
137
[email protected]b96aa932009-08-12 21:34:49138TEST(ShellIntegrationTest, GetDesktopShortcutFilename) {
139 const struct {
140 const FilePath::CharType* path;
141 const char* url;
142 } test_cases[] = {
143 { FPL("http___foo_.desktop"), "http://foo" },
144 { FPL("http___foo_bar_.desktop"), "http://foo/bar/" },
145 { FPL("http___foo_bar_a=b&c=d.desktop"), "http://foo/bar?a=b&c=d" },
146
147 // Now we're starting to be more evil...
148 { FPL("http___foo_.desktop"), "http://foo/bar/baz/../../../../../" },
149 { FPL("http___foo_.desktop"), "http://foo/bar/././../baz/././../" },
150 { FPL("http___.._.desktop"), "http://../../../../" },
151 };
152 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) {
[email protected]4f260d02010-12-23 18:35:42153 EXPECT_EQ(std::string(chrome::kBrowserProcessExecutableName) + "-" +
[email protected]42896802009-08-28 23:39:44154 test_cases[i].path,
155 ShellIntegration::GetDesktopShortcutFilename(
156 GURL(test_cases[i].url)).value()) <<
157 " while testing " << test_cases[i].url;
[email protected]b96aa932009-08-12 21:34:49158 }
159}
160
161TEST(ShellIntegrationTest, GetDesktopFileContents) {
162 const struct {
163 const char* url;
164 const char* title;
[email protected]0b303cc2009-09-28 22:35:15165 const char* icon_name;
[email protected]b96aa932009-08-12 21:34:49166 const char* template_contents;
167 const char* expected_output;
168 } test_cases[] = {
169 // Dumb case.
[email protected]0b303cc2009-09-28 22:35:15170 { "ignored", "ignored", "ignored", "", "#!/usr/bin/env xdg-open\n" },
[email protected]b96aa932009-08-12 21:34:49171
172 // Real-world case.
173 { "http://gmail.com",
174 "GMail",
[email protected]0b303cc2009-09-28 22:35:15175 "chrome-http__gmail.com",
[email protected]b96aa932009-08-12 21:34:49176
177 "[Desktop Entry]\n"
178 "Version=1.0\n"
179 "Encoding=UTF-8\n"
180 "Name=Google Chrome\n"
181 "Comment=The web browser from Google\n"
182 "Exec=/opt/google/chrome/google-chrome %U\n"
183 "Terminal=false\n"
184 "Icon=/opt/google/chrome/product_logo_48.png\n"
185 "Type=Application\n"
186 "Categories=Application;Network;WebBrowser;\n"
187 "MimeType=text/html;text/xml;application/xhtml_xml;\n",
188
[email protected]82810fe12009-09-25 16:21:57189 "#!/usr/bin/env xdg-open\n"
[email protected]b96aa932009-08-12 21:34:49190 "[Desktop Entry]\n"
191 "Version=1.0\n"
192 "Encoding=UTF-8\n"
193 "Name=GMail\n"
[email protected]b10392932011-03-08 21:28:14194 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
[email protected]b96aa932009-08-12 21:34:49195 "Terminal=false\n"
[email protected]0b303cc2009-09-28 22:35:15196 "Icon=chrome-http__gmail.com\n"
[email protected]b96aa932009-08-12 21:34:49197 "Type=Application\n"
198 "Categories=Application;Network;WebBrowser;\n"
[email protected]b96aa932009-08-12 21:34:49199 },
200
[email protected]82810fe12009-09-25 16:21:57201 // Make sure we don't insert duplicate shebangs.
202 { "http://gmail.com",
203 "GMail",
[email protected]0b303cc2009-09-28 22:35:15204 "chrome-http__gmail.com",
[email protected]82810fe12009-09-25 16:21:57205
206 "#!/some/shebang\n"
207 "Name=Google Chrome\n"
208 "Exec=/opt/google/chrome/google-chrome %U\n",
209
210 "#!/usr/bin/env xdg-open\n"
211 "Name=GMail\n"
[email protected]b10392932011-03-08 21:28:14212 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
[email protected]82810fe12009-09-25 16:21:57213 },
214
215 // Make sure i18n-ed comments are removed.
216 { "http://gmail.com",
217 "GMail",
[email protected]0b303cc2009-09-28 22:35:15218 "chrome-http__gmail.com",
[email protected]82810fe12009-09-25 16:21:57219
220 "Name=Google Chrome\n"
221 "Exec=/opt/google/chrome/google-chrome %U\n"
222 "Comment[pl]=Jakis komentarz.\n",
223
224 "#!/usr/bin/env xdg-open\n"
225 "Name=GMail\n"
[email protected]b10392932011-03-08 21:28:14226 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
[email protected]82810fe12009-09-25 16:21:57227 },
228
[email protected]0b303cc2009-09-28 22:35:15229 // Make sure that empty icons are replaced by the chrome icon.
230 { "http://gmail.com",
231 "GMail",
232 "",
233
234 "Name=Google Chrome\n"
235 "Exec=/opt/google/chrome/google-chrome %U\n"
236 "Comment[pl]=Jakis komentarz.\n"
237 "Icon=/opt/google/chrome/product_logo_48.png\n",
238
239 "#!/usr/bin/env xdg-open\n"
240 "Name=GMail\n"
[email protected]b10392932011-03-08 21:28:14241 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
[email protected]0b303cc2009-09-28 22:35:15242 "Icon=/opt/google/chrome/product_logo_48.png\n"
243 },
244
[email protected]b96aa932009-08-12 21:34:49245 // Now we're starting to be more evil...
246 { "http://evil.com/evil --join-the-b0tnet",
247 "Ownz0red\nExec=rm -rf /",
[email protected]0b303cc2009-09-28 22:35:15248 "chrome-http__evil.com_evil",
[email protected]b96aa932009-08-12 21:34:49249
250 "Name=Google Chrome\n"
251 "Exec=/opt/google/chrome/google-chrome %U\n",
252
[email protected]82810fe12009-09-25 16:21:57253 "#!/usr/bin/env xdg-open\n"
[email protected]b96aa932009-08-12 21:34:49254 "Name=http://evil.com/evil%20--join-the-b0tnet\n"
255 "Exec=/opt/google/chrome/google-chrome "
[email protected]b10392932011-03-08 21:28:14256 "--app=http://evil.com/evil%20--join-the-b0tnet\n"
[email protected]b96aa932009-08-12 21:34:49257 },
[email protected]82810fe12009-09-25 16:21:57258 { "http://evil.com/evil; rm -rf /; \"; rm -rf $HOME >ownz0red",
259 "Innocent Title",
[email protected]0b303cc2009-09-28 22:35:15260 "chrome-http__evil.com_evil",
[email protected]82810fe12009-09-25 16:21:57261
262 "Name=Google Chrome\n"
263 "Exec=/opt/google/chrome/google-chrome %U\n",
264
265 "#!/usr/bin/env xdg-open\n"
266 "Name=Innocent Title\n"
267 "Exec=/opt/google/chrome/google-chrome "
[email protected]b10392932011-03-08 21:28:14268 "\"--app=http://evil.com/evil;%20rm%20-rf%20/;%20%22;%20rm%20"
269 // Note: $ is escaped as \$ within an arg to Exec, and then
270 // the \ is escaped as \\ as all strings in a Desktop file should
271 // be; finally, \\ becomes \\\\ when represented in a C++ string!
272 "-rf%20\\\\$HOME%20%3Eownz0red\"\n"
[email protected]82810fe12009-09-25 16:21:57273 },
[email protected]790613c2009-12-30 14:49:41274 { "http://evil.com/evil | cat `echo ownz0red` >/dev/null",
[email protected]82810fe12009-09-25 16:21:57275 "Innocent Title",
[email protected]0b303cc2009-09-28 22:35:15276 "chrome-http__evil.com_evil",
[email protected]82810fe12009-09-25 16:21:57277
278 "Name=Google Chrome\n"
279 "Exec=/opt/google/chrome/google-chrome %U\n",
280
281 "#!/usr/bin/env xdg-open\n"
282 "Name=Innocent Title\n"
283 "Exec=/opt/google/chrome/google-chrome "
[email protected]b10392932011-03-08 21:28:14284 "--app=http://evil.com/evil%20%7C%20cat%20%60echo%20ownz0red"
285 "%60%20%3E/dev/null\n"
[email protected]82810fe12009-09-25 16:21:57286 },
[email protected]b96aa932009-08-12 21:34:49287 };
288 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) {
[email protected]b10392932011-03-08 21:28:14289 SCOPED_TRACE(i);
[email protected]b96aa932009-08-12 21:34:49290 EXPECT_EQ(test_cases[i].expected_output,
291 ShellIntegration::GetDesktopFileContents(
292 test_cases[i].template_contents,
293 GURL(test_cases[i].url),
[email protected]01ed1962011-03-04 19:03:13294 "",
[email protected]0b303cc2009-09-28 22:35:15295 ASCIIToUTF16(test_cases[i].title),
296 test_cases[i].icon_name));
[email protected]b96aa932009-08-12 21:34:49297 }
298}
[email protected]12f520c2010-01-06 18:11:15299#elif defined(OS_WIN)
300TEST(ShellIntegrationTest, GetChromiumAppIdTest) {
301 // Empty profile path should get chrome::kBrowserAppID
302 FilePath empty_path;
[email protected]1caa92612010-06-11 00:13:56303 EXPECT_EQ(BrowserDistribution::GetDistribution()->GetBrowserAppId(),
[email protected]12f520c2010-01-06 18:11:15304 ShellIntegration::GetChromiumAppId(empty_path));
305
306 // Default profile path should get chrome::kBrowserAppID
307 FilePath default_user_data_dir;
308 chrome::GetDefaultUserDataDirectory(&default_user_data_dir);
309 FilePath default_profile_path =
310 default_user_data_dir.Append(chrome::kNotSignedInProfile);
[email protected]1caa92612010-06-11 00:13:56311 EXPECT_EQ(BrowserDistribution::GetDistribution()->GetBrowserAppId(),
[email protected]12f520c2010-01-06 18:11:15312 ShellIntegration::GetChromiumAppId(default_profile_path));
313
314 // Non-default profile path should get chrome::kBrowserAppID joined with
315 // profile info.
316 FilePath profile_path(FILE_PATH_LITERAL("root"));
317 profile_path = profile_path.Append(FILE_PATH_LITERAL("udd"));
318 profile_path = profile_path.Append(FILE_PATH_LITERAL("User Data - Test"));
[email protected]1caa92612010-06-11 00:13:56319 EXPECT_EQ(BrowserDistribution::GetDistribution()->GetBrowserAppId() +
320 L".udd.UserDataTest",
[email protected]12f520c2010-01-06 18:11:15321 ShellIntegration::GetChromiumAppId(profile_path));
322}
323#endif