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 <objbase.h> 6 7 #include <string> 8 9 #include "base/files/file_path.h" 10 #include "base/files/file_util.h" 11 #include "base/files/scoped_temp_dir.h" 12 #include "base/memory/scoped_ptr.h" 13 #include "base/path_service.h" 14 #include "base/strings/string16.h" 15 #include "base/strings/utf_string_conversions.h" 16 #include "base/test/scoped_path_override.h" 17 #include "base/test/test_shortcut_win.h" 18 #include "base/version.h" 19 #include "base/win/shortcut.h" 20 #include "chrome/installer/setup/install.h" 21 #include "chrome/installer/setup/install_worker.h" 22 #include "chrome/installer/setup/setup_constants.h" 23 #include "chrome/installer/util/browser_distribution.h" 24 #include "chrome/installer/util/installer_state.h" 25 #include "chrome/installer/util/master_preferences.h" 26 #include "chrome/installer/util/master_preferences_constants.h" 27 #include "chrome/installer/util/product.h" 28 #include "chrome/installer/util/shell_util.h" 29 #include "chrome/installer/util/util_constants.h" 30 #include "testing/gtest/include/gtest/gtest.h" 31 32 namespace { 33 34 class CreateVisualElementsManifestTest : public testing::Test { 35 protected: 36 virtual void SetUp() OVERRIDE { 37 // Create a temp directory for testing. 38 ASSERT_TRUE(test_dir_.CreateUniqueTempDir()); 39 40 version_ = Version("0.0.0.0"); 41 42 version_dir_ = test_dir_.path().AppendASCII(version_.GetString()); 43 ASSERT_TRUE(base::CreateDirectory(version_dir_)); 44 45 manifest_path_ = 46 test_dir_.path().Append(installer::kVisualElementsManifest); 47 } 48 49 virtual void TearDown() OVERRIDE { 50 // Clean up test directory manually so we can fail if it leaks. 51 ASSERT_TRUE(test_dir_.Delete()); 52 } 53 54 // The temporary directory used to contain the test operations. 55 base::ScopedTempDir test_dir_; 56 57 // A dummy version number used to create the version directory. 58 Version version_; 59 60 // The path to |test_dir_|\|version_|. 61 base::FilePath version_dir_; 62 63 // The path to VisualElementsManifest.xml. 64 base::FilePath manifest_path_; 65 }; 66 67 class InstallShortcutTest : public testing::Test { 68 protected: 69 virtual void SetUp() OVERRIDE { 70 EXPECT_EQ(S_OK, CoInitialize(NULL)); 71 72 dist_ = BrowserDistribution::GetDistribution(); 73 ASSERT_TRUE(dist_ != NULL); 74 product_.reset(new installer::Product(dist_)); 75 76 ASSERT_TRUE(temp_dir_.CreateUniqueTempDir()); 77 chrome_exe_ = temp_dir_.path().Append(installer::kChromeExe); 78 EXPECT_EQ(0, base::WriteFile(chrome_exe_, "", 0)); 79 80 ShellUtil::ShortcutProperties chrome_properties(ShellUtil::CURRENT_USER); 81 product_->AddDefaultShortcutProperties(chrome_exe_, &chrome_properties); 82 83 expected_properties_.set_target(chrome_exe_); 84 expected_properties_.set_icon(chrome_properties.icon, 85 chrome_properties.icon_index); 86 expected_properties_.set_app_id(chrome_properties.app_id); 87 expected_properties_.set_description(chrome_properties.description); 88 expected_properties_.set_dual_mode(false); 89 expected_start_menu_properties_ = expected_properties_; 90 expected_start_menu_properties_.set_dual_mode(true); 91 92 prefs_.reset(GetFakeMasterPrefs(false, false, false)); 93 94 ASSERT_TRUE(fake_user_desktop_.CreateUniqueTempDir()); 95 ASSERT_TRUE(fake_common_desktop_.CreateUniqueTempDir()); 96 ASSERT_TRUE(fake_user_quick_launch_.CreateUniqueTempDir()); 97 ASSERT_TRUE(fake_start_menu_.CreateUniqueTempDir()); 98 ASSERT_TRUE(fake_common_start_menu_.CreateUniqueTempDir()); 99 user_desktop_override_.reset( 100 new base::ScopedPathOverride(base::DIR_USER_DESKTOP, 101 fake_user_desktop_.path())); 102 common_desktop_override_.reset( 103 new base::ScopedPathOverride(base::DIR_COMMON_DESKTOP, 104 fake_common_desktop_.path())); 105 user_quick_launch_override_.reset( 106 new base::ScopedPathOverride(base::DIR_USER_QUICK_LAUNCH, 107 fake_user_quick_launch_.path())); 108 start_menu_override_.reset( 109 new base::ScopedPathOverride(base::DIR_START_MENU, 110 fake_start_menu_.path())); 111 common_start_menu_override_.reset( 112 new base::ScopedPathOverride(base::DIR_COMMON_START_MENU, 113 fake_common_start_menu_.path())); 114 115 base::string16 shortcut_name( 116 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME) + 117 installer::kLnkExt); 118 base::string16 alternate_shortcut_name( 119 dist_->GetShortcutName(BrowserDistribution::SHORTCUT_CHROME_ALTERNATE) + 120 installer::kLnkExt); 121 122 user_desktop_shortcut_ = 123 fake_user_desktop_.path().Append(shortcut_name); 124 user_quick_launch_shortcut_ = 125 fake_user_quick_launch_.path().Append(shortcut_name); 126 user_start_menu_shortcut_ = 127 fake_start_menu_.path().Append( 128 dist_->GetStartMenuShortcutSubfolder( 129 BrowserDistribution::SUBFOLDER_CHROME)) 130 .Append(shortcut_name); 131 system_desktop_shortcut_ = 132 fake_common_desktop_.path().Append(shortcut_name); 133 system_start_menu_shortcut_ = 134 fake_common_start_menu_.path().Append( 135 dist_->GetStartMenuShortcutSubfolder( 136 BrowserDistribution::SUBFOLDER_CHROME)) 137 .Append(shortcut_name); 138 user_alternate_desktop_shortcut_ = 139 fake_user_desktop_.path().Append(alternate_shortcut_name); 140 } 141 142 virtual void TearDown() OVERRIDE { 143 // Try to unpin potentially pinned shortcuts (although pinning isn't tested, 144 // the call itself might still have pinned the Start Menu shortcuts). 145 base::win::TaskbarUnpinShortcutLink( 146 user_start_menu_shortcut_.value().c_str()); 147 base::win::TaskbarUnpinShortcutLink( 148 system_start_menu_shortcut_.value().c_str()); 149 CoUninitialize(); 150 } 151 152 installer::MasterPreferences* GetFakeMasterPrefs( 153 bool do_not_create_desktop_shortcut, 154 bool do_not_create_quick_launch_shortcut, 155 bool alternate_desktop_shortcut) { 156 const struct { 157 const char* pref_name; 158 bool is_desired; 159 } desired_prefs[] = { 160 { installer::master_preferences::kDoNotCreateDesktopShortcut, 161 do_not_create_desktop_shortcut }, 162 { installer::master_preferences::kDoNotCreateQuickLaunchShortcut, 163 do_not_create_quick_launch_shortcut }, 164 { installer::master_preferences::kAltShortcutText, 165 alternate_desktop_shortcut }, 166 }; 167 168 std::string master_prefs("{\"distribution\":{"); 169 for (size_t i = 0; i < arraysize(desired_prefs); ++i) { 170 master_prefs += (i == 0 ? "\"" : ",\""); 171 master_prefs += desired_prefs[i].pref_name; 172 master_prefs += "\":"; 173 master_prefs += desired_prefs[i].is_desired ? "true" : "false"; 174 } 175 master_prefs += "}}"; 176 177 return new installer::MasterPreferences(master_prefs); 178 } 179 180 base::win::ShortcutProperties expected_properties_; 181 base::win::ShortcutProperties expected_start_menu_properties_; 182 183 BrowserDistribution* dist_; 184 base::FilePath chrome_exe_; 185 scoped_ptr<installer::Product> product_; 186 scoped_ptr<installer::MasterPreferences> prefs_; 187 188 base::ScopedTempDir temp_dir_; 189 base::ScopedTempDir fake_user_desktop_; 190 base::ScopedTempDir fake_common_desktop_; 191 base::ScopedTempDir fake_user_quick_launch_; 192 base::ScopedTempDir fake_start_menu_; 193 base::ScopedTempDir fake_common_start_menu_; 194 scoped_ptr<base::ScopedPathOverride> user_desktop_override_; 195 scoped_ptr<base::ScopedPathOverride> common_desktop_override_; 196 scoped_ptr<base::ScopedPathOverride> user_quick_launch_override_; 197 scoped_ptr<base::ScopedPathOverride> start_menu_override_; 198 scoped_ptr<base::ScopedPathOverride> common_start_menu_override_; 199 200 base::FilePath user_desktop_shortcut_; 201 base::FilePath user_quick_launch_shortcut_; 202 base::FilePath user_start_menu_shortcut_; 203 base::FilePath system_desktop_shortcut_; 204 base::FilePath system_start_menu_shortcut_; 205 base::FilePath user_alternate_desktop_shortcut_; 206 }; 207 208 } // namespace 209 210 // Test that VisualElementsManifest.xml is not created when VisualElements are 211 // not present. 212 TEST_F(CreateVisualElementsManifestTest, VisualElementsManifestNotCreated) { 213 ASSERT_TRUE( 214 installer::CreateVisualElementsManifest(test_dir_.path(), version_)); 215 ASSERT_FALSE(base::PathExists(manifest_path_)); 216 } 217 218 // Test that VisualElementsManifest.xml is created with the correct content when 219 // VisualElements are present. 220 TEST_F(CreateVisualElementsManifestTest, VisualElementsManifestCreated) { 221 ASSERT_TRUE(base::CreateDirectory( 222 version_dir_.Append(installer::kVisualElements))); 223 ASSERT_TRUE( 224 installer::CreateVisualElementsManifest(test_dir_.path(), version_)); 225 ASSERT_TRUE(base::PathExists(manifest_path_)); 226 227 std::string read_manifest; 228 ASSERT_TRUE(base::ReadFileToString(manifest_path_, &read_manifest)); 229 230 static const char kExpectedManifest[] = 231 "<Application>\r\n" 232 " <VisualElements\r\n" 233 " DisplayName='Google Chrome'\r\n" 234 " Logo='0.0.0.0\\VisualElements\\Logo.png'\r\n" 235 " SmallLogo='0.0.0.0\\VisualElements\\SmallLogo.png'\r\n" 236 " ForegroundText='light'\r\n" 237 " BackgroundColor='#323232'>\r\n" 238 " <DefaultTile ShowName='allLogos'/>\r\n" 239 " <SplashScreen Image='0.0.0.0\\VisualElements\\splash-620x300.png'/>" 240 "\r\n" 241 " </VisualElements>\r\n" 242 "</Application>"; 243 244 ASSERT_STREQ(kExpectedManifest, read_manifest.c_str()); 245 } 246 247 TEST_F(InstallShortcutTest, CreateAllShortcuts) { 248 installer::CreateOrUpdateShortcuts( 249 chrome_exe_, *product_, *prefs_, installer::CURRENT_USER, 250 installer::INSTALL_SHORTCUT_CREATE_ALL); 251 base::win::ValidateShortcut(user_desktop_shortcut_, expected_properties_); 252 base::win::ValidateShortcut(user_quick_launch_shortcut_, 253 expected_properties_); 254 base::win::ValidateShortcut(user_start_menu_shortcut_, 255 expected_start_menu_properties_); 256 } 257 258 TEST_F(InstallShortcutTest, CreateAllShortcutsSystemLevel) { 259 installer::CreateOrUpdateShortcuts( 260 chrome_exe_, *product_, *prefs_, installer::ALL_USERS, 261 installer::INSTALL_SHORTCUT_CREATE_ALL); 262 base::win::ValidateShortcut(system_desktop_shortcut_, expected_properties_); 263 base::win::ValidateShortcut(system_start_menu_shortcut_, 264 expected_start_menu_properties_); 265 // The quick launch shortcut is always created per-user for the admin running 266 // the install (other users will get it via Active Setup). 267 base::win::ValidateShortcut(user_quick_launch_shortcut_, 268 expected_properties_); 269 } 270 271 TEST_F(InstallShortcutTest, CreateAllShortcutsAlternateDesktopName) { 272 scoped_ptr<installer::MasterPreferences> prefs_alt_desktop( 273 GetFakeMasterPrefs(false, false, true)); 274 installer::CreateOrUpdateShortcuts( 275 chrome_exe_, *product_, *prefs_alt_desktop, installer::CURRENT_USER, 276 installer::INSTALL_SHORTCUT_CREATE_ALL); 277 base::win::ValidateShortcut(user_alternate_desktop_shortcut_, 278 expected_properties_); 279 base::win::ValidateShortcut(user_quick_launch_shortcut_, 280 expected_properties_); 281 base::win::ValidateShortcut(user_start_menu_shortcut_, 282 expected_start_menu_properties_); 283 } 284 285 TEST_F(InstallShortcutTest, CreateAllShortcutsButDesktopShortcut) { 286 scoped_ptr<installer::MasterPreferences> prefs_no_desktop( 287 GetFakeMasterPrefs(true, false, false)); 288 installer::CreateOrUpdateShortcuts( 289 chrome_exe_, *product_, *prefs_no_desktop, installer::CURRENT_USER, 290 installer::INSTALL_SHORTCUT_CREATE_ALL); 291 ASSERT_FALSE(base::PathExists(user_desktop_shortcut_)); 292 base::win::ValidateShortcut(user_quick_launch_shortcut_, 293 expected_properties_); 294 base::win::ValidateShortcut(user_start_menu_shortcut_, 295 expected_start_menu_properties_); 296 } 297 298 TEST_F(InstallShortcutTest, CreateAllShortcutsButQuickLaunchShortcut) { 299 scoped_ptr<installer::MasterPreferences> prefs_no_ql( 300 GetFakeMasterPrefs(false, true, false)); 301 installer::CreateOrUpdateShortcuts( 302 chrome_exe_, *product_, *prefs_no_ql, installer::CURRENT_USER, 303 installer::INSTALL_SHORTCUT_CREATE_ALL); 304 base::win::ValidateShortcut(user_desktop_shortcut_, expected_properties_); 305 ASSERT_FALSE(base::PathExists(user_quick_launch_shortcut_)); 306 base::win::ValidateShortcut(user_start_menu_shortcut_, 307 expected_start_menu_properties_); 308 } 309 310 TEST_F(InstallShortcutTest, ReplaceAll) { 311 base::win::ShortcutProperties dummy_properties; 312 base::FilePath dummy_target; 313 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &dummy_target)); 314 dummy_properties.set_target(dummy_target); 315 dummy_properties.set_working_dir(fake_user_desktop_.path()); 316 dummy_properties.set_arguments(L"--dummy --args"); 317 dummy_properties.set_app_id(L"El.Dummiest"); 318 319 ASSERT_TRUE(base::win::CreateOrUpdateShortcutLink( 320 user_desktop_shortcut_, dummy_properties, 321 base::win::SHORTCUT_CREATE_ALWAYS)); 322 ASSERT_TRUE(base::win::CreateOrUpdateShortcutLink( 323 user_quick_launch_shortcut_, dummy_properties, 324 base::win::SHORTCUT_CREATE_ALWAYS)); 325 ASSERT_TRUE(base::CreateDirectory(user_start_menu_shortcut_.DirName())); 326 ASSERT_TRUE(base::win::CreateOrUpdateShortcutLink( 327 user_start_menu_shortcut_, dummy_properties, 328 base::win::SHORTCUT_CREATE_ALWAYS)); 329 330 installer::CreateOrUpdateShortcuts( 331 chrome_exe_, *product_, *prefs_, installer::CURRENT_USER, 332 installer::INSTALL_SHORTCUT_REPLACE_EXISTING); 333 base::win::ValidateShortcut(user_desktop_shortcut_, expected_properties_); 334 base::win::ValidateShortcut(user_quick_launch_shortcut_, 335 expected_properties_); 336 base::win::ValidateShortcut(user_start_menu_shortcut_, 337 expected_start_menu_properties_); 338 } 339 340 TEST_F(InstallShortcutTest, ReplaceExisting) { 341 base::win::ShortcutProperties dummy_properties; 342 base::FilePath dummy_target; 343 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &dummy_target)); 344 dummy_properties.set_target(dummy_target); 345 dummy_properties.set_working_dir(fake_user_desktop_.path()); 346 dummy_properties.set_arguments(L"--dummy --args"); 347 dummy_properties.set_app_id(L"El.Dummiest"); 348 349 ASSERT_TRUE(base::win::CreateOrUpdateShortcutLink( 350 user_desktop_shortcut_, dummy_properties, 351 base::win::SHORTCUT_CREATE_ALWAYS)); 352 ASSERT_TRUE(base::CreateDirectory(user_start_menu_shortcut_.DirName())); 353 354 installer::CreateOrUpdateShortcuts( 355 chrome_exe_, *product_, *prefs_, installer::CURRENT_USER, 356 installer::INSTALL_SHORTCUT_REPLACE_EXISTING); 357 base::win::ValidateShortcut(user_desktop_shortcut_, expected_properties_); 358 ASSERT_FALSE(base::PathExists(user_quick_launch_shortcut_)); 359 ASSERT_FALSE(base::PathExists(user_start_menu_shortcut_)); 360 } 361 362 TEST_F(InstallShortcutTest, CreateIfNoSystemLevelAllSystemShortcutsExist) { 363 base::win::ShortcutProperties dummy_properties; 364 base::FilePath dummy_target; 365 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &dummy_target)); 366 dummy_properties.set_target(dummy_target); 367 368 ASSERT_TRUE(base::win::CreateOrUpdateShortcutLink( 369 system_desktop_shortcut_, dummy_properties, 370 base::win::SHORTCUT_CREATE_ALWAYS)); 371 ASSERT_TRUE(base::CreateDirectory( 372 system_start_menu_shortcut_.DirName())); 373 ASSERT_TRUE(base::win::CreateOrUpdateShortcutLink( 374 system_start_menu_shortcut_, dummy_properties, 375 base::win::SHORTCUT_CREATE_ALWAYS)); 376 377 installer::CreateOrUpdateShortcuts( 378 chrome_exe_, *product_, *prefs_, installer::CURRENT_USER, 379 installer::INSTALL_SHORTCUT_CREATE_EACH_IF_NO_SYSTEM_LEVEL); 380 ASSERT_FALSE(base::PathExists(user_desktop_shortcut_)); 381 ASSERT_FALSE(base::PathExists(user_start_menu_shortcut_)); 382 // There is no system-level quick launch shortcut, so creating the user-level 383 // one should always succeed. 384 ASSERT_TRUE(base::PathExists(user_quick_launch_shortcut_)); 385 } 386 387 TEST_F(InstallShortcutTest, CreateIfNoSystemLevelNoSystemShortcutsExist) { 388 installer::CreateOrUpdateShortcuts( 389 chrome_exe_, *product_, *prefs_, installer::CURRENT_USER, 390 installer::INSTALL_SHORTCUT_CREATE_EACH_IF_NO_SYSTEM_LEVEL); 391 base::win::ValidateShortcut(user_desktop_shortcut_, expected_properties_); 392 base::win::ValidateShortcut(user_quick_launch_shortcut_, 393 expected_properties_); 394 base::win::ValidateShortcut(user_start_menu_shortcut_, 395 expected_start_menu_properties_); 396 } 397 398 TEST_F(InstallShortcutTest, CreateIfNoSystemLevelSomeSystemShortcutsExist) { 399 base::win::ShortcutProperties dummy_properties; 400 base::FilePath dummy_target; 401 ASSERT_TRUE(base::CreateTemporaryFileInDir(temp_dir_.path(), &dummy_target)); 402 dummy_properties.set_target(dummy_target); 403 404 ASSERT_TRUE(base::win::CreateOrUpdateShortcutLink( 405 system_desktop_shortcut_, dummy_properties, 406 base::win::SHORTCUT_CREATE_ALWAYS)); 407 408 installer::CreateOrUpdateShortcuts( 409 chrome_exe_, *product_, *prefs_, installer::CURRENT_USER, 410 installer::INSTALL_SHORTCUT_CREATE_EACH_IF_NO_SYSTEM_LEVEL); 411 ASSERT_FALSE(base::PathExists(user_desktop_shortcut_)); 412 base::win::ValidateShortcut(user_quick_launch_shortcut_, 413 expected_properties_); 414 base::win::ValidateShortcut(user_start_menu_shortcut_, 415 expected_start_menu_properties_); 416 } 417 418 TEST(EscapeXmlAttributeValueTest, EscapeCrazyValue) { 419 base::string16 val(L"This has 'crazy' \"chars\" && < and > signs."); 420 static const wchar_t kExpectedEscapedVal[] = 421 L"This has 'crazy' \"chars\" && < and > signs."; 422 installer::EscapeXmlAttributeValueInSingleQuotes(&val); 423 ASSERT_STREQ(kExpectedEscapedVal, val.c_str()); 424 } 425 426 TEST(EscapeXmlAttributeValueTest, DontEscapeNormalValue) { 427 base::string16 val(L"Google Chrome"); 428 static const wchar_t kExpectedEscapedVal[] = L"Google Chrome"; 429 installer::EscapeXmlAttributeValueInSingleQuotes(&val); 430 ASSERT_STREQ(kExpectedEscapedVal, val.c_str()); 431 } 432