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