Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(191)

Side by Side Diff: chrome/installer/util/shell_util.cc

Issue 14287008: Refactoring installer shortcut deletion; adding dedicated shortcut update feature. (Closed) Base URL: http://chromium.googlesource.com/chromium/src.git@master
Patch Set: Adding tests for cookie migration code; using SHORTCUT_REPLACE_EXISTING now. Created 7 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 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 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 // 4 //
5 // This file defines functions that integrate Chrome in Windows shell. These 5 // This file defines functions that integrate Chrome in Windows shell. These
6 // functions can be used by Chrome as well as Chrome installer. All of the 6 // functions can be used by Chrome as well as Chrome installer. All of the
7 // work is done by the local functions defined in anonymous namespace in 7 // work is done by the local functions defined in anonymous namespace in
8 // this class. 8 // this class.
9 9
10 #include "chrome/installer/util/shell_util.h" 10 #include "chrome/installer/util/shell_util.h"
11 11
12 #include <windows.h> 12 #include <windows.h>
13 #include <shlobj.h> 13 #include <shlobj.h>
14 14
15 #include <limits> 15 #include <limits>
16 #include <string> 16 #include <string>
17 17
18 #include "base/bind.h"
18 #include "base/command_line.h" 19 #include "base/command_line.h"
19 #include "base/file_util.h" 20 #include "base/file_util.h"
20 #include "base/files/file_path.h" 21 #include "base/files/file_path.h"
21 #include "base/lazy_instance.h" 22 #include "base/lazy_instance.h"
22 #include "base/logging.h" 23 #include "base/logging.h"
23 #include "base/md5.h" 24 #include "base/md5.h"
24 #include "base/memory/scoped_ptr.h" 25 #include "base/memory/scoped_ptr.h"
25 #include "base/memory/scoped_vector.h" 26 #include "base/memory/scoped_vector.h"
26 #include "base/path_service.h" 27 #include "base/path_service.h"
27 #include "base/string16.h" 28 #include "base/string16.h"
(...skipping 1124 matching lines...) Expand 10 before | Expand all | Expand 10 after
1152 const base::win::Version windows_version = base::win::GetVersion(); 1153 const base::win::Version windows_version = base::win::GetVersion();
1153 1154
1154 if (windows_version >= base::win::VERSION_WIN8) 1155 if (windows_version >= base::win::VERSION_WIN8)
1155 return ProbeCurrentDefaultHandlers(protocols, num_protocols); 1156 return ProbeCurrentDefaultHandlers(protocols, num_protocols);
1156 else if (windows_version >= base::win::VERSION_VISTA) 1157 else if (windows_version >= base::win::VERSION_VISTA)
1157 return ProbeAppIsDefaultHandlers(protocols, num_protocols); 1158 return ProbeAppIsDefaultHandlers(protocols, num_protocols);
1158 1159
1159 return ProbeOpenCommandHandlers(protocols, num_protocols); 1160 return ProbeOpenCommandHandlers(protocols, num_protocols);
1160 } 1161 }
1161 1162
1162 // Removes shortcut at |shortcut_path| if it is a shortcut that points to 1163 // (Windows 8+) Returns the folder for app shortcuts, or empty if none found.
1163 // |target_exe|. If |delete_folder| is true, deletes the parent folder of 1164 base::FilePath GetAppShortcutsFolder(BrowserDistribution* dist,
gab 2013/04/29 19:06:36 I feel it would be better to have GetAppShortcutsF
huangs 2013/04/30 03:04:16 Done.
1164 // the shortcut completely. Returns true if either the shortcut was deleted 1165 bool is_user_level) {
1165 // successfully or if the shortcut did not point to |target_exe|. 1166 if (base::win::GetVersion() < base::win::VERSION_WIN8)
1166 bool MaybeRemoveShortcutAtPath(const base::FilePath& shortcut_path, 1167 return base::FilePath();
1167 const base::FilePath& target_exe,
1168 bool delete_folder) {
1169 base::FilePath target_path;
1170 if (!base::win::ResolveShortcut(shortcut_path, &target_path, NULL))
1171 return false;
1172 1168
1173 if (InstallUtil::ProgramCompare(target_exe).EvaluatePath(target_path)) { 1169 base::FilePath folder;
1174 // Unpin the shortcut if it was ever pinned by the user or the installer. 1170 if (!PathService::Get(base::DIR_APP_SHORTCUTS, &folder)) {
1175 VLOG(1) << "Trying to unpin " << shortcut_path.value(); 1171 LOG(ERROR) << "Could not get application shortcuts location.";
1176 if (!base::win::TaskbarUnpinShortcutLink(shortcut_path.value().c_str())) { 1172 return base::FilePath();
1177 VLOG(1) << shortcut_path.value()
1178 << " wasn't pinned (or the unpin failed).";
1179 }
1180 if (delete_folder)
1181 return file_util::Delete(shortcut_path.DirName(), true);
1182 else
1183 return file_util::Delete(shortcut_path, false);
1184 } 1173 }
1185 1174
1186 // The shortcut at |shortcut_path| doesn't point to |target_exe|, act as if 1175 folder = folder.Append(ShellUtil::GetBrowserModelId(dist, is_user_level));
1187 // our shortcut had been deleted. 1176 if (!file_util::DirectoryExists(folder)) {
1177 VLOG(1) << "No start screen shortcuts.";
1178 return base::FilePath();
1179 }
1180
1181 return folder;
1182 }
1183
1184 const wchar_t kAllFiles[] = L"*";
gab 2013/04/29 19:06:36 Rename kAllShortcuts and add the extension (if you
huangs 2013/04/30 03:04:16 Done.
1185
1186 typedef base::Callback<bool(const base::FilePath&)> FileOperationCallback;
1187
1188 // Shortcut operations for BatchShortcutAction().
1189
1190 bool ShortcutOpNone(const base::FilePath& shortcut_path) {
1188 return true; 1191 return true;
1189 } 1192 }
1190 1193
1194 bool ShortcutOpUnpin(const base::FilePath& shortcut_path) {
1195 VLOG(1) << "Trying to unpin " << shortcut_path.value();
1196 if (!base::win::TaskbarUnpinShortcutLink(shortcut_path.value().c_str())) {
1197 VLOG(1) << shortcut_path.value() << " wasn't pinned (or the unpin failed).";
1198 // No error, since shortcut might not be pinned.
1199 }
1200 return true;
1201 }
1202
1203 bool ShortcutOpDelete(const base::FilePath& shortcut_path) {
1204 return file_util::Delete(shortcut_path, false);
1205 }
1206
1207 bool ShortcutOpUnpinAndDelete(const base::FilePath& shortcut_path) {
1208 // Want to try both, without short-circuiting.
1209 bool ret1 = ShortcutOpUnpin(shortcut_path);
1210 bool ret2 = ShortcutOpDelete(shortcut_path);
1211 return ret1 && ret2;
1212 }
1213
1214 bool ShortcutOpSetTarget(const base::FilePath& target_path,
1215 const base::FilePath& shortcut_path) {
1216 base::win::ShortcutProperties shortcut_properties;
1217 shortcut_properties.set_target(target_path);
1218 shortcut_properties.set_working_dir(target_path.DirName());
1219 return base::win::CreateOrUpdateShortcutLink(
1220 shortcut_path, shortcut_properties, base::win::SHORTCUT_REPLACE_EXISTING);
1221 }
1222
1223 // Folder operations for BatchShortcutAction().
1224
1225 bool FolderOpNone(const base::FilePath& folder_path) {
1226 return true;
1227 }
1228
1229 bool FolderOpDelete(const base::FilePath& folder_path) {
1230 return file_util::Delete(folder_path, true);
1231 }
1232
1233 // {|location|, |dist|, |level|} determine |shortcut_folder| to operate in.
1234 // In |shortcut_folder|, iterate over shortcuts that have names matching
1235 // |name_filter|, and have |target_exe| as the target.
gab 2013/04/29 19:06:36 Remove comma (it is only an enumeration of 2 thing
huangs 2013/04/30 03:04:16 Rephrased.
1236 // Applies |opShortcut| on each matching shortcuts, then at the end, applies
1237 // |opFolder| on |shortcut_folder|.
gab 2013/04/29 19:06:36 What about: // Applies |shortcut_operation| on ea
huangs 2013/04/30 03:04:16 Done.
1238 // If |name_filter| is empty, then ignores |opShortcut|; otherwise iterate
1239 // with implicitly ".lnk" suffix. |kAllFiles| is used to specify all shortcuts.
1240 // Returns true iff all operations are successful.
1241 bool BatchShortcutAction(const FileOperationCallback& opShortcut,
gab 2013/04/29 19:06:36 Use underscore casing for variable names, not Came
huangs 2013/04/30 03:04:16 Done (language mix-up :).
1242 const FileOperationCallback& opFolder,
1243 ShellUtil::ShortcutLocation location,
1244 BrowserDistribution* dist,
1245 ShellUtil::ShellChange level,
1246 const base::FilePath& target_exe,
1247 const string16& name_filter) {
1248 base::FilePath shortcut_folder;
1249 if (!ShellUtil::GetShortcutPath(location, dist, level, &shortcut_folder) ||
1250 !file_util::PathExists(shortcut_folder)) {
1251 LOG(ERROR) << "Cannot find path at location " << location;
gab 2013/04/29 19:06:36 This is more an WARNING, then an ERROR imo.
huangs 2013/04/30 03:04:16 Done.
1252 return false;
1253 }
1254
1255 // Operate on specified shortcuts in the folder.
1256 InstallUtil::ProgramCompare target_compare(target_exe);
1257 bool success = true;
1258 if (!name_filter.empty()) {
1259 // Ensure ".lnk" extension.
1260 string16 pattern = name_filter + installer::kLnkExt;
1261 if (!EndsWith(pattern, installer::kLnkExt, false))
gab 2013/04/29 19:06:36 You just added installer::kLnkExt above so it will
huangs 2013/04/30 03:04:16 Ah, good catch! Done.
1262 pattern.append(installer::kLnkExt);
1263 file_util::FileEnumerator enumerator(shortcut_folder, false,
1264 file_util::FileEnumerator::FILES, pattern);
gab 2013/04/29 19:06:36 either indent parameters at the paranthesis or 4 s
huangs 2013/04/30 03:04:16 Done.
1265 for (base::FilePath shortcut_path = enumerator.Next();
1266 !shortcut_path.empty();
1267 shortcut_path = enumerator.Next()) {
1268 base::FilePath target_path;
1269 if (base::win::ResolveShortcut(shortcut_path, &target_path, NULL)) {
1270 if (target_compare.EvaluatePath(target_path)) {
1271 if (!opShortcut.Run(shortcut_path)) {
gab 2013/04/29 19:06:36 Merge this if with the previous one via "&&" (sinc
huangs 2013/04/30 03:04:16 Done.
1272 LOG(ERROR) << "Failed shortcut operation on "
1273 << shortcut_path.value();
1274 success = false;
1275 }
1276 }
1277 } else {
1278 LOG(ERROR) << "Cannot resolve shortcut at " << shortcut_path.value();
1279 success = false;
1280 }
1281 }
1282 }
1283
1284 // Operate on shortcut folder itself.
1285 if (!opFolder.Run(shortcut_folder)) {
1286 LOG(ERROR) << "Failed folder operation on " << shortcut_folder.value();
1287 success = false;
1288 }
1289 return success;
1290 }
1291
1191 } // namespace 1292 } // namespace
1192 1293
1193 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; 1294 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon";
1194 const wchar_t* ShellUtil::kRegShellPath = L"\\shell"; 1295 const wchar_t* ShellUtil::kRegShellPath = L"\\shell";
1195 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command"; 1296 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command";
1196 const wchar_t* ShellUtil::kRegStartMenuInternet = 1297 const wchar_t* ShellUtil::kRegStartMenuInternet =
1197 L"Software\\Clients\\StartMenuInternet"; 1298 L"Software\\Clients\\StartMenuInternet";
1198 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes"; 1299 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes";
1199 const wchar_t* ShellUtil::kRegRegisteredApplications = 1300 const wchar_t* ShellUtil::kRegRegisteredApplications =
1200 L"Software\\RegisteredApplications"; 1301 L"Software\\RegisteredApplications";
(...skipping 62 matching lines...) Expand 10 before | Expand all | Expand 10 after
1263 break; 1364 break;
1264 case SHORTCUT_LOCATION_QUICK_LAUNCH: 1365 case SHORTCUT_LOCATION_QUICK_LAUNCH:
1265 dir_key = (level == CURRENT_USER) ? base::DIR_USER_QUICK_LAUNCH : 1366 dir_key = (level == CURRENT_USER) ? base::DIR_USER_QUICK_LAUNCH :
1266 base::DIR_DEFAULT_USER_QUICK_LAUNCH; 1367 base::DIR_DEFAULT_USER_QUICK_LAUNCH;
1267 break; 1368 break;
1268 case SHORTCUT_LOCATION_START_MENU: 1369 case SHORTCUT_LOCATION_START_MENU:
1269 dir_key = (level == CURRENT_USER) ? base::DIR_START_MENU : 1370 dir_key = (level == CURRENT_USER) ? base::DIR_START_MENU :
1270 base::DIR_COMMON_START_MENU; 1371 base::DIR_COMMON_START_MENU;
1271 add_folder_for_dist = true; 1372 add_folder_for_dist = true;
1272 break; 1373 break;
1374 case SHORTCUT_LOCATION_TASKBAR_PINS:
gab 2013/04/29 19:06:36 I feel this should fail if (base::win::GetVersion(
huangs 2013/04/30 03:04:16 You mean, fail if (base::win::GetVersion() < base:
1375 dir_key = base::DIR_TASKBAR_PINS;
1376 break;
1377 case SHORTCUT_LOCATION_APP_SHORTCUTS: {
1378 base::FilePath ret(GetAppShortcutsFolder(dist, level == CURRENT_USER));
1379 if (!ret.empty())
1380 *path = ret;
1381 return !ret.empty();
1382 }
1273 default: 1383 default:
1274 NOTREACHED(); 1384 NOTREACHED();
1275 return false; 1385 return false;
1276 } 1386 }
1277 1387
1278 if (!PathService::Get(dir_key, path) || path->empty()) { 1388 if (!PathService::Get(dir_key, path) || path->empty()) {
1279 NOTREACHED() << dir_key; 1389 NOTREACHED() << dir_key;
1280 return false; 1390 return false;
1281 } 1391 }
1282 1392
1283 if (add_folder_for_dist) 1393 if (add_folder_for_dist)
1284 *path = path->Append(dist->GetAppShortCutName()); 1394 *path = path->Append(dist->GetAppShortCutName());
1285 1395
1286 return true; 1396 return true;
1287 } 1397 }
1288 1398
1289 bool ShellUtil::CreateOrUpdateShortcut( 1399 bool ShellUtil::CreateOrUpdateShortcut(
1290 ShellUtil::ShortcutLocation location, 1400 ShellUtil::ShortcutLocation location,
1291 BrowserDistribution* dist, 1401 BrowserDistribution* dist,
1292 const ShellUtil::ShortcutProperties& properties, 1402 const ShellUtil::ShortcutProperties& properties,
1293 ShellUtil::ShortcutOperation operation) { 1403 ShellUtil::ShortcutOperation operation) {
1294 DCHECK(dist); 1404 DCHECK(dist);
1295 // |pin_to_taskbar| is only acknowledged when first creating the shortcut. 1405 // |pin_to_taskbar| is only acknowledged when first creating the shortcut.
1296 DCHECK(!properties.pin_to_taskbar || 1406 DCHECK(!properties.pin_to_taskbar ||
1297 operation == SHELL_SHORTCUT_CREATE_ALWAYS || 1407 operation == SHELL_SHORTCUT_CREATE_ALWAYS ||
1298 operation == SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL); 1408 operation == SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL);
1299 1409
1300 base::FilePath user_shortcut_path; 1410 base::FilePath user_shortcut_path;
1301 base::FilePath system_shortcut_path; 1411 base::FilePath system_shortcut_path;
1302 if (!GetShortcutPath(location, dist, SYSTEM_LEVEL, &system_shortcut_path) || 1412 if (!GetShortcutPath(location, dist, SYSTEM_LEVEL, &system_shortcut_path)) {
1303 system_shortcut_path.empty()) {
gab 2013/04/29 19:06:36 GetShortcutPath() is already designed to only retu
huangs 2013/04/30 03:04:16 This IS the original code; my CL already removes t
1304 NOTREACHED(); 1413 NOTREACHED();
1305 return false; 1414 return false;
1306 } 1415 }
1307 1416
1308 string16 shortcut_name(ExtractShortcutNameFromProperties(dist, properties)); 1417 string16 shortcut_name(ExtractShortcutNameFromProperties(dist, properties));
1309 system_shortcut_path = system_shortcut_path.Append(shortcut_name); 1418 system_shortcut_path = system_shortcut_path.Append(shortcut_name);
1310 1419
1311 base::FilePath* chosen_path; 1420 base::FilePath* chosen_path;
1312 bool should_install_shortcut = true; 1421 bool should_install_shortcut = true;
1313 if (properties.level == SYSTEM_LEVEL) { 1422 if (properties.level == SYSTEM_LEVEL) {
1314 // Install the system-level shortcut if requested. 1423 // Install the system-level shortcut if requested.
1315 chosen_path = &system_shortcut_path; 1424 chosen_path = &system_shortcut_path;
1316 } else if (operation != SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL || 1425 } else if (operation != SHELL_SHORTCUT_CREATE_IF_NO_SYSTEM_LEVEL ||
1317 !file_util::PathExists(system_shortcut_path)) { 1426 !file_util::PathExists(system_shortcut_path)) {
1318 // Otherwise install the user-level shortcut, unless the system-level 1427 // Otherwise install the user-level shortcut, unless the system-level
1319 // variant of this shortcut is present on the machine and |operation| states 1428 // variant of this shortcut is present on the machine and |operation| states
1320 // not to create a user-level shortcut in that case. 1429 // not to create a user-level shortcut in that case.
1321 if (!GetShortcutPath(location, dist, CURRENT_USER, &user_shortcut_path) || 1430 if (!GetShortcutPath(location, dist, CURRENT_USER, &user_shortcut_path)) {
1322 user_shortcut_path.empty()) {
1323 NOTREACHED(); 1431 NOTREACHED();
1324 return false; 1432 return false;
1325 } 1433 }
1326 user_shortcut_path = user_shortcut_path.Append(shortcut_name); 1434 user_shortcut_path = user_shortcut_path.Append(shortcut_name);
1327 chosen_path = &user_shortcut_path; 1435 chosen_path = &user_shortcut_path;
1328 } else { 1436 } else {
1329 // Do not install any shortcut if we are told to install a user-level 1437 // Do not install any shortcut if we are told to install a user-level
1330 // shortcut, but the system-level variant of that shortcut is present. 1438 // shortcut, but the system-level variant of that shortcut is present.
1331 // Other actions (e.g., pinning) can still happen with respect to the 1439 // Other actions (e.g., pinning) can still happen with respect to the
1332 // existing system-level shortcut however. 1440 // existing system-level shortcut however.
(...skipping 518 matching lines...) Expand 10 before | Expand all | Expand 10 after
1851 } else if (elevate_if_not_admin && 1959 } else if (elevate_if_not_admin &&
1852 base::win::GetVersion() >= base::win::VERSION_VISTA) { 1960 base::win::GetVersion() >= base::win::VERSION_VISTA) {
1853 // Elevate to do the whole job 1961 // Elevate to do the whole job
1854 return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol); 1962 return ElevateAndRegisterChrome(dist, chrome_exe, suffix, protocol);
1855 } else { 1963 } else {
1856 // Admin rights are required to register capabilities before Windows 8. 1964 // Admin rights are required to register capabilities before Windows 8.
1857 return false; 1965 return false;
1858 } 1966 }
1859 } 1967 }
1860 1968
1969 // static
1970 bool ShellUtil::RemoveShortcutWithName(ShellUtil::ShortcutLocation location,
1971 BrowserDistribution* dist,
1972 ShellChange level,
1973 const base::FilePath& target_path,
1974 const string16& name_filter) {
1975 bool delete_folder = (location == SHORTCUT_LOCATION_START_MENU);
1976 return BatchShortcutAction(
1977 base::Bind(&ShortcutOpUnpinAndDelete),
1978 base::Bind(delete_folder ? &FolderOpDelete : &FolderOpNone),
1979 location, dist, level, target_path, name_filter);
1980 }
1981
1982 // static
1861 bool ShellUtil::RemoveShortcut(ShellUtil::ShortcutLocation location, 1983 bool ShellUtil::RemoveShortcut(ShellUtil::ShortcutLocation location,
gab 2013/04/29 19:06:36 Consider renaming to RemoveShortcutsAtLocation now
huangs 2013/04/30 03:04:16 Moot; removed routine.
1862 BrowserDistribution* dist, 1984 BrowserDistribution* dist,
1863 const base::FilePath& target_exe,
1864 ShellChange level, 1985 ShellChange level,
1865 const string16* shortcut_name) { 1986 const base::FilePath& target_path) {
1866 const bool delete_folder = (location == SHORTCUT_LOCATION_START_MENU); 1987 return ShellUtil::RemoveShortcutWithName(
1867 1988 location, dist, level, target_path, kAllFiles);
1868 base::FilePath shortcut_folder;
1869 if (!GetShortcutPath(location, dist, level, &shortcut_folder) ||
1870 shortcut_folder.empty()) {
1871 NOTREACHED();
1872 return false;
1873 }
1874
1875 if (!delete_folder && !shortcut_name) {
1876 file_util::FileEnumerator enumerator(shortcut_folder, false,
1877 file_util::FileEnumerator::FILES);
1878 bool had_failures = false;
1879 for (base::FilePath path = enumerator.Next(); !path.empty();
1880 path = enumerator.Next()) {
1881 if (path.Extension() != installer::kLnkExt)
1882 continue;
1883
1884 if (!MaybeRemoveShortcutAtPath(path, target_exe, delete_folder))
1885 had_failures = true;
1886 }
1887 return !had_failures;
1888 }
1889
1890 const string16 shortcut_base_name(
1891 (shortcut_name ? *shortcut_name : dist->GetAppShortCutName()) +
1892 installer::kLnkExt);
1893 const base::FilePath shortcut_path(
1894 shortcut_folder.Append(shortcut_base_name));
1895 if (!file_util::PathExists(shortcut_path))
1896 return true;
1897
1898 return MaybeRemoveShortcutAtPath(shortcut_path, target_exe, delete_folder);
1899 } 1989 }
1900 1990
1991 // static
1901 void ShellUtil::RemoveTaskbarShortcuts(const string16& target_exe) { 1992 void ShellUtil::RemoveTaskbarShortcuts(const string16& target_exe) {
gab 2013/04/29 19:06:36 This call and RemoveStartScreenShortcuts() below d
huangs 2013/04/30 03:04:16 Changed routine and the caller. To maintain behavi
1902 if (base::win::GetVersion() < base::win::VERSION_WIN7) 1993 if (base::win::GetVersion() < base::win::VERSION_WIN7)
1903 return; 1994 return;
1904 1995
1905 base::FilePath taskbar_pins_path; 1996 ShortcutLocation location = SHORTCUT_LOCATION_TASKBAR_PINS;
1906 if (!PathService::Get(base::DIR_TASKBAR_PINS, &taskbar_pins_path) || 1997 ShellChange level = ShellUtil::CURRENT_USER;
1907 !file_util::PathExists(taskbar_pins_path)) { 1998 BatchShortcutAction(base::Bind(&ShortcutOpUnpin), base::Bind(&FolderOpNone),
1908 LOG(ERROR) << "Couldn't find path to taskbar pins."; 1999 location, NULL, level, base::FilePath(target_exe),
1909 return; 2000 kAllFiles);
1910 }
1911
1912 file_util::FileEnumerator shortcuts_enum(
1913 taskbar_pins_path, false,
1914 file_util::FileEnumerator::FILES, FILE_PATH_LITERAL("*.lnk"));
1915
1916 base::FilePath target_path(target_exe);
1917 InstallUtil::ProgramCompare target_compare(target_path);
1918 for (base::FilePath shortcut_path = shortcuts_enum.Next();
1919 !shortcut_path.empty();
1920 shortcut_path = shortcuts_enum.Next()) {
1921 base::FilePath read_target;
1922 if (!base::win::ResolveShortcut(shortcut_path, &read_target, NULL)) {
1923 LOG(ERROR) << "Couldn't resolve shortcut at " << shortcut_path.value();
1924 continue;
1925 }
1926 if (target_compare.EvaluatePath(read_target)) {
1927 // Unpin this shortcut if it points to |target_exe|.
1928 base::win::TaskbarUnpinShortcutLink(shortcut_path.value().c_str());
1929 }
1930 }
1931 } 2001 }
1932 2002
2003 // static
1933 void ShellUtil::RemoveStartScreenShortcuts(BrowserDistribution* dist, 2004 void ShellUtil::RemoveStartScreenShortcuts(BrowserDistribution* dist,
1934 const string16& target_exe) { 2005 const string16& target_exe) {
1935 if (base::win::GetVersion() < base::win::VERSION_WIN8) 2006 if (base::win::GetVersion() < base::win::VERSION_WIN8)
1936 return; 2007 return;
1937 2008
1938 base::FilePath app_shortcuts_path; 2009 ShortcutLocation location = SHORTCUT_LOCATION_APP_SHORTCUTS;
1939 if (!PathService::Get(base::DIR_APP_SHORTCUTS, &app_shortcuts_path)) { 2010 ShellChange level = InstallUtil::IsPerUserInstall(target_exe.c_str()) ?
1940 LOG(ERROR) << "Could not get application shortcuts location to delete" 2011 ShellUtil::CURRENT_USER : ShellUtil::SYSTEM_LEVEL;
1941 << " start screen shortcuts."; 2012 VLOG(1) << "Removing start screen shortcuts.";
1942 return; 2013 if (!BatchShortcutAction(base::Bind(&ShortcutOpNone),
gab 2013/04/29 19:06:36 This will still unnecessarily iterate over all sho
huangs 2013/04/30 03:04:16 This won't do useless cycles because |name_filter|
1943 } 2014 base::Bind(&FolderOpDelete),
1944 2015 location, dist, level, base::FilePath(target_exe),
1945 app_shortcuts_path = app_shortcuts_path.Append( 2016 L"")) {
1946 GetBrowserModelId(dist, 2017 LOG(ERROR) << "Failed to remove start screen shortcuts.";
1947 InstallUtil::IsPerUserInstall(target_exe.c_str())));
1948 if (!file_util::DirectoryExists(app_shortcuts_path)) {
1949 VLOG(1) << "No start screen shortcuts to delete.";
1950 return;
1951 }
1952
1953 VLOG(1) << "Removing start screen shortcuts from "
1954 << app_shortcuts_path.value();
1955 if (!file_util::Delete(app_shortcuts_path, true)) {
1956 LOG(ERROR) << "Failed to remove start screen shortcuts from "
1957 << app_shortcuts_path.value();
1958 } 2018 }
1959 } 2019 }
1960 2020
2021 // static
2022 bool ShellUtil::MigrateShortcut(ShellUtil::ShortcutLocation location,
2023 BrowserDistribution* dist,
2024 ShellChange level,
2025 const base::FilePath& old_target_path,
2026 const base::FilePath& new_target_path) {
gab 2013/04/29 19:06:36 A per above comment, change _path to _exe when ref
huangs 2013/04/30 03:04:16 Done.
2027 return BatchShortcutAction(base::Bind(&ShortcutOpSetTarget, new_target_path),
2028 base::Bind(&FolderOpNone),
2029 location, dist, level, old_target_path, kAllFiles);
2030 }
2031
2032 // static
2033 void ShellUtil::MigrateTaskbarShortcuts(const string16& old_target_exe,
2034 const string16& new_target_exe) {
2035 if (base::win::GetVersion() < base::win::VERSION_WIN7)
2036 return;
2037
2038 base::FilePath new_target_path(new_target_exe);
2039 ShortcutLocation location = SHORTCUT_LOCATION_TASKBAR_PINS;
2040 ShellChange level = ShellUtil::CURRENT_USER;
2041 BatchShortcutAction(base::Bind(&ShortcutOpSetTarget, new_target_path),
2042 base::Bind(&FolderOpNone),
2043 location, NULL, level, base::FilePath(old_target_exe),
2044 kAllFiles);
2045 }
2046
2047 // static
2048 void ShellUtil::MigrateStartScreenShortcuts(BrowserDistribution* dist,
2049 const string16& old_target_exe,
2050 const string16& new_target_exe) {
2051 if (base::win::GetVersion() < base::win::VERSION_WIN8)
2052 return;
2053
2054 base::FilePath new_target_path(new_target_exe);
2055 ShortcutLocation location = SHORTCUT_LOCATION_APP_SHORTCUTS;
2056 ShellChange level = InstallUtil::IsPerUserInstall(old_target_exe.c_str()) ?
2057 ShellUtil::CURRENT_USER : ShellUtil::SYSTEM_LEVEL;
2058 VLOG(1) << "Migrating start screen shortcuts.";
2059 if (!BatchShortcutAction(base::Bind(&ShortcutOpSetTarget, new_target_path),
2060 base::Bind(&FolderOpNone), location, dist, level,
2061 base::FilePath(old_target_exe), kAllFiles)) {
2062 LOG(ERROR) << "Failed to migrate start screen shortcuts.";
2063 }
2064
2065 }
2066
1961 bool ShellUtil::GetUserSpecificRegistrySuffix(string16* suffix) { 2067 bool ShellUtil::GetUserSpecificRegistrySuffix(string16* suffix) {
1962 // Use a thread-safe cache for the user's suffix. 2068 // Use a thread-safe cache for the user's suffix.
1963 static base::LazyInstance<UserSpecificRegistrySuffix>::Leaky suffix_instance = 2069 static base::LazyInstance<UserSpecificRegistrySuffix>::Leaky suffix_instance =
1964 LAZY_INSTANCE_INITIALIZER; 2070 LAZY_INSTANCE_INITIALIZER;
1965 return suffix_instance.Get().GetSuffix(suffix); 2071 return suffix_instance.Get().GetSuffix(suffix);
1966 } 2072 }
1967 2073
1968 bool ShellUtil::GetOldUserSpecificRegistrySuffix(string16* suffix) { 2074 bool ShellUtil::GetOldUserSpecificRegistrySuffix(string16* suffix) {
1969 wchar_t user_name[256]; 2075 wchar_t user_name[256];
1970 DWORD size = arraysize(user_name); 2076 DWORD size = arraysize(user_name);
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
2018 // are any left...). 2124 // are any left...).
2019 if (free_bits >= 8 && next_byte_index < size) { 2125 if (free_bits >= 8 && next_byte_index < size) {
2020 free_bits -= 8; 2126 free_bits -= 8;
2021 bit_stream += bytes[next_byte_index++] << free_bits; 2127 bit_stream += bytes[next_byte_index++] << free_bits;
2022 } 2128 }
2023 } 2129 }
2024 2130
2025 DCHECK_EQ(ret.length(), encoded_length); 2131 DCHECK_EQ(ret.length(), encoded_length);
2026 return ret; 2132 return ret;
2027 } 2133 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698