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/installer/util/shell_util.h"
9 #include "base/base_paths.h"
10 #include "base/base_paths_win.h"
11 #include "base/file_util.h"
12 #include "base/files/file_enumerator.h"
13 #include "base/files/scoped_temp_dir.h"
15 #include "base/memory/scoped_ptr.h"
16 #include "base/strings/string16.h"
17 #include "base/strings/string_util.h"
18 #include "base/test/scoped_path_override.h"
19 #include "base/test/test_shortcut_win.h"
20 #include "base/win/shortcut.h"
21 #include "base/win/windows_version.h"
22 #include "chrome/installer/util/browser_distribution.h"
23 #include "chrome/installer/util/product.h"
24 #include "chrome/installer/util/util_constants.h"
25 #include "testing/gtest/include/gtest/gtest.h"
29 const wchar_t kManganeseExe
[] = L
"manganese.exe";
30 const wchar_t kIronExe
[] = L
"iron.exe";
31 const wchar_t kOtherIco
[] = L
"other.ico";
33 // TODO(huangs): Separate this into generic shortcut tests and Chrome-specific
34 // tests. Specifically, we should not overly rely on getting shortcut properties
35 // from product_->AddDefaultShortcutProperties().
36 class ShellUtilShortcutTest
: public testing::Test
{
38 ShellUtilShortcutTest() : test_properties_(ShellUtil::CURRENT_USER
) {}
40 virtual void SetUp() OVERRIDE
{
41 dist_
= BrowserDistribution::GetDistribution();
42 ASSERT_TRUE(dist_
!= NULL
);
43 product_
.reset(new installer::Product(dist_
));
45 ASSERT_TRUE(temp_dir_
.CreateUniqueTempDir());
46 chrome_exe_
= temp_dir_
.path().Append(installer::kChromeExe
);
47 EXPECT_EQ(0, file_util::WriteFile(chrome_exe_
, "", 0));
49 manganese_exe_
= temp_dir_
.path().Append(kManganeseExe
);
50 EXPECT_EQ(0, file_util::WriteFile(manganese_exe_
, "", 0));
52 iron_exe_
= temp_dir_
.path().Append(kIronExe
);
53 EXPECT_EQ(0, file_util::WriteFile(iron_exe_
, "", 0));
55 other_ico_
= temp_dir_
.path().Append(kOtherIco
);
56 EXPECT_EQ(0, file_util::WriteFile(other_ico_
, "", 0));
58 ASSERT_TRUE(fake_user_desktop_
.CreateUniqueTempDir());
59 ASSERT_TRUE(fake_common_desktop_
.CreateUniqueTempDir());
60 ASSERT_TRUE(fake_user_quick_launch_
.CreateUniqueTempDir());
61 ASSERT_TRUE(fake_default_user_quick_launch_
.CreateUniqueTempDir());
62 ASSERT_TRUE(fake_start_menu_
.CreateUniqueTempDir());
63 ASSERT_TRUE(fake_common_start_menu_
.CreateUniqueTempDir());
64 user_desktop_override_
.reset(
65 new base::ScopedPathOverride(base::DIR_USER_DESKTOP
,
66 fake_user_desktop_
.path()));
67 common_desktop_override_
.reset(
68 new base::ScopedPathOverride(base::DIR_COMMON_DESKTOP
,
69 fake_common_desktop_
.path()));
70 user_quick_launch_override_
.reset(
71 new base::ScopedPathOverride(base::DIR_USER_QUICK_LAUNCH
,
72 fake_user_quick_launch_
.path()));
73 default_user_quick_launch_override_
.reset(
74 new base::ScopedPathOverride(base::DIR_DEFAULT_USER_QUICK_LAUNCH
,
75 fake_default_user_quick_launch_
.path()));
76 start_menu_override_
.reset(
77 new base::ScopedPathOverride(base::DIR_START_MENU
,
78 fake_start_menu_
.path()));
79 common_start_menu_override_
.reset(
80 new base::ScopedPathOverride(base::DIR_COMMON_START_MENU
,
81 fake_common_start_menu_
.path()));
83 base::FilePath icon_path
;
84 base::CreateTemporaryFileInDir(temp_dir_
.path(), &icon_path
);
85 test_properties_
.set_target(chrome_exe_
);
86 test_properties_
.set_arguments(L
"--test --chrome");
87 test_properties_
.set_description(L
"Makes polar bears dance.");
88 test_properties_
.set_icon(icon_path
, 7);
89 test_properties_
.set_app_id(L
"Polar.Bear");
90 test_properties_
.set_dual_mode(true);
93 // Returns the expected path of a test shortcut. Returns an empty FilePath on
95 base::FilePath
GetExpectedShortcutPath(
96 ShellUtil::ShortcutLocation location
,
97 BrowserDistribution
* dist
,
98 const ShellUtil::ShortcutProperties
& properties
) {
99 base::FilePath expected_path
;
101 case ShellUtil::SHORTCUT_LOCATION_DESKTOP
:
102 expected_path
= (properties
.level
== ShellUtil::CURRENT_USER
) ?
103 fake_user_desktop_
.path() : fake_common_desktop_
.path();
105 case ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH
:
106 expected_path
= (properties
.level
== ShellUtil::CURRENT_USER
) ?
107 fake_user_quick_launch_
.path() :
108 fake_default_user_quick_launch_
.path();
110 case ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR
:
111 expected_path
= (properties
.level
== ShellUtil::CURRENT_USER
) ?
112 fake_start_menu_
.path() : fake_common_start_menu_
.path();
113 expected_path
= expected_path
.Append(
114 dist_
->GetStartMenuShortcutSubfolder(
115 BrowserDistribution::SUBFOLDER_CHROME
));
118 ADD_FAILURE() << "Unknown location";
119 return base::FilePath();
122 base::string16 shortcut_name
= properties
.has_shortcut_name() ?
123 properties
.shortcut_name
:
124 dist_
->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME
);
125 shortcut_name
.append(installer::kLnkExt
);
126 return expected_path
.Append(shortcut_name
);
129 // Validates that the shortcut at |location| matches |properties| (and
130 // implicit default properties) for |dist|.
131 // Note: This method doesn't verify the |pin_to_taskbar| property as it
132 // implies real (non-mocked) state which is flaky to test.
133 void ValidateChromeShortcut(
134 ShellUtil::ShortcutLocation location
,
135 BrowserDistribution
* dist
,
136 const ShellUtil::ShortcutProperties
& properties
) {
137 base::FilePath
expected_path(
138 GetExpectedShortcutPath(location
, dist
, properties
));
140 base::win::ShortcutProperties expected_properties
;
141 if (properties
.has_target()) {
142 expected_properties
.set_target(properties
.target
);
143 expected_properties
.set_working_dir(properties
.target
.DirName());
145 expected_properties
.set_target(chrome_exe_
);
146 expected_properties
.set_working_dir(chrome_exe_
.DirName());
149 if (properties
.has_arguments())
150 expected_properties
.set_arguments(properties
.arguments
);
152 expected_properties
.set_arguments(base::string16());
154 if (properties
.has_description())
155 expected_properties
.set_description(properties
.description
);
157 expected_properties
.set_description(dist
->GetAppDescription());
159 if (properties
.has_icon()) {
160 expected_properties
.set_icon(properties
.icon
, properties
.icon_index
);
162 int icon_index
= dist
->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME
);
163 expected_properties
.set_icon(chrome_exe_
, icon_index
);
166 if (properties
.has_app_id()) {
167 expected_properties
.set_app_id(properties
.app_id
);
169 // Tests are always seen as user-level installs in ShellUtil.
170 expected_properties
.set_app_id(ShellUtil::GetBrowserModelId(dist
, true));
173 if (properties
.has_dual_mode())
174 expected_properties
.set_dual_mode(properties
.dual_mode
);
176 expected_properties
.set_dual_mode(false);
178 base::win::ValidateShortcut(expected_path
, expected_properties
);
181 BrowserDistribution
* dist_
;
182 scoped_ptr
<installer::Product
> product_
;
184 // A ShellUtil::ShortcutProperties object with common properties set already.
185 ShellUtil::ShortcutProperties test_properties_
;
187 base::ScopedTempDir temp_dir_
;
188 base::ScopedTempDir fake_user_desktop_
;
189 base::ScopedTempDir fake_common_desktop_
;
190 base::ScopedTempDir fake_user_quick_launch_
;
191 base::ScopedTempDir fake_default_user_quick_launch_
;
192 base::ScopedTempDir fake_start_menu_
;
193 base::ScopedTempDir fake_common_start_menu_
;
194 scoped_ptr
<base::ScopedPathOverride
> user_desktop_override_
;
195 scoped_ptr
<base::ScopedPathOverride
> common_desktop_override_
;
196 scoped_ptr
<base::ScopedPathOverride
> user_quick_launch_override_
;
197 scoped_ptr
<base::ScopedPathOverride
> default_user_quick_launch_override_
;
198 scoped_ptr
<base::ScopedPathOverride
> start_menu_override_
;
199 scoped_ptr
<base::ScopedPathOverride
> common_start_menu_override_
;
201 base::FilePath chrome_exe_
;
202 base::FilePath manganese_exe_
;
203 base::FilePath iron_exe_
;
204 base::FilePath other_ico_
;
209 TEST_F(ShellUtilShortcutTest
, GetShortcutPath
) {
211 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
,
212 ShellUtil::CURRENT_USER
, &path
);
213 EXPECT_EQ(fake_user_desktop_
.path(), path
);
214 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
,
215 ShellUtil::SYSTEM_LEVEL
, &path
);
216 EXPECT_EQ(fake_common_desktop_
.path(), path
);
217 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH
, dist_
,
218 ShellUtil::CURRENT_USER
, &path
);
219 EXPECT_EQ(fake_user_quick_launch_
.path(), path
);
220 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH
, dist_
,
221 ShellUtil::SYSTEM_LEVEL
, &path
);
222 EXPECT_EQ(fake_default_user_quick_launch_
.path(), path
);
223 base::string16 start_menu_subfolder
=
224 dist_
->GetStartMenuShortcutSubfolder(
225 BrowserDistribution::SUBFOLDER_CHROME
);
226 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR
,
227 dist_
, ShellUtil::CURRENT_USER
, &path
);
228 EXPECT_EQ(fake_start_menu_
.path().Append(start_menu_subfolder
),
230 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR
,
231 dist_
, ShellUtil::SYSTEM_LEVEL
, &path
);
232 EXPECT_EQ(fake_common_start_menu_
.path().Append(start_menu_subfolder
),
236 TEST_F(ShellUtilShortcutTest
, CreateChromeExeShortcutWithDefaultProperties
) {
237 ShellUtil::ShortcutProperties
properties(ShellUtil::CURRENT_USER
);
238 product_
->AddDefaultShortcutProperties(chrome_exe_
, &properties
);
239 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
240 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, properties
,
241 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
242 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
,
246 TEST_F(ShellUtilShortcutTest
, CreateStartMenuShortcutWithAllProperties
) {
247 test_properties_
.set_shortcut_name(L
"Bobo le shortcut");
248 test_properties_
.level
= ShellUtil::SYSTEM_LEVEL
;
249 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
250 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR
,
251 dist_
, test_properties_
,
252 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
253 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR
,
254 dist_
, test_properties_
);
257 TEST_F(ShellUtilShortcutTest
, ReplaceSystemLevelQuickLaunchShortcut
) {
258 test_properties_
.level
= ShellUtil::SYSTEM_LEVEL
;
259 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
260 ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH
,
261 dist_
, test_properties_
,
262 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
264 ShellUtil::ShortcutProperties
new_properties(ShellUtil::SYSTEM_LEVEL
);
265 product_
->AddDefaultShortcutProperties(chrome_exe_
, &new_properties
);
266 new_properties
.set_description(L
"New description");
267 new_properties
.set_arguments(L
"--new-arguments");
268 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
269 ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH
,
270 dist_
, new_properties
,
271 ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING
));
273 // Expect the properties set in |new_properties| to be set as above and
274 // properties that don't have a default value to be set back to their default
275 // (as validated in ValidateChromeShortcut()) or unset if they don't .
276 ShellUtil::ShortcutProperties
expected_properties(new_properties
);
277 expected_properties
.set_dual_mode(false);
279 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH
, dist_
,
280 expected_properties
);
283 TEST_F(ShellUtilShortcutTest
, UpdateQuickLaunchShortcutArguments
) {
284 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
285 ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH
,
286 dist_
, test_properties_
,
287 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
289 // Only changing one property, don't need all the defaults.
290 ShellUtil::ShortcutProperties
updated_properties(ShellUtil::CURRENT_USER
);
291 updated_properties
.set_arguments(L
"--updated --arguments");
292 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
293 ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH
,
294 dist_
, updated_properties
,
295 ShellUtil::SHELL_SHORTCUT_UPDATE_EXISTING
));
297 // Expect the properties set in |updated_properties| to be set as above and
298 // all other properties to remain unchanged.
299 ShellUtil::ShortcutProperties
expected_properties(test_properties_
);
300 expected_properties
.set_arguments(updated_properties
.arguments
);
302 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH
, dist_
,
303 expected_properties
);
306 TEST_F(ShellUtilShortcutTest
, UpdateAddDualModeToStartMenuShortcut
) {
307 ShellUtil::ShortcutProperties
properties(ShellUtil::CURRENT_USER
);
308 product_
->AddDefaultShortcutProperties(chrome_exe_
, &properties
);
309 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
310 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR
, dist_
,
311 properties
, ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
313 ShellUtil::ShortcutProperties
added_properties(ShellUtil::CURRENT_USER
);
314 added_properties
.set_dual_mode(true);
315 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
316 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR
, dist_
,
317 added_properties
, ShellUtil::SHELL_SHORTCUT_UPDATE_EXISTING
));
319 ShellUtil::ShortcutProperties
expected_properties(properties
);
320 expected_properties
.set_dual_mode(true);
322 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR
,
323 dist_
, expected_properties
);
326 TEST_F(ShellUtilShortcutTest
, CreateIfNoSystemLevel
) {
327 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
328 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
329 ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL
));
330 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
,
334 TEST_F(ShellUtilShortcutTest
, CreateIfNoSystemLevelWithSystemLevelPresent
) {
335 base::string16
shortcut_name(
336 dist_
->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME
) +
339 test_properties_
.level
= ShellUtil::SYSTEM_LEVEL
;
340 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
341 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
342 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
343 ASSERT_TRUE(base::PathExists(
344 fake_common_desktop_
.path().Append(shortcut_name
)));
346 test_properties_
.level
= ShellUtil::CURRENT_USER
;
347 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
348 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
349 ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL
));
350 ASSERT_FALSE(base::PathExists(
351 fake_user_desktop_
.path().Append(shortcut_name
)));
354 TEST_F(ShellUtilShortcutTest
, CreateIfNoSystemLevelStartMenu
) {
355 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
356 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR
,
357 dist_
, test_properties_
,
358 ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL
));
359 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR
,
360 dist_
, test_properties_
);
363 TEST_F(ShellUtilShortcutTest
, CreateAlwaysUserWithSystemLevelPresent
) {
364 base::string16
shortcut_name(
365 dist_
->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME
) +
368 test_properties_
.level
= ShellUtil::SYSTEM_LEVEL
;
369 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
370 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
371 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
372 ASSERT_TRUE(base::PathExists(
373 fake_common_desktop_
.path().Append(shortcut_name
)));
375 test_properties_
.level
= ShellUtil::CURRENT_USER
;
376 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
377 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
378 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
379 ASSERT_TRUE(base::PathExists(
380 fake_user_desktop_
.path().Append(shortcut_name
)));
383 TEST_F(ShellUtilShortcutTest
, RemoveChromeShortcut
) {
384 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
385 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
386 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
387 base::FilePath shortcut_path
= GetExpectedShortcutPath(
388 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
);
389 ASSERT_TRUE(base::PathExists(shortcut_path
));
391 ASSERT_TRUE(ShellUtil::RemoveShortcuts(
392 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, ShellUtil::CURRENT_USER
,
394 ASSERT_FALSE(base::PathExists(shortcut_path
));
395 ASSERT_TRUE(base::PathExists(shortcut_path
.DirName()));
398 TEST_F(ShellUtilShortcutTest
, RemoveSystemLevelChromeShortcut
) {
399 test_properties_
.level
= ShellUtil::SYSTEM_LEVEL
;
400 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
401 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
402 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
403 base::FilePath shortcut_path
= GetExpectedShortcutPath(
404 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
);
405 ASSERT_TRUE(base::PathExists(shortcut_path
));
407 ASSERT_TRUE(ShellUtil::RemoveShortcuts(
408 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, ShellUtil::SYSTEM_LEVEL
,
410 ASSERT_FALSE(base::PathExists(shortcut_path
));
411 ASSERT_TRUE(base::PathExists(shortcut_path
.DirName()));
414 TEST_F(ShellUtilShortcutTest
, RemoveMultipleChromeShortcuts
) {
415 // Shortcut 1: targets "chrome.exe"; no arguments.
416 test_properties_
.set_shortcut_name(L
"Chrome 1");
417 test_properties_
.set_arguments(L
"");
418 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
419 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
420 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
421 base::FilePath shortcut1_path
= GetExpectedShortcutPath(
422 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
);
423 ASSERT_TRUE(base::PathExists(shortcut1_path
));
425 // Shortcut 2: targets "chrome.exe"; has arguments; icon set to "other.ico".
426 test_properties_
.set_shortcut_name(L
"Chrome 2");
427 test_properties_
.set_arguments(L
"--profile-directory=\"Profile 2\"");
428 test_properties_
.set_icon(other_ico_
, 0);
429 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
430 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
431 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
432 base::FilePath shortcut2_path
= GetExpectedShortcutPath(
433 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
);
434 ASSERT_TRUE(base::PathExists(shortcut2_path
));
436 // Shortcut 3: targets "iron.exe"; has arguments; icon set to "chrome.exe".
437 test_properties_
.set_shortcut_name(L
"Iron 3");
438 test_properties_
.set_target(iron_exe_
);
439 test_properties_
.set_icon(chrome_exe_
, 3);
440 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
441 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
442 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
443 base::FilePath shortcut3_path
= GetExpectedShortcutPath(
444 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
);
445 ASSERT_TRUE(base::PathExists(shortcut3_path
));
447 // Remove shortcuts that target "chrome.exe".
448 ASSERT_TRUE(ShellUtil::RemoveShortcuts(
449 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, ShellUtil::CURRENT_USER
,
451 ASSERT_FALSE(base::PathExists(shortcut1_path
));
452 ASSERT_FALSE(base::PathExists(shortcut2_path
));
453 ASSERT_TRUE(base::PathExists(shortcut3_path
));
454 ASSERT_TRUE(base::PathExists(shortcut1_path
.DirName()));
457 TEST_F(ShellUtilShortcutTest
, RetargetShortcutsWithArgs
) {
458 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
459 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
460 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
461 ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath(
462 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
)));
464 base::FilePath new_exe
= manganese_exe_
;
465 // Relies on the fact that |test_properties_| has non-empty arguments.
466 ASSERT_TRUE(ShellUtil::RetargetShortcutsWithArgs(
467 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, ShellUtil::CURRENT_USER
,
468 chrome_exe_
, new_exe
));
470 ShellUtil::ShortcutProperties
expected_properties(test_properties_
);
471 expected_properties
.set_target(new_exe
);
472 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
,
473 expected_properties
);
476 TEST_F(ShellUtilShortcutTest
, RetargetSystemLevelChromeShortcutsWithArgs
) {
477 test_properties_
.level
= ShellUtil::SYSTEM_LEVEL
;
478 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
479 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
480 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
481 ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath(
482 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
)));
484 base::FilePath new_exe
= manganese_exe_
;
485 // Relies on the fact that |test_properties_| has non-empty arguments.
486 ASSERT_TRUE(ShellUtil::RetargetShortcutsWithArgs(
487 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, ShellUtil::SYSTEM_LEVEL
,
488 chrome_exe_
, new_exe
));
490 ShellUtil::ShortcutProperties
expected_properties(test_properties_
);
491 expected_properties
.set_target(new_exe
);
492 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
,
493 expected_properties
);
496 TEST_F(ShellUtilShortcutTest
, RetargetChromeShortcutsWithArgsEmpty
) {
497 // Shortcut 1: targets "chrome.exe"; no arguments.
498 test_properties_
.set_shortcut_name(L
"Chrome 1");
499 test_properties_
.set_arguments(L
"");
500 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
501 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
502 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
503 ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath(
504 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
)));
505 ShellUtil::ShortcutProperties
expected_properties1(test_properties_
);
507 // Shortcut 2: targets "chrome.exe"; has arguments.
508 test_properties_
.set_shortcut_name(L
"Chrome 2");
509 test_properties_
.set_arguments(L
"--profile-directory=\"Profile 2\"");
510 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
511 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
512 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
513 ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath(
514 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
)));
515 ShellUtil::ShortcutProperties
expected_properties2(test_properties_
);
517 // Retarget shortcuts: replace "chrome.exe" with "manganese.exe". Only
518 // shortcuts with non-empty arguments (i.e., shortcut 2) gets updated.
519 base::FilePath new_exe
= manganese_exe_
;
520 ASSERT_TRUE(ShellUtil::RetargetShortcutsWithArgs(
521 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, ShellUtil::CURRENT_USER
,
522 chrome_exe_
, new_exe
));
524 // Verify shortcut 1: no change.
525 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
,
526 expected_properties1
);
528 // Verify shortcut 2: target => "manganese.exe".
529 expected_properties2
.set_target(new_exe
);
530 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
,
531 expected_properties2
);
534 TEST_F(ShellUtilShortcutTest
, RetargetChromeShortcutsWithArgsIcon
) {
535 const int kTestIconIndex1
= 3;
536 const int kTestIconIndex2
= 5;
537 const int kTestIconIndex3
= 8;
539 // Shortcut 1: targets "chrome.exe"; icon same as target.
540 test_properties_
.set_shortcut_name(L
"Chrome 1");
541 test_properties_
.set_icon(test_properties_
.target
, kTestIconIndex1
);
542 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
543 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
544 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
545 ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath(
546 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
)));
547 ShellUtil::ShortcutProperties
expected_properties1(test_properties_
);
549 // Shortcut 2: targets "chrome.exe"; icon set to "other.ico".
550 test_properties_
.set_shortcut_name(L
"Chrome 2");
551 test_properties_
.set_icon(other_ico_
, kTestIconIndex2
);
552 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
553 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
554 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
555 ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath(
556 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
)));
557 ShellUtil::ShortcutProperties
expected_properties2(test_properties_
);
559 // Shortcut 3: targets "iron.exe"; icon set to "chrome.exe".
560 test_properties_
.set_target(iron_exe_
);
561 test_properties_
.set_shortcut_name(L
"Iron 3");
562 test_properties_
.set_icon(chrome_exe_
, kTestIconIndex3
);
563 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
564 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
565 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
566 ASSERT_TRUE(base::PathExists(GetExpectedShortcutPath(
567 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
)));
568 ShellUtil::ShortcutProperties
expected_properties3(test_properties_
);
570 // Retarget shortcuts: replace "chrome.exe" with "manganese.exe".
571 // Relies on the fact that |test_properties_| has non-empty arguments.
572 base::FilePath new_exe
= manganese_exe_
;
573 ASSERT_TRUE(ShellUtil::RetargetShortcutsWithArgs(
574 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, ShellUtil::CURRENT_USER
,
575 chrome_exe_
, new_exe
));
577 // Verify shortcut 1: target & icon => "manganese.exe", kept same icon index.
578 expected_properties1
.set_target(new_exe
);
579 expected_properties1
.set_icon(new_exe
, kTestIconIndex1
);
580 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
,
581 expected_properties1
);
583 // Verify shortcut 2: target => "manganese.exe", kept icon.
584 expected_properties2
.set_target(new_exe
);
585 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
,
586 expected_properties2
);
588 // Verify shortcut 3: no change, since target doesn't match.
589 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
,
590 expected_properties3
);
593 TEST_F(ShellUtilShortcutTest
, CreateMultipleStartMenuShortcutsAndRemoveFolder
) {
594 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
595 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR
,
596 dist_
, test_properties_
,
597 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
598 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
599 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR
,
600 dist_
, test_properties_
,
601 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
602 test_properties_
.set_shortcut_name(L
"A second shortcut");
603 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
604 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR
,
605 dist_
, test_properties_
,
606 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
607 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
608 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR
,
609 dist_
, test_properties_
,
610 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
612 base::FilePath
chrome_shortcut_folder(
613 fake_start_menu_
.path().Append(
614 dist_
->GetStartMenuShortcutSubfolder(
615 BrowserDistribution::SUBFOLDER_CHROME
)));
616 base::FilePath
chrome_apps_shortcut_folder(
617 fake_start_menu_
.path().Append(
618 dist_
->GetStartMenuShortcutSubfolder(
619 BrowserDistribution::SUBFOLDER_APPS
)));
621 base::FileEnumerator
chrome_file_counter(chrome_shortcut_folder
, false,
622 base::FileEnumerator::FILES
);
624 while (!chrome_file_counter
.Next().empty())
628 base::FileEnumerator
chrome_apps_file_counter(chrome_apps_shortcut_folder
,
630 base::FileEnumerator::FILES
);
632 while (!chrome_apps_file_counter
.Next().empty())
636 ASSERT_TRUE(base::PathExists(chrome_shortcut_folder
));
637 ASSERT_TRUE(ShellUtil::RemoveShortcuts(
638 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR
, dist_
,
639 ShellUtil::CURRENT_USER
, chrome_exe_
));
640 ASSERT_FALSE(base::PathExists(chrome_shortcut_folder
));
642 ASSERT_TRUE(base::PathExists(chrome_apps_shortcut_folder
));
643 ASSERT_TRUE(ShellUtil::RemoveShortcuts(
644 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR
, dist_
,
645 ShellUtil::CURRENT_USER
, chrome_exe_
));
646 ASSERT_FALSE(base::PathExists(chrome_apps_shortcut_folder
));
649 TEST_F(ShellUtilShortcutTest
,
650 DeleteStartMenuRootShortcutWithoutRemovingFolder
) {
651 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
652 ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT
,
653 dist_
, test_properties_
,
654 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
656 base::string16
shortcut_name(
657 dist_
->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME
) +
659 base::FilePath
shortcut_path(
660 fake_start_menu_
.path().Append(shortcut_name
));
662 ASSERT_TRUE(base::PathExists(fake_start_menu_
.path()));
663 ASSERT_TRUE(base::PathExists(shortcut_path
));
664 ASSERT_TRUE(ShellUtil::RemoveShortcuts(
665 ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT
, dist_
,
666 ShellUtil::CURRENT_USER
, chrome_exe_
));
667 // The shortcut should be removed but the "Start Menu" root directory should
669 ASSERT_TRUE(base::PathExists(fake_start_menu_
.path()));
670 ASSERT_FALSE(base::PathExists(shortcut_path
));
673 TEST_F(ShellUtilShortcutTest
, DontRemoveChromeShortcutIfPointsToAnotherChrome
) {
674 base::ScopedTempDir other_exe_dir
;
675 ASSERT_TRUE(other_exe_dir
.CreateUniqueTempDir());
676 base::FilePath other_chrome_exe
=
677 other_exe_dir
.path().Append(installer::kChromeExe
);
678 EXPECT_EQ(0, file_util::WriteFile(other_chrome_exe
, "", 0));
680 test_properties_
.set_target(other_chrome_exe
);
681 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
682 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, test_properties_
,
683 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS
));
685 base::string16
shortcut_name(
686 dist_
->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME
) +
688 base::FilePath
shortcut_path(fake_user_desktop_
.path().Append(shortcut_name
));
689 ASSERT_TRUE(base::PathExists(shortcut_path
));
691 // The shortcut shouldn't be removed as it was installed pointing to
692 // |other_chrome_exe| and RemoveChromeShortcut() is being told that the
693 // removed shortcut should point to |chrome_exe_|.
694 ASSERT_TRUE(ShellUtil::RemoveShortcuts(
695 ShellUtil::SHORTCUT_LOCATION_DESKTOP
, dist_
, ShellUtil::CURRENT_USER
,
697 ASSERT_TRUE(base::PathExists(shortcut_path
));
698 ASSERT_TRUE(base::PathExists(shortcut_path
.DirName()));
701 TEST(ShellUtilTest
, BuildAppModelIdBasic
) {
702 std::vector
<base::string16
> components
;
703 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
704 const base::string16
base_app_id(dist
->GetBaseAppId());
705 components
.push_back(base_app_id
);
706 ASSERT_EQ(base_app_id
, ShellUtil::BuildAppModelId(components
));
709 TEST(ShellUtilTest
, BuildAppModelIdManySmall
) {
710 std::vector
<base::string16
> components
;
711 BrowserDistribution
* dist
= BrowserDistribution::GetDistribution();
712 const base::string16
suffixed_app_id(dist
->GetBaseAppId().append(L
".gab"));
713 components
.push_back(suffixed_app_id
);
714 components
.push_back(L
"Default");
715 components
.push_back(L
"Test");
716 ASSERT_EQ(suffixed_app_id
+ L
".Default.Test",
717 ShellUtil::BuildAppModelId(components
));
720 TEST(ShellUtilTest
, BuildAppModelIdLongUsernameNormalProfile
) {
721 std::vector
<base::string16
> components
;
722 const base::string16
long_appname(
723 L
"Chrome.a_user_who_has_a_crazy_long_name_with_some_weird@symbols_in_it_"
724 L
"that_goes_over_64_characters");
725 components
.push_back(long_appname
);
726 components
.push_back(L
"Default");
727 ASSERT_EQ(L
"Chrome.a_user_wer_64_characters.Default",
728 ShellUtil::BuildAppModelId(components
));
731 TEST(ShellUtilTest
, BuildAppModelIdLongEverything
) {
732 std::vector
<base::string16
> components
;
733 const base::string16
long_appname(L
"Chrome.a_user_who_has_a_crazy_long_name_"
734 L
"with_some_weird@symbols_in_"
735 L
"it_" L
"that_goes_over_64_characters");
736 components
.push_back(long_appname
);
737 components
.push_back(
738 L
"A_crazy_profile_name_not_even_sure_whether_that_is_possible");
739 const base::string16
constructed_app_id(
740 ShellUtil::BuildAppModelId(components
));
741 ASSERT_LE(constructed_app_id
.length(), installer::kMaxAppModelIdLength
);
742 ASSERT_EQ(L
"Chrome.a_user_wer_64_characters.A_crazy_profilethat_is_possible",
746 TEST(ShellUtilTest
, GetUserSpecificRegistrySuffix
) {
747 base::string16 suffix
;
748 ASSERT_TRUE(ShellUtil::GetUserSpecificRegistrySuffix(&suffix
));
749 ASSERT_TRUE(StartsWith(suffix
, L
".", true));
750 ASSERT_EQ(27, suffix
.length());
751 ASSERT_TRUE(ContainsOnlyChars(suffix
.substr(1),
752 L
"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"));
755 TEST(ShellUtilTest
, GetOldUserSpecificRegistrySuffix
) {
756 base::string16 suffix
;
757 ASSERT_TRUE(ShellUtil::GetOldUserSpecificRegistrySuffix(&suffix
));
758 ASSERT_TRUE(StartsWith(suffix
, L
".", true));
760 wchar_t user_name
[256];
761 DWORD size
= arraysize(user_name
);
762 ASSERT_NE(0, ::GetUserName(user_name
, &size
));
764 ASSERT_STREQ(user_name
, suffix
.substr(1).c_str());
767 TEST(ShellUtilTest
, ByteArrayToBase32
) {
768 // Tests from http://tools.ietf.org/html/rfc4648#section-10.
769 const unsigned char test_array
[] = { 'f', 'o', 'o', 'b', 'a', 'r' };
771 const base::string16 expected
[] = { L
"", L
"MY", L
"MZXQ", L
"MZXW6", L
"MZXW6YQ",
772 L
"MZXW6YTB", L
"MZXW6YTBOI"};
774 // Run the tests, with one more letter in the input every pass.
775 for (int i
= 0; i
< arraysize(expected
); ++i
) {
776 ASSERT_EQ(expected
[i
],
777 ShellUtil::ByteArrayToBase32(test_array
, i
));