Unwind the URL-based experiment IDs.
[chromium-blink-merge.git] / chrome / browser / shell_integration_linux_unittest.cc
blobd99a8c8ac0b1a84c65796676d8f5e979bb700032
1 // Copyright 2013 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_linux.h"
7 #include <algorithm>
8 #include <cstdlib>
9 #include <map>
10 #include <vector>
12 #include "base/base_paths.h"
13 #include "base/command_line.h"
14 #include "base/environment.h"
15 #include "base/files/file_path.h"
16 #include "base/files/file_util.h"
17 #include "base/files/scoped_temp_dir.h"
18 #include "base/message_loop/message_loop.h"
19 #include "base/stl_util.h"
20 #include "base/strings/string_util.h"
21 #include "base/strings/utf_string_conversions.h"
22 #include "base/test/scoped_path_override.h"
23 #include "chrome/common/chrome_constants.h"
24 #include "content/public/test/test_browser_thread.h"
25 #include "testing/gmock/include/gmock/gmock.h"
26 #include "testing/gtest/include/gtest/gtest.h"
27 #include "url/gurl.h"
29 using content::BrowserThread;
30 using ::testing::ElementsAre;
32 namespace shell_integration_linux {
34 namespace {
36 // Provides mock environment variables values based on a stored map.
37 class MockEnvironment : public base::Environment {
38 public:
39 MockEnvironment() {}
41 void Set(const std::string& name, const std::string& value) {
42 variables_[name] = value;
45 bool GetVar(const char* variable_name, std::string* result) override {
46 if (ContainsKey(variables_, variable_name)) {
47 *result = variables_[variable_name];
48 return true;
51 return false;
54 bool SetVar(const char* variable_name,
55 const std::string& new_value) override {
56 ADD_FAILURE();
57 return false;
60 bool UnSetVar(const char* variable_name) override {
61 ADD_FAILURE();
62 return false;
65 private:
66 std::map<std::string, std::string> variables_;
68 DISALLOW_COPY_AND_ASSIGN(MockEnvironment);
71 // This helps EXPECT_THAT(..., ElementsAre(...)) print out more meaningful
72 // failure messages.
73 std::vector<std::string> FilePathsToStrings(
74 const std::vector<base::FilePath>& paths) {
75 std::vector<std::string> values;
76 for (const auto& path : paths)
77 values.push_back(path.value());
78 return values;
81 bool WriteEmptyFile(const base::FilePath& path) {
82 return base::WriteFile(path, "", 0) == 0;
85 bool WriteString(const base::FilePath& path, const base::StringPiece& str) {
86 int bytes_written = base::WriteFile(path, str.data(), str.size());
87 if (bytes_written < 0)
88 return false;
90 return static_cast<size_t>(bytes_written) == str.size();
93 } // namespace
95 TEST(ShellIntegrationTest, GetDataWriteLocation) {
96 base::MessageLoop message_loop;
97 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
99 // Test that it returns $XDG_DATA_HOME.
101 MockEnvironment env;
102 base::ScopedPathOverride home_override(base::DIR_HOME,
103 base::FilePath("/home/user"),
104 true /* absolute? */,
105 false /* create? */);
106 env.Set("XDG_DATA_HOME", "/user/path");
107 base::FilePath path = GetDataWriteLocation(&env);
108 EXPECT_EQ("/user/path", path.value());
111 // Test that $XDG_DATA_HOME falls back to $HOME/.local/share.
113 MockEnvironment env;
114 base::ScopedPathOverride home_override(base::DIR_HOME,
115 base::FilePath("/home/user"),
116 true /* absolute? */,
117 false /* create? */);
118 base::FilePath path = GetDataWriteLocation(&env);
119 EXPECT_EQ("/home/user/.local/share", path.value());
123 TEST(ShellIntegrationTest, GetDataSearchLocations) {
124 base::MessageLoop message_loop;
125 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
127 // Test that it returns $XDG_DATA_HOME + $XDG_DATA_DIRS.
129 MockEnvironment env;
130 base::ScopedPathOverride home_override(base::DIR_HOME,
131 base::FilePath("/home/user"),
132 true /* absolute? */,
133 false /* create? */);
134 env.Set("XDG_DATA_HOME", "/user/path");
135 env.Set("XDG_DATA_DIRS", "/system/path/1:/system/path/2");
136 EXPECT_THAT(
137 FilePathsToStrings(GetDataSearchLocations(&env)),
138 ElementsAre("/user/path",
139 "/system/path/1",
140 "/system/path/2"));
143 // Test that $XDG_DATA_HOME falls back to $HOME/.local/share.
145 MockEnvironment env;
146 base::ScopedPathOverride home_override(base::DIR_HOME,
147 base::FilePath("/home/user"),
148 true /* absolute? */,
149 false /* create? */);
150 env.Set("XDG_DATA_DIRS", "/system/path/1:/system/path/2");
151 EXPECT_THAT(
152 FilePathsToStrings(GetDataSearchLocations(&env)),
153 ElementsAre("/home/user/.local/share",
154 "/system/path/1",
155 "/system/path/2"));
158 // Test that if neither $XDG_DATA_HOME nor $HOME are specified, it still
159 // succeeds.
161 MockEnvironment env;
162 env.Set("XDG_DATA_DIRS", "/system/path/1:/system/path/2");
163 std::vector<std::string> results =
164 FilePathsToStrings(GetDataSearchLocations(&env));
165 ASSERT_EQ(3U, results.size());
166 EXPECT_FALSE(results[0].empty());
167 EXPECT_EQ("/system/path/1", results[1]);
168 EXPECT_EQ("/system/path/2", results[2]);
171 // Test that $XDG_DATA_DIRS falls back to the two default paths.
173 MockEnvironment env;
174 base::ScopedPathOverride home_override(base::DIR_HOME,
175 base::FilePath("/home/user"),
176 true /* absolute? */,
177 false /* create? */);
178 env.Set("XDG_DATA_HOME", "/user/path");
179 EXPECT_THAT(
180 FilePathsToStrings(GetDataSearchLocations(&env)),
181 ElementsAre("/user/path",
182 "/usr/local/share",
183 "/usr/share"));
187 TEST(ShellIntegrationTest, GetExistingShortcutLocations) {
188 base::FilePath kProfilePath("Profile 1");
189 const char kExtensionId[] = "test_extension";
190 const char kTemplateFilename[] = "chrome-test_extension-Profile_1.desktop";
191 base::FilePath kTemplateFilepath(kTemplateFilename);
192 const char kNoDisplayDesktopFile[] = "[Desktop Entry]\nNoDisplay=true";
194 base::MessageLoop message_loop;
195 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
197 // No existing shortcuts.
199 MockEnvironment env;
200 web_app::ShortcutLocations result =
201 GetExistingShortcutLocations(&env, kProfilePath, kExtensionId);
202 EXPECT_FALSE(result.on_desktop);
203 EXPECT_EQ(web_app::APP_MENU_LOCATION_NONE,
204 result.applications_menu_location);
206 EXPECT_FALSE(result.in_quick_launch_bar);
209 // Shortcut on desktop.
211 base::ScopedTempDir temp_dir;
212 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
213 base::FilePath desktop_path = temp_dir.path();
215 MockEnvironment env;
216 ASSERT_TRUE(base::CreateDirectory(desktop_path));
217 ASSERT_TRUE(WriteEmptyFile(desktop_path.Append(kTemplateFilename)));
218 web_app::ShortcutLocations result = GetExistingShortcutLocations(
219 &env, kProfilePath, kExtensionId, desktop_path);
220 EXPECT_TRUE(result.on_desktop);
221 EXPECT_EQ(web_app::APP_MENU_LOCATION_NONE,
222 result.applications_menu_location);
224 EXPECT_FALSE(result.in_quick_launch_bar);
227 // Shortcut in applications directory.
229 base::ScopedTempDir temp_dir;
230 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
231 base::FilePath apps_path = temp_dir.path().Append("applications");
233 MockEnvironment env;
234 env.Set("XDG_DATA_HOME", temp_dir.path().value());
235 ASSERT_TRUE(base::CreateDirectory(apps_path));
236 ASSERT_TRUE(WriteEmptyFile(apps_path.Append(kTemplateFilename)));
237 web_app::ShortcutLocations result =
238 GetExistingShortcutLocations(&env, kProfilePath, kExtensionId);
239 EXPECT_FALSE(result.on_desktop);
240 EXPECT_EQ(web_app::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS,
241 result.applications_menu_location);
243 EXPECT_FALSE(result.in_quick_launch_bar);
246 // Shortcut in applications directory with NoDisplay=true.
248 base::ScopedTempDir temp_dir;
249 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
250 base::FilePath apps_path = temp_dir.path().Append("applications");
252 MockEnvironment env;
253 env.Set("XDG_DATA_HOME", temp_dir.path().value());
254 ASSERT_TRUE(base::CreateDirectory(apps_path));
255 ASSERT_TRUE(WriteString(apps_path.Append(kTemplateFilename),
256 kNoDisplayDesktopFile));
257 web_app::ShortcutLocations result =
258 GetExistingShortcutLocations(&env, kProfilePath, kExtensionId);
259 // Doesn't count as being in applications menu.
260 EXPECT_FALSE(result.on_desktop);
261 EXPECT_EQ(web_app::APP_MENU_LOCATION_HIDDEN,
262 result.applications_menu_location);
263 EXPECT_FALSE(result.in_quick_launch_bar);
266 // Shortcut on desktop and in applications directory.
268 base::ScopedTempDir temp_dir1;
269 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
270 base::FilePath desktop_path = temp_dir1.path();
272 base::ScopedTempDir temp_dir2;
273 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
274 base::FilePath apps_path = temp_dir2.path().Append("applications");
276 MockEnvironment env;
277 ASSERT_TRUE(base::CreateDirectory(desktop_path));
278 ASSERT_TRUE(WriteEmptyFile(desktop_path.Append(kTemplateFilename)));
279 env.Set("XDG_DATA_HOME", temp_dir2.path().value());
280 ASSERT_TRUE(base::CreateDirectory(apps_path));
281 ASSERT_TRUE(WriteEmptyFile(apps_path.Append(kTemplateFilename)));
282 web_app::ShortcutLocations result = GetExistingShortcutLocations(
283 &env, kProfilePath, kExtensionId, desktop_path);
284 EXPECT_TRUE(result.on_desktop);
285 EXPECT_EQ(web_app::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS,
286 result.applications_menu_location);
287 EXPECT_FALSE(result.in_quick_launch_bar);
291 TEST(ShellIntegrationTest, GetExistingShortcutContents) {
292 const char kTemplateFilename[] = "shortcut-test.desktop";
293 base::FilePath kTemplateFilepath(kTemplateFilename);
294 const char kTestData1[] = "a magical testing string";
295 const char kTestData2[] = "a different testing string";
297 base::MessageLoop message_loop;
298 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
300 // Test that it searches $XDG_DATA_HOME/applications.
302 base::ScopedTempDir temp_dir;
303 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
305 MockEnvironment env;
306 env.Set("XDG_DATA_HOME", temp_dir.path().value());
307 // Create a file in a non-applications directory. This should be ignored.
308 ASSERT_TRUE(WriteString(temp_dir.path().Append(kTemplateFilename),
309 kTestData2));
310 ASSERT_TRUE(base::CreateDirectory(
311 temp_dir.path().Append("applications")));
312 ASSERT_TRUE(WriteString(
313 temp_dir.path().Append("applications").Append(kTemplateFilename),
314 kTestData1));
315 std::string contents;
316 ASSERT_TRUE(
317 GetExistingShortcutContents(&env, kTemplateFilepath, &contents));
318 EXPECT_EQ(kTestData1, contents);
321 // Test that it falls back to $HOME/.local/share/applications.
323 base::ScopedTempDir temp_dir;
324 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
326 MockEnvironment env;
327 base::ScopedPathOverride home_override(base::DIR_HOME,
328 temp_dir.path(),
329 true /* absolute? */,
330 false /* create? */);
331 ASSERT_TRUE(base::CreateDirectory(
332 temp_dir.path().Append(".local/share/applications")));
333 ASSERT_TRUE(WriteString(
334 temp_dir.path().Append(".local/share/applications")
335 .Append(kTemplateFilename),
336 kTestData1));
337 std::string contents;
338 ASSERT_TRUE(
339 GetExistingShortcutContents(&env, kTemplateFilepath, &contents));
340 EXPECT_EQ(kTestData1, contents);
343 // Test that it searches $XDG_DATA_DIRS/applications.
345 base::ScopedTempDir temp_dir;
346 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
348 MockEnvironment env;
349 env.Set("XDG_DATA_DIRS", temp_dir.path().value());
350 ASSERT_TRUE(base::CreateDirectory(
351 temp_dir.path().Append("applications")));
352 ASSERT_TRUE(WriteString(
353 temp_dir.path().Append("applications").Append(kTemplateFilename),
354 kTestData2));
355 std::string contents;
356 ASSERT_TRUE(
357 GetExistingShortcutContents(&env, kTemplateFilepath, &contents));
358 EXPECT_EQ(kTestData2, contents);
361 // Test that it searches $X/applications for each X in $XDG_DATA_DIRS.
363 base::ScopedTempDir temp_dir1;
364 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
365 base::ScopedTempDir temp_dir2;
366 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
368 MockEnvironment env;
369 env.Set("XDG_DATA_DIRS", temp_dir1.path().value() + ":" +
370 temp_dir2.path().value());
371 // Create a file in a non-applications directory. This should be ignored.
372 ASSERT_TRUE(WriteString(temp_dir1.path().Append(kTemplateFilename),
373 kTestData1));
374 // Only create a findable desktop file in the second path.
375 ASSERT_TRUE(base::CreateDirectory(
376 temp_dir2.path().Append("applications")));
377 ASSERT_TRUE(WriteString(
378 temp_dir2.path().Append("applications").Append(kTemplateFilename),
379 kTestData2));
380 std::string contents;
381 ASSERT_TRUE(
382 GetExistingShortcutContents(&env, kTemplateFilepath, &contents));
383 EXPECT_EQ(kTestData2, contents);
387 TEST(ShellIntegrationTest, GetExtensionShortcutFilename) {
388 base::FilePath kProfilePath("a/b/c/Profile Name?");
389 const char kExtensionId[] = "extensionid";
390 EXPECT_EQ(base::FilePath("chrome-extensionid-Profile_Name_.desktop"),
391 GetExtensionShortcutFilename(kProfilePath, kExtensionId));
394 TEST(ShellIntegrationTest, GetExistingProfileShortcutFilenames) {
395 base::FilePath kProfilePath("a/b/c/Profile Name?");
396 const char kApp1Filename[] = "chrome-extension1-Profile_Name_.desktop";
397 const char kApp2Filename[] = "chrome-extension2-Profile_Name_.desktop";
398 const char kUnrelatedAppFilename[] = "chrome-extension-Other_Profile.desktop";
400 base::MessageLoop message_loop;
401 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
403 base::ScopedTempDir temp_dir;
404 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
405 ASSERT_TRUE(WriteEmptyFile(temp_dir.path().Append(kApp1Filename)));
406 ASSERT_TRUE(WriteEmptyFile(temp_dir.path().Append(kApp2Filename)));
407 // This file should not be returned in the results.
408 ASSERT_TRUE(WriteEmptyFile(temp_dir.path().Append(kUnrelatedAppFilename)));
409 std::vector<base::FilePath> paths =
410 GetExistingProfileShortcutFilenames(kProfilePath, temp_dir.path());
411 // Path order is arbitrary. Sort the output for consistency.
412 std::sort(paths.begin(), paths.end());
413 EXPECT_THAT(paths,
414 ElementsAre(base::FilePath(kApp1Filename),
415 base::FilePath(kApp2Filename)));
418 TEST(ShellIntegrationTest, GetWebShortcutFilename) {
419 const struct {
420 const char* const path;
421 const char* const url;
422 } test_cases[] = {
423 { "http___foo_.desktop", "http://foo" },
424 { "http___foo_bar_.desktop", "http://foo/bar/" },
425 { "http___foo_bar_a=b&c=d.desktop", "http://foo/bar?a=b&c=d" },
427 // Now we're starting to be more evil...
428 { "http___foo_.desktop", "http://foo/bar/baz/../../../../../" },
429 { "http___foo_.desktop", "http://foo/bar/././../baz/././../" },
430 { "http___.._.desktop", "http://../../../../" },
432 for (size_t i = 0; i < arraysize(test_cases); i++) {
433 EXPECT_EQ(std::string(chrome::kBrowserProcessExecutableName) + "-" +
434 test_cases[i].path,
435 GetWebShortcutFilename(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* const url;
444 const char* const title;
445 const char* const icon_name;
446 const char* const categories;
447 bool nodisplay;
448 const char* const expected_output;
449 } test_cases[] = {
450 // Real-world case.
451 { "http://gmail.com",
452 "GMail",
453 "chrome-http__gmail.com",
455 false,
457 "#!/usr/bin/env xdg-open\n"
458 "[Desktop Entry]\n"
459 "Version=1.0\n"
460 "Terminal=false\n"
461 "Type=Application\n"
462 "Name=GMail\n"
463 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
464 "Icon=chrome-http__gmail.com\n"
465 "StartupWMClass=gmail.com\n"
468 // Make sure that empty icons are replaced by the chrome icon.
469 { "http://gmail.com",
470 "GMail",
473 false,
475 "#!/usr/bin/env xdg-open\n"
476 "[Desktop Entry]\n"
477 "Version=1.0\n"
478 "Terminal=false\n"
479 "Type=Application\n"
480 "Name=GMail\n"
481 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
482 #if defined(GOOGLE_CHROME_BUILD)
483 "Icon=google-chrome\n"
484 #else
485 "Icon=chromium-browser\n"
486 #endif
487 "StartupWMClass=gmail.com\n"
490 // Test adding categories and NoDisplay=true.
491 { "http://gmail.com",
492 "GMail",
493 "chrome-http__gmail.com",
494 "Graphics;Education;",
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 "Categories=Graphics;Education;\n"
506 "NoDisplay=true\n"
507 "StartupWMClass=gmail.com\n"
510 // Now we're starting to be more evil...
511 { "http://evil.com/evil --join-the-b0tnet",
512 "Ownz0red\nExec=rm -rf /",
513 "chrome-http__evil.com_evil",
515 false,
517 "#!/usr/bin/env xdg-open\n"
518 "[Desktop Entry]\n"
519 "Version=1.0\n"
520 "Terminal=false\n"
521 "Type=Application\n"
522 "Name=http://evil.com/evil%20--join-the-b0tnet\n"
523 "Exec=/opt/google/chrome/google-chrome "
524 "--app=http://evil.com/evil%20--join-the-b0tnet\n"
525 "Icon=chrome-http__evil.com_evil\n"
526 "StartupWMClass=evil.com__evil%20--join-the-b0tnet\n"
528 { "http://evil.com/evil; rm -rf /; \"; rm -rf $HOME >ownz0red",
529 "Innocent Title",
530 "chrome-http__evil.com_evil",
532 false,
534 "#!/usr/bin/env xdg-open\n"
535 "[Desktop Entry]\n"
536 "Version=1.0\n"
537 "Terminal=false\n"
538 "Type=Application\n"
539 "Name=Innocent Title\n"
540 "Exec=/opt/google/chrome/google-chrome "
541 "\"--app=http://evil.com/evil;%20rm%20-rf%20/;%20%22;%20rm%20"
542 // Note: $ is escaped as \$ within an arg to Exec, and then
543 // the \ is escaped as \\ as all strings in a Desktop file should
544 // be; finally, \\ becomes \\\\ when represented in a C++ string!
545 "-rf%20\\\\$HOME%20%3Eownz0red\"\n"
546 "Icon=chrome-http__evil.com_evil\n"
547 "StartupWMClass=evil.com__evil;%20rm%20-rf%20_;%20%22;%20"
548 "rm%20-rf%20$HOME%20%3Eownz0red\n"
550 { "http://evil.com/evil | cat `echo ownz0red` >/dev/null",
551 "Innocent Title",
552 "chrome-http__evil.com_evil",
554 false,
556 "#!/usr/bin/env xdg-open\n"
557 "[Desktop Entry]\n"
558 "Version=1.0\n"
559 "Terminal=false\n"
560 "Type=Application\n"
561 "Name=Innocent Title\n"
562 "Exec=/opt/google/chrome/google-chrome "
563 "--app=http://evil.com/evil%20%7C%20cat%20%60echo%20ownz0red"
564 "%60%20%3E/dev/null\n"
565 "Icon=chrome-http__evil.com_evil\n"
566 "StartupWMClass=evil.com__evil%20%7C%20cat%20%60echo%20ownz0red"
567 "%60%20%3E_dev_null\n"
571 for (size_t i = 0; i < arraysize(test_cases); i++) {
572 SCOPED_TRACE(i);
573 EXPECT_EQ(
574 test_cases[i].expected_output,
575 GetDesktopFileContents(
576 kChromeExePath,
577 web_app::GenerateApplicationNameFromURL(GURL(test_cases[i].url)),
578 GURL(test_cases[i].url),
579 std::string(),
580 base::ASCIIToUTF16(test_cases[i].title),
581 test_cases[i].icon_name,
582 base::FilePath(),
583 test_cases[i].categories,
584 test_cases[i].nodisplay));
588 TEST(ShellIntegrationTest, GetDesktopFileContentsAppList) {
589 const base::FilePath kChromeExePath("/opt/google/chrome/google-chrome");
590 base::CommandLine command_line(kChromeExePath);
591 command_line.AppendSwitch("--show-app-list");
592 EXPECT_EQ(
593 "#!/usr/bin/env xdg-open\n"
594 "[Desktop Entry]\n"
595 "Version=1.0\n"
596 "Terminal=false\n"
597 "Type=Application\n"
598 "Name=Chrome App Launcher\n"
599 "Exec=/opt/google/chrome/google-chrome --show-app-list\n"
600 "Icon=chrome_app_list\n"
601 "Categories=Network;WebBrowser;\n"
602 "StartupWMClass=chrome-app-list\n",
603 GetDesktopFileContentsForCommand(
604 command_line,
605 "chrome-app-list",
606 GURL(),
607 base::ASCIIToUTF16("Chrome App Launcher"),
608 "chrome_app_list",
609 "Network;WebBrowser;",
610 false));
613 TEST(ShellIntegrationTest, GetDirectoryFileContents) {
614 const struct {
615 const char* const title;
616 const char* const icon_name;
617 const char* const expected_output;
618 } test_cases[] = {
619 // Real-world case.
620 { "Chrome Apps",
621 "chrome-apps",
623 "[Desktop Entry]\n"
624 "Version=1.0\n"
625 "Type=Directory\n"
626 "Name=Chrome Apps\n"
627 "Icon=chrome-apps\n"
630 // Make sure that empty icons are replaced by the chrome icon.
631 { "Chrome Apps",
634 "[Desktop Entry]\n"
635 "Version=1.0\n"
636 "Type=Directory\n"
637 "Name=Chrome Apps\n"
638 #if defined(GOOGLE_CHROME_BUILD)
639 "Icon=google-chrome\n"
640 #else
641 "Icon=chromium-browser\n"
642 #endif
646 for (size_t i = 0; i < arraysize(test_cases); i++) {
647 SCOPED_TRACE(i);
648 EXPECT_EQ(test_cases[i].expected_output,
649 GetDirectoryFileContents(base::ASCIIToUTF16(test_cases[i].title),
650 test_cases[i].icon_name));
654 } // namespace shell_integration_linux