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