- Added search icon and search clear button in 1x and 2x. Screenshot: http://i.imgur...
[chromium-blink-merge.git] / chrome / browser / shell_integration_unittest.cc
blob82a9b6a826f04adfd22d61cead91a8d6a8a95d48
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
3 // found in the LICENSE file.
5 #include "chrome/browser/shell_integration.h"
7 #include <algorithm>
8 #include <cstdlib>
9 #include <map>
11 #include "base/base_paths.h"
12 #include "base/file_util.h"
13 #include "base/files/file_path.h"
14 #include "base/files/scoped_temp_dir.h"
15 #include "base/message_loop/message_loop.h"
16 #include "base/stl_util.h"
17 #include "base/strings/string_util.h"
18 #include "base/strings/utf_string_conversions.h"
19 #include "base/test/scoped_path_override.h"
20 #include "chrome/browser/web_applications/web_app.h"
21 #include "chrome/common/chrome_constants.h"
22 #include "content/public/test/test_browser_thread.h"
23 #include "testing/gmock/include/gmock/gmock.h"
24 #include "testing/gtest/include/gtest/gtest.h"
25 #include "url/gurl.h"
27 #if defined(OS_POSIX) && !defined(OS_MACOSX)
28 #include "base/environment.h"
29 #include "chrome/browser/shell_integration_linux.h"
30 #endif
32 #define FPL FILE_PATH_LITERAL
34 using content::BrowserThread;
35 using ::testing::ElementsAre;
37 #if defined(OS_POSIX) && !defined(OS_MACOSX)
38 namespace {
40 // Provides mock environment variables values based on a stored map.
41 class MockEnvironment : public base::Environment {
42 public:
43 MockEnvironment() {}
45 void Set(const std::string& name, const std::string& value) {
46 variables_[name] = value;
49 virtual bool GetVar(const char* variable_name, std::string* result) OVERRIDE {
50 if (ContainsKey(variables_, variable_name)) {
51 *result = variables_[variable_name];
52 return true;
55 return false;
58 virtual bool SetVar(const char* variable_name,
59 const std::string& new_value) OVERRIDE {
60 ADD_FAILURE();
61 return false;
64 virtual bool UnSetVar(const char* variable_name) OVERRIDE {
65 ADD_FAILURE();
66 return false;
69 private:
70 std::map<std::string, std::string> variables_;
72 DISALLOW_COPY_AND_ASSIGN(MockEnvironment);
75 } // namespace
77 TEST(ShellIntegrationTest, GetDataWriteLocation) {
78 base::MessageLoop message_loop;
79 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
81 // Test that it returns $XDG_DATA_HOME.
83 MockEnvironment env;
84 env.Set("HOME", "/home/user");
85 env.Set("XDG_DATA_HOME", "/user/path");
86 base::FilePath path;
87 ASSERT_TRUE(ShellIntegrationLinux::GetDataWriteLocation(&env, &path));
88 EXPECT_EQ(base::FilePath("/user/path"), path);
91 // Test that $XDG_DATA_HOME falls back to $HOME/.local/share.
93 MockEnvironment env;
94 env.Set("HOME", "/home/user");
95 base::FilePath path;
96 ASSERT_TRUE(ShellIntegrationLinux::GetDataWriteLocation(&env, &path));
97 EXPECT_EQ(base::FilePath("/home/user/.local/share"), path);
100 // Test that if neither $XDG_DATA_HOME nor $HOME are specified, it fails.
102 MockEnvironment env;
103 base::FilePath path;
104 ASSERT_FALSE(ShellIntegrationLinux::GetDataWriteLocation(&env, &path));
108 TEST(ShellIntegrationTest, GetDataSearchLocations) {
109 base::MessageLoop message_loop;
110 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
112 // Test that it returns $XDG_DATA_HOME + $XDG_DATA_DIRS.
114 MockEnvironment env;
115 env.Set("HOME", "/home/user");
116 env.Set("XDG_DATA_HOME", "/user/path");
117 env.Set("XDG_DATA_DIRS", "/system/path/1:/system/path/2");
118 EXPECT_THAT(
119 ShellIntegrationLinux::GetDataSearchLocations(&env),
120 ElementsAre(base::FilePath("/user/path"),
121 base::FilePath("/system/path/1"),
122 base::FilePath("/system/path/2")));
125 // Test that $XDG_DATA_HOME falls back to $HOME/.local/share.
127 MockEnvironment env;
128 env.Set("HOME", "/home/user");
129 env.Set("XDG_DATA_DIRS", "/system/path/1:/system/path/2");
130 EXPECT_THAT(
131 ShellIntegrationLinux::GetDataSearchLocations(&env),
132 ElementsAre(base::FilePath("/home/user/.local/share"),
133 base::FilePath("/system/path/1"),
134 base::FilePath("/system/path/2")));
137 // Test that if neither $XDG_DATA_HOME nor $HOME are specified, it still
138 // succeeds.
140 MockEnvironment env;
141 env.Set("XDG_DATA_DIRS", "/system/path/1:/system/path/2");
142 EXPECT_THAT(
143 ShellIntegrationLinux::GetDataSearchLocations(&env),
144 ElementsAre(base::FilePath("/system/path/1"),
145 base::FilePath("/system/path/2")));
148 // Test that $XDG_DATA_DIRS falls back to the two default paths.
150 MockEnvironment env;
151 env.Set("HOME", "/home/user");
152 env.Set("XDG_DATA_HOME", "/user/path");
153 EXPECT_THAT(
154 ShellIntegrationLinux::GetDataSearchLocations(&env),
155 ElementsAre(base::FilePath("/user/path"),
156 base::FilePath("/usr/local/share"),
157 base::FilePath("/usr/share")));
161 TEST(ShellIntegrationTest, GetExistingShortcutLocations) {
162 base::FilePath kProfilePath("Profile 1");
163 const char kExtensionId[] = "test_extension";
164 const char kTemplateFilename[] = "chrome-test_extension-Profile_1.desktop";
165 base::FilePath kTemplateFilepath(kTemplateFilename);
166 const char kNoDisplayDesktopFile[] = "[Desktop Entry]\nNoDisplay=true";
168 base::MessageLoop message_loop;
169 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
171 // No existing shortcuts.
173 MockEnvironment env;
174 ShellIntegration::ShortcutLocations result =
175 ShellIntegrationLinux::GetExistingShortcutLocations(
176 &env, kProfilePath, kExtensionId);
177 EXPECT_FALSE(result.on_desktop);
178 EXPECT_FALSE(result.in_applications_menu);
179 EXPECT_FALSE(result.in_quick_launch_bar);
180 EXPECT_FALSE(result.hidden);
183 // Shortcut on desktop.
185 base::ScopedTempDir temp_dir;
186 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
187 base::FilePath desktop_path = temp_dir.path();
189 MockEnvironment env;
190 ASSERT_TRUE(file_util::CreateDirectory(desktop_path));
191 ASSERT_FALSE(file_util::WriteFile(
192 desktop_path.AppendASCII(kTemplateFilename),
193 "", 0));
194 ShellIntegration::ShortcutLocations result =
195 ShellIntegrationLinux::GetExistingShortcutLocations(
196 &env, kProfilePath, kExtensionId, desktop_path);
197 EXPECT_TRUE(result.on_desktop);
198 EXPECT_FALSE(result.in_applications_menu);
199 EXPECT_FALSE(result.in_quick_launch_bar);
200 EXPECT_FALSE(result.hidden);
203 // Shortcut in applications directory.
205 base::ScopedTempDir temp_dir;
206 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
207 base::FilePath apps_path = temp_dir.path().AppendASCII("applications");
209 MockEnvironment env;
210 env.Set("XDG_DATA_HOME", temp_dir.path().value());
211 ASSERT_TRUE(file_util::CreateDirectory(apps_path));
212 ASSERT_FALSE(file_util::WriteFile(
213 apps_path.AppendASCII(kTemplateFilename),
214 "", 0));
215 ShellIntegration::ShortcutLocations result =
216 ShellIntegrationLinux::GetExistingShortcutLocations(
217 &env, kProfilePath, kExtensionId);
218 EXPECT_FALSE(result.on_desktop);
219 EXPECT_TRUE(result.in_applications_menu);
220 EXPECT_FALSE(result.in_quick_launch_bar);
221 EXPECT_FALSE(result.hidden);
224 // Shortcut in applications directory with NoDisplay=true.
226 base::ScopedTempDir temp_dir;
227 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
228 base::FilePath apps_path = temp_dir.path().AppendASCII("applications");
230 MockEnvironment env;
231 env.Set("XDG_DATA_HOME", temp_dir.path().value());
232 ASSERT_TRUE(file_util::CreateDirectory(apps_path));
233 ASSERT_TRUE(file_util::WriteFile(
234 apps_path.AppendASCII(kTemplateFilename),
235 kNoDisplayDesktopFile, strlen(kNoDisplayDesktopFile)));
236 ShellIntegration::ShortcutLocations result =
237 ShellIntegrationLinux::GetExistingShortcutLocations(
238 &env, kProfilePath, kExtensionId);
239 // Doesn't count as being in applications menu.
240 EXPECT_FALSE(result.on_desktop);
241 EXPECT_FALSE(result.in_applications_menu);
242 EXPECT_FALSE(result.in_quick_launch_bar);
243 EXPECT_TRUE(result.hidden);
246 // Shortcut on desktop and in applications directory.
248 base::ScopedTempDir temp_dir1;
249 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
250 base::FilePath desktop_path = temp_dir1.path();
252 base::ScopedTempDir temp_dir2;
253 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
254 base::FilePath apps_path = temp_dir2.path().AppendASCII("applications");
256 MockEnvironment env;
257 ASSERT_TRUE(file_util::CreateDirectory(desktop_path));
258 ASSERT_FALSE(file_util::WriteFile(
259 desktop_path.AppendASCII(kTemplateFilename),
260 "", 0));
261 env.Set("XDG_DATA_HOME", temp_dir2.path().value());
262 ASSERT_TRUE(file_util::CreateDirectory(apps_path));
263 ASSERT_FALSE(file_util::WriteFile(
264 apps_path.AppendASCII(kTemplateFilename),
265 "", 0));
266 ShellIntegration::ShortcutLocations result =
267 ShellIntegrationLinux::GetExistingShortcutLocations(
268 &env, kProfilePath, kExtensionId, desktop_path);
269 EXPECT_TRUE(result.on_desktop);
270 EXPECT_TRUE(result.in_applications_menu);
271 EXPECT_FALSE(result.in_quick_launch_bar);
272 EXPECT_FALSE(result.hidden);
276 TEST(ShellIntegrationTest, GetExistingShortcutContents) {
277 const char kTemplateFilename[] = "shortcut-test.desktop";
278 base::FilePath kTemplateFilepath(kTemplateFilename);
279 const char kTestData1[] = "a magical testing string";
280 const char kTestData2[] = "a different testing string";
282 base::MessageLoop message_loop;
283 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
285 // Test that it searches $XDG_DATA_HOME/applications.
287 base::ScopedTempDir temp_dir;
288 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
290 MockEnvironment env;
291 env.Set("XDG_DATA_HOME", temp_dir.path().value());
292 // Create a file in a non-applications directory. This should be ignored.
293 ASSERT_TRUE(file_util::WriteFile(
294 temp_dir.path().AppendASCII(kTemplateFilename),
295 kTestData2, strlen(kTestData2)));
296 ASSERT_TRUE(file_util::CreateDirectory(
297 temp_dir.path().AppendASCII("applications")));
298 ASSERT_TRUE(file_util::WriteFile(
299 temp_dir.path().AppendASCII("applications")
300 .AppendASCII(kTemplateFilename),
301 kTestData1, strlen(kTestData1)));
302 std::string contents;
303 ASSERT_TRUE(
304 ShellIntegrationLinux::GetExistingShortcutContents(
305 &env, kTemplateFilepath, &contents));
306 EXPECT_EQ(kTestData1, contents);
309 // Test that it falls back to $HOME/.local/share/applications.
311 base::ScopedTempDir temp_dir;
312 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
314 MockEnvironment env;
315 env.Set("HOME", temp_dir.path().value());
316 ASSERT_TRUE(file_util::CreateDirectory(
317 temp_dir.path().AppendASCII(".local/share/applications")));
318 ASSERT_TRUE(file_util::WriteFile(
319 temp_dir.path().AppendASCII(".local/share/applications")
320 .AppendASCII(kTemplateFilename),
321 kTestData1, strlen(kTestData1)));
322 std::string contents;
323 ASSERT_TRUE(
324 ShellIntegrationLinux::GetExistingShortcutContents(
325 &env, kTemplateFilepath, &contents));
326 EXPECT_EQ(kTestData1, contents);
329 // Test that it searches $XDG_DATA_DIRS/applications.
331 base::ScopedTempDir temp_dir;
332 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
334 MockEnvironment env;
335 env.Set("XDG_DATA_DIRS", temp_dir.path().value());
336 ASSERT_TRUE(file_util::CreateDirectory(
337 temp_dir.path().AppendASCII("applications")));
338 ASSERT_TRUE(file_util::WriteFile(
339 temp_dir.path().AppendASCII("applications")
340 .AppendASCII(kTemplateFilename),
341 kTestData2, strlen(kTestData2)));
342 std::string contents;
343 ASSERT_TRUE(
344 ShellIntegrationLinux::GetExistingShortcutContents(
345 &env, kTemplateFilepath, &contents));
346 EXPECT_EQ(kTestData2, contents);
349 // Test that it searches $X/applications for each X in $XDG_DATA_DIRS.
351 base::ScopedTempDir temp_dir1;
352 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
353 base::ScopedTempDir temp_dir2;
354 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
356 MockEnvironment env;
357 env.Set("XDG_DATA_DIRS", temp_dir1.path().value() + ":" +
358 temp_dir2.path().value());
359 // Create a file in a non-applications directory. This should be ignored.
360 ASSERT_TRUE(file_util::WriteFile(
361 temp_dir1.path().AppendASCII(kTemplateFilename),
362 kTestData1, strlen(kTestData1)));
363 // Only create a findable desktop file in the second path.
364 ASSERT_TRUE(file_util::CreateDirectory(
365 temp_dir2.path().AppendASCII("applications")));
366 ASSERT_TRUE(file_util::WriteFile(
367 temp_dir2.path().AppendASCII("applications")
368 .AppendASCII(kTemplateFilename),
369 kTestData2, strlen(kTestData2)));
370 std::string contents;
371 ASSERT_TRUE(
372 ShellIntegrationLinux::GetExistingShortcutContents(
373 &env, kTemplateFilepath, &contents));
374 EXPECT_EQ(kTestData2, contents);
378 TEST(ShellIntegrationTest, GetExtensionShortcutFilename) {
379 base::FilePath kProfilePath("a/b/c/Profile Name?");
380 const char kExtensionId[] = "extensionid";
381 EXPECT_EQ(base::FilePath("chrome-extensionid-Profile_Name_.desktop"),
382 ShellIntegrationLinux::GetExtensionShortcutFilename(
383 kProfilePath, kExtensionId));
386 TEST(ShellIntegrationTest, GetExistingProfileShortcutFilenames) {
387 base::FilePath kProfilePath("a/b/c/Profile Name?");
388 const char kApp1Filename[] = "chrome-extension1-Profile_Name_.desktop";
389 const char kApp2Filename[] = "chrome-extension2-Profile_Name_.desktop";
390 const char kUnrelatedAppFilename[] = "chrome-extension-Other_Profile.desktop";
392 base::MessageLoop message_loop;
393 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
395 base::ScopedTempDir temp_dir;
396 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
397 ASSERT_EQ(0,
398 file_util::WriteFile(
399 temp_dir.path().AppendASCII(kApp1Filename), "", 0));
400 ASSERT_EQ(0,
401 file_util::WriteFile(
402 temp_dir.path().AppendASCII(kApp2Filename), "", 0));
403 // This file should not be returned in the results.
404 ASSERT_EQ(0,
405 file_util::WriteFile(
406 temp_dir.path().AppendASCII(kUnrelatedAppFilename), "", 0));
407 std::vector<base::FilePath> paths =
408 ShellIntegrationLinux::GetExistingProfileShortcutFilenames(
409 kProfilePath, temp_dir.path());
410 // Path order is arbitrary. Sort the output for consistency.
411 std::sort(paths.begin(), paths.end());
412 EXPECT_THAT(paths,
413 ElementsAre(base::FilePath(kApp1Filename),
414 base::FilePath(kApp2Filename)));
417 TEST(ShellIntegrationTest, GetWebShortcutFilename) {
418 const struct {
419 const base::FilePath::CharType* path;
420 const char* url;
421 } test_cases[] = {
422 { FPL("http___foo_.desktop"), "http://foo" },
423 { FPL("http___foo_bar_.desktop"), "http://foo/bar/" },
424 { FPL("http___foo_bar_a=b&c=d.desktop"), "http://foo/bar?a=b&c=d" },
426 // Now we're starting to be more evil...
427 { FPL("http___foo_.desktop"), "http://foo/bar/baz/../../../../../" },
428 { FPL("http___foo_.desktop"), "http://foo/bar/././../baz/././../" },
429 { FPL("http___.._.desktop"), "http://../../../../" },
431 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) {
432 EXPECT_EQ(std::string(chrome::kBrowserProcessExecutableName) + "-" +
433 test_cases[i].path,
434 ShellIntegrationLinux::GetWebShortcutFilename(
435 GURL(test_cases[i].url)).value()) <<
436 " while testing " << test_cases[i].url;
440 TEST(ShellIntegrationTest, GetDesktopFileContents) {
441 const base::FilePath kChromeExePath("/opt/google/chrome/google-chrome");
442 const struct {
443 const char* url;
444 const char* title;
445 const char* icon_name;
446 bool nodisplay;
447 const char* expected_output;
448 } test_cases[] = {
449 // Real-world case.
450 { "http://gmail.com",
451 "GMail",
452 "chrome-http__gmail.com",
453 false,
455 "#!/usr/bin/env xdg-open\n"
456 "[Desktop Entry]\n"
457 "Version=1.0\n"
458 "Terminal=false\n"
459 "Type=Application\n"
460 "Name=GMail\n"
461 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
462 "Icon=chrome-http__gmail.com\n"
463 #if !defined(USE_AURA)
464 // Aura Chrome does not (yet) set WMClass, so we only expect
465 // StartupWMClass on non-Aura builds.
466 "StartupWMClass=gmail.com\n"
467 #endif
470 // Make sure that empty icons are replaced by the chrome icon.
471 { "http://gmail.com",
472 "GMail",
474 false,
476 "#!/usr/bin/env xdg-open\n"
477 "[Desktop Entry]\n"
478 "Version=1.0\n"
479 "Terminal=false\n"
480 "Type=Application\n"
481 "Name=GMail\n"
482 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
483 "Icon=chromium-browser\n"
484 #if !defined(USE_AURA)
485 // Aura Chrome does not (yet) set WMClass, so we only expect
486 // StartupWMClass on non-Aura builds.
487 "StartupWMClass=gmail.com\n"
488 #endif
491 // Test adding NoDisplay=true.
492 { "http://gmail.com",
493 "GMail",
494 "chrome-http__gmail.com",
495 true,
497 "#!/usr/bin/env xdg-open\n"
498 "[Desktop Entry]\n"
499 "Version=1.0\n"
500 "Terminal=false\n"
501 "Type=Application\n"
502 "Name=GMail\n"
503 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
504 "Icon=chrome-http__gmail.com\n"
505 "NoDisplay=true\n"
506 #if !defined(USE_AURA)
507 // Aura Chrome does not (yet) set WMClass, so we only expect
508 // StartupWMClass on non-Aura builds.
509 "StartupWMClass=gmail.com\n"
510 #endif
513 // Now we're starting to be more evil...
514 { "http://evil.com/evil --join-the-b0tnet",
515 "Ownz0red\nExec=rm -rf /",
516 "chrome-http__evil.com_evil",
517 false,
519 "#!/usr/bin/env xdg-open\n"
520 "[Desktop Entry]\n"
521 "Version=1.0\n"
522 "Terminal=false\n"
523 "Type=Application\n"
524 "Name=http://evil.com/evil%20--join-the-b0tnet\n"
525 "Exec=/opt/google/chrome/google-chrome "
526 "--app=http://evil.com/evil%20--join-the-b0tnet\n"
527 "Icon=chrome-http__evil.com_evil\n"
528 #if !defined(USE_AURA)
529 // Aura Chrome does not (yet) set WMClass, so we only expect
530 // StartupWMClass on non-Aura builds.
531 "StartupWMClass=evil.com__evil%20--join-the-b0tnet\n"
532 #endif
534 { "http://evil.com/evil; rm -rf /; \"; rm -rf $HOME >ownz0red",
535 "Innocent Title",
536 "chrome-http__evil.com_evil",
537 false,
539 "#!/usr/bin/env xdg-open\n"
540 "[Desktop Entry]\n"
541 "Version=1.0\n"
542 "Terminal=false\n"
543 "Type=Application\n"
544 "Name=Innocent Title\n"
545 "Exec=/opt/google/chrome/google-chrome "
546 "\"--app=http://evil.com/evil;%20rm%20-rf%20/;%20%22;%20rm%20"
547 // Note: $ is escaped as \$ within an arg to Exec, and then
548 // the \ is escaped as \\ as all strings in a Desktop file should
549 // be; finally, \\ becomes \\\\ when represented in a C++ string!
550 "-rf%20\\\\$HOME%20%3Eownz0red\"\n"
551 "Icon=chrome-http__evil.com_evil\n"
552 #if !defined(USE_AURA)
553 // Aura Chrome does not (yet) set WMClass, so we only expect
554 // StartupWMClass on non-Aura builds.
555 "StartupWMClass=evil.com__evil;%20rm%20-rf%20_;%20%22;%20"
556 "rm%20-rf%20$HOME%20%3Eownz0red\n"
557 #endif
559 { "http://evil.com/evil | cat `echo ownz0red` >/dev/null",
560 "Innocent Title",
561 "chrome-http__evil.com_evil",
562 false,
564 "#!/usr/bin/env xdg-open\n"
565 "[Desktop Entry]\n"
566 "Version=1.0\n"
567 "Terminal=false\n"
568 "Type=Application\n"
569 "Name=Innocent Title\n"
570 "Exec=/opt/google/chrome/google-chrome "
571 "--app=http://evil.com/evil%20%7C%20cat%20%60echo%20ownz0red"
572 "%60%20%3E/dev/null\n"
573 "Icon=chrome-http__evil.com_evil\n"
574 #if !defined(USE_AURA)
575 // Aura Chrome does not (yet) set WMClass, so we only expect
576 // StartupWMClass on non-Aura builds.
577 "StartupWMClass=evil.com__evil%20%7C%20cat%20%60echo%20ownz0red"
578 "%60%20%3E_dev_null\n"
579 #endif
583 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) {
584 SCOPED_TRACE(i);
585 EXPECT_EQ(
586 test_cases[i].expected_output,
587 ShellIntegrationLinux::GetDesktopFileContents(
588 kChromeExePath,
589 web_app::GenerateApplicationNameFromURL(GURL(test_cases[i].url)),
590 GURL(test_cases[i].url),
591 std::string(),
592 base::FilePath(),
593 ASCIIToUTF16(test_cases[i].title),
594 test_cases[i].icon_name,
595 base::FilePath(),
596 test_cases[i].nodisplay));
600 TEST(ShellIntegrationTest, GetDirectoryFileContents) {
601 const struct {
602 const char* title;
603 const char* icon_name;
604 const char* expected_output;
605 } test_cases[] = {
606 // Real-world case.
607 { "Chrome Apps",
608 "chrome-apps",
610 "[Desktop Entry]\n"
611 "Version=1.0\n"
612 "Type=Directory\n"
613 "Name=Chrome Apps\n"
614 "Icon=chrome-apps\n"
617 // Make sure that empty icons are replaced by the chrome icon.
618 { "Chrome Apps",
621 "[Desktop Entry]\n"
622 "Version=1.0\n"
623 "Type=Directory\n"
624 "Name=Chrome Apps\n"
625 "Icon=chromium-browser\n"
629 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) {
630 SCOPED_TRACE(i);
631 EXPECT_EQ(
632 test_cases[i].expected_output,
633 ShellIntegrationLinux::GetDirectoryFileContents(
634 ASCIIToUTF16(test_cases[i].title),
635 test_cases[i].icon_name));
639 #endif