seccomp-bpf: Remove legacy SandboxBPFPolicy class
[chromium-blink-merge.git] / chrome / browser / shell_integration_linux_unittest.cc
blob051b566eda09029078f0d61174803a576b5e363b
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>
11 #include "base/base_paths.h"
12 #include "base/command_line.h"
13 #include "base/environment.h"
14 #include "base/files/file_path.h"
15 #include "base/files/file_util.h"
16 #include "base/files/scoped_temp_dir.h"
17 #include "base/message_loop/message_loop.h"
18 #include "base/stl_util.h"
19 #include "base/strings/string_util.h"
20 #include "base/strings/utf_string_conversions.h"
21 #include "base/test/scoped_path_override.h"
22 #include "chrome/common/chrome_constants.h"
23 #include "content/public/test/test_browser_thread.h"
24 #include "testing/gmock/include/gmock/gmock.h"
25 #include "testing/gtest/include/gtest/gtest.h"
26 #include "url/gurl.h"
28 #define FPL FILE_PATH_LITERAL
30 using content::BrowserThread;
31 using ::testing::ElementsAre;
33 namespace shell_integration_linux {
35 namespace {
37 // Provides mock environment variables values based on a stored map.
38 class MockEnvironment : public base::Environment {
39 public:
40 MockEnvironment() {}
42 void Set(const std::string& name, const std::string& value) {
43 variables_[name] = value;
46 virtual bool GetVar(const char* variable_name, std::string* result) override {
47 if (ContainsKey(variables_, variable_name)) {
48 *result = variables_[variable_name];
49 return true;
52 return false;
55 virtual bool SetVar(const char* variable_name,
56 const std::string& new_value) override {
57 ADD_FAILURE();
58 return false;
61 virtual bool UnSetVar(const char* variable_name) override {
62 ADD_FAILURE();
63 return false;
66 private:
67 std::map<std::string, std::string> variables_;
69 DISALLOW_COPY_AND_ASSIGN(MockEnvironment);
72 } // namespace
74 TEST(ShellIntegrationTest, GetDataWriteLocation) {
75 base::MessageLoop message_loop;
76 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
78 // Test that it returns $XDG_DATA_HOME.
80 MockEnvironment env;
81 env.Set("HOME", "/home/user");
82 env.Set("XDG_DATA_HOME", "/user/path");
83 base::FilePath path;
84 ASSERT_TRUE(GetDataWriteLocation(&env, &path));
85 EXPECT_EQ(base::FilePath("/user/path"), path);
88 // Test that $XDG_DATA_HOME falls back to $HOME/.local/share.
90 MockEnvironment env;
91 env.Set("HOME", "/home/user");
92 base::FilePath path;
93 ASSERT_TRUE(GetDataWriteLocation(&env, &path));
94 EXPECT_EQ(base::FilePath("/home/user/.local/share"), path);
97 // Test that if neither $XDG_DATA_HOME nor $HOME are specified, it fails.
99 MockEnvironment env;
100 base::FilePath path;
101 ASSERT_FALSE(GetDataWriteLocation(&env, &path));
105 TEST(ShellIntegrationTest, GetDataSearchLocations) {
106 base::MessageLoop message_loop;
107 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
109 // Test that it returns $XDG_DATA_HOME + $XDG_DATA_DIRS.
111 MockEnvironment env;
112 env.Set("HOME", "/home/user");
113 env.Set("XDG_DATA_HOME", "/user/path");
114 env.Set("XDG_DATA_DIRS", "/system/path/1:/system/path/2");
115 EXPECT_THAT(
116 GetDataSearchLocations(&env),
117 ElementsAre(base::FilePath("/user/path"),
118 base::FilePath("/system/path/1"),
119 base::FilePath("/system/path/2")));
122 // Test that $XDG_DATA_HOME falls back to $HOME/.local/share.
124 MockEnvironment env;
125 env.Set("HOME", "/home/user");
126 env.Set("XDG_DATA_DIRS", "/system/path/1:/system/path/2");
127 EXPECT_THAT(
128 GetDataSearchLocations(&env),
129 ElementsAre(base::FilePath("/home/user/.local/share"),
130 base::FilePath("/system/path/1"),
131 base::FilePath("/system/path/2")));
134 // Test that if neither $XDG_DATA_HOME nor $HOME are specified, it still
135 // succeeds.
137 MockEnvironment env;
138 env.Set("XDG_DATA_DIRS", "/system/path/1:/system/path/2");
139 EXPECT_THAT(
140 GetDataSearchLocations(&env),
141 ElementsAre(base::FilePath("/system/path/1"),
142 base::FilePath("/system/path/2")));
145 // Test that $XDG_DATA_DIRS falls back to the two default paths.
147 MockEnvironment env;
148 env.Set("HOME", "/home/user");
149 env.Set("XDG_DATA_HOME", "/user/path");
150 EXPECT_THAT(
151 GetDataSearchLocations(&env),
152 ElementsAre(base::FilePath("/user/path"),
153 base::FilePath("/usr/local/share"),
154 base::FilePath("/usr/share")));
158 TEST(ShellIntegrationTest, GetExistingShortcutLocations) {
159 base::FilePath kProfilePath("Profile 1");
160 const char kExtensionId[] = "test_extension";
161 const char kTemplateFilename[] = "chrome-test_extension-Profile_1.desktop";
162 base::FilePath kTemplateFilepath(kTemplateFilename);
163 const char kNoDisplayDesktopFile[] = "[Desktop Entry]\nNoDisplay=true";
165 base::MessageLoop message_loop;
166 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
168 // No existing shortcuts.
170 MockEnvironment env;
171 web_app::ShortcutLocations result =
172 GetExistingShortcutLocations(&env, kProfilePath, kExtensionId);
173 EXPECT_FALSE(result.on_desktop);
174 EXPECT_EQ(web_app::APP_MENU_LOCATION_NONE,
175 result.applications_menu_location);
177 EXPECT_FALSE(result.in_quick_launch_bar);
180 // Shortcut on desktop.
182 base::ScopedTempDir temp_dir;
183 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
184 base::FilePath desktop_path = temp_dir.path();
186 MockEnvironment env;
187 ASSERT_TRUE(base::CreateDirectory(desktop_path));
188 ASSERT_FALSE(base::WriteFile(
189 desktop_path.AppendASCII(kTemplateFilename),
190 "", 0));
191 web_app::ShortcutLocations result = GetExistingShortcutLocations(
192 &env, kProfilePath, kExtensionId, desktop_path);
193 EXPECT_TRUE(result.on_desktop);
194 EXPECT_EQ(web_app::APP_MENU_LOCATION_NONE,
195 result.applications_menu_location);
197 EXPECT_FALSE(result.in_quick_launch_bar);
200 // Shortcut in applications directory.
202 base::ScopedTempDir temp_dir;
203 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
204 base::FilePath apps_path = temp_dir.path().AppendASCII("applications");
206 MockEnvironment env;
207 env.Set("XDG_DATA_HOME", temp_dir.path().value());
208 ASSERT_TRUE(base::CreateDirectory(apps_path));
209 ASSERT_FALSE(base::WriteFile(
210 apps_path.AppendASCII(kTemplateFilename),
211 "", 0));
212 web_app::ShortcutLocations result =
213 GetExistingShortcutLocations(&env, kProfilePath, kExtensionId);
214 EXPECT_FALSE(result.on_desktop);
215 EXPECT_EQ(web_app::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS,
216 result.applications_menu_location);
218 EXPECT_FALSE(result.in_quick_launch_bar);
221 // Shortcut in applications directory with NoDisplay=true.
223 base::ScopedTempDir temp_dir;
224 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
225 base::FilePath apps_path = temp_dir.path().AppendASCII("applications");
227 MockEnvironment env;
228 env.Set("XDG_DATA_HOME", temp_dir.path().value());
229 ASSERT_TRUE(base::CreateDirectory(apps_path));
230 ASSERT_TRUE(base::WriteFile(
231 apps_path.AppendASCII(kTemplateFilename),
232 kNoDisplayDesktopFile, strlen(kNoDisplayDesktopFile)));
233 web_app::ShortcutLocations result =
234 GetExistingShortcutLocations(&env, kProfilePath, kExtensionId);
235 // Doesn't count as being in applications menu.
236 EXPECT_FALSE(result.on_desktop);
237 EXPECT_EQ(web_app::APP_MENU_LOCATION_HIDDEN,
238 result.applications_menu_location);
239 EXPECT_FALSE(result.in_quick_launch_bar);
242 // Shortcut on desktop and in applications directory.
244 base::ScopedTempDir temp_dir1;
245 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
246 base::FilePath desktop_path = temp_dir1.path();
248 base::ScopedTempDir temp_dir2;
249 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
250 base::FilePath apps_path = temp_dir2.path().AppendASCII("applications");
252 MockEnvironment env;
253 ASSERT_TRUE(base::CreateDirectory(desktop_path));
254 ASSERT_FALSE(base::WriteFile(
255 desktop_path.AppendASCII(kTemplateFilename),
256 "", 0));
257 env.Set("XDG_DATA_HOME", temp_dir2.path().value());
258 ASSERT_TRUE(base::CreateDirectory(apps_path));
259 ASSERT_FALSE(base::WriteFile(
260 apps_path.AppendASCII(kTemplateFilename),
261 "", 0));
262 web_app::ShortcutLocations result = GetExistingShortcutLocations(
263 &env, kProfilePath, kExtensionId, desktop_path);
264 EXPECT_TRUE(result.on_desktop);
265 EXPECT_EQ(web_app::APP_MENU_LOCATION_SUBDIR_CHROMEAPPS,
266 result.applications_menu_location);
267 EXPECT_FALSE(result.in_quick_launch_bar);
271 TEST(ShellIntegrationTest, GetExistingShortcutContents) {
272 const char kTemplateFilename[] = "shortcut-test.desktop";
273 base::FilePath kTemplateFilepath(kTemplateFilename);
274 const char kTestData1[] = "a magical testing string";
275 const char kTestData2[] = "a different testing string";
277 base::MessageLoop message_loop;
278 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
280 // Test that it searches $XDG_DATA_HOME/applications.
282 base::ScopedTempDir temp_dir;
283 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
285 MockEnvironment env;
286 env.Set("XDG_DATA_HOME", temp_dir.path().value());
287 // Create a file in a non-applications directory. This should be ignored.
288 ASSERT_TRUE(base::WriteFile(
289 temp_dir.path().AppendASCII(kTemplateFilename),
290 kTestData2, strlen(kTestData2)));
291 ASSERT_TRUE(base::CreateDirectory(
292 temp_dir.path().AppendASCII("applications")));
293 ASSERT_TRUE(base::WriteFile(
294 temp_dir.path().AppendASCII("applications")
295 .AppendASCII(kTemplateFilename),
296 kTestData1, strlen(kTestData1)));
297 std::string contents;
298 ASSERT_TRUE(
299 GetExistingShortcutContents(&env, kTemplateFilepath, &contents));
300 EXPECT_EQ(kTestData1, contents);
303 // Test that it falls back to $HOME/.local/share/applications.
305 base::ScopedTempDir temp_dir;
306 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
308 MockEnvironment env;
309 env.Set("HOME", temp_dir.path().value());
310 ASSERT_TRUE(base::CreateDirectory(
311 temp_dir.path().AppendASCII(".local/share/applications")));
312 ASSERT_TRUE(base::WriteFile(
313 temp_dir.path().AppendASCII(".local/share/applications")
314 .AppendASCII(kTemplateFilename),
315 kTestData1, strlen(kTestData1)));
316 std::string contents;
317 ASSERT_TRUE(
318 GetExistingShortcutContents(&env, kTemplateFilepath, &contents));
319 EXPECT_EQ(kTestData1, contents);
322 // Test that it searches $XDG_DATA_DIRS/applications.
324 base::ScopedTempDir temp_dir;
325 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
327 MockEnvironment env;
328 env.Set("XDG_DATA_DIRS", temp_dir.path().value());
329 ASSERT_TRUE(base::CreateDirectory(
330 temp_dir.path().AppendASCII("applications")));
331 ASSERT_TRUE(base::WriteFile(
332 temp_dir.path().AppendASCII("applications")
333 .AppendASCII(kTemplateFilename),
334 kTestData2, strlen(kTestData2)));
335 std::string contents;
336 ASSERT_TRUE(
337 GetExistingShortcutContents(&env, kTemplateFilepath, &contents));
338 EXPECT_EQ(kTestData2, contents);
341 // Test that it searches $X/applications for each X in $XDG_DATA_DIRS.
343 base::ScopedTempDir temp_dir1;
344 ASSERT_TRUE(temp_dir1.CreateUniqueTempDir());
345 base::ScopedTempDir temp_dir2;
346 ASSERT_TRUE(temp_dir2.CreateUniqueTempDir());
348 MockEnvironment env;
349 env.Set("XDG_DATA_DIRS", temp_dir1.path().value() + ":" +
350 temp_dir2.path().value());
351 // Create a file in a non-applications directory. This should be ignored.
352 ASSERT_TRUE(base::WriteFile(
353 temp_dir1.path().AppendASCII(kTemplateFilename),
354 kTestData1, strlen(kTestData1)));
355 // Only create a findable desktop file in the second path.
356 ASSERT_TRUE(base::CreateDirectory(
357 temp_dir2.path().AppendASCII("applications")));
358 ASSERT_TRUE(base::WriteFile(
359 temp_dir2.path().AppendASCII("applications")
360 .AppendASCII(kTemplateFilename),
361 kTestData2, strlen(kTestData2)));
362 std::string contents;
363 ASSERT_TRUE(
364 GetExistingShortcutContents(&env, kTemplateFilepath, &contents));
365 EXPECT_EQ(kTestData2, contents);
369 TEST(ShellIntegrationTest, GetExtensionShortcutFilename) {
370 base::FilePath kProfilePath("a/b/c/Profile Name?");
371 const char kExtensionId[] = "extensionid";
372 EXPECT_EQ(base::FilePath("chrome-extensionid-Profile_Name_.desktop"),
373 GetExtensionShortcutFilename(kProfilePath, kExtensionId));
376 TEST(ShellIntegrationTest, GetExistingProfileShortcutFilenames) {
377 base::FilePath kProfilePath("a/b/c/Profile Name?");
378 const char kApp1Filename[] = "chrome-extension1-Profile_Name_.desktop";
379 const char kApp2Filename[] = "chrome-extension2-Profile_Name_.desktop";
380 const char kUnrelatedAppFilename[] = "chrome-extension-Other_Profile.desktop";
382 base::MessageLoop message_loop;
383 content::TestBrowserThread file_thread(BrowserThread::FILE, &message_loop);
385 base::ScopedTempDir temp_dir;
386 ASSERT_TRUE(temp_dir.CreateUniqueTempDir());
387 ASSERT_EQ(0,
388 base::WriteFile(
389 temp_dir.path().AppendASCII(kApp1Filename), "", 0));
390 ASSERT_EQ(0,
391 base::WriteFile(
392 temp_dir.path().AppendASCII(kApp2Filename), "", 0));
393 // This file should not be returned in the results.
394 ASSERT_EQ(0,
395 base::WriteFile(
396 temp_dir.path().AppendASCII(kUnrelatedAppFilename), "", 0));
397 std::vector<base::FilePath> paths =
398 GetExistingProfileShortcutFilenames(kProfilePath, temp_dir.path());
399 // Path order is arbitrary. Sort the output for consistency.
400 std::sort(paths.begin(), paths.end());
401 EXPECT_THAT(paths,
402 ElementsAre(base::FilePath(kApp1Filename),
403 base::FilePath(kApp2Filename)));
406 TEST(ShellIntegrationTest, GetWebShortcutFilename) {
407 const struct {
408 const base::FilePath::CharType* path;
409 const char* url;
410 } test_cases[] = {
411 { FPL("http___foo_.desktop"), "http://foo" },
412 { FPL("http___foo_bar_.desktop"), "http://foo/bar/" },
413 { FPL("http___foo_bar_a=b&c=d.desktop"), "http://foo/bar?a=b&c=d" },
415 // Now we're starting to be more evil...
416 { FPL("http___foo_.desktop"), "http://foo/bar/baz/../../../../../" },
417 { FPL("http___foo_.desktop"), "http://foo/bar/././../baz/././../" },
418 { FPL("http___.._.desktop"), "http://../../../../" },
420 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) {
421 EXPECT_EQ(std::string(chrome::kBrowserProcessExecutableName) + "-" +
422 test_cases[i].path,
423 GetWebShortcutFilename(GURL(test_cases[i].url)).value()) <<
424 " while testing " << test_cases[i].url;
428 TEST(ShellIntegrationTest, GetDesktopFileContents) {
429 const base::FilePath kChromeExePath("/opt/google/chrome/google-chrome");
430 const struct {
431 const char* url;
432 const char* title;
433 const char* icon_name;
434 const char* categories;
435 bool nodisplay;
436 const char* expected_output;
437 } test_cases[] = {
438 // Real-world case.
439 { "http://gmail.com",
440 "GMail",
441 "chrome-http__gmail.com",
443 false,
445 "#!/usr/bin/env xdg-open\n"
446 "[Desktop Entry]\n"
447 "Version=1.0\n"
448 "Terminal=false\n"
449 "Type=Application\n"
450 "Name=GMail\n"
451 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
452 "Icon=chrome-http__gmail.com\n"
453 "StartupWMClass=gmail.com\n"
456 // Make sure that empty icons are replaced by the chrome icon.
457 { "http://gmail.com",
458 "GMail",
461 false,
463 "#!/usr/bin/env xdg-open\n"
464 "[Desktop Entry]\n"
465 "Version=1.0\n"
466 "Terminal=false\n"
467 "Type=Application\n"
468 "Name=GMail\n"
469 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
470 #if defined(GOOGLE_CHROME_BUILD)
471 "Icon=google-chrome\n"
472 #else
473 "Icon=chromium-browser\n"
474 #endif
475 "StartupWMClass=gmail.com\n"
478 // Test adding categories and NoDisplay=true.
479 { "http://gmail.com",
480 "GMail",
481 "chrome-http__gmail.com",
482 "Graphics;Education;",
483 true,
485 "#!/usr/bin/env xdg-open\n"
486 "[Desktop Entry]\n"
487 "Version=1.0\n"
488 "Terminal=false\n"
489 "Type=Application\n"
490 "Name=GMail\n"
491 "Exec=/opt/google/chrome/google-chrome --app=http://gmail.com/\n"
492 "Icon=chrome-http__gmail.com\n"
493 "Categories=Graphics;Education;\n"
494 "NoDisplay=true\n"
495 "StartupWMClass=gmail.com\n"
498 // Now we're starting to be more evil...
499 { "http://evil.com/evil --join-the-b0tnet",
500 "Ownz0red\nExec=rm -rf /",
501 "chrome-http__evil.com_evil",
503 false,
505 "#!/usr/bin/env xdg-open\n"
506 "[Desktop Entry]\n"
507 "Version=1.0\n"
508 "Terminal=false\n"
509 "Type=Application\n"
510 "Name=http://evil.com/evil%20--join-the-b0tnet\n"
511 "Exec=/opt/google/chrome/google-chrome "
512 "--app=http://evil.com/evil%20--join-the-b0tnet\n"
513 "Icon=chrome-http__evil.com_evil\n"
514 "StartupWMClass=evil.com__evil%20--join-the-b0tnet\n"
516 { "http://evil.com/evil; rm -rf /; \"; rm -rf $HOME >ownz0red",
517 "Innocent Title",
518 "chrome-http__evil.com_evil",
520 false,
522 "#!/usr/bin/env xdg-open\n"
523 "[Desktop Entry]\n"
524 "Version=1.0\n"
525 "Terminal=false\n"
526 "Type=Application\n"
527 "Name=Innocent Title\n"
528 "Exec=/opt/google/chrome/google-chrome "
529 "\"--app=http://evil.com/evil;%20rm%20-rf%20/;%20%22;%20rm%20"
530 // Note: $ is escaped as \$ within an arg to Exec, and then
531 // the \ is escaped as \\ as all strings in a Desktop file should
532 // be; finally, \\ becomes \\\\ when represented in a C++ string!
533 "-rf%20\\\\$HOME%20%3Eownz0red\"\n"
534 "Icon=chrome-http__evil.com_evil\n"
535 "StartupWMClass=evil.com__evil;%20rm%20-rf%20_;%20%22;%20"
536 "rm%20-rf%20$HOME%20%3Eownz0red\n"
538 { "http://evil.com/evil | cat `echo ownz0red` >/dev/null",
539 "Innocent Title",
540 "chrome-http__evil.com_evil",
542 false,
544 "#!/usr/bin/env xdg-open\n"
545 "[Desktop Entry]\n"
546 "Version=1.0\n"
547 "Terminal=false\n"
548 "Type=Application\n"
549 "Name=Innocent Title\n"
550 "Exec=/opt/google/chrome/google-chrome "
551 "--app=http://evil.com/evil%20%7C%20cat%20%60echo%20ownz0red"
552 "%60%20%3E/dev/null\n"
553 "Icon=chrome-http__evil.com_evil\n"
554 "StartupWMClass=evil.com__evil%20%7C%20cat%20%60echo%20ownz0red"
555 "%60%20%3E_dev_null\n"
559 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) {
560 SCOPED_TRACE(i);
561 EXPECT_EQ(
562 test_cases[i].expected_output,
563 GetDesktopFileContents(
564 kChromeExePath,
565 web_app::GenerateApplicationNameFromURL(GURL(test_cases[i].url)),
566 GURL(test_cases[i].url),
567 std::string(),
568 base::ASCIIToUTF16(test_cases[i].title),
569 test_cases[i].icon_name,
570 base::FilePath(),
571 test_cases[i].categories,
572 test_cases[i].nodisplay));
576 TEST(ShellIntegrationTest, GetDesktopFileContentsAppList) {
577 const base::FilePath kChromeExePath("/opt/google/chrome/google-chrome");
578 base::CommandLine command_line(kChromeExePath);
579 command_line.AppendSwitch("--show-app-list");
580 EXPECT_EQ(
581 "#!/usr/bin/env xdg-open\n"
582 "[Desktop Entry]\n"
583 "Version=1.0\n"
584 "Terminal=false\n"
585 "Type=Application\n"
586 "Name=Chrome App Launcher\n"
587 "Exec=/opt/google/chrome/google-chrome --show-app-list\n"
588 "Icon=chrome_app_list\n"
589 "Categories=Network;WebBrowser;\n"
590 "StartupWMClass=chrome-app-list\n",
591 GetDesktopFileContentsForCommand(
592 command_line,
593 "chrome-app-list",
594 GURL(),
595 base::ASCIIToUTF16("Chrome App Launcher"),
596 "chrome_app_list",
597 "Network;WebBrowser;",
598 false));
601 TEST(ShellIntegrationTest, GetDirectoryFileContents) {
602 const struct {
603 const char* title;
604 const char* icon_name;
605 const char* expected_output;
606 } test_cases[] = {
607 // Real-world case.
608 { "Chrome Apps",
609 "chrome-apps",
611 "[Desktop Entry]\n"
612 "Version=1.0\n"
613 "Type=Directory\n"
614 "Name=Chrome Apps\n"
615 "Icon=chrome-apps\n"
618 // Make sure that empty icons are replaced by the chrome icon.
619 { "Chrome Apps",
622 "[Desktop Entry]\n"
623 "Version=1.0\n"
624 "Type=Directory\n"
625 "Name=Chrome Apps\n"
626 #if defined(GOOGLE_CHROME_BUILD)
627 "Icon=google-chrome\n"
628 #else
629 "Icon=chromium-browser\n"
630 #endif
634 for (size_t i = 0; i < ARRAYSIZE_UNSAFE(test_cases); i++) {
635 SCOPED_TRACE(i);
636 EXPECT_EQ(test_cases[i].expected_output,
637 GetDirectoryFileContents(base::ASCIIToUTF16(test_cases[i].title),
638 test_cases[i].icon_name));
642 } // namespace shell_integration_linux