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

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

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