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.
4
5 #include "chrome/installer/util/shell_util.h"
6
7 #include <vector>
8
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"
14 #include "base/md5.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"
26
27 namespace {
28
29 const wchar_t kManganeseExe[] = L"manganese.exe";
30
31 // TODO(huangs): Separate this into generic shortcut tests and Chrome-specific
32 // tests. Specifically, we should not overly rely on getting shortcut properties
33 // from product_->AddDefaultShortcutProperties().
34 class ShellUtilShortcutTest : public testing::Test {
35 protected:
ShellUtilShortcutTest()36 ShellUtilShortcutTest() : test_properties_(ShellUtil::CURRENT_USER) {}
37
SetUp()38 virtual void SetUp() OVERRIDE {
39 dist_ = BrowserDistribution::GetDistribution();
40 ASSERT_TRUE(dist_ != NULL);
41 product_.reset(new installer::Product(dist_));
42
43 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir());
44 chrome_exe_ = temp_dir_.path().Append(installer::kChromeExe);
45 EXPECT_EQ(0, file_util::WriteFile(chrome_exe_, "", 0));
46
47 manganese_exe_ = temp_dir_.path().Append(kManganeseExe);
48 EXPECT_EQ(0, file_util::WriteFile(manganese_exe_, "", 0));
49
50 ASSERT_TRUE(fake_user_desktop_.CreateUniqueTempDir());
51 ASSERT_TRUE(fake_common_desktop_.CreateUniqueTempDir());
52 ASSERT_TRUE(fake_user_quick_launch_.CreateUniqueTempDir());
53 ASSERT_TRUE(fake_default_user_quick_launch_.CreateUniqueTempDir());
54 ASSERT_TRUE(fake_start_menu_.CreateUniqueTempDir());
55 ASSERT_TRUE(fake_common_start_menu_.CreateUniqueTempDir());
56 user_desktop_override_.reset(
57 new base::ScopedPathOverride(base::DIR_USER_DESKTOP,
58 fake_user_desktop_.path()));
59 common_desktop_override_.reset(
60 new base::ScopedPathOverride(base::DIR_COMMON_DESKTOP,
61 fake_common_desktop_.path()));
62 user_quick_launch_override_.reset(
63 new base::ScopedPathOverride(base::DIR_USER_QUICK_LAUNCH,
64 fake_user_quick_launch_.path()));
65 default_user_quick_launch_override_.reset(
66 new base::ScopedPathOverride(base::DIR_DEFAULT_USER_QUICK_LAUNCH,
67 fake_default_user_quick_launch_.path()));
68 start_menu_override_.reset(
69 new base::ScopedPathOverride(base::DIR_START_MENU,
70 fake_start_menu_.path()));
71 common_start_menu_override_.reset(
72 new base::ScopedPathOverride(base::DIR_COMMON_START_MENU,
73 fake_common_start_menu_.path()));
74
75 base::FilePath icon_path;
76 base::CreateTemporaryFileInDir(temp_dir_.path(), &icon_path);
77 test_properties_.set_target(chrome_exe_);
78 test_properties_.set_arguments(L"--test --chrome");
79 test_properties_.set_description(L"Makes polar bears dance.");
80 test_properties_.set_icon(icon_path, 0);
81 test_properties_.set_app_id(L"Polar.Bear");
82 test_properties_.set_dual_mode(true);
83 }
84
85 // Validates that the shortcut at |location| matches |properties| (and
86 // implicit default properties) for |dist|.
87 // Note: This method doesn't verify the |pin_to_taskbar| property as it
88 // implies real (non-mocked) state which is flaky to test.
ValidateChromeShortcut(ShellUtil::ShortcutLocation location,BrowserDistribution * dist,const ShellUtil::ShortcutProperties & properties)89 void ValidateChromeShortcut(
90 ShellUtil::ShortcutLocation location,
91 BrowserDistribution* dist,
92 const ShellUtil::ShortcutProperties& properties) {
93 base::FilePath expected_path;
94 switch (location) {
95 case ShellUtil::SHORTCUT_LOCATION_DESKTOP:
96 expected_path = (properties.level == ShellUtil::CURRENT_USER) ?
97 fake_user_desktop_.path() : fake_common_desktop_.path();
98 break;
99 case ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH:
100 expected_path = (properties.level == ShellUtil::CURRENT_USER) ?
101 fake_user_quick_launch_.path() :
102 fake_default_user_quick_launch_.path();
103 break;
104 case ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR:
105 expected_path = (properties.level == ShellUtil::CURRENT_USER) ?
106 fake_start_menu_.path() : fake_common_start_menu_.path();
107 expected_path = expected_path.Append(
108 dist_->GetStartMenuShortcutSubfolder(
109 BrowserDistribution::SUBFOLDER_CHROME));
110 break;
111 default:
112 ADD_FAILURE() << "Unknown location";
113 return;
114 }
115
116 string16 shortcut_name;
117 if (properties.has_shortcut_name()) {
118 shortcut_name = properties.shortcut_name;
119 } else {
120 shortcut_name =
121 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME);
122 }
123 shortcut_name.append(installer::kLnkExt);
124 expected_path = expected_path.Append(shortcut_name);
125
126 base::win::ShortcutProperties expected_properties;
127 if (properties.has_target()) {
128 expected_properties.set_target(properties.target);
129 expected_properties.set_working_dir(properties.target.DirName());
130 } else {
131 expected_properties.set_target(chrome_exe_);
132 expected_properties.set_working_dir(chrome_exe_.DirName());
133 }
134
135 if (properties.has_arguments())
136 expected_properties.set_arguments(properties.arguments);
137 else
138 expected_properties.set_arguments(string16());
139
140 if (properties.has_description())
141 expected_properties.set_description(properties.description);
142 else
143 expected_properties.set_description(dist->GetAppDescription());
144
145 if (properties.has_icon()) {
146 expected_properties.set_icon(properties.icon, 0);
147 } else {
148 int icon_index = dist->GetIconIndex(BrowserDistribution::SHORTCUT_CHROME);
149 expected_properties.set_icon(chrome_exe_, icon_index);
150 }
151
152 if (properties.has_app_id()) {
153 expected_properties.set_app_id(properties.app_id);
154 } else {
155 // Tests are always seen as user-level installs in ShellUtil.
156 expected_properties.set_app_id(ShellUtil::GetBrowserModelId(dist, true));
157 }
158
159 if (properties.has_dual_mode())
160 expected_properties.set_dual_mode(properties.dual_mode);
161 else
162 expected_properties.set_dual_mode(false);
163
164 base::win::ValidateShortcut(expected_path, expected_properties);
165 }
166
167 BrowserDistribution* dist_;
168 scoped_ptr<installer::Product> product_;
169
170 // A ShellUtil::ShortcutProperties object with common properties set already.
171 ShellUtil::ShortcutProperties test_properties_;
172
173 base::ScopedTempDir temp_dir_;
174 base::ScopedTempDir fake_user_desktop_;
175 base::ScopedTempDir fake_common_desktop_;
176 base::ScopedTempDir fake_user_quick_launch_;
177 base::ScopedTempDir fake_default_user_quick_launch_;
178 base::ScopedTempDir fake_start_menu_;
179 base::ScopedTempDir fake_common_start_menu_;
180 scoped_ptr<base::ScopedPathOverride> user_desktop_override_;
181 scoped_ptr<base::ScopedPathOverride> common_desktop_override_;
182 scoped_ptr<base::ScopedPathOverride> user_quick_launch_override_;
183 scoped_ptr<base::ScopedPathOverride> default_user_quick_launch_override_;
184 scoped_ptr<base::ScopedPathOverride> start_menu_override_;
185 scoped_ptr<base::ScopedPathOverride> common_start_menu_override_;
186
187 base::FilePath chrome_exe_;
188 base::FilePath manganese_exe_;
189 };
190
191 } // namespace
192
TEST_F(ShellUtilShortcutTest,GetShortcutPath)193 TEST_F(ShellUtilShortcutTest, GetShortcutPath) {
194 base::FilePath path;
195 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
196 ShellUtil::CURRENT_USER, &path);
197 EXPECT_EQ(fake_user_desktop_.path(), path);
198 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
199 ShellUtil::SYSTEM_LEVEL, &path);
200 EXPECT_EQ(fake_common_desktop_.path(), path);
201 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, dist_,
202 ShellUtil::CURRENT_USER, &path);
203 EXPECT_EQ(fake_user_quick_launch_.path(), path);
204 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, dist_,
205 ShellUtil::SYSTEM_LEVEL, &path);
206 EXPECT_EQ(fake_default_user_quick_launch_.path(), path);
207 string16 start_menu_subfolder =
208 dist_->GetStartMenuShortcutSubfolder(
209 BrowserDistribution::SUBFOLDER_CHROME);
210 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
211 dist_, ShellUtil::CURRENT_USER, &path);
212 EXPECT_EQ(fake_start_menu_.path().Append(start_menu_subfolder),
213 path);
214 ShellUtil::GetShortcutPath(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
215 dist_, ShellUtil::SYSTEM_LEVEL, &path);
216 EXPECT_EQ(fake_common_start_menu_.path().Append(start_menu_subfolder),
217 path);
218 }
219
TEST_F(ShellUtilShortcutTest,CreateChromeExeShortcutWithDefaultProperties)220 TEST_F(ShellUtilShortcutTest, CreateChromeExeShortcutWithDefaultProperties) {
221 ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER);
222 product_->AddDefaultShortcutProperties(chrome_exe_, &properties);
223 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
224 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, properties,
225 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
226 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
227 properties);
228 }
229
TEST_F(ShellUtilShortcutTest,CreateStartMenuShortcutWithAllProperties)230 TEST_F(ShellUtilShortcutTest, CreateStartMenuShortcutWithAllProperties) {
231 test_properties_.set_shortcut_name(L"Bobo le shortcut");
232 test_properties_.level = ShellUtil::SYSTEM_LEVEL;
233 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
234 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
235 dist_, test_properties_,
236 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
237 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
238 dist_, test_properties_);
239 }
240
TEST_F(ShellUtilShortcutTest,ReplaceSystemLevelQuickLaunchShortcut)241 TEST_F(ShellUtilShortcutTest, ReplaceSystemLevelQuickLaunchShortcut) {
242 test_properties_.level = ShellUtil::SYSTEM_LEVEL;
243 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
244 ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH,
245 dist_, test_properties_,
246 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
247
248 ShellUtil::ShortcutProperties new_properties(ShellUtil::SYSTEM_LEVEL);
249 product_->AddDefaultShortcutProperties(chrome_exe_, &new_properties);
250 new_properties.set_description(L"New description");
251 new_properties.set_arguments(L"--new-arguments");
252 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
253 ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH,
254 dist_, new_properties,
255 ShellUtil::SHELL_SHORTCUT_REPLACE_EXISTING));
256
257 // Expect the properties set in |new_properties| to be set as above and
258 // properties that don't have a default value to be set back to their default
259 // (as validated in ValidateChromeShortcut()) or unset if they don't .
260 ShellUtil::ShortcutProperties expected_properties(new_properties);
261 expected_properties.set_dual_mode(false);
262
263 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, dist_,
264 expected_properties);
265 }
266
TEST_F(ShellUtilShortcutTest,UpdateQuickLaunchShortcutArguments)267 TEST_F(ShellUtilShortcutTest, UpdateQuickLaunchShortcutArguments) {
268 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
269 ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH,
270 dist_, test_properties_,
271 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
272
273 // Only changing one property, don't need all the defaults.
274 ShellUtil::ShortcutProperties updated_properties(ShellUtil::CURRENT_USER);
275 updated_properties.set_arguments(L"--updated --arguments");
276 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
277 ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH,
278 dist_, updated_properties,
279 ShellUtil::SHELL_SHORTCUT_UPDATE_EXISTING));
280
281 // Expect the properties set in |updated_properties| to be set as above and
282 // all other properties to remain unchanged.
283 ShellUtil::ShortcutProperties expected_properties(test_properties_);
284 expected_properties.set_arguments(updated_properties.arguments);
285
286 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_QUICK_LAUNCH, dist_,
287 expected_properties);
288 }
289
TEST_F(ShellUtilShortcutTest,UpdateAddDualModeToStartMenuShortcut)290 TEST_F(ShellUtilShortcutTest, UpdateAddDualModeToStartMenuShortcut) {
291 ShellUtil::ShortcutProperties properties(ShellUtil::CURRENT_USER);
292 product_->AddDefaultShortcutProperties(chrome_exe_, &properties);
293 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
294 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, dist_,
295 properties, ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
296
297 ShellUtil::ShortcutProperties added_properties(ShellUtil::CURRENT_USER);
298 added_properties.set_dual_mode(true);
299 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
300 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, dist_,
301 added_properties, ShellUtil::SHELL_SHORTCUT_UPDATE_EXISTING));
302
303 ShellUtil::ShortcutProperties expected_properties(properties);
304 expected_properties.set_dual_mode(true);
305
306 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
307 dist_, expected_properties);
308 }
309
TEST_F(ShellUtilShortcutTest,CreateIfNoSystemLevel)310 TEST_F(ShellUtilShortcutTest, CreateIfNoSystemLevel) {
311 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
312 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
313 ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL));
314 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
315 test_properties_);
316 }
317
TEST_F(ShellUtilShortcutTest,CreateIfNoSystemLevelWithSystemLevelPresent)318 TEST_F(ShellUtilShortcutTest, CreateIfNoSystemLevelWithSystemLevelPresent) {
319 string16 shortcut_name(
320 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
321 installer::kLnkExt);
322
323 test_properties_.level = ShellUtil::SYSTEM_LEVEL;
324 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
325 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
326 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
327 ASSERT_TRUE(base::PathExists(
328 fake_common_desktop_.path().Append(shortcut_name)));
329
330 test_properties_.level = ShellUtil::CURRENT_USER;
331 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
332 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
333 ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL));
334 ASSERT_FALSE(base::PathExists(
335 fake_user_desktop_.path().Append(shortcut_name)));
336 }
337
TEST_F(ShellUtilShortcutTest,CreateIfNoSystemLevelStartMenu)338 TEST_F(ShellUtilShortcutTest, CreateIfNoSystemLevelStartMenu) {
339 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
340 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
341 dist_, test_properties_,
342 ShellUtil::SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL));
343 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
344 dist_, test_properties_);
345 }
346
TEST_F(ShellUtilShortcutTest,CreateAlwaysUserWithSystemLevelPresent)347 TEST_F(ShellUtilShortcutTest, CreateAlwaysUserWithSystemLevelPresent) {
348 string16 shortcut_name(
349 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
350 installer::kLnkExt);
351
352 test_properties_.level = ShellUtil::SYSTEM_LEVEL;
353 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
354 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
355 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
356 ASSERT_TRUE(base::PathExists(
357 fake_common_desktop_.path().Append(shortcut_name)));
358
359 test_properties_.level = ShellUtil::CURRENT_USER;
360 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
361 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
362 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
363 ASSERT_TRUE(base::PathExists(
364 fake_user_desktop_.path().Append(shortcut_name)));
365 }
366
TEST_F(ShellUtilShortcutTest,RemoveChromeShortcut)367 TEST_F(ShellUtilShortcutTest, RemoveChromeShortcut) {
368 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
369 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
370 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
371
372 string16 shortcut_name(
373 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
374 installer::kLnkExt);
375 base::FilePath shortcut_path(fake_user_desktop_.path().Append(shortcut_name));
376 ASSERT_TRUE(base::PathExists(shortcut_path));
377
378 ASSERT_TRUE(ShellUtil::RemoveShortcuts(
379 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER,
380 chrome_exe_));
381 ASSERT_FALSE(base::PathExists(shortcut_path));
382 ASSERT_TRUE(base::PathExists(shortcut_path.DirName()));
383 }
384
TEST_F(ShellUtilShortcutTest,RemoveSystemLevelChromeShortcut)385 TEST_F(ShellUtilShortcutTest, RemoveSystemLevelChromeShortcut) {
386 test_properties_.level = ShellUtil::SYSTEM_LEVEL;
387 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
388 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
389 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
390
391 string16 shortcut_name(
392 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
393 installer::kLnkExt);
394 base::FilePath shortcut_path(
395 fake_common_desktop_.path().Append(shortcut_name));
396 ASSERT_TRUE(base::PathExists(shortcut_path));
397
398 ASSERT_TRUE(ShellUtil::RemoveShortcuts(
399 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::SYSTEM_LEVEL,
400 chrome_exe_));
401 ASSERT_FALSE(base::PathExists(shortcut_path));
402 ASSERT_TRUE(base::PathExists(shortcut_path.DirName()));
403 }
404
TEST_F(ShellUtilShortcutTest,RemoveMultipleChromeShortcuts)405 TEST_F(ShellUtilShortcutTest, RemoveMultipleChromeShortcuts) {
406 const wchar_t kShortcutName1[] = L"Chrome 1";
407 const wchar_t kShortcutName2[] = L"Chrome 2";
408
409 test_properties_.set_shortcut_name(kShortcutName1);
410 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
411 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
412 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
413 string16 shortcut1_name(
414 string16(kShortcutName1).append(installer::kLnkExt));
415 base::FilePath shortcut1_path(
416 fake_user_desktop_.path().Append(shortcut1_name));
417 ASSERT_TRUE(base::PathExists(shortcut1_path));
418
419 test_properties_.set_shortcut_name(kShortcutName2);
420 test_properties_.set_arguments(L"--profile-directory=\"Profile 2\"");
421 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
422 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
423 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
424 string16 shortcut2_name(string16(kShortcutName2).append(installer::kLnkExt));
425 base::FilePath shortcut2_path(
426 fake_user_desktop_.path().Append(shortcut2_name));
427 ASSERT_TRUE(base::PathExists(shortcut2_path));
428
429 ASSERT_TRUE(ShellUtil::RemoveShortcuts(
430 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER,
431 chrome_exe_));
432 ASSERT_FALSE(base::PathExists(shortcut1_path));
433 ASSERT_FALSE(base::PathExists(shortcut2_path));
434 ASSERT_TRUE(base::PathExists(shortcut1_path.DirName()));
435 }
436
TEST_F(ShellUtilShortcutTest,UpdateChromeShortcutsWithArgs)437 TEST_F(ShellUtilShortcutTest, UpdateChromeShortcutsWithArgs) {
438 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
439 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
440 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
441
442 string16 shortcut_name(
443 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
444 installer::kLnkExt);
445 base::FilePath shortcut_path(fake_user_desktop_.path().Append(shortcut_name));
446 ASSERT_TRUE(base::PathExists(shortcut_path));
447
448 base::FilePath new_exe = temp_dir_.path().Append(kManganeseExe);
449 ShellUtil::ShortcutProperties updated_properties(ShellUtil::CURRENT_USER);
450 updated_properties.set_target(new_exe);
451 // |updated_properties| has arguments.
452 ASSERT_TRUE(ShellUtil::UpdateShortcutsWithArgs(
453 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER,
454 chrome_exe_, updated_properties));
455
456 ShellUtil::ShortcutProperties expected_properties(test_properties_);
457 expected_properties.set_target(new_exe);
458 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
459 expected_properties);
460 }
461
TEST_F(ShellUtilShortcutTest,UpdateSystemLevelChromeShortcutsWithArgs)462 TEST_F(ShellUtilShortcutTest, UpdateSystemLevelChromeShortcutsWithArgs) {
463 test_properties_.level = ShellUtil::SYSTEM_LEVEL;
464 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
465 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
466 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
467
468 string16 shortcut_name(
469 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
470 installer::kLnkExt);
471 base::FilePath shortcut_path(
472 fake_common_desktop_.path().Append(shortcut_name));
473 ASSERT_TRUE(base::PathExists(shortcut_path));
474
475 base::FilePath new_exe = temp_dir_.path().Append(kManganeseExe);
476 ShellUtil::ShortcutProperties updated_properties(ShellUtil::CURRENT_USER);
477 updated_properties.set_target(new_exe);
478 // |updated_properties| has arguments.
479 ASSERT_TRUE(ShellUtil::UpdateShortcutsWithArgs(
480 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::SYSTEM_LEVEL,
481 chrome_exe_, updated_properties));
482
483 ShellUtil::ShortcutProperties expected_properties(test_properties_);
484 expected_properties.set_target(new_exe);
485 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
486 expected_properties);
487 }
488
TEST_F(ShellUtilShortcutTest,UpdateMultipleChromeShortcutsWithArgs)489 TEST_F(ShellUtilShortcutTest, UpdateMultipleChromeShortcutsWithArgs) {
490 const wchar_t kShortcutName1[] = L"Chrome 1";
491 const wchar_t kShortcutName2[] = L"Chrome 2";
492
493 // Setup shortcut 1, which has empty arguments.
494 test_properties_.set_shortcut_name(kShortcutName1);
495 test_properties_.set_arguments(L"");
496 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
497 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
498 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
499 string16 shortcut1_name(string16(kShortcutName1).append(installer::kLnkExt));
500 base::FilePath shortcut1_path(
501 fake_user_desktop_.path().Append(shortcut1_name));
502 ShellUtil::ShortcutProperties expected_properties1(test_properties_);
503
504 // Setup shortcut 2, which has non-empty arguments.
505 string16 shortcut2_args = L"--profile-directory=\"Profile 2\"";
506 test_properties_.set_shortcut_name(kShortcutName2);
507 test_properties_.set_arguments(shortcut2_args);
508 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
509 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
510 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
511 string16 shortcut2_name(string16(kShortcutName2).append(installer::kLnkExt));
512 base::FilePath shortcut2_path(
513 fake_user_desktop_.path().Append(shortcut2_name));
514 ASSERT_TRUE(base::PathExists(shortcut2_path));
515 ShellUtil::ShortcutProperties expected_properties2(test_properties_);
516
517 // Update shortcuts: target "manganese.exe" instead of "chrome.exe".
518 base::FilePath new_exe = temp_dir_.path().Append(kManganeseExe);
519 ShellUtil::ShortcutProperties updated_properties(ShellUtil::CURRENT_USER);
520 updated_properties.set_target(new_exe);
521
522 // Only changing shrotcuts that have non-empty arguments, i.e., shortcut 2.
523 ASSERT_TRUE(ShellUtil::UpdateShortcutsWithArgs(
524 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER,
525 chrome_exe_, updated_properties));
526 // Verify shortcut 1.
527 // |expected_properties1| was unchanged and still targets "chrome.exe", since
528 // it has empty target, yet we passed |require_args| = true.
529 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
530 expected_properties1);
531 // Verify shortcut 2.
532 expected_properties2.set_target(new_exe);
533 ValidateChromeShortcut(ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_,
534 expected_properties2);
535 }
536
TEST_F(ShellUtilShortcutTest,CreateMultipleStartMenuShortcutsAndRemoveFolder)537 TEST_F(ShellUtilShortcutTest, CreateMultipleStartMenuShortcutsAndRemoveFolder) {
538 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
539 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
540 dist_, test_properties_,
541 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
542 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
543 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR,
544 dist_, test_properties_,
545 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
546 test_properties_.set_shortcut_name(L"A second shortcut");
547 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
548 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR,
549 dist_, test_properties_,
550 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
551 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
552 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR,
553 dist_, test_properties_,
554 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
555
556 base::FilePath chrome_shortcut_folder(
557 fake_start_menu_.path().Append(
558 dist_->GetStartMenuShortcutSubfolder(
559 BrowserDistribution::SUBFOLDER_CHROME)));
560 base::FilePath chrome_apps_shortcut_folder(
561 fake_start_menu_.path().Append(
562 dist_->GetStartMenuShortcutSubfolder(
563 BrowserDistribution::SUBFOLDER_APPS)));
564
565 base::FileEnumerator chrome_file_counter(chrome_shortcut_folder, false,
566 base::FileEnumerator::FILES);
567 int count = 0;
568 while (!chrome_file_counter.Next().empty())
569 ++count;
570 EXPECT_EQ(2, count);
571
572 base::FileEnumerator chrome_apps_file_counter(chrome_apps_shortcut_folder,
573 false,
574 base::FileEnumerator::FILES);
575 count = 0;
576 while (!chrome_apps_file_counter.Next().empty())
577 ++count;
578 EXPECT_EQ(2, count);
579
580 ASSERT_TRUE(base::PathExists(chrome_shortcut_folder));
581 ASSERT_TRUE(ShellUtil::RemoveShortcuts(
582 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_DIR, dist_,
583 ShellUtil::CURRENT_USER, chrome_exe_));
584 ASSERT_FALSE(base::PathExists(chrome_shortcut_folder));
585
586 ASSERT_TRUE(base::PathExists(chrome_apps_shortcut_folder));
587 ASSERT_TRUE(ShellUtil::RemoveShortcuts(
588 ShellUtil::SHORTCUT_LOCATION_START_MENU_CHROME_APPS_DIR, dist_,
589 ShellUtil::CURRENT_USER, chrome_exe_));
590 ASSERT_FALSE(base::PathExists(chrome_apps_shortcut_folder));
591 }
592
TEST_F(ShellUtilShortcutTest,DeleteStartMenuRootShortcutWithoutRemovingFolder)593 TEST_F(ShellUtilShortcutTest,
594 DeleteStartMenuRootShortcutWithoutRemovingFolder) {
595 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
596 ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT,
597 dist_, test_properties_,
598 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
599
600 string16 shortcut_name(
601 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
602 installer::kLnkExt);
603 base::FilePath shortcut_path(
604 fake_start_menu_.path().Append(shortcut_name));
605
606 ASSERT_TRUE(base::PathExists(fake_start_menu_.path()));
607 ASSERT_TRUE(base::PathExists(shortcut_path));
608 ASSERT_TRUE(ShellUtil::RemoveShortcuts(
609 ShellUtil::SHORTCUT_LOCATION_START_MENU_ROOT, dist_,
610 ShellUtil::CURRENT_USER, chrome_exe_));
611 // The shortcut should be removed but the "Start Menu" root directory should
612 // remain.
613 ASSERT_TRUE(base::PathExists(fake_start_menu_.path()));
614 ASSERT_FALSE(base::PathExists(shortcut_path));
615 }
616
TEST_F(ShellUtilShortcutTest,DontRemoveChromeShortcutIfPointsToAnotherChrome)617 TEST_F(ShellUtilShortcutTest, DontRemoveChromeShortcutIfPointsToAnotherChrome) {
618 base::ScopedTempDir other_exe_dir;
619 ASSERT_TRUE(other_exe_dir.CreateUniqueTempDir());
620 base::FilePath other_chrome_exe =
621 other_exe_dir.path().Append(installer::kChromeExe);
622 EXPECT_EQ(0, file_util::WriteFile(other_chrome_exe, "", 0));
623
624 test_properties_.set_target(other_chrome_exe);
625 ASSERT_TRUE(ShellUtil::CreateOrUpdateShortcut(
626 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, test_properties_,
627 ShellUtil::SHELL_SHORTCUT_CREATE_ALWAYS));
628
629 string16 shortcut_name(
630 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) +
631 installer::kLnkExt);
632 base::FilePath shortcut_path(fake_user_desktop_.path().Append(shortcut_name));
633 ASSERT_TRUE(base::PathExists(shortcut_path));
634
635 // The shortcut shouldn't be removed as it was installed pointing to
636 // |other_chrome_exe| and RemoveChromeShortcut() is being told that the
637 // removed shortcut should point to |chrome_exe_|.
638 ASSERT_TRUE(ShellUtil::RemoveShortcuts(
639 ShellUtil::SHORTCUT_LOCATION_DESKTOP, dist_, ShellUtil::CURRENT_USER,
640 chrome_exe_));
641 ASSERT_TRUE(base::PathExists(shortcut_path));
642 ASSERT_TRUE(base::PathExists(shortcut_path.DirName()));
643 }
644
TEST(ShellUtilTest,BuildAppModelIdBasic)645 TEST(ShellUtilTest, BuildAppModelIdBasic) {
646 std::vector<string16> components;
647 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
648 const string16 base_app_id(dist->GetBaseAppId());
649 components.push_back(base_app_id);
650 ASSERT_EQ(base_app_id, ShellUtil::BuildAppModelId(components));
651 }
652
TEST(ShellUtilTest,BuildAppModelIdManySmall)653 TEST(ShellUtilTest, BuildAppModelIdManySmall) {
654 std::vector<string16> components;
655 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
656 const string16 suffixed_app_id(dist->GetBaseAppId().append(L".gab"));
657 components.push_back(suffixed_app_id);
658 components.push_back(L"Default");
659 components.push_back(L"Test");
660 ASSERT_EQ(suffixed_app_id + L".Default.Test",
661 ShellUtil::BuildAppModelId(components));
662 }
663
TEST(ShellUtilTest,BuildAppModelIdLongUsernameNormalProfile)664 TEST(ShellUtilTest, BuildAppModelIdLongUsernameNormalProfile) {
665 std::vector<string16> components;
666 const string16 long_appname(
667 L"Chrome.a_user_who_has_a_crazy_long_name_with_some_weird@symbols_in_it_"
668 L"that_goes_over_64_characters");
669 components.push_back(long_appname);
670 components.push_back(L"Default");
671 ASSERT_EQ(L"Chrome.a_user_wer_64_characters.Default",
672 ShellUtil::BuildAppModelId(components));
673 }
674
TEST(ShellUtilTest,BuildAppModelIdLongEverything)675 TEST(ShellUtilTest, BuildAppModelIdLongEverything) {
676 std::vector<string16> components;
677 const string16 long_appname(
678 L"Chrome.a_user_who_has_a_crazy_long_name_with_some_weird@symbols_in_it_"
679 L"that_goes_over_64_characters");
680 components.push_back(long_appname);
681 components.push_back(
682 L"A_crazy_profile_name_not_even_sure_whether_that_is_possible");
683 const string16 constructed_app_id(ShellUtil::BuildAppModelId(components));
684 ASSERT_LE(constructed_app_id.length(), installer::kMaxAppModelIdLength);
685 ASSERT_EQ(L"Chrome.a_user_wer_64_characters.A_crazy_profilethat_is_possible",
686 constructed_app_id);
687 }
688
TEST(ShellUtilTest,GetUserSpecificRegistrySuffix)689 TEST(ShellUtilTest, GetUserSpecificRegistrySuffix) {
690 string16 suffix;
691 ASSERT_TRUE(ShellUtil::GetUserSpecificRegistrySuffix(&suffix));
692 ASSERT_TRUE(StartsWith(suffix, L".", true));
693 ASSERT_EQ(27, suffix.length());
694 ASSERT_TRUE(ContainsOnlyChars(suffix.substr(1),
695 L"ABCDEFGHIJKLMNOPQRSTUVWXYZ234567"));
696 }
697
TEST(ShellUtilTest,GetOldUserSpecificRegistrySuffix)698 TEST(ShellUtilTest, GetOldUserSpecificRegistrySuffix) {
699 string16 suffix;
700 ASSERT_TRUE(ShellUtil::GetOldUserSpecificRegistrySuffix(&suffix));
701 ASSERT_TRUE(StartsWith(suffix, L".", true));
702
703 wchar_t user_name[256];
704 DWORD size = arraysize(user_name);
705 ASSERT_NE(0, ::GetUserName(user_name, &size));
706 ASSERT_GE(size, 1U);
707 ASSERT_STREQ(user_name, suffix.substr(1).c_str());
708 }
709
TEST(ShellUtilTest,ByteArrayToBase32)710 TEST(ShellUtilTest, ByteArrayToBase32) {
711 // Tests from http://tools.ietf.org/html/rfc4648#section-10.
712 const unsigned char test_array[] = { 'f', 'o', 'o', 'b', 'a', 'r' };
713
714 const string16 expected[] = { L"", L"MY", L"MZXQ", L"MZXW6", L"MZXW6YQ",
715 L"MZXW6YTB", L"MZXW6YTBOI"};
716
717 // Run the tests, with one more letter in the input every pass.
718 for (int i = 0; i < arraysize(expected); ++i) {
719 ASSERT_EQ(expected[i],
720 ShellUtil::ByteArrayToBase32(test_array, i));
721 }
722 }
723