• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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