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

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

Issue 11127002: Move "default for protocol" probing logic out of shell_integration_win.cc into shell_util.cc. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: better order in enum Created 8 years, 2 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 | Annotate | Revision Log
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"
(...skipping 13 matching lines...) Expand all
24 #include "base/memory/scoped_ptr.h" 24 #include "base/memory/scoped_ptr.h"
25 #include "base/memory/scoped_vector.h" 25 #include "base/memory/scoped_vector.h"
26 #include "base/path_service.h" 26 #include "base/path_service.h"
27 #include "base/string16.h" 27 #include "base/string16.h"
28 #include "base/string_number_conversions.h" 28 #include "base/string_number_conversions.h"
29 #include "base/string_split.h" 29 #include "base/string_split.h"
30 #include "base/string_util.h" 30 #include "base/string_util.h"
31 #include "base/utf_string_conversions.h" 31 #include "base/utf_string_conversions.h"
32 #include "base/values.h" 32 #include "base/values.h"
33 #include "base/win/registry.h" 33 #include "base/win/registry.h"
34 #include "base/win/scoped_co_mem.h"
34 #include "base/win/scoped_comptr.h" 35 #include "base/win/scoped_comptr.h"
35 #include "base/win/shortcut.h" 36 #include "base/win/shortcut.h"
36 #include "base/win/win_util.h" 37 #include "base/win/win_util.h"
37 #include "base/win/windows_version.h" 38 #include "base/win/windows_version.h"
38 #include "chrome/common/chrome_constants.h" 39 #include "chrome/common/chrome_constants.h"
39 #include "chrome/common/chrome_switches.h" 40 #include "chrome/common/chrome_switches.h"
40 #include "chrome/installer/util/browser_distribution.h" 41 #include "chrome/installer/util/browser_distribution.h"
41 #include "chrome/installer/util/install_util.h" 42 #include "chrome/installer/util/install_util.h"
42 #include "chrome/installer/util/master_preferences.h" 43 #include "chrome/installer/util/master_preferences.h"
43 #include "chrome/installer/util/master_preferences_constants.h" 44 #include "chrome/installer/util/master_preferences_constants.h"
(...skipping 964 matching lines...) Expand 10 before | Expand all | Expand 10 after
1008 shortcut_properties.set_app_id( 1009 shortcut_properties.set_app_id(
1009 ShellUtil::GetBrowserModelId(dist, is_per_user_install)); 1010 ShellUtil::GetBrowserModelId(dist, is_per_user_install));
1010 } 1011 }
1011 1012
1012 if (properties.has_dual_mode()) 1013 if (properties.has_dual_mode())
1013 shortcut_properties.set_dual_mode(properties.dual_mode); 1014 shortcut_properties.set_dual_mode(properties.dual_mode);
1014 1015
1015 return shortcut_properties; 1016 return shortcut_properties;
1016 } 1017 }
1017 1018
1019 // Gets the short (8.3) form of |path|, putting the result in |short_path| and
1020 // returning true on success. |short_path| is not modified on failure.
1021 bool ShortNameFromPath(const FilePath& path, string16* short_path) {
1022 DCHECK(short_path);
1023 string16 result(MAX_PATH, L'\0');
1024 DWORD short_length = GetShortPathName(path.value().c_str(), &result[0],
1025 result.size());
1026 if (short_length == 0 || short_length > result.size()) {
1027 PLOG(ERROR) << "Error getting short (8.3) path";
1028 return false;
1029 }
1030
1031 result.resize(short_length);
1032 short_path->swap(result);
1033 return true;
1034 }
1035
1036 // Probe using IApplicationAssociationRegistration::QueryCurrentDefault
1037 // (Windows 8); see ProbeProtocolHandlers. This mechanism is not suitable for
1038 // use on previous versions of Windows despite the presence of
1039 // QueryCurrentDefault on them since versions of Windows prior to Windows 8
1040 // did not perform validation on the ProgID registered as the current default.
1041 // As a result, stale ProgIDs could be returned, leading to false positives.
1042 ShellUtil::DefaultState ProbeCurrentDefaultHandlers(
1043 const wchar_t* const* protocols,
1044 size_t num_protocols) {
1045 base::win::ScopedComPtr<IApplicationAssociationRegistration> registration;
1046 HRESULT hr = registration.CreateInstance(
1047 CLSID_ApplicationAssociationRegistration, NULL, CLSCTX_INPROC);
1048 if (FAILED(hr))
1049 return ShellUtil::UNKNOWN_DEFAULT;
1050
1051 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
1052 FilePath chrome_exe;
1053 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
1054 NOTREACHED();
1055 return ShellUtil::UNKNOWN_DEFAULT;
1056 }
1057 string16 prog_id(ShellUtil::kChromeHTMLProgId);
1058 prog_id += ShellUtil::GetCurrentInstallationSuffix(dist, chrome_exe.value());
1059
1060 for (size_t i = 0; i < num_protocols; ++i) {
1061 base::win::ScopedCoMem<wchar_t> current_app;
1062 hr = registration->QueryCurrentDefault(protocols[i], AT_URLPROTOCOL,
1063 AL_EFFECTIVE, &current_app);
1064 if (FAILED(hr) || prog_id.compare(current_app) != 0)
1065 return ShellUtil::NOT_DEFAULT;
1066 }
1067
1068 return ShellUtil::IS_DEFAULT;
1069 }
1070
1071 // Probe using IApplicationAssociationRegistration::QueryAppIsDefault (Vista and
1072 // Windows 7); see ProbeProtocolHandlers.
1073 ShellUtil::DefaultState ProbeAppIsDefaultHandlers(
1074 const wchar_t* const* protocols,
1075 size_t num_protocols) {
1076 base::win::ScopedComPtr<IApplicationAssociationRegistration> registration;
1077 HRESULT hr = registration.CreateInstance(
1078 CLSID_ApplicationAssociationRegistration, NULL, CLSCTX_INPROC);
1079 if (FAILED(hr))
1080 return ShellUtil::UNKNOWN_DEFAULT;
1081
1082 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
1083 FilePath chrome_exe;
1084 if (!PathService::Get(base::FILE_EXE, &chrome_exe)) {
1085 NOTREACHED();
1086 return ShellUtil::UNKNOWN_DEFAULT;
1087 }
1088 string16 app_name(ShellUtil::GetApplicationName(dist, chrome_exe.value()));
1089
1090 BOOL result;
1091 for (size_t i = 0; i < num_protocols; ++i) {
1092 result = TRUE;
1093 hr = registration->QueryAppIsDefault(protocols[i], AT_URLPROTOCOL,
1094 AL_EFFECTIVE, app_name.c_str(), &result);
1095 if (FAILED(hr) || result == FALSE)
1096 return ShellUtil::NOT_DEFAULT;
1097 }
1098
1099 return ShellUtil::IS_DEFAULT;
1100 }
1101
1102 // Probe the current commands registered to handle the shell "open" verb for
1103 // |protocols| (Windows XP); see ProbeProtocolHandlers.
1104 ShellUtil::DefaultState ProbeOpenCommandHandlers(
1105 const wchar_t* const* protocols,
1106 size_t num_protocols) {
1107 // Get the path to the current exe (Chrome).
1108 FilePath app_path;
1109 if (!PathService::Get(base::FILE_EXE, &app_path)) {
1110 LOG(ERROR) << "Error getting app exe path";
1111 return ShellUtil::UNKNOWN_DEFAULT;
1112 }
1113
1114 // Get its short (8.3) form.
1115 string16 short_app_path;
1116 if (!ShortNameFromPath(app_path, &short_app_path))
1117 return ShellUtil::UNKNOWN_DEFAULT;
M-A Ruel 2015/10/14 20:08:04 This code is incorrect; it's possible that a path
gab 2015/10/14 20:32:07 This CL moved this code from shell_integration_win
Mark P 2015/10/14 22:07:19 Filed bug https://code.google.com/p/chromium/issue
1118
1119 const HKEY root_key = HKEY_CLASSES_ROOT;
1120 string16 key_path;
1121 base::win::RegKey key;
1122 string16 value;
1123 CommandLine command_line(CommandLine::NO_PROGRAM);
1124 string16 short_path;
1125
1126 for (size_t i = 0; i < num_protocols; ++i) {
1127 // Get the command line from HKCU\<protocol>\shell\open\command.
1128 key_path.assign(protocols[i]).append(ShellUtil::kRegShellOpen);
1129 if ((key.Open(root_key, key_path.c_str(),
1130 KEY_QUERY_VALUE) != ERROR_SUCCESS) ||
1131 (key.ReadValue(L"", &value) != ERROR_SUCCESS)) {
1132 return ShellUtil::NOT_DEFAULT;
1133 }
1134
1135 // Need to normalize path in case it's been munged.
1136 command_line = CommandLine::FromString(value);
1137 if (!ShortNameFromPath(command_line.GetProgram(), &short_path))
1138 return ShellUtil::UNKNOWN_DEFAULT;
1139
1140 if (!FilePath::CompareEqualIgnoreCase(short_path, short_app_path))
1141 return ShellUtil::NOT_DEFAULT;
1142 }
1143
1144 return ShellUtil::IS_DEFAULT;
1145 }
1146
1147 // A helper function that probes default protocol handler registration (in a
1148 // manner appropriate for the current version of Windows) to determine if
1149 // Chrome is the default handler for |protocols|. Returns IS_DEFAULT_WEB_CLIENT
1150 // only if Chrome is the default for all specified protocols.
1151 ShellUtil::DefaultState ProbeProtocolHandlers(
1152 const wchar_t* const* protocols,
1153 size_t num_protocols) {
1154 DCHECK(!num_protocols || protocols);
1155 if (DCHECK_IS_ON()) {
1156 for (size_t i = 0; i < num_protocols; ++i)
1157 DCHECK(protocols[i] && *protocols[i]);
1158 }
1159
1160 const base::win::Version windows_version = base::win::GetVersion();
1161
1162 if (windows_version >= base::win::VERSION_WIN8)
1163 return ProbeCurrentDefaultHandlers(protocols, num_protocols);
1164 else if (windows_version >= base::win::VERSION_VISTA)
1165 return ProbeAppIsDefaultHandlers(protocols, num_protocols);
1166
1167 return ProbeOpenCommandHandlers(protocols, num_protocols);
1168 }
1169
1018 } // namespace 1170 } // namespace
1019 1171
1020 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; 1172 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon";
1021 const wchar_t* ShellUtil::kRegShellPath = L"\\shell"; 1173 const wchar_t* ShellUtil::kRegShellPath = L"\\shell";
1022 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command"; 1174 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command";
1023 const wchar_t* ShellUtil::kRegStartMenuInternet = 1175 const wchar_t* ShellUtil::kRegStartMenuInternet =
1024 L"Software\\Clients\\StartMenuInternet"; 1176 L"Software\\Clients\\StartMenuInternet";
1025 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes"; 1177 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes";
1026 const wchar_t* ShellUtil::kRegRegisteredApplications = 1178 const wchar_t* ShellUtil::kRegRegisteredApplications =
1027 L"Software\\RegisteredApplications"; 1179 L"Software\\RegisteredApplications";
(...skipping 301 matching lines...) Expand 10 before | Expand all | Expand 10 after
1329 string16::npos); 1481 string16::npos);
1330 } else { 1482 } else {
1331 app_id.append(component); 1483 app_id.append(component);
1332 } 1484 }
1333 } 1485 }
1334 // No spaces are allowed in the AppUserModelId according to MSDN. 1486 // No spaces are allowed in the AppUserModelId according to MSDN.
1335 ReplaceChars(app_id, L" ", L"_", &app_id); 1487 ReplaceChars(app_id, L" ", L"_", &app_id);
1336 return app_id; 1488 return app_id;
1337 } 1489 }
1338 1490
1491 ShellUtil::DefaultState ShellUtil::IsChromeDefault() {
1492 // When we check for default browser we don't necessarily want to count file
1493 // type handlers and icons as having changed the default browser status,
1494 // since the user may have changed their shell settings to cause HTML files
1495 // to open with a text editor for example. We also don't want to aggressively
1496 // claim FTP, since the user may have a separate FTP client. It is an open
1497 // question as to how to "heal" these settings. Perhaps the user should just
1498 // re-run the installer or run with the --set-default-browser command line
1499 // flag. There is doubtless some other key we can hook into to cause "Repair"
1500 // to show up in Add/Remove programs for us.
1501 static const wchar_t* const kChromeProtocols[] = { L"http", L"https" };
1502 return ProbeProtocolHandlers(kChromeProtocols, arraysize(kChromeProtocols));
1503 }
1504
1505 ShellUtil::DefaultState ShellUtil::IsChromeDefaultProtocolClient(
1506 const string16& protocol) {
1507 if (protocol.empty())
1508 return UNKNOWN_DEFAULT;
1509
1510 const wchar_t* const protocols[] = { protocol.c_str() };
1511 return ProbeProtocolHandlers(protocols, arraysize(protocols));
1512 }
1513
1339 // static 1514 // static
1340 bool ShellUtil::CanMakeChromeDefaultUnattended() { 1515 bool ShellUtil::CanMakeChromeDefaultUnattended() {
1341 return base::win::GetVersion() < base::win::VERSION_WIN8; 1516 return base::win::GetVersion() < base::win::VERSION_WIN8;
1342 } 1517 }
1343 1518
1344 bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist, 1519 bool ShellUtil::MakeChromeDefault(BrowserDistribution* dist,
1345 int shell_change, 1520 int shell_change,
1346 const string16& chrome_exe, 1521 const string16& chrome_exe,
1347 bool elevate_if_not_admin) { 1522 bool elevate_if_not_admin) {
1348 DCHECK(!(shell_change & ShellUtil::SYSTEM_LEVEL) || IsUserAnAdmin()); 1523 DCHECK(!(shell_change & ShellUtil::SYSTEM_LEVEL) || IsUserAnAdmin());
(...skipping 387 matching lines...) Expand 10 before | Expand all | Expand 10 after
1736 // are any left...). 1911 // are any left...).
1737 if (free_bits >= 8 && next_byte_index < size) { 1912 if (free_bits >= 8 && next_byte_index < size) {
1738 free_bits -= 8; 1913 free_bits -= 8;
1739 bit_stream += bytes[next_byte_index++] << free_bits; 1914 bit_stream += bytes[next_byte_index++] << free_bits;
1740 } 1915 }
1741 } 1916 }
1742 1917
1743 DCHECK_EQ(ret.length(), encoded_length); 1918 DCHECK_EQ(ret.length(), encoded_length);
1744 return ret; 1919 return ret;
1745 } 1920 }
OLDNEW
« chrome/browser/shell_integration_win.cc ('K') | « chrome/installer/util/shell_util.h ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698