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

Side by Side Diff: chrome/browser/shell_integration_unittest.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: Diff against Issue 12386077. 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 unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/shell_integration.h" 5 #include "chrome/browser/shell_integration.h"
6 6
7 #include <cstdlib> 7 #include <cstdlib>
8 #include <map> 8 #include <map>
9 9
10 #include "base/file_util.h" 10 #include "base/file_util.h"
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after
99 private: 99 private:
100 // Map from name to original value, or the empty string if there was no 100 // Map from name to original value, or the empty string if there was no
101 // previous value. 101 // previous value.
102 std::map<std::string, std::string> old_variables_; 102 std::map<std::string, std::string> old_variables_;
103 103
104 DISALLOW_COPY_AND_ASSIGN(ScopedEnvironment); 104 DISALLOW_COPY_AND_ASSIGN(ScopedEnvironment);
105 }; 105 };
106 106
107 } // namespace 107 } // namespace
108 108
109 TEST(ShellIntegrationTest, GetDesktopShortcutTemplate) { 109 TEST(ShellIntegrationTest, GetExistingDesktopShortcutContents) {
110 #if defined(GOOGLE_CHROME_BUILD) 110 const char kTemplateFilename[] = "shortcut-test.desktop";
111 const char kTemplateFilename[] = "google-chrome.desktop"; 111 base::FilePath kTemplateFilepath(kTemplateFilename);
112 #else // CHROMIUM_BUILD
113 const char kTemplateFilename[] = "chromium-browser.desktop";
114 #endif
115
116 const char kTestData1[] = "a magical testing string"; 112 const char kTestData1[] = "a magical testing string";
117 const char kTestData2[] = "a different testing string"; 113 const char kTestData2[] = "a different testing string";
118 114
119 MessageLoop message_loop; 115 MessageLoop message_loop;
120 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop); 116 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
121 117
122 // Test that it searches $XDG_DATA_HOME/applications. 118 // Test that it searches $XDG_DATA_HOME/applications.
123 { 119 {
124 base::ScopedTempDir temp_dir; 120 base::ScopedTempDir temp_dir;
125 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 121 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
126 122
127 MockEnvironment env; 123 MockEnvironment env;
128 env.Set("XDG_DATA_HOME", temp_dir.path().value()); 124 env.Set("XDG_DATA_HOME", temp_dir.path().value());
129 // Create a file in a non-applications directory. This should be ignored. 125 // Create a file in a non-applications directory. This should be ignored.
130 ASSERT_TRUE(file_util::WriteFile( 126 ASSERT_TRUE(file_util::WriteFile(
131 temp_dir.path().AppendASCII(kTemplateFilename), 127 temp_dir.path().AppendASCII(kTemplateFilename),
132 kTestData2, strlen(kTestData2))); 128 kTestData2, strlen(kTestData2)));
133 ASSERT_TRUE(file_util::CreateDirectory( 129 ASSERT_TRUE(file_util::CreateDirectory(
134 temp_dir.path().AppendASCII("applications"))); 130 temp_dir.path().AppendASCII("applications")));
135 ASSERT_TRUE(file_util::WriteFile( 131 ASSERT_TRUE(file_util::WriteFile(
136 temp_dir.path().AppendASCII("applications") 132 temp_dir.path().AppendASCII("applications")
137 .AppendASCII(kTemplateFilename), 133 .AppendASCII(kTemplateFilename),
138 kTestData1, strlen(kTestData1))); 134 kTestData1, strlen(kTestData1)));
139 std::string contents; 135 std::string contents;
140 ASSERT_TRUE(ShellIntegrationLinux::GetDesktopShortcutTemplate(&env, 136 ASSERT_TRUE(
141 &contents)); 137 ShellIntegrationLinux::GetExistingDesktopShortcutContents(
138 &env, kTemplateFilepath, &contents));
142 EXPECT_EQ(kTestData1, contents); 139 EXPECT_EQ(kTestData1, contents);
143 } 140 }
144 141
145 // Test that it falls back to $HOME/.local/share/applications. 142 // Test that it falls back to $HOME/.local/share/applications.
146 { 143 {
147 base::ScopedTempDir temp_dir; 144 base::ScopedTempDir temp_dir;
148 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 145 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
149 146
150 MockEnvironment env; 147 MockEnvironment env;
151 env.Set("HOME", temp_dir.path().value()); 148 env.Set("HOME", temp_dir.path().value());
152 ASSERT_TRUE(file_util::CreateDirectory( 149 ASSERT_TRUE(file_util::CreateDirectory(
153 temp_dir.path().AppendASCII(".local/share/applications"))); 150 temp_dir.path().AppendASCII(".local/share/applications")));
154 ASSERT_TRUE(file_util::WriteFile( 151 ASSERT_TRUE(file_util::WriteFile(
155 temp_dir.path().AppendASCII(".local/share/applications") 152 temp_dir.path().AppendASCII(".local/share/applications")
156 .AppendASCII(kTemplateFilename), 153 .AppendASCII(kTemplateFilename),
157 kTestData1, strlen(kTestData1))); 154 kTestData1, strlen(kTestData1)));
158 std::string contents; 155 std::string contents;
159 ASSERT_TRUE(ShellIntegrationLinux::GetDesktopShortcutTemplate(&env, 156 ASSERT_TRUE(
160 &contents)); 157 ShellIntegrationLinux::GetExistingDesktopShortcutContents(
158 &env, kTemplateFilepath, &contents));
161 EXPECT_EQ(kTestData1, contents); 159 EXPECT_EQ(kTestData1, contents);
162 } 160 }
163 161
164 // Test that it searches $XDG_DATA_DIRS/applications. 162 // Test that it searches $XDG_DATA_DIRS/applications.
165 { 163 {
166 base::ScopedTempDir temp_dir; 164 base::ScopedTempDir temp_dir;
167 ASSERT_TRUE(temp_dir.CreateUniqueTempDir()); 165 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
168 166
169 MockEnvironment env; 167 MockEnvironment env;
170 env.Set("XDG_DATA_DIRS", temp_dir.path().value()); 168 env.Set("XDG_DATA_DIRS", temp_dir.path().value());
171 ASSERT_TRUE(file_util::CreateDirectory( 169 ASSERT_TRUE(file_util::CreateDirectory(
172 temp_dir.path().AppendASCII("applications"))); 170 temp_dir.path().AppendASCII("applications")));
173 ASSERT_TRUE(file_util::WriteFile( 171 ASSERT_TRUE(file_util::WriteFile(
174 temp_dir.path().AppendASCII("applications") 172 temp_dir.path().AppendASCII("applications")
175 .AppendASCII(kTemplateFilename), 173 .AppendASCII(kTemplateFilename),
176 kTestData2, strlen(kTestData2))); 174 kTestData2, strlen(kTestData2)));
177 std::string contents; 175 std::string contents;
178 ASSERT_TRUE(ShellIntegrationLinux::GetDesktopShortcutTemplate(&env, 176 ASSERT_TRUE(
179 &contents)); 177 ShellIntegrationLinux::GetExistingDesktopShortcutContents(
178 &env, kTemplateFilepath, &contents));
180 EXPECT_EQ(kTestData2, contents); 179 EXPECT_EQ(kTestData2, contents);
181 } 180 }
182 181
183 // Test that it searches $X/applications for each X in $XDG_DATA_DIRS. 182 // Test that it searches $X/applications for each X in $XDG_DATA_DIRS.
184 { 183 {
185 base::ScopedTempDir temp_dir1; 184 base::ScopedTempDir temp_dir1;
186 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir()); 185 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
187 base::ScopedTempDir temp_dir2; 186 base::ScopedTempDir temp_dir2;
188 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir()); 187 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
189 188
190 MockEnvironment env; 189 MockEnvironment env;
191 env.Set("XDG_DATA_DIRS", temp_dir1.path().value() + ":" + 190 env.Set("XDG_DATA_DIRS", temp_dir1.path().value() + ":" +
192 temp_dir2.path().value()); 191 temp_dir2.path().value());
193 // Create a file in a non-applications directory. This should be ignored. 192 // Create a file in a non-applications directory. This should be ignored.
194 ASSERT_TRUE(file_util::WriteFile( 193 ASSERT_TRUE(file_util::WriteFile(
195 temp_dir1.path().AppendASCII(kTemplateFilename), 194 temp_dir1.path().AppendASCII(kTemplateFilename),
196 kTestData1, strlen(kTestData1))); 195 kTestData1, strlen(kTestData1)));
197 // Only create a findable desktop file in the second path. 196 // Only create a findable desktop file in the second path.
198 ASSERT_TRUE(file_util::CreateDirectory( 197 ASSERT_TRUE(file_util::CreateDirectory(
199 temp_dir2.path().AppendASCII("applications"))); 198 temp_dir2.path().AppendASCII("applications")));
200 ASSERT_TRUE(file_util::WriteFile( 199 ASSERT_TRUE(file_util::WriteFile(
201 temp_dir2.path().AppendASCII("applications") 200 temp_dir2.path().AppendASCII("applications")
202 .AppendASCII(kTemplateFilename), 201 .AppendASCII(kTemplateFilename),
203 kTestData2, strlen(kTestData2))); 202 kTestData2, strlen(kTestData2)));
204 std::string contents; 203 std::string contents;
205 ASSERT_TRUE(ShellIntegrationLinux::GetDesktopShortcutTemplate(&env, 204 ASSERT_TRUE(
206 &contents)); 205 ShellIntegrationLinux::GetExistingDesktopShortcutContents(
206 &env, kTemplateFilepath, &contents));
207 EXPECT_EQ(kTestData2, contents); 207 EXPECT_EQ(kTestData2, contents);
208 } 208 }
209 } 209 }
210 210
211 TEST(ShellIntegrationTest, GetDesktopShortcutTemplate) {
212 #if defined(GOOGLE_CHROME_BUILD)
213 const char kTemplateFilename[] = "google-chrome.desktop";
214 #else // CHROMIUM_BUILD
215 const char kTemplateFilename[] = "chromium-browser.desktop";
216 #endif
217
218 const char kTestData[] = "a magical testing string";
219
220 MessageLoop message_loop;
221 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
222
223 // Just do a simple test. The details are covered by
224 // GetExistingDesktopShortcutContents test.
225 {
226 base::ScopedTempDir temp_dir;
227 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
228
229 MockEnvironment env;
230 env.Set("XDG_DATA_HOME", temp_dir.path().value());
231 ASSERT_TRUE(file_util::CreateDirectory(
232 temp_dir.path().AppendASCII("applications")));
233 ASSERT_TRUE(file_util::WriteFile(
234 temp_dir.path().AppendASCII("applications")
235 .AppendASCII(kTemplateFilename),
236 kTestData, strlen(kTestData)));
237 std::string contents;
238 ASSERT_TRUE(ShellIntegrationLinux::GetDesktopShortcutTemplate(&env,
239 &contents));
240 EXPECT_EQ(kTestData, contents);
241 }
242 }
243
211 TEST(ShellIntegrationTest, GetWebShortcutFilename) { 244 TEST(ShellIntegrationTest, GetWebShortcutFilename) {
212 const struct { 245 const struct {
213 const base::FilePath::CharType* path; 246 const base::FilePath::CharType* path;
214 const char* url; 247 const char* url;
215 } test_cases[] = { 248 } test_cases[] = {
216 { FPL("http___foo_.desktop"), "http://foo" }, 249 { FPL("http___foo_.desktop"), "http://foo" },
217 { FPL("http___foo_bar_.desktop"), "http://foo/bar/" }, 250 { FPL("http___foo_bar_.desktop"), "http://foo/bar/" },
218 { FPL("http___foo_bar_a=b&c=d.desktop"), "http://foo/bar?a=b&c=d" }, 251 { FPL("http___foo_bar_a=b&c=d.desktop"), "http://foo/bar?a=b&c=d" },
219 252
220 // Now we're starting to be more evil... 253 // Now we're starting to be more evil...
221 { FPL("http___foo_.desktop"), "http://foo/bar/baz/../../../../../" }, 254 { FPL("http___foo_.desktop"), "http://foo/bar/baz/../../../../../" },
222 { FPL("http___foo_.desktop"), "http://foo/bar/././../baz/././../" }, 255 { FPL("http___foo_.desktop"), "http://foo/bar/././../baz/././../" },
223 { FPL("http___.._.desktop"), "http://../../../../" }, 256 { FPL("http___.._.desktop"), "http://../../../../" },
224 }; 257 };
225 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) { 258 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) {
226 EXPECT_EQ(std::string(chrome::kBrowserProcessExecutableName) + "-" + 259 EXPECT_EQ(std::string(chrome::kBrowserProcessExecutableName) + "-" +
227 test_cases[i].path, 260 test_cases[i].path,
228 ShellIntegrationLinux::GetWebShortcutFilename( 261 ShellIntegrationLinux::GetWebShortcutFilename(
229 GURL(test_cases[i].url)).value()) << 262 GURL(test_cases[i].url)).value()) <<
230 " while testing " << test_cases[i].url; 263 " while testing " << test_cases[i].url;
231 } 264 }
232 } 265 }
233 266
234 TEST(ShellIntegrationTest, GetDesktopFileContents) { 267 TEST(ShellIntegrationTest, GetDesktopFileContents) {
235 const struct { 268 const struct {
236 const char* url; 269 const char* url;
237 const char* title; 270 const char* title;
238 const char* icon_name; 271 const char* icon_name;
272 bool nodisplay;
239 const char* template_contents; 273 const char* template_contents;
240 const char* expected_output; 274 const char* expected_output;
241 } test_cases[] = { 275 } test_cases[] = {
242 // Dumb case. 276 // Dumb case.
243 { "ignored", "ignored", "ignored", "", "#!/usr/bin/env xdg-open\n" }, 277 { "ignored", "ignored", "ignored", false, "", "#!/usr/bin/env xdg-open\n" },
244 278
245 // Real-world case. 279 // Real-world case.
246 { "http://gmail.com", 280 { "http://gmail.com",
247 "GMail", 281 "GMail",
248 "chrome-http__gmail.com", 282 "chrome-http__gmail.com",
283 false,
249 284
250 "[Desktop Entry]\n" 285 "[Desktop Entry]\n"
251 "Version=1.0\n" 286 "Version=1.0\n"
252 "Encoding=UTF-8\n" 287 "Encoding=UTF-8\n"
253 "Name=Google Chrome\n" 288 "Name=Google Chrome\n"
254 "GenericName=Web Browser\n" 289 "GenericName=Web Browser\n"
255 "Comment=The web browser from Google\n" 290 "Comment=The web browser from Google\n"
256 "Exec=/opt/google/chrome/google-chrome %U\n" 291 "Exec=/opt/google/chrome/google-chrome %U\n"
257 "Terminal=false\n" 292 "Terminal=false\n"
258 "Icon=/opt/google/chrome/product_logo_48.png\n" 293 "Icon=/opt/google/chrome/product_logo_48.png\n"
(...skipping 21 matching lines...) Expand all
280 // Aura Chrome does not (yet) set WMClass, so we only expect 315 // Aura Chrome does not (yet) set WMClass, so we only expect
281 // StartupWMClass on non-Aura builds. 316 // StartupWMClass on non-Aura builds.
282 "StartupWMClass=gmail.com\n" 317 "StartupWMClass=gmail.com\n"
283 #endif 318 #endif
284 }, 319 },
285 320
286 // Make sure we don't insert duplicate shebangs. 321 // Make sure we don't insert duplicate shebangs.
287 { "http://gmail.com", 322 { "http://gmail.com",
288 "GMail", 323 "GMail",
289 "chrome-http__gmail.com", 324 "chrome-http__gmail.com",
325 false,
290 326
291 "#!/some/shebang\n" 327 "#!/some/shebang\n"
292 "[Desktop Entry]\n" 328 "[Desktop Entry]\n"
293 "Name=Google Chrome\n" 329 "Name=Google Chrome\n"
294 "Exec=/opt/google/chrome/google-chrome %U\n", 330 "Exec=/opt/google/chrome/google-chrome %U\n",
295 331
296 "#!/usr/bin/env xdg-open\n" 332 "#!/usr/bin/env xdg-open\n"
297 "[Desktop Entry]\n" 333 "[Desktop Entry]\n"
298 "Name=GMail\n" 334 "Name=GMail\n"
299 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n" 335 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
300 "Icon=chrome-http__gmail.com\n" 336 "Icon=chrome-http__gmail.com\n"
301 #if !defined(USE_AURA) 337 #if !defined(USE_AURA)
302 // Aura Chrome does not (yet) set WMClass, so we only expect 338 // Aura Chrome does not (yet) set WMClass, so we only expect
303 // StartupWMClass on non-Aura builds. 339 // StartupWMClass on non-Aura builds.
304 "StartupWMClass=gmail.com\n" 340 "StartupWMClass=gmail.com\n"
305 #endif 341 #endif
306 }, 342 },
307 343
308 // Make sure i18n-ed names and other fields are removed. 344 // Make sure i18n-ed names and other fields are removed.
309 { "http://gmail.com", 345 { "http://gmail.com",
310 "GMail", 346 "GMail",
311 "chrome-http__gmail.com", 347 "chrome-http__gmail.com",
348 false,
312 349
313 "[Desktop Entry]\n" 350 "[Desktop Entry]\n"
314 "Name=Google Chrome\n" 351 "Name=Google Chrome\n"
315 "Name[en_AU]=Google Chrome\n" 352 "Name[en_AU]=Google Chrome\n"
316 "Name[pl]=Google Chrome\n" 353 "Name[pl]=Google Chrome\n"
317 "GenericName=Web Browser\n" 354 "GenericName=Web Browser\n"
318 "GenericName[en_AU]=Web Browser\n" 355 "GenericName[en_AU]=Web Browser\n"
319 "GenericName[pl]=Navegador Web\n" 356 "GenericName[pl]=Navegador Web\n"
320 "Exec=/opt/google/chrome/google-chrome %U\n" 357 "Exec=/opt/google/chrome/google-chrome %U\n"
321 "Comment[en_AU]=Some comment.\n" 358 "Comment[en_AU]=Some comment.\n"
322 "Comment[pl]=Jakis komentarz.\n", 359 "Comment[pl]=Jakis komentarz.\n",
323 360
324 "#!/usr/bin/env xdg-open\n" 361 "#!/usr/bin/env xdg-open\n"
325 "[Desktop Entry]\n" 362 "[Desktop Entry]\n"
326 "Name=GMail\n" 363 "Name=GMail\n"
327 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n" 364 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
328 "Icon=chrome-http__gmail.com\n" 365 "Icon=chrome-http__gmail.com\n"
329 #if !defined(USE_AURA) 366 #if !defined(USE_AURA)
330 // Aura Chrome does not (yet) set WMClass, so we only expect 367 // Aura Chrome does not (yet) set WMClass, so we only expect
331 // StartupWMClass on non-Aura builds. 368 // StartupWMClass on non-Aura builds.
332 "StartupWMClass=gmail.com\n" 369 "StartupWMClass=gmail.com\n"
333 #endif 370 #endif
334 }, 371 },
335 372
336 // Make sure that empty icons are replaced by the chrome icon. 373 // Make sure that empty icons are replaced by the chrome icon.
337 { "http://gmail.com", 374 { "http://gmail.com",
338 "GMail", 375 "GMail",
339 "", 376 "",
377 false,
340 378
341 "[Desktop Entry]\n" 379 "[Desktop Entry]\n"
342 "Name=Google Chrome\n" 380 "Name=Google Chrome\n"
343 "Exec=/opt/google/chrome/google-chrome %U\n" 381 "Exec=/opt/google/chrome/google-chrome %U\n"
344 "Comment[pl]=Jakis komentarz.\n" 382 "Comment[pl]=Jakis komentarz.\n"
345 "Icon=/opt/google/chrome/product_logo_48.png\n", 383 "Icon=/opt/google/chrome/product_logo_48.png\n",
346 384
347 "#!/usr/bin/env xdg-open\n" 385 "#!/usr/bin/env xdg-open\n"
348 "[Desktop Entry]\n" 386 "[Desktop Entry]\n"
349 "Name=GMail\n" 387 "Name=GMail\n"
350 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n" 388 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
351 "Icon=/opt/google/chrome/product_logo_48.png\n" 389 "Icon=/opt/google/chrome/product_logo_48.png\n"
352 #if !defined(USE_AURA) 390 #if !defined(USE_AURA)
353 // Aura Chrome does not (yet) set WMClass, so we only expect 391 // Aura Chrome does not (yet) set WMClass, so we only expect
354 // StartupWMClass on non-Aura builds. 392 // StartupWMClass on non-Aura builds.
355 "StartupWMClass=gmail.com\n" 393 "StartupWMClass=gmail.com\n"
356 #endif 394 #endif
357 }, 395 },
358 396
397 // Test adding NoDisplay=true.
398 { "http://gmail.com",
399 "GMail",
400 "chrome-http__gmail.com",
401 true,
402
403 "[Desktop Entry]\n"
404 "Name=Google Chrome\n"
405 "Exec=/opt/google/chrome/google-chrome %U\n",
406
407 "#!/usr/bin/env xdg-open\n"
408 "[Desktop Entry]\n"
409 "Name=GMail\n"
410 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
411 "Icon=chrome-http__gmail.com\n"
412 "NoDisplay=true\n"
413 #if !defined(USE_AURA)
414 // Aura Chrome does not (yet) set WMClass, so we only expect
415 // StartupWMClass on non-Aura builds.
416 "StartupWMClass=gmail.com\n"
417 #endif
418 },
419
359 // Now we're starting to be more evil... 420 // Now we're starting to be more evil...
360 { "http://evil.com/evil --join-the-b0tnet", 421 { "http://evil.com/evil --join-the-b0tnet",
361 "Ownz0red\nExec=rm -rf /", 422 "Ownz0red\nExec=rm -rf /",
362 "chrome-http__evil.com_evil", 423 "chrome-http__evil.com_evil",
424 false,
363 425
364 "[Desktop Entry]\n" 426 "[Desktop Entry]\n"
365 "Name=Google Chrome\n" 427 "Name=Google Chrome\n"
366 "Exec=/opt/google/chrome/google-chrome %U\n", 428 "Exec=/opt/google/chrome/google-chrome %U\n",
367 429
368 "#!/usr/bin/env xdg-open\n" 430 "#!/usr/bin/env xdg-open\n"
369 "[Desktop Entry]\n" 431 "[Desktop Entry]\n"
370 "Name=http://evil.com/evil%20--join-the-b0tnet\n" 432 "Name=http://evil.com/evil%20--join-the-b0tnet\n"
371 "Exec=/opt/google/chrome/google-chrome " 433 "Exec=/opt/google/chrome/google-chrome "
372 "--app=http://evil.com/evil%20--join-the-b0tnet\n" 434 "--app=http://evil.com/evil%20--join-the-b0tnet\n"
373 "Icon=chrome-http__evil.com_evil\n" 435 "Icon=chrome-http__evil.com_evil\n"
374 #if !defined(USE_AURA) 436 #if !defined(USE_AURA)
375 // Aura Chrome does not (yet) set WMClass, so we only expect 437 // Aura Chrome does not (yet) set WMClass, so we only expect
376 // StartupWMClass on non-Aura builds. 438 // StartupWMClass on non-Aura builds.
377 "StartupWMClass=evil.com__evil%20--join-the-b0tnet\n" 439 "StartupWMClass=evil.com__evil%20--join-the-b0tnet\n"
378 #endif 440 #endif
379 }, 441 },
380 { "http://evil.com/evil; rm -rf /; \"; rm -rf $HOME >ownz0red", 442 { "http://evil.com/evil; rm -rf /; \"; rm -rf $HOME >ownz0red",
381 "Innocent Title", 443 "Innocent Title",
382 "chrome-http__evil.com_evil", 444 "chrome-http__evil.com_evil",
445 false,
383 446
384 "[Desktop Entry]\n" 447 "[Desktop Entry]\n"
385 "Name=Google Chrome\n" 448 "Name=Google Chrome\n"
386 "Exec=/opt/google/chrome/google-chrome %U\n", 449 "Exec=/opt/google/chrome/google-chrome %U\n",
387 450
388 "#!/usr/bin/env xdg-open\n" 451 "#!/usr/bin/env xdg-open\n"
389 "[Desktop Entry]\n" 452 "[Desktop Entry]\n"
390 "Name=Innocent Title\n" 453 "Name=Innocent Title\n"
391 "Exec=/opt/google/chrome/google-chrome " 454 "Exec=/opt/google/chrome/google-chrome "
392 "\"--app=http://evil.com/evil;%20rm%20-rf%20/;%20%22;%20rm%20" 455 "\"--app=http://evil.com/evil;%20rm%20-rf%20/;%20%22;%20rm%20"
393 // Note: $ is escaped as \$ within an arg to Exec, and then 456 // Note: $ is escaped as \$ within an arg to Exec, and then
394 // the \ is escaped as \\ as all strings in a Desktop file should 457 // the \ is escaped as \\ as all strings in a Desktop file should
395 // be; finally, \\ becomes \\\\ when represented in a C++ string! 458 // be; finally, \\ becomes \\\\ when represented in a C++ string!
396 "-rf%20\\\\$HOME%20%3Eownz0red\"\n" 459 "-rf%20\\\\$HOME%20%3Eownz0red\"\n"
397 "Icon=chrome-http__evil.com_evil\n" 460 "Icon=chrome-http__evil.com_evil\n"
398 #if !defined(USE_AURA) 461 #if !defined(USE_AURA)
399 // Aura Chrome does not (yet) set WMClass, so we only expect 462 // Aura Chrome does not (yet) set WMClass, so we only expect
400 // StartupWMClass on non-Aura builds. 463 // StartupWMClass on non-Aura builds.
401 "StartupWMClass=evil.com__evil;%20rm%20-rf%20_;%20%22;%20" 464 "StartupWMClass=evil.com__evil;%20rm%20-rf%20_;%20%22;%20"
402 "rm%20-rf%20$HOME%20%3Eownz0red\n" 465 "rm%20-rf%20$HOME%20%3Eownz0red\n"
403 #endif 466 #endif
404 }, 467 },
405 { "http://evil.com/evil | cat `echo ownz0red` >/dev/null", 468 { "http://evil.com/evil | cat `echo ownz0red` >/dev/null",
406 "Innocent Title", 469 "Innocent Title",
407 "chrome-http__evil.com_evil", 470 "chrome-http__evil.com_evil",
471 false,
408 472
409 "[Desktop Entry]\n" 473 "[Desktop Entry]\n"
410 "Name=Google Chrome\n" 474 "Name=Google Chrome\n"
411 "Exec=/opt/google/chrome/google-chrome %U\n", 475 "Exec=/opt/google/chrome/google-chrome %U\n",
412 476
413 "#!/usr/bin/env xdg-open\n" 477 "#!/usr/bin/env xdg-open\n"
414 "[Desktop Entry]\n" 478 "[Desktop Entry]\n"
415 "Name=Innocent Title\n" 479 "Name=Innocent Title\n"
416 "Exec=/opt/google/chrome/google-chrome " 480 "Exec=/opt/google/chrome/google-chrome "
417 "--app=http://evil.com/evil%20%7C%20cat%20%60echo%20ownz0red" 481 "--app=http://evil.com/evil%20%7C%20cat%20%60echo%20ownz0red"
(...skipping 19 matching lines...) Expand all
437 EXPECT_EQ( 501 EXPECT_EQ(
438 test_cases[i].expected_output, 502 test_cases[i].expected_output,
439 ShellIntegrationLinux::GetDesktopFileContents( 503 ShellIntegrationLinux::GetDesktopFileContents(
440 test_cases[i].template_contents, 504 test_cases[i].template_contents,
441 web_app::GenerateApplicationNameFromURL(GURL(test_cases[i].url)), 505 web_app::GenerateApplicationNameFromURL(GURL(test_cases[i].url)),
442 GURL(test_cases[i].url), 506 GURL(test_cases[i].url),
443 "", 507 "",
444 base::FilePath(), 508 base::FilePath(),
445 ASCIIToUTF16(test_cases[i].title), 509 ASCIIToUTF16(test_cases[i].title),
446 test_cases[i].icon_name, 510 test_cases[i].icon_name,
447 base::FilePath())); 511 base::FilePath(),
512 test_cases[i].nodisplay));
448 } 513 }
449 } 514 }
515
516 TEST(ShellIntegrationTest, DesktopShortcutLocations) {
517 base::FilePath kProfilePath("Default");
518 const char kExtensionId[] = "test_extension";
519 const char kTemplateFilename[] = "chrome-test_extension-Default.desktop";
520 base::FilePath kTemplateFilepath(kTemplateFilename);
521 const char kNoDisplayDesktopFile[] = "[Desktop Entry]\nNoDisplay=true";
522
523 MessageLoop message_loop;
524 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
525
526 // No existing shortcuts.
527 {
528 MockEnvironment env;
529 ShellIntegration::ShortcutLocations result =
530 ShellIntegrationLinux::DesktopShortcutLocations(
531 &env, kProfilePath, kExtensionId);
532 EXPECT_FALSE(result.on_desktop);
533 EXPECT_FALSE(result.in_applications_menu);
534 EXPECT_FALSE(result.in_quick_launch_bar);
535 }
536
537 // Shortcut on desktop.
538 {
539 base::ScopedTempDir temp_dir;
540 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
541 base::FilePath desktop_path = temp_dir.path();
542
543 MockEnvironment env;
544 ASSERT_TRUE(file_util::CreateDirectory(desktop_path));
545 ASSERT_FALSE(file_util::WriteFile(
546 desktop_path.AppendASCII(kTemplateFilename),
547 "", 0));
548 ShellIntegration::ShortcutLocations result =
549 ShellIntegrationLinux::DesktopShortcutLocations(
550 &env, kProfilePath, kExtensionId, desktop_path);
551 EXPECT_TRUE(result.on_desktop);
552 EXPECT_FALSE(result.in_applications_menu);
553 EXPECT_FALSE(result.in_quick_launch_bar);
554 }
555
556 // Shortcut in applications directory.
557 {
558 base::ScopedTempDir temp_dir;
559 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
560 base::FilePath apps_path = temp_dir.path().AppendASCII("applications");
561
562 MockEnvironment env;
563 env.Set("XDG_DATA_HOME", temp_dir.path().value());
564 ASSERT_TRUE(file_util::CreateDirectory(apps_path));
565 ASSERT_FALSE(file_util::WriteFile(
566 apps_path.AppendASCII(kTemplateFilename),
567 "", 0));
568 ShellIntegration::ShortcutLocations result =
569 ShellIntegrationLinux::DesktopShortcutLocations(
570 &env, kProfilePath, kExtensionId);
571 EXPECT_FALSE(result.on_desktop);
572 EXPECT_TRUE(result.in_applications_menu);
573 EXPECT_FALSE(result.in_quick_launch_bar);
574 }
575
576 // Shortcut in applications directory with NoDisplay=true.
577 {
578 base::ScopedTempDir temp_dir;
579 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
580 base::FilePath apps_path = temp_dir.path().AppendASCII("applications");
581
582 MockEnvironment env;
583 env.Set("XDG_DATA_HOME", temp_dir.path().value());
584 ASSERT_TRUE(file_util::CreateDirectory(apps_path));
585 ASSERT_TRUE(file_util::WriteFile(
586 apps_path.AppendASCII(kTemplateFilename),
587 kNoDisplayDesktopFile, strlen(kNoDisplayDesktopFile)));
588 ShellIntegration::ShortcutLocations result =
589 ShellIntegrationLinux::DesktopShortcutLocations(
590 &env, kProfilePath, kExtensionId);
591 // Doesn't count as being in applications menu.
592 EXPECT_FALSE(result.on_desktop);
593 EXPECT_FALSE(result.in_applications_menu);
594 EXPECT_FALSE(result.in_quick_launch_bar);
595 }
596
597 // Shortcut on desktop and in applications directory.
598 {
599 base::ScopedTempDir temp_dir1;
600 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
601 base::FilePath desktop_path = temp_dir1.path();
602
603 base::ScopedTempDir temp_dir2;
604 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
605 base::FilePath apps_path = temp_dir2.path().AppendASCII("applications");
606
607 MockEnvironment env;
608 ASSERT_TRUE(file_util::CreateDirectory(desktop_path));
609 ASSERT_FALSE(file_util::WriteFile(
610 desktop_path.AppendASCII(kTemplateFilename),
611 "", 0));
612 env.Set("XDG_DATA_HOME", temp_dir2.path().value());
613 ASSERT_TRUE(file_util::CreateDirectory(apps_path));
614 ASSERT_FALSE(file_util::WriteFile(
615 apps_path.AppendASCII(kTemplateFilename),
616 "", 0));
617 ShellIntegration::ShortcutLocations result =
618 ShellIntegrationLinux::DesktopShortcutLocations(
619 &env, kProfilePath, kExtensionId, desktop_path);
620 EXPECT_TRUE(result.on_desktop);
621 EXPECT_TRUE(result.in_applications_menu);
622 EXPECT_FALSE(result.in_quick_launch_bar);
623 }
624 }
625
450 #endif 626 #endif
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698