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

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

Issue 164408: Merge 21428 - Allow two user level installs of Chrome to have default browser... (Closed) Base URL: svn://chrome-svn/chrome/branches/195/src/
Patch Set: Created 11 years, 4 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
« no previous file with comments | « chrome/installer/util/shell_util.h ('k') | chrome/installer/util/util_constants.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Property Changes:
Modified: svn:mergeinfo
Merged /trunk/src/chrome/installer/util/shell_util.cc:r21428
OLDNEW
1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2009 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"
11
10 #include <windows.h> 12 #include <windows.h>
11 #include <shellapi.h>
12 #include <shlobj.h> 13 #include <shlobj.h>
13 14
14 #include "chrome/installer/util/shell_util.h"
15
16 #include "base/command_line.h" 15 #include "base/command_line.h"
17 #include "base/file_path.h" 16 #include "base/file_path.h"
18 #include "base/file_util.h" 17 #include "base/file_util.h"
19 #include "base/logging.h" 18 #include "base/logging.h"
20 #include "base/path_service.h"
21 #include "base/registry.h" 19 #include "base/registry.h"
22 #include "base/scoped_ptr.h" 20 #include "base/scoped_ptr.h"
21 #include "base/stl_util-inl.h"
23 #include "base/string_util.h" 22 #include "base/string_util.h"
24 #include "base/win_util.h" 23 #include "base/win_util.h"
25 #include "chrome/common/chrome_constants.h" 24 #include "chrome/common/chrome_constants.h"
26 #include "chrome/common/chrome_switches.h" 25 #include "chrome/common/chrome_switches.h"
27 #include "chrome/installer/util/browser_distribution.h" 26 #include "chrome/installer/util/browser_distribution.h"
28 #include "chrome/installer/util/create_reg_key_work_item.h"
29 #include "chrome/installer/util/install_util.h" 27 #include "chrome/installer/util/install_util.h"
28 #include "chrome/installer/util/l10n_string_util.h"
30 #include "chrome/installer/util/master_preferences.h" 29 #include "chrome/installer/util/master_preferences.h"
31 #include "chrome/installer/util/l10n_string_util.h"
32 #include "chrome/installer/util/set_reg_value_work_item.h" 30 #include "chrome/installer/util/set_reg_value_work_item.h"
33 #include "chrome/installer/util/util_constants.h" 31 #include "chrome/installer/util/util_constants.h"
34 #include "chrome/installer/util/work_item.h" 32 #include "chrome/installer/util/work_item.h"
35 33
36 #include "installer_util_strings.h" 34 #include "installer_util_strings.h"
37 35
38 namespace { 36 namespace {
39 37
40 // This class represents a single registry entry. The objective is to 38 // This class represents a single registry entry. The objective is to
41 // encapsulate all the registry entries required for registering Chrome at one 39 // encapsulate all the registry entries required for registering Chrome at one
42 // place. This class can not be instantiated outside the class and the objects 40 // place. This class can not be instantiated outside the class and the objects
43 // of this class type can be obtained only by calling a static method of this 41 // of this class type can be obtained only by calling a static method of this
44 // class. 42 // class.
45 class RegistryEntry { 43 class RegistryEntry {
46 public: 44 public:
47 // This method returns a list of all the registry entries that are needed 45 // This method returns a list of all the registry entries that
48 // to register Chrome. 46 // are needed to register Chromium ProgIds.
49 static std::list<RegistryEntry*> GetAllEntries( 47 static bool GetProgIdEntries(const std::wstring& chrome_exe,
50 const std::wstring& chrome_exe) { 48 const std::wstring& suffix,
51 std::list<RegistryEntry*> entries; 49 std::list<RegistryEntry*>* entries) {
52 std::wstring icon_path(chrome_exe); 50 std::wstring icon_path = ShellUtil::GetChromeIcon(chrome_exe);
53 ShellUtil::GetChromeIcon(icon_path);
54 std::wstring quoted_exe_path = L"\"" + chrome_exe + L"\"";
55 std::wstring open_cmd = ShellUtil::GetChromeShellOpenCmd(chrome_exe); 51 std::wstring open_cmd = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
56 52
53 // File association ProgId
57 std::wstring chrome_html_prog_id(ShellUtil::kRegClasses); 54 std::wstring chrome_html_prog_id(ShellUtil::kRegClasses);
58 file_util::AppendToPath(&chrome_html_prog_id, ShellUtil::kChromeHTMLProgId); 55 file_util::AppendToPath(&chrome_html_prog_id, ShellUtil::kChromeHTMLProgId);
59 entries.push_front(new RegistryEntry(chrome_html_prog_id, 56 chrome_html_prog_id.append(suffix);
60 ShellUtil::kChromeHTMLProgIdDesc)); 57 entries->push_front(new RegistryEntry(
61 entries.push_front(new RegistryEntry(chrome_html_prog_id, 58 chrome_html_prog_id, ShellUtil::kChromeHTMLProgIdDesc));
62 ShellUtil::kRegUrlProtocol, L"")); 59 entries->push_front(new RegistryEntry(
63 entries.push_front(new RegistryEntry( 60 chrome_html_prog_id, ShellUtil::kRegUrlProtocol, L""));
61 entries->push_front(new RegistryEntry(
64 chrome_html_prog_id + ShellUtil::kRegDefaultIcon, icon_path)); 62 chrome_html_prog_id + ShellUtil::kRegDefaultIcon, icon_path));
65 entries.push_front(new RegistryEntry( 63 entries->push_front(new RegistryEntry(
66 chrome_html_prog_id + ShellUtil::kRegShellOpen, open_cmd)); 64 chrome_html_prog_id + ShellUtil::kRegShellOpen, open_cmd));
67 65
68 std::wstring exe_name = file_util::GetFilenameFromPath(chrome_exe); 66 // Chrome Extension ProgId
69 std::wstring app_key = L"Software\\Classes\\Applications\\" + exe_name + 67 std::wstring ext_prog_id(ShellUtil::kRegClasses);
70 L"\\shell\\open\\command"; 68 file_util::AppendToPath(&ext_prog_id, ShellUtil::kChromeExtProgId);
71 entries.push_front(new RegistryEntry(app_key, open_cmd)); 69 ext_prog_id.append(suffix);
72 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { 70 entries->push_front(new RegistryEntry(
73 std::wstring open_with_key(L"Software\\Classes\\"); 71 ext_prog_id, ShellUtil::kChromeExtProgIdDesc));
74 open_with_key.append(ShellUtil::kFileAssociations[i]); 72 entries->push_front(new RegistryEntry(
75 open_with_key.append(L"\\OpenWithList\\" + exe_name); 73 ext_prog_id + ShellUtil::kRegDefaultIcon, icon_path));
76 entries.push_front(new RegistryEntry(open_with_key, std::wstring()));
77 }
78
79 // Chrome Extension file handler
80 std::wstring install_cmd = 74 std::wstring install_cmd =
81 ShellUtil::GetChromeInstallExtensionCmd(chrome_exe); 75 ShellUtil::GetChromeInstallExtensionCmd(chrome_exe);
82 std::wstring prog_id = std::wstring(L"Software\\Classes\\") + 76 entries->push_front(new RegistryEntry(
83 ShellUtil::kChromeExtProgId; 77 ext_prog_id + ShellUtil::kRegShellOpen, install_cmd));
84 entries.push_front(new RegistryEntry(prog_id, 78
85 ShellUtil::kChromeExtProgIdDesc)); 79 return true;
86 entries.push_front(new RegistryEntry( 80 }
87 prog_id + ShellUtil::kRegDefaultIcon, icon_path)); 81
88 entries.push_front(new RegistryEntry( 82 // This method returns a list of all the system level registry entries that
89 prog_id + ShellUtil::kRegShellOpen, install_cmd)); 83 // are needed to register Chromium on the machine.
84 static bool GetSystemEntries(const std::wstring& chrome_exe,
85 const std::wstring& suffix,
86 std::list<RegistryEntry*>* entries) {
87 std::wstring icon_path = ShellUtil::GetChromeIcon(chrome_exe);
88 std::wstring quoted_exe_path = L"\"" + chrome_exe + L"\"";
90 89
91 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 90 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
91 std::wstring app_name = dist->GetApplicationName() + suffix;
92 std::wstring start_menu_entry(ShellUtil::kRegStartMenuInternet); 92 std::wstring start_menu_entry(ShellUtil::kRegStartMenuInternet);
93 start_menu_entry.append(L"\\" + dist->GetApplicationName()); 93 start_menu_entry.append(L"\\" + app_name);
94 entries.push_front(new RegistryEntry(start_menu_entry, 94 entries->push_front(new RegistryEntry(start_menu_entry, app_name));
95 dist->GetApplicationName())); 95 entries->push_front(new RegistryEntry(
96 entries.push_front(new RegistryEntry(
97 start_menu_entry + ShellUtil::kRegShellOpen, quoted_exe_path)); 96 start_menu_entry + ShellUtil::kRegShellOpen, quoted_exe_path));
98 entries.push_front(new RegistryEntry( 97 entries->push_front(new RegistryEntry(
99 start_menu_entry + ShellUtil::kRegDefaultIcon, icon_path)); 98 start_menu_entry + ShellUtil::kRegDefaultIcon, icon_path));
100 99
101 std::wstring install_info(start_menu_entry + L"\\InstallInfo"); 100 std::wstring install_info(start_menu_entry + L"\\InstallInfo");
102 entries.push_front(new RegistryEntry(install_info, L"ReinstallCommand", 101 entries->push_front(new RegistryEntry(install_info, L"ReinstallCommand",
103 quoted_exe_path + L" --" + switches::kMakeDefaultBrowser)); 102 quoted_exe_path + L" --" + switches::kMakeDefaultBrowser));
104 entries.push_front(new RegistryEntry(install_info, L"HideIconsCommand", 103 entries->push_front(new RegistryEntry(install_info, L"HideIconsCommand",
105 quoted_exe_path + L" --" + switches::kHideIcons)); 104 quoted_exe_path + L" --" + switches::kHideIcons));
106 entries.push_front(new RegistryEntry(install_info, L"ShowIconsCommand", 105 entries->push_front(new RegistryEntry(install_info, L"ShowIconsCommand",
107 quoted_exe_path + L" --" + switches::kShowIcons)); 106 quoted_exe_path + L" --" + switches::kShowIcons));
108 entries.push_front(new RegistryEntry(install_info, L"IconsVisible", 1)); 107 entries->push_front(new RegistryEntry(install_info, L"IconsVisible", 1));
109 108
110 std::wstring capabilities(start_menu_entry + L"\\Capabilities"); 109 std::wstring capabilities(start_menu_entry + L"\\Capabilities");
111 entries.push_front(new RegistryEntry(ShellUtil::kRegRegisteredApplications, 110 entries->push_front(new RegistryEntry(ShellUtil::kRegRegisteredApplications,
112 dist->GetApplicationName(), 111 app_name, capabilities));
113 capabilities)); 112 entries->push_front(new RegistryEntry(
114 entries.push_front(new RegistryEntry(
115 capabilities, L"ApplicationDescription", dist->GetApplicationName())); 113 capabilities, L"ApplicationDescription", dist->GetApplicationName()));
116 entries.push_front(new RegistryEntry( 114 entries->push_front(new RegistryEntry(
117 capabilities, L"ApplicationIcon", icon_path)); 115 capabilities, L"ApplicationIcon", icon_path));
118 entries.push_front(new RegistryEntry( 116 entries->push_front(new RegistryEntry(
119 capabilities, L"ApplicationName", dist->GetApplicationName())); 117 capabilities, L"ApplicationName", app_name));
120 118
121 entries.push_front(new RegistryEntry(capabilities + L"\\StartMenu", 119 entries->push_front(new RegistryEntry(capabilities + L"\\StartMenu",
122 L"StartMenuInternet", dist->GetApplicationName())); 120 L"StartMenuInternet", app_name));
121
122 std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId);
123 html_prog_id.append(suffix);
123 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { 124 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
124 entries.push_front(new RegistryEntry( 125 entries->push_front(new RegistryEntry(
125 capabilities + L"\\FileAssociations", 126 capabilities + L"\\FileAssociations",
126 ShellUtil::kFileAssociations[i], ShellUtil::kChromeHTMLProgId)); 127 ShellUtil::kFileAssociations[i], html_prog_id));
127 } 128 }
128 entries.push_front(new RegistryEntry( 129 for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) {
130 entries->push_front(new RegistryEntry(
131 capabilities + L"\\URLAssociations",
132 ShellUtil::kProtocolAssociations[i], html_prog_id));
133 }
134 std::wstring ext_prog_id(ShellUtil::kChromeExtProgId);
135 ext_prog_id.append(suffix);
136 entries->push_front(new RegistryEntry(
129 capabilities + L"\\FileAssociations", 137 capabilities + L"\\FileAssociations",
130 chrome::kExtensionFileExtension, ShellUtil::kChromeExtProgId)); 138 chrome::kExtensionFileExtension, ext_prog_id));
139
140 FilePath chrome_path(chrome_exe);
141 std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey);
142 file_util::AppendToPath(&app_path_key, chrome_path.BaseName().value());
143 entries->push_front(new RegistryEntry(app_path_key, chrome_exe));
144 entries->push_front(new RegistryEntry(app_path_key,
145 ShellUtil::kAppPathsRegistryPathName, chrome_path.DirName().value()));
146
147 // TODO: add chrome to open with list (Bug 16726).
148 return true;
149 }
150
151 // This method returns a list of all the user level registry entries that
152 // are needed to make Chromium default browser.
153 static bool GetUserEntries(const std::wstring& chrome_exe,
154 const std::wstring& suffix,
155 std::list<RegistryEntry*>* entries) {
156 // File extension associations.
157 std::wstring html_prog_id(ShellUtil::kChromeHTMLProgId);
158 html_prog_id.append(suffix);
159 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) {
160 std::wstring ext_key(ShellUtil::kRegClasses);
161 file_util::AppendToPath(&ext_key, ShellUtil::kFileAssociations[i]);
162 entries->push_front(new RegistryEntry(ext_key, html_prog_id));
163 }
164
165 // .crx file type extension.
166 std::wstring ext_key(ShellUtil::kRegClasses);
167 ext_key.append(L".");
168 ext_key.append(chrome::kExtensionFileExtension);
169 std::wstring ext_prog_id(ShellUtil::kChromeExtProgId);
170 ext_prog_id.append(suffix);
171 entries->push_front(new RegistryEntry(ext_key, ext_prog_id));
172
173 // Protocols associations.
174 std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
175 std::wstring chrome_icon = ShellUtil::GetChromeIcon(chrome_exe);
131 for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) { 176 for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) {
132 entries.push_front(new RegistryEntry( 177 std::wstring url_key(ShellUtil::kRegClasses);
133 capabilities + L"\\URLAssociations", 178 file_util::AppendToPath(&url_key, ShellUtil::kProtocolAssociations[i]);
134 ShellUtil::kProtocolAssociations[i], ShellUtil::kChromeHTMLProgId)); 179
180 // <root hkey>\Software\Classes\<protocol>\DefaultIcon
181 std::wstring icon_key = url_key + ShellUtil::kRegDefaultIcon;
182 entries->push_front(new RegistryEntry(icon_key, chrome_icon));
183
184 // <root hkey>\Software\Classes\<protocol>\shell\open\command
185 std::wstring shell_key = url_key + ShellUtil::kRegShellOpen;
186 entries->push_front(new RegistryEntry(shell_key, chrome_open));
187
188 // <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec
189 std::wstring dde_key = url_key + L"\\shell\\open\\ddeexec";
190 entries->push_front(new RegistryEntry(dde_key, L""));
191
192 // <root hkey>\Software\Classes\<protocol>\shell\@
193 std::wstring protocol_shell_key = url_key + ShellUtil::kRegShellPath;
194 entries->push_front(new RegistryEntry(protocol_shell_key, L"open"));
135 } 195 }
136 return entries; 196
197 // start->Internet shortcut.
198 std::wstring start_menu(ShellUtil::kRegStartMenuInternet);
199 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
200 entries->push_front(new RegistryEntry(start_menu,
201 dist->GetApplicationName()));
202 return true;
137 } 203 }
138 204
139 // Generate work_item tasks required to create current registry entry and 205 // Generate work_item tasks required to create current registry entry and
140 // add them to the given work item list. 206 // add them to the given work item list.
141 void AddToWorkItemList(HKEY root, WorkItemList *items) { 207 void AddToWorkItemList(HKEY root, WorkItemList *items) const {
142 items->AddCreateRegKeyWorkItem(root, _key_path); 208 items->AddCreateRegKeyWorkItem(root, _key_path);
143 if (_is_string) { 209 if (_is_string) {
144 items->AddSetRegValueWorkItem(root, _key_path, _name, _value, true); 210 items->AddSetRegValueWorkItem(root, _key_path, _name, _value, true);
145 } else { 211 } else {
146 items->AddSetRegValueWorkItem(root, _key_path, _name, _int_value, true); 212 items->AddSetRegValueWorkItem(root, _key_path, _name, _int_value, true);
147 } 213 }
148 } 214 }
149 215
150 // Checks if the current registry entry exists in HKLM registry and the value 216 // Checks if the current registry entry exists in HKLM registry and the value
151 // is same. 217 // is same.
152 bool ExistsInHKLM() { 218 bool ExistsInHKLM() const {
153 RegKey key(HKEY_LOCAL_MACHINE, _key_path.c_str()); 219 RegKey key(HKEY_LOCAL_MACHINE, _key_path.c_str());
154 bool found = false; 220 bool found = false;
155 if (_is_string) { 221 if (_is_string) {
156 std::wstring read_value; 222 std::wstring read_value;
157 found = (key.ReadValue(_name.c_str(), &read_value)) && 223 found = (key.ReadValue(_name.c_str(), &read_value)) &&
158 (read_value.size() == _value.size()) && 224 (read_value.size() == _value.size()) &&
159 (std::equal(_value.begin(), _value.end(), read_value.begin(), 225 (std::equal(_value.begin(), _value.end(), read_value.begin(),
160 CaseInsensitiveCompare<wchar_t>())); 226 CaseInsensitiveCompare<wchar_t>()));
161 } else { 227 } else {
162 DWORD read_value; 228 DWORD read_value;
163 found = key.ReadValueDW(_name.c_str(), &read_value) && 229 found = key.ReadValueDW(_name.c_str(), &read_value) &&
164 read_value == _int_value; 230 read_value == _int_value;
165 } 231 }
166 key.Close(); 232 key.Close();
167 return found; 233 return found;
168 } 234 }
169 235
170 // Checks if the current registry entry exists in HKLM registry 236 // Checks if the current registry entry exists in HKLM registry
171 // (only the name). 237 // (only the name).
172 bool NameExistsInHKLM() { 238 bool NameExistsInHKLM() const {
173 RegKey key(HKEY_LOCAL_MACHINE, _key_path.c_str()); 239 RegKey key(HKEY_LOCAL_MACHINE, _key_path.c_str());
174 bool found = false; 240 bool found = false;
175 if (_is_string) { 241 if (_is_string) {
176 std::wstring read_value; 242 std::wstring read_value;
177 found = key.ReadValue(_name.c_str(), &read_value); 243 found = key.ReadValue(_name.c_str(), &read_value);
178 } else { 244 } else {
179 DWORD read_value; 245 DWORD read_value;
180 found = key.ReadValueDW(_name.c_str(), &read_value); 246 found = key.ReadValueDW(_name.c_str(), &read_value);
181 } 247 }
182 key.Close(); 248 key.Close();
183 return found; 249 return found;
184 } 250 }
185 251
186 private: 252 private:
253 DISALLOW_COPY_AND_ASSIGN(RegistryEntry);
254
187 // Create a object that represent default value of a key 255 // Create a object that represent default value of a key
188 RegistryEntry(const std::wstring& key_path, const std::wstring& value) : 256 RegistryEntry(const std::wstring& key_path, const std::wstring& value) :
189 _key_path(key_path), _name(L""), _value(value), 257 _key_path(key_path), _name(L""), _value(value),
190 _is_string(true) { 258 _is_string(true) {
191 } 259 }
192 260
193 // Create a object that represent a key of type REG_SZ 261 // Create a object that represent a key of type REG_SZ
194 RegistryEntry(const std::wstring& key_path, const std::wstring& name, 262 RegistryEntry(const std::wstring& key_path, const std::wstring& name,
195 const std::wstring& value) : _key_path(key_path), 263 const std::wstring& value) : _key_path(key_path),
196 _name(name), _value(value), _is_string(true) { 264 _name(name), _value(value), _is_string(true) {
197 } 265 }
198 266
199 // Create a object that represent a key of integer type 267 // Create a object that represent a key of integer type
200 RegistryEntry(const std::wstring& key_path, const std::wstring& name, 268 RegistryEntry(const std::wstring& key_path, const std::wstring& name,
201 DWORD value) : _key_path(key_path), 269 DWORD value) : _key_path(key_path),
202 _name(name), _int_value(value), _is_string(false) { 270 _name(name), _int_value(value), _is_string(false) {
203 } 271 }
204 272
205 bool _is_string; // true if current registry entry is of type REG_SZ 273 bool _is_string; // true if current registry entry is of type REG_SZ
206 std::wstring _key_path; // key path for the registry entry 274 std::wstring _key_path; // key path for the registry entry
207 std::wstring _name; // name of the registry entry 275 std::wstring _name; // name of the registry entry
208 std::wstring _value; // string value (useful if _is_string = true) 276 std::wstring _value; // string value (useful if _is_string = true)
209 DWORD _int_value; // integer value (useful if _is_string = false) 277 DWORD _int_value; // integer value (useful if _is_string = false)
210 }; // class RegistryEntry 278 }; // class RegistryEntry
211 279
212 280
213 // This method checks if Chrome is already registered on the local machine. 281 // This method converts all the RegistryEntries from the given list to
214 // It gets all the required registry entries for Chrome and then checks if 282 // Set/CreateRegWorkItems and runs them using WorkItemList.
215 // they exist in HKLM. Returns true if all the entries exist, otherwise false. 283 bool AddRegistryEntries(HKEY root, const std::list<RegistryEntry*>& entries) {
216 bool IsChromeRegistered(const std::wstring& chrome_exe) {
217 bool registered = true;
218 std::list<RegistryEntry*> entries = RegistryEntry::GetAllEntries(chrome_exe);
219 for (std::list<RegistryEntry*>::iterator itr = entries.begin();
220 itr != entries.end(); ++itr) {
221 if (registered && !(*itr)->ExistsInHKLM())
222 registered = false;
223 delete (*itr);
224 }
225 LOG(INFO) << "Check for Chrome registration returned " << registered;
226 return registered;
227 }
228
229 bool BindChromeAssociations(HKEY root_key, const std::wstring& chrome_exe) {
230 // Create a list of registry entries to create so that we can rollback
231 // in case of problem.
232 scoped_ptr<WorkItemList> items(WorkItem::CreateWorkItemList()); 284 scoped_ptr<WorkItemList> items(WorkItem::CreateWorkItemList());
233 285
234 // file extension associations 286 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin();
235 std::wstring classes_path(ShellUtil::kRegClasses); 287 itr != entries.end(); ++itr)
236 for (int i = 0; ShellUtil::kFileAssociations[i] != NULL; i++) { 288 (*itr)->AddToWorkItemList(root, items.get());
237 std::wstring key_path = classes_path + L"\\" +
238 ShellUtil::kFileAssociations[i];
239 items->AddCreateRegKeyWorkItem(root_key, key_path);
240 items->AddSetRegValueWorkItem(root_key, key_path, L"",
241 ShellUtil::kChromeHTMLProgId, true);
242 }
243
244 // .crx file type extension
245 std::wstring file_extension_key = classes_path + L"\\." +
246 chrome::kExtensionFileExtension;
247 items->AddCreateRegKeyWorkItem(root_key, file_extension_key);
248 items->AddSetRegValueWorkItem(root_key, file_extension_key, L"",
249 ShellUtil::kChromeExtProgId, true);
250
251
252 // protocols associations
253 std::wstring chrome_open = ShellUtil::GetChromeShellOpenCmd(chrome_exe);
254 std::wstring chrome_icon(chrome_exe);
255 ShellUtil::GetChromeIcon(chrome_icon);
256 for (int i = 0; ShellUtil::kProtocolAssociations[i] != NULL; i++) {
257 std::wstring key_path = classes_path + L"\\" +
258 ShellUtil::kProtocolAssociations[i];
259 // <root hkey>\Software\Classes\<protocol>\DefaultIcon
260 std::wstring icon_path = key_path + ShellUtil::kRegDefaultIcon;
261 items->AddCreateRegKeyWorkItem(root_key, icon_path);
262 items->AddSetRegValueWorkItem(root_key, icon_path, L"",
263 chrome_icon, true);
264 // <root hkey>\Software\Classes\<protocol>\shell\open\command
265 std::wstring shell_path = key_path + ShellUtil::kRegShellOpen;
266 items->AddCreateRegKeyWorkItem(root_key, shell_path);
267 items->AddSetRegValueWorkItem(root_key, shell_path, L"",
268 chrome_open, true);
269 // <root hkey>\Software\Classes\<protocol>\shell\open\ddeexec
270 std::wstring dde_path = key_path + L"\\shell\\open\\ddeexec";
271 items->AddCreateRegKeyWorkItem(root_key, dde_path);
272 items->AddSetRegValueWorkItem(root_key, dde_path, L"", L"", true);
273 // <root hkey>\Software\Classes\<protocol>\shell\@
274 std::wstring protocol_shell_path = key_path + ShellUtil::kRegShellPath;
275 items->AddSetRegValueWorkItem(root_key, protocol_shell_path, L"",
276 L"open", true);
277 }
278
279 // start->Internet shortcut.
280 std::wstring start_internet(ShellUtil::kRegStartMenuInternet);
281 items->AddCreateRegKeyWorkItem(root_key, start_internet);
282 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
283 items->AddSetRegValueWorkItem(root_key, start_internet, L"",
284 dist->GetApplicationName(), true);
285 289
286 // Apply all the registry changes and if there is a problem, rollback 290 // Apply all the registry changes and if there is a problem, rollback
287 if (!items->Do()) { 291 if (!items->Do()) {
288 LOG(ERROR) << "Error while registering Chrome as default browser";
289 items->Rollback(); 292 items->Rollback();
290 return false; 293 return false;
291 } 294 }
292 return true; 295 return true;
293 } 296 }
294 297
295 // Populate work_item_list with WorkItem entries that will add chrome.exe to 298 // This method checks if Chrome is already registered on the local machine.
296 // the set of App Paths registry keys so that ShellExecute can find it. Note 299 // It gets all the required registry entries for Chrome and then checks if
297 // that this is done in HKLM, regardless of whether this is a single-user 300 // they exist in HKLM. Returns true if all the entries exist, otherwise false.
298 // install or not. For non-admin users, this will fail. 301 bool IsChromeRegistered(const std::wstring& chrome_exe,
299 // chrome_exe: full path to chrome.exe 302 const std::wstring& suffix) {
300 // work_item_list: pointer to the WorkItemList that will be populated 303 bool registered = true;
301 void AddChromeAppPathWorkItems(const std::wstring& chrome_exe, 304 std::list<RegistryEntry*> entries;
302 WorkItemList* item_list) { 305 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
303 FilePath chrome_path(chrome_exe); 306 RegistryEntry::GetProgIdEntries(chrome_exe, suffix, &entries);
304 std::wstring app_path_key(ShellUtil::kAppPathsRegistryKey); 307 RegistryEntry::GetSystemEntries(chrome_exe, suffix, &entries);
305 file_util::AppendToPath(&app_path_key, chrome_path.BaseName().value()); 308 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin();
306 item_list->AddCreateRegKeyWorkItem(HKEY_LOCAL_MACHINE, app_path_key); 309 itr != entries.end() && registered; ++itr) {
307 item_list->AddSetRegValueWorkItem(HKEY_LOCAL_MACHINE, app_path_key, L"", 310 // We do not need registered = registered && ... since the loop condition
308 chrome_exe, true); 311 // is set to exit early.
309 item_list->AddSetRegValueWorkItem(HKEY_LOCAL_MACHINE, app_path_key, 312 registered = (*itr)->ExistsInHKLM();
310 ShellUtil::kAppPathsRegistryPathName, 313 }
311 chrome_path.DirName().value(), true); 314 return registered;
312 } 315 }
313 316
314 // This method creates the registry entries required for Add/Remove Programs-> 317 // This method registers Chrome on Vista by launching eleavated setup.exe.
315 // Set Program Access and Defaults, Start->Default Programs on Windows Vista 318 // That will show user standard Vista elevation prompt. If user accepts it
316 // and Chrome ProgIds for file extension and protocol handler. root_key is 319 // the new process will make the necessary changes and return SUCCESS that
317 // the root registry (HKLM or HKCU). 320 // we capture and return.
318 bool SetAccessDefaultRegEntries(HKEY root_key, 321 bool ElevateAndRegisterChrome(const std::wstring& chrome_exe,
319 const std::wstring& chrome_exe) { 322 const std::wstring& suffix) {
320 LOG(INFO) << "Registering Chrome browser " << chrome_exe; 323 std::wstring exe_path(file_util::GetDirectoryFromPath(chrome_exe));
321 // Create a list of registry entries work items so that we can rollback 324 file_util::AppendToPath(&exe_path, installer_util::kSetupExe);
322 // in case of problem. 325 if (!file_util::PathExists(exe_path)) {
323 scoped_ptr<WorkItemList> items(WorkItem::CreateWorkItemList()); 326 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
327 HKEY reg_root = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ?
328 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
329 RegKey key(reg_root, dist->GetUninstallRegPath().c_str());
330 key.ReadValue(installer_util::kUninstallStringField, &exe_path);
331 CommandLine command_line(L"");
332 command_line.ParseFromString(exe_path);
333 exe_path = command_line.program();
334 }
335 if (file_util::PathExists(exe_path)) {
336 std::wstring params(L"--");
337 params.append(installer_util::switches::kRegisterChromeBrowser);
338 params.append(L"=\"" + chrome_exe + L"\"");
339 if (!suffix.empty()) {
340 params.append(L"--");
341 params.append(installer_util::switches::kRegisterChromeBrowserSuffix);
342 params.append(L"=\"" + suffix + L"\"");
343 }
344 DWORD ret_val = 0;
345 InstallUtil::ExecuteExeAsAdmin(exe_path, params, &ret_val);
346 if (ret_val == 0)
347 return true;
348 }
349 return false;
350 }
324 351
325 std::list<RegistryEntry*> entries = RegistryEntry::GetAllEntries(chrome_exe); 352 // This method checks if user specific default browser registry entry exists.
326 for (std::list<RegistryEntry*>::iterator itr = entries.begin(); 353 // (i.e. Software\Clients\StartMenuInternet\Chromium.<user>)
327 itr != entries.end(); ++itr) { 354 bool UserSpecificDefaultBrowserEntryExists() {
328 (*itr)->AddToWorkItemList(root_key, items.get()); 355 std::wstring suffix;
329 delete (*itr); 356 if (!ShellUtil::GetUserSpecificDefaultBrowserSuffix(&suffix))
357 return false;
358
359 std::wstring start_menu_entry(ShellUtil::kRegStartMenuInternet);
360 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
361 start_menu_entry.append(L"\\" + dist->GetApplicationName() + suffix);
362 RegKey key(HKEY_LOCAL_MACHINE, start_menu_entry.c_str());
363 return key.Valid();
364 }
365
366 // This method tries to figure out if another user has already registered her
367 // own copy of Chrome so that we can avoid overwriting it and append current
368 // user's login name to default browser registry entries. This function is
369 // not meant to detect all cases. It just tries to handle the most common case.
370 // All the conditions below have to be true for it to return true:
371 // - Software\Clients\StartMenuInternet\Chromium\"" key should have a valid
372 // value.
373 // - The value should not be same as given value in |chrome_exe|
374 // - Finally to handle the default install path (C:\Document and Settings\
375 // <user>\Local Settings\Application Data\Chromium\Application) the value
376 // of the above key should differ from |chrome_exe| only in user name.
377 bool AnotherUserHasDefaultBrowser(const std::wstring& chrome_exe) {
378 std::wstring reg_key(ShellUtil::kRegStartMenuInternet);
379 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
380 reg_key.append(L"\\" + dist->GetApplicationName() + ShellUtil::kRegShellOpen);
381 RegKey key(HKEY_LOCAL_MACHINE, reg_key.c_str());
382 std::wstring registry_chrome_exe;
383 if (!key.ReadValue(L"", &registry_chrome_exe) ||
384 registry_chrome_exe.length() < 2)
385 return false;
386
387 registry_chrome_exe = registry_chrome_exe.substr(1,
388 registry_chrome_exe.length() - 2);
389 if ((registry_chrome_exe.size() == chrome_exe.size()) &&
390 (std::equal(chrome_exe.begin(), chrome_exe.end(),
391 registry_chrome_exe.begin(),
392 CaseInsensitiveCompare<wchar_t>())))
393 return false;
394
395 std::vector<std::wstring> v1, v2;
396 SplitString(registry_chrome_exe, L'\\', &v1);
397 SplitString(chrome_exe, L'\\', &v2);
398 if (v1.size() == 0 || v2.size() == 0 || v1.size() != v2.size())
399 return false;
400
401 // Now check that only one of the values within two '\' chars differ.
402 std::vector<std::wstring>::iterator itr1 = v1.begin();
403 std::vector<std::wstring>::iterator itr2 = v2.begin();
404 bool one_mismatch = false;
405 for ( ; itr1 < v1.end() && itr2 < v2.end(); ++itr1, ++itr2) {
406 std::wstring s1 = *itr1;
407 std::wstring s2 = *itr2;
408 if ((s1.size() != s2.size()) ||
409 (!std::equal(s1.begin(), s1.end(),
410 s2.begin(), CaseInsensitiveCompare<wchar_t>()))) {
411 if (one_mismatch)
412 return false;
413 else
414 one_mismatch = true;
415 }
330 } 416 }
331
332 // Append the App Paths registry entries. Do this only if we are an admin,
333 // since they are always written to HKLM.
334 if (IsUserAnAdmin())
335 AddChromeAppPathWorkItems(chrome_exe, items.get());
336
337 // Apply all the registry changes and if there is a problem, rollback.
338 if (!items->Do()) {
339 LOG(ERROR) << "Failed to add Chrome to Set Program Access and Defaults";
340 items->Rollback();
341 return false;
342 }
343
344 return true; 417 return true;
345 } 418 }
346 419
347
348 // This method registers Chrome on Vista. It checks if we are currently
349 // running as admin and if not, it launches setup.exe as administrator which
350 // will show user standard Vista elevation prompt. If user accepts it
351 // the new process will make the necessary changes and return SUCCESS that
352 // we capture and return.
353 ShellUtil::RegisterStatus RegisterOnVista(const std::wstring& chrome_exe,
354 bool skip_if_not_admin) {
355 if (IsUserAnAdmin() &&
356 SetAccessDefaultRegEntries(HKEY_LOCAL_MACHINE, chrome_exe))
357 return ShellUtil::SUCCESS;
358
359 if (!skip_if_not_admin) {
360 std::wstring exe_path(file_util::GetDirectoryFromPath(chrome_exe));
361 file_util::AppendToPath(&exe_path, installer_util::kSetupExe);
362 if (!file_util::PathExists(exe_path)) {
363 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
364 HKEY reg_root = InstallUtil::IsPerUserInstall(chrome_exe.c_str()) ?
365 HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
366 RegKey key(reg_root, dist->GetUninstallRegPath().c_str());
367 key.ReadValue(installer_util::kUninstallStringField, &exe_path);
368 CommandLine command_line(L"");
369 command_line.ParseFromString(exe_path);
370 exe_path = command_line.program();
371 }
372 if (file_util::PathExists(exe_path)) {
373 std::wstring params(L"--");
374 params.append(installer_util::switches::kRegisterChromeBrowser);
375 params.append(L"=\"" + chrome_exe + L"\"");
376 DWORD ret_val = ShellUtil::SUCCESS;
377 InstallUtil::ExecuteExeAsAdmin(exe_path, params, &ret_val);
378 if (ret_val == ShellUtil::SUCCESS)
379 return ShellUtil::SUCCESS;
380 }
381 }
382 return ShellUtil::FAILURE;
383 }
384
385 } // namespace 420 } // namespace
386 421
387 422
388 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon"; 423 const wchar_t* ShellUtil::kRegDefaultIcon = L"\\DefaultIcon";
389 const wchar_t* ShellUtil::kRegShellPath = L"\\shell"; 424 const wchar_t* ShellUtil::kRegShellPath = L"\\shell";
390 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command"; 425 const wchar_t* ShellUtil::kRegShellOpen = L"\\shell\\open\\command";
391 const wchar_t* ShellUtil::kRegStartMenuInternet = 426 const wchar_t* ShellUtil::kRegStartMenuInternet =
392 L"Software\\Clients\\StartMenuInternet"; 427 L"Software\\Clients\\StartMenuInternet";
393 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes"; 428 const wchar_t* ShellUtil::kRegClasses = L"Software\\Classes";
394 const wchar_t* ShellUtil::kRegRegisteredApplications = 429 const wchar_t* ShellUtil::kRegRegisteredApplications =
395 L"Software\\RegisteredApplications"; 430 L"Software\\RegisteredApplications";
396 const wchar_t* ShellUtil::kRegVistaUrlPrefs = 431 const wchar_t* ShellUtil::kRegVistaUrlPrefs =
397 L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\" 432 L"Software\\Microsoft\\Windows\\Shell\\Associations\\UrlAssociations\\"
398 L"http\\UserChoice"; 433 L"http\\UserChoice";
399 const wchar_t* ShellUtil::kAppPathsRegistryKey = 434 const wchar_t* ShellUtil::kAppPathsRegistryKey =
400 L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths"; 435 L"Software\\Microsoft\\Windows\\CurrentVersion\\App Paths";
401 const wchar_t* ShellUtil::kAppPathsRegistryPathName = L"Path"; 436 const wchar_t* ShellUtil::kAppPathsRegistryPathName = L"Path";
402 437
403 #if defined(GOOGLE_CHROME_BUILD) 438 #if defined(GOOGLE_CHROME_BUILD)
404 const wchar_t* ShellUtil::kChromeExtProgId = L"ChromeExt"; 439 const wchar_t* ShellUtil::kChromeExtProgId = L"ChromeExt";
405 const wchar_t* ShellUtil::kChromeHTMLProgId = L"ChromeHTML"; 440 const wchar_t* ShellUtil::kChromeHTMLProgId = L"ChromeHTML";
406 const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chrome HTML"; 441 const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chrome HTML Document";
407 #else 442 #else
408 const wchar_t* ShellUtil::kChromeExtProgId = L"ChromiumExt"; 443 const wchar_t* ShellUtil::kChromeExtProgId = L"ChromiumExt";
409 const wchar_t* ShellUtil::kChromeHTMLProgId = L"ChromiumHTML"; 444 const wchar_t* ShellUtil::kChromeHTMLProgId = L"ChromiumHTML";
410 const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chromium HTML"; 445 const wchar_t* ShellUtil::kChromeHTMLProgIdDesc = L"Chromium HTML Document";
411 #endif 446 #endif
412 447
413 const wchar_t* ShellUtil::kFileAssociations[] = {L".htm", L".html", L".shtml", 448 const wchar_t* ShellUtil::kFileAssociations[] = {L".htm", L".html", L".shtml",
414 L".xht", L".xhtml", NULL}; 449 L".xht", L".xhtml", NULL};
415 const wchar_t* ShellUtil::kProtocolAssociations[] = {L"ftp", L"http", L"https", 450 const wchar_t* ShellUtil::kProtocolAssociations[] = {L"ftp", L"http", L"https",
416 NULL}; 451 NULL};
417 const wchar_t* ShellUtil::kRegUrlProtocol = L"URL Protocol"; 452 const wchar_t* ShellUtil::kRegUrlProtocol = L"URL Protocol";
418 453
419 const wchar_t* ShellUtil::kChromeExtProgIdDesc = L"Chrome Extension Installer"; 454 const wchar_t* ShellUtil::kChromeExtProgIdDesc = L"Chrome Extension Installer";
420 455
421 ShellUtil::RegisterStatus ShellUtil::AddChromeToSetAccessDefaults(
422 const std::wstring& chrome_exe, bool skip_if_not_admin) {
423 if (IsChromeRegistered(chrome_exe))
424 return ShellUtil::SUCCESS;
425
426 if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA)
427 return RegisterOnVista(chrome_exe, skip_if_not_admin);
428
429 // Try adding these entries to HKLM first and if that fails try adding
430 // to HKCU.
431 if (SetAccessDefaultRegEntries(HKEY_LOCAL_MACHINE, chrome_exe))
432 return ShellUtil::SUCCESS;
433
434 if (!skip_if_not_admin &&
435 SetAccessDefaultRegEntries(HKEY_CURRENT_USER, chrome_exe))
436 return ShellUtil::REGISTERED_PER_USER;
437
438 return ShellUtil::FAILURE;
439 }
440
441 bool ShellUtil::AdminNeededForRegistryCleanup() { 456 bool ShellUtil::AdminNeededForRegistryCleanup() {
442 bool cleanup_needed = false; 457 bool cleanup_needed = false;
443 std::list<RegistryEntry*> entries = RegistryEntry::GetAllEntries( 458 std::list<RegistryEntry*> entries;
444 installer_util::kChromeExe); 459 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
445 for (std::list<RegistryEntry*>::iterator itr = entries.begin(); 460 RegistryEntry::GetProgIdEntries(L"chrome.exe", L"", &entries);
446 itr != entries.end(); ++itr) { 461 RegistryEntry::GetSystemEntries(L"chrome.exe", L"", &entries);
447 if (!cleanup_needed && (*itr)->NameExistsInHKLM()) 462
448 cleanup_needed = true; 463 std::wstring suffix;
449 delete (*itr); 464 GetUserSpecificDefaultBrowserSuffix(&suffix);
465 RegistryEntry::GetProgIdEntries(L"chrome.exe", suffix, &entries);
466 RegistryEntry::GetSystemEntries(L"chrome.exe", suffix, &entries);
467 for (std::list<RegistryEntry*>::const_iterator itr = entries.begin();
468 itr != entries.end() && !cleanup_needed; ++itr) {
469 cleanup_needed = (*itr)->NameExistsInHKLM();
450 } 470 }
451 return cleanup_needed; 471 return cleanup_needed;
452 } 472 }
453 473
454 bool ShellUtil::GetChromeIcon(std::wstring& chrome_icon) {
455 if (chrome_icon.empty())
456 return false;
457
458 chrome_icon.append(L",0");
459 return true;
460 }
461
462 std::wstring ShellUtil::GetChromeShellOpenCmd(const std::wstring& chrome_exe) {
463 return L"\"" + chrome_exe + L"\" -- \"%1\"";
464 }
465
466 std::wstring ShellUtil::GetChromeInstallExtensionCmd(
467 const std::wstring& chrome_exe) {
468 return L"\"" + chrome_exe + L"\" --install-extension=\"%1\"";
469 }
470
471 bool ShellUtil::GetChromeShortcutName(std::wstring* shortcut, bool alternate) {
472 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
473 shortcut->assign(alternate ? dist->GetAlternateApplicationName() :
474 dist->GetApplicationName());
475 shortcut->append(L".lnk");
476 return true;
477 }
478
479 bool ShellUtil::GetDesktopPath(bool system_level, std::wstring* path) {
480 wchar_t desktop[MAX_PATH];
481 int dir = system_level ? CSIDL_COMMON_DESKTOPDIRECTORY :
482 CSIDL_DESKTOPDIRECTORY;
483 if (FAILED(SHGetFolderPath(NULL, dir, NULL, SHGFP_TYPE_CURRENT, desktop)))
484 return false;
485 *path = desktop;
486 return true;
487 }
488
489 bool ShellUtil::GetQuickLaunchPath(bool system_level, std::wstring* path) {
490 const static wchar_t* kQuickLaunchPath =
491 L"Microsoft\\Internet Explorer\\Quick Launch";
492 wchar_t qlaunch[MAX_PATH];
493 if (system_level) {
494 // We are accessing GetDefaultUserProfileDirectory this way so that we do
495 // not have to declare dependency to Userenv.lib for chrome.exe
496 typedef BOOL (WINAPI *PROFILE_FUNC)(LPWSTR, LPDWORD);
497 HMODULE module = LoadLibrary(L"Userenv.dll");
498 PROFILE_FUNC p = reinterpret_cast<PROFILE_FUNC>(GetProcAddress(module,
499 "GetDefaultUserProfileDirectoryW"));
500 DWORD size = _countof(qlaunch);
501 if ((p == NULL) || ((p)(qlaunch, &size) != TRUE))
502 return false;
503 *path = qlaunch;
504 if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
505 file_util::AppendToPath(path, L"AppData\\Roaming");
506 } else {
507 file_util::AppendToPath(path, L"Application Data");
508 }
509 } else {
510 if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL,
511 SHGFP_TYPE_CURRENT, qlaunch)))
512 return false;
513 *path = qlaunch;
514 }
515 file_util::AppendToPath(path, kQuickLaunchPath);
516 return true;
517 }
518
519 bool ShellUtil::CreateChromeDesktopShortcut(const std::wstring& chrome_exe, 474 bool ShellUtil::CreateChromeDesktopShortcut(const std::wstring& chrome_exe,
520 const std::wstring& description, 475 const std::wstring& description,
521 int shell_change, bool alternate, 476 int shell_change, bool alternate,
522 bool create_new) { 477 bool create_new) {
523 std::wstring shortcut_name; 478 std::wstring shortcut_name;
524 if (!ShellUtil::GetChromeShortcutName(&shortcut_name, alternate)) 479 if (!ShellUtil::GetChromeShortcutName(&shortcut_name, alternate))
525 return false; 480 return false;
526 481
527 bool ret = true; 482 bool ret = true;
528 if (shell_change & ShellUtil::CURRENT_USER) { 483 if (shell_change & ShellUtil::CURRENT_USER) {
(...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after
579 ret = ShellUtil::UpdateChromeShortcut(chrome_exe, default_ql_path, 534 ret = ShellUtil::UpdateChromeShortcut(chrome_exe, default_ql_path,
580 L"", create_new) && ret; 535 L"", create_new) && ret;
581 } else { 536 } else {
582 ret = false; 537 ret = false;
583 } 538 }
584 } 539 }
585 540
586 return ret; 541 return ret;
587 } 542 }
588 543
544 std::wstring ShellUtil::GetChromeIcon(const std::wstring& chrome_exe) {
545 std::wstring chrome_icon(chrome_exe);
546 chrome_icon.append(L",0");
547 return chrome_icon;
548 }
549
550 std::wstring ShellUtil::GetChromeInstallExtensionCmd(
551 const std::wstring& chrome_exe) {
552 return L"\"" + chrome_exe + L"\" --install-extension=\"%1\"";
553 }
554
555 std::wstring ShellUtil::GetChromeShellOpenCmd(const std::wstring& chrome_exe) {
556 return L"\"" + chrome_exe + L"\" -- \"%1\"";
557 }
558
559 bool ShellUtil::GetChromeShortcutName(std::wstring* shortcut, bool alternate) {
560 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
561 shortcut->assign(alternate ? dist->GetAlternateApplicationName() :
562 dist->GetApplicationName());
563 shortcut->append(L".lnk");
564 return true;
565 }
566
567 bool ShellUtil::GetDesktopPath(bool system_level, std::wstring* path) {
568 wchar_t desktop[MAX_PATH];
569 int dir = system_level ? CSIDL_COMMON_DESKTOPDIRECTORY :
570 CSIDL_DESKTOPDIRECTORY;
571 if (FAILED(SHGetFolderPath(NULL, dir, NULL, SHGFP_TYPE_CURRENT, desktop)))
572 return false;
573 *path = desktop;
574 return true;
575 }
576
577 bool ShellUtil::GetQuickLaunchPath(bool system_level, std::wstring* path) {
578 const static wchar_t* kQuickLaunchPath =
579 L"Microsoft\\Internet Explorer\\Quick Launch";
580 wchar_t qlaunch[MAX_PATH];
581 if (system_level) {
582 // We are accessing GetDefaultUserProfileDirectory this way so that we do
583 // not have to declare dependency to Userenv.lib for chrome.exe
584 typedef BOOL (WINAPI *PROFILE_FUNC)(LPWSTR, LPDWORD);
585 HMODULE module = LoadLibrary(L"Userenv.dll");
586 PROFILE_FUNC p = reinterpret_cast<PROFILE_FUNC>(GetProcAddress(module,
587 "GetDefaultUserProfileDirectoryW"));
588 DWORD size = _countof(qlaunch);
589 if ((p == NULL) || ((p)(qlaunch, &size) != TRUE))
590 return false;
591 *path = qlaunch;
592 if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
593 file_util::AppendToPath(path, L"AppData\\Roaming");
594 } else {
595 file_util::AppendToPath(path, L"Application Data");
596 }
597 } else {
598 if (FAILED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL,
599 SHGFP_TYPE_CURRENT, qlaunch)))
600 return false;
601 *path = qlaunch;
602 }
603 file_util::AppendToPath(path, kQuickLaunchPath);
604 return true;
605 }
606
607 bool ShellUtil::GetUserSpecificDefaultBrowserSuffix(std::wstring* entry) {
608 wchar_t user_name[256];
609 DWORD size = _countof(user_name);
610 if (::GetUserName(user_name, &size) == 0)
611 return false;
612 entry->assign(L".");
613 entry->append(user_name);
614 return true;
615 }
616
589 bool ShellUtil::MakeChromeDefault(int shell_change, 617 bool ShellUtil::MakeChromeDefault(int shell_change,
590 const std::wstring chrome_exe) { 618 const std::wstring& chrome_exe,
619 bool elevate_if_not_admin) {
620 ShellUtil::RegisterChromeBrowser(chrome_exe, L"", elevate_if_not_admin);
621
591 bool ret = true; 622 bool ret = true;
592 // First use the new "recommended" way on Vista to make Chrome default 623 // First use the new "recommended" way on Vista to make Chrome default
593 // browser. 624 // browser.
594 if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) { 625 if (win_util::GetWinVersion() >= win_util::WINVERSION_VISTA) {
595 LOG(INFO) << "Registering Chrome as default browser on Vista."; 626 LOG(INFO) << "Registering Chrome as default browser on Vista.";
596 IApplicationAssociationRegistration* pAAR; 627 IApplicationAssociationRegistration* pAAR;
597 HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration, 628 HRESULT hr = CoCreateInstance(CLSID_ApplicationAssociationRegistration,
598 NULL, CLSCTX_INPROC, __uuidof(IApplicationAssociationRegistration), 629 NULL, CLSCTX_INPROC, __uuidof(IApplicationAssociationRegistration),
599 (void**)&pAAR); 630 (void**)&pAAR);
600 if (SUCCEEDED(hr)) { 631 if (SUCCEEDED(hr)) {
601 BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 632 BrowserDistribution* dist = BrowserDistribution::GetDistribution();
602 hr = pAAR->SetAppAsDefaultAll(dist->GetApplicationName().c_str()); 633 hr = pAAR->SetAppAsDefaultAll(dist->GetApplicationName().c_str());
603 pAAR->Release(); 634 pAAR->Release();
604 } 635 }
605 if (!SUCCEEDED(hr)) { 636 if (!SUCCEEDED(hr)) {
606 ret = false; 637 ret = false;
607 LOG(ERROR) << "Could not make Chrome default browser."; 638 LOG(ERROR) << "Could not make Chrome default browser.";
608 } 639 }
609 } 640 }
610 641
611 // Now use the old way to associate Chrome with supported protocols and file 642 // Now use the old way to associate Chrome with supported protocols and file
612 // associations. This should not be required on Vista but since some 643 // associations. This should not be required on Vista but since some
613 // applications still read Software\Classes\http key directly, we have to do 644 // applications still read Software\Classes\http key directly, we have to do
614 // this on Vista also. 645 // this on Vista also.
646
647 std::list<RegistryEntry*> entries;
648 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
649 std::wstring suffix;
650 if (UserSpecificDefaultBrowserEntryExists())
651 GetUserSpecificDefaultBrowserSuffix(&suffix);
652 RegistryEntry::GetUserEntries(chrome_exe, suffix, &entries);
615 // Change the default browser for current user. 653 // Change the default browser for current user.
616 if ((shell_change & ShellUtil::CURRENT_USER) && 654 if ((shell_change & ShellUtil::CURRENT_USER) &&
617 !BindChromeAssociations(HKEY_CURRENT_USER, chrome_exe)) 655 !AddRegistryEntries(HKEY_CURRENT_USER, entries))
618 ret = false; 656 ret = false;
619 657
620 // Chrome as default browser at system level. 658 // Chrome as default browser at system level.
621 if ((shell_change & ShellUtil::SYSTEM_LEVEL) && 659 if ((shell_change & ShellUtil::SYSTEM_LEVEL) &&
622 !BindChromeAssociations(HKEY_LOCAL_MACHINE, chrome_exe)) 660 !AddRegistryEntries(HKEY_LOCAL_MACHINE, entries))
623 ret = false; 661 ret = false;
624 662
625 // Send Windows notification event so that it can update icons for 663 // Send Windows notification event so that it can update icons for
626 // file associations. 664 // file associations.
627 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL); 665 SHChangeNotify(SHCNE_ASSOCCHANGED, SHCNF_IDLIST, NULL, NULL);
628 return ret; 666 return ret;
629 } 667 }
630 668
669 bool ShellUtil::RegisterChromeBrowser(const std::wstring& chrome_exe,
670 const std::wstring& unique_suffix,
671 bool elevate_if_not_admin) {
672 // First figure out we need to append a suffix to the registry entries to
673 // make them unique.
674 std::wstring suffix;
675 if (!unique_suffix.empty()) {
676 suffix = unique_suffix;
677 } else if (InstallUtil::IsPerUserInstall(chrome_exe.c_str()) &&
678 (UserSpecificDefaultBrowserEntryExists() ||
679 AnotherUserHasDefaultBrowser(chrome_exe))) {
680 GetUserSpecificDefaultBrowserSuffix(&suffix);
681 }
682
683 // Check if Chromium is already registered with this suffix.
684 if (IsChromeRegistered(chrome_exe, suffix))
685 return true;
686
687 // If user is an admin try to register and return the status.
688 if (IsUserAnAdmin()) {
689 std::list<RegistryEntry*> entries;
690 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
691 RegistryEntry::GetProgIdEntries(chrome_exe, suffix, &entries);
692 RegistryEntry::GetSystemEntries(chrome_exe, suffix, &entries);
693 return AddRegistryEntries(HKEY_LOCAL_MACHINE, entries);
694 }
695
696 // If user is not an admin and OS is Vista, try to elevate and register.
697 if (elevate_if_not_admin &&
698 win_util::GetWinVersion() >= win_util::WINVERSION_VISTA &&
699 ElevateAndRegisterChrome(chrome_exe, suffix))
700 return true;
701
702 // If we got to this point then all we can do is create ProgIds under HKCU
703 // on XP as well as Vista.
704 std::list<RegistryEntry*> entries;
705 STLElementDeleter<std::list<RegistryEntry*>> entries_deleter(&entries);
706 RegistryEntry::GetProgIdEntries(chrome_exe, L"", &entries);
707 return AddRegistryEntries(HKEY_CURRENT_USER, entries);
708 }
709
631 bool ShellUtil::RemoveChromeDesktopShortcut(int shell_change, bool alternate) { 710 bool ShellUtil::RemoveChromeDesktopShortcut(int shell_change, bool alternate) {
632 std::wstring shortcut_name; 711 std::wstring shortcut_name;
633 if (!ShellUtil::GetChromeShortcutName(&shortcut_name, alternate)) 712 if (!ShellUtil::GetChromeShortcutName(&shortcut_name, alternate))
634 return false; 713 return false;
635 714
636 bool ret = true; 715 bool ret = true;
637 if (shell_change & ShellUtil::CURRENT_USER) { 716 if (shell_change & ShellUtil::CURRENT_USER) {
638 std::wstring shortcut_path; 717 std::wstring shortcut_path;
639 if (ShellUtil::GetDesktopPath(false, &shortcut_path)) { 718 if (ShellUtil::GetDesktopPath(false, &shortcut_path)) {
640 file_util::AppendToPath(&shortcut_path, shortcut_name); 719 file_util::AppendToPath(&shortcut_path, shortcut_name);
(...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after
712 } else { 791 } else {
713 return file_util::UpdateShortcutLink(chrome_exe.c_str(), // target 792 return file_util::UpdateShortcutLink(chrome_exe.c_str(), // target
714 shortcut.c_str(), // shortcut 793 shortcut.c_str(), // shortcut
715 chrome_path.c_str(), // working dir 794 chrome_path.c_str(), // working dir
716 NULL, // arguments 795 NULL, // arguments
717 description.c_str(), // description 796 description.c_str(), // description
718 chrome_exe.c_str(), // icon file 797 chrome_exe.c_str(), // icon file
719 0); // icon index 798 0); // icon index
720 } 799 }
721 } 800 }
OLDNEW
« no previous file with comments | « chrome/installer/util/shell_util.h ('k') | chrome/installer/util/util_constants.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698