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

Side by Side Diff: chrome/browser/first_run/first_run_win.cc

Issue 10837222: Enable EULA dialog to be shown from metro Chrome. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Bit o' spit n' polish. Created 8 years, 3 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "chrome/browser/first_run/first_run.h" 5 #include "chrome/browser/first_run/first_run.h"
6 6
7 #include <shellapi.h>
7 #include <shlobj.h> 8 #include <shlobj.h>
8 #include <windows.h> 9 #include <windows.h>
9 10
10 #include "base/environment.h" 11 #include "base/environment.h"
11 #include "base/file_util.h" 12 #include "base/file_util.h"
12 #include "base/path_service.h" 13 #include "base/path_service.h"
13 #include "base/process_util.h" 14 #include "base/process_util.h"
14 #include "base/string_number_conversions.h" 15 #include "base/string_number_conversions.h"
15 #include "base/string_split.h" 16 #include "base/string_split.h"
16 #include "base/stringprintf.h" 17 #include "base/stringprintf.h"
17 #include "base/utf_string_conversions.h" 18 #include "base/utf_string_conversions.h"
19 #include "base/win/metro.h"
18 #include "base/win/object_watcher.h" 20 #include "base/win/object_watcher.h"
19 #include "base/win/windows_version.h" 21 #include "base/win/windows_version.h"
20 #include "chrome/browser/browser_process.h" 22 #include "chrome/browser/browser_process.h"
21 #include "chrome/browser/extensions/extension_service.h" 23 #include "chrome/browser/extensions/extension_service.h"
22 #include "chrome/browser/extensions/updater/extension_updater.h" 24 #include "chrome/browser/extensions/updater/extension_updater.h"
23 #include "chrome/browser/first_run/first_run_import_observer.h" 25 #include "chrome/browser/first_run/first_run_import_observer.h"
24 #include "chrome/browser/first_run/first_run_internal.h" 26 #include "chrome/browser/first_run/first_run_internal.h"
25 #include "chrome/browser/importer/importer_host.h" 27 #include "chrome/browser/importer/importer_host.h"
26 #include "chrome/browser/importer/importer_list.h" 28 #include "chrome/browser/importer/importer_list.h"
27 #include "chrome/browser/importer/importer_progress_dialog.h" 29 #include "chrome/browser/importer/importer_progress_dialog.h"
(...skipping 17 matching lines...) Expand all
45 #include "content/public/browser/notification_service.h" 47 #include "content/public/browser/notification_service.h"
46 #include "content/public/browser/user_metrics.h" 48 #include "content/public/browser/user_metrics.h"
47 #include "google_update/google_update_idl.h" 49 #include "google_update/google_update_idl.h"
48 #include "grit/chromium_strings.h" 50 #include "grit/chromium_strings.h"
49 #include "grit/generated_resources.h" 51 #include "grit/generated_resources.h"
50 #include "grit/locale_settings.h" 52 #include "grit/locale_settings.h"
51 #include "grit/theme_resources.h" 53 #include "grit/theme_resources.h"
52 #include "ui/base/l10n/l10n_util.h" 54 #include "ui/base/l10n/l10n_util.h"
53 #include "ui/base/layout.h" 55 #include "ui/base/layout.h"
54 #include "ui/base/ui_base_switches.h" 56 #include "ui/base/ui_base_switches.h"
57 #include "ui/base/win/shell.h"
55 58
56 namespace { 59 namespace {
57 60
58 const char kEULASentinelFile[] = "EULA Accepted";
59
60 // Helper class that performs delayed first-run tasks that need more of the 61 // Helper class that performs delayed first-run tasks that need more of the
61 // chrome infrastructure to be up and running before they can be attempted. 62 // chrome infrastructure to be up and running before they can be attempted.
62 class FirstRunDelayedTasks : public content::NotificationObserver { 63 class FirstRunDelayedTasks : public content::NotificationObserver {
63 public: 64 public:
64 enum Tasks { 65 enum Tasks {
65 NO_TASK, 66 NO_TASK,
66 INSTALL_EXTENSIONS 67 INSTALL_EXTENSIONS
67 }; 68 };
68 69
69 explicit FirstRunDelayedTasks(Tasks task) { 70 explicit FirstRunDelayedTasks(Tasks task) {
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after
137 } 138 }
138 139
139 void PlatformSetup(Profile* profile) { 140 void PlatformSetup(Profile* profile) {
140 CreateChromeDesktopShortcut(); 141 CreateChromeDesktopShortcut();
141 142
142 // Windows 7 has deprecated the quick launch bar. 143 // Windows 7 has deprecated the quick launch bar.
143 if (base::win::GetVersion() < base::win::VERSION_WIN7) 144 if (base::win::GetVersion() < base::win::VERSION_WIN7)
144 CreateChromeQuickLaunchShortcut(); 145 CreateChromeQuickLaunchShortcut();
145 } 146 }
146 147
147 // Launches the setup exe with the given parameter/value on the command-line, 148 // Launches the setup exe with the given parameter/value on the command-line.
148 // waits for its termination, returns its exit code in |*ret_code|, and 149 // For non-metro Windows, it waits for its termination, returns its exit code
149 // returns true if the exit code is valid. 150 // in |*ret_code|, and returns true if the exit code is valid.
150 bool LaunchSetupWithParam(const std::string& param, 151 // For metro Windows, it launches setup via ShellExecuteEx and returns in order
151 const FilePath::StringType& value, 152 // to bounce the user back to the desktop, then returns immediately.
152 int* ret_code) { 153 bool LaunchSetupForEula(const FilePath::StringType& value, int* ret_code) {
153 FilePath exe_path; 154 FilePath exe_dir;
154 if (!PathService::Get(base::DIR_MODULE, &exe_path)) 155 if (!PathService::Get(base::DIR_MODULE, &exe_dir))
155 return false; 156 return false;
156 exe_path = exe_path.Append(installer::kInstallerDir); 157 exe_dir = exe_dir.Append(installer::kInstallerDir);
157 exe_path = exe_path.Append(installer::kSetupExe); 158 FilePath exe_path = exe_dir.Append(installer::kSetupExe);
158 base::ProcessHandle ph; 159 base::ProcessHandle ph;
159 CommandLine cl(exe_path); 160
160 cl.AppendSwitchNative(param, value); 161 CommandLine cl(CommandLine::NO_PROGRAM);
162 cl.AppendSwitchNative(installer::switches::kShowEula, value);
161 163
162 CommandLine* browser_command_line = CommandLine::ForCurrentProcess(); 164 CommandLine* browser_command_line = CommandLine::ForCurrentProcess();
163 if (browser_command_line->HasSwitch(switches::kChromeFrame)) { 165 if (browser_command_line->HasSwitch(switches::kChromeFrame)) {
164 cl.AppendSwitch(switches::kChromeFrame); 166 cl.AppendSwitch(switches::kChromeFrame);
165 } 167 }
166 168
167 // TODO(evan): should this use options.wait = true? 169 if (base::win::IsMetroProcess()) {
168 if (!base::LaunchProcess(cl, base::LaunchOptions(), &ph)) 170 cl.AppendSwitch(installer::switches::kShowEulaForMetro);
171
172 // This obscure use of the 'log usage' mask for windows 8 is documented
173 // here http://goo.gl/HBOe9. It causes the desktop process to receive
grt (UTC plus 2) 2012/09/20 15:58:31 please link to the current version of the MS doc r
robertshield 2012/09/21 01:24:43 Done.
174 // focus. Pass SEE_MASK_FLAG_NO_UI to avoid hangs if an error occurs since
175 // the UI can't be shown from a metro process.
176 ui::win::OpenAnyViaShell(exe_path.value(),
177 exe_dir.value(),
178 cl.GetCommandLineString(),
179 SEE_MASK_FLAG_LOG_USAGE | SEE_MASK_FLAG_NO_UI);
169 return false; 180 return false;
170 DWORD wr = ::WaitForSingleObject(ph, INFINITE); 181 } else {
171 if (wr != WAIT_OBJECT_0) 182 base::LaunchOptions launch_options;
172 return false; 183 launch_options.wait = true;
173 return (TRUE == ::GetExitCodeProcess(ph, reinterpret_cast<DWORD*>(ret_code))); 184 CommandLine setup_path(exe_path);
185 setup_path.AppendArguments(cl, false);
186
187 if (!base::LaunchProcess(setup_path, launch_options, &ph))
188 return false;
189 return (
190 TRUE == ::GetExitCodeProcess(ph, reinterpret_cast<DWORD*>(ret_code)));
grt (UTC plus 2) 2012/09/20 15:58:31 1. please COMPILE_ASSERT(sizeof(*ret_code) == size
robertshield 2012/09/21 01:24:43 Done.
191 }
174 } 192 }
175 193
176 // Populates |path| with the path to |file| in the sentinel directory. This is 194 // Populates |path| with the path to |file| in the sentinel directory. This is
177 // the application directory for user-level installs, and the default user data 195 // the application directory for user-level installs, and the default user data
178 // dir for system-level installs. Returns false on error. 196 // dir for system-level installs. Returns false on error.
179 bool GetSentinelFilePath(const char* file, FilePath* path) { 197 bool GetSentinelFilePath(const char* file, FilePath* path) {
180 FilePath exe_path; 198 FilePath exe_path;
181 if (!PathService::Get(base::DIR_EXE, &exe_path)) 199 if (!PathService::Get(base::DIR_EXE, &exe_path))
182 return false; 200 return false;
183 if (InstallUtil::IsPerUserInstall(exe_path.value().c_str())) 201 if (InstallUtil::IsPerUserInstall(exe_path.value().c_str()))
184 *path = exe_path; 202 *path = exe_path;
185 else if (!PathService::Get(chrome::DIR_USER_DATA, path)) 203 else if (!PathService::Get(chrome::DIR_USER_DATA, path))
186 return false; 204 return false;
187 205
188 *path = path->AppendASCII(file); 206 *path = path->AppendASCII(file);
189 return true; 207 return true;
190 } 208 }
191 209
192 bool GetEULASentinelFilePath(FilePath* path) { 210 bool GetEULASentinelFilePath(FilePath* path) {
193 return GetSentinelFilePath(kEULASentinelFile, path); 211 return GetSentinelFilePath(installer::kEULASentinelFile, path);
194 } 212 }
195 213
196 // Returns true if the EULA is required but has not been accepted by this user. 214 // Returns true if the EULA is required but has not been accepted by this user.
197 // The EULA is considered having been accepted if the user has gotten past 215 // The EULA is considered having been accepted if the user has gotten past
198 // first run in the "other" environment (desktop or metro). 216 // first run in the "other" environment (desktop or metro).
199 bool IsEULANotAccepted(installer::MasterPreferences* install_prefs) { 217 bool IsEULANotAccepted(installer::MasterPreferences* install_prefs) {
200 bool value = false; 218 bool value = false;
201 if (install_prefs->GetBool(installer::master_preferences::kRequireEula, 219 if (install_prefs->GetBool(installer::master_preferences::kRequireEula,
202 &value) && value) { 220 &value) && value) {
203 FilePath eula_sentinel; 221 FilePath eula_sentinel;
(...skipping 23 matching lines...) Expand all
227 245
228 // Creates the sentinel indicating that the EULA was required and has been 246 // Creates the sentinel indicating that the EULA was required and has been
229 // accepted. 247 // accepted.
230 bool CreateEULASentinel() { 248 bool CreateEULASentinel() {
231 FilePath eula_sentinel; 249 FilePath eula_sentinel;
232 if (!GetEULASentinelFilePath(&eula_sentinel)) 250 if (!GetEULASentinelFilePath(&eula_sentinel))
233 return false; 251 return false;
234 return file_util::WriteFile(eula_sentinel, "", 0) != -1; 252 return file_util::WriteFile(eula_sentinel, "", 0) != -1;
235 } 253 }
236 254
237 void ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) { 255 // Shows the EULA dialog if required. Returns true if the EULA is accepted,
256 // returns false if the EULA has not been accepted, in which case the browser
257 // should exit.
258 bool ShowPostInstallEULAIfNeeded(installer::MasterPreferences* install_prefs) {
238 if (IsEULANotAccepted(install_prefs)) { 259 if (IsEULANotAccepted(install_prefs)) {
239 // Show the post-installation EULA. This is done by setup.exe and the 260 // Show the post-installation EULA. This is done by setup.exe and the
240 // result determines if we continue or not. We wait here until the user 261 // result determines if we continue or not. We wait here until the user
241 // dismisses the dialog. 262 // dismisses the dialog.
242 263
243 // The actual eula text is in a resource in chrome. We extract it to 264 // The actual eula text is in a resource in chrome. We extract it to
244 // a text file so setup.exe can use it as an inner frame. 265 // a text file so setup.exe can use it as an inner frame.
245 FilePath inner_html; 266 FilePath inner_html;
246 if (WriteEULAtoTempFile(&inner_html)) { 267 if (WriteEULAtoTempFile(&inner_html)) {
247 int retcode = 0; 268 int retcode = 0;
248 if (!LaunchSetupWithParam(installer::switches::kShowEula, 269 if (!LaunchSetupForEula(inner_html.value(), &retcode) ||
249 inner_html.value(), &retcode) ||
250 (retcode != installer::EULA_ACCEPTED && 270 (retcode != installer::EULA_ACCEPTED &&
251 retcode != installer::EULA_ACCEPTED_OPT_IN)) { 271 retcode != installer::EULA_ACCEPTED_OPT_IN)) {
252 LOG(WARNING) << "EULA rejected. Fast exit."; 272 LOG(WARNING) << "EULA flow requires fast exit.";
253 ::ExitProcess(1); 273 return false;
254 } 274 }
255 CreateEULASentinel(); 275 CreateEULASentinel();
276
256 if (retcode == installer::EULA_ACCEPTED) { 277 if (retcode == installer::EULA_ACCEPTED) {
257 VLOG(1) << "EULA : no collection"; 278 VLOG(1) << "EULA : no collection";
258 GoogleUpdateSettings::SetCollectStatsConsent(false); 279 GoogleUpdateSettings::SetCollectStatsConsent(false);
259 } else if (retcode == installer::EULA_ACCEPTED_OPT_IN) { 280 } else if (retcode == installer::EULA_ACCEPTED_OPT_IN) {
260 VLOG(1) << "EULA : collection consent"; 281 VLOG(1) << "EULA : collection consent";
261 GoogleUpdateSettings::SetCollectStatsConsent(true); 282 GoogleUpdateSettings::SetCollectStatsConsent(true);
262 } 283 }
263 } 284 }
264 } 285 }
286 return true;
265 } 287 }
266 288
267 // Installs a task to do an extensions update check once the extensions system 289 // Installs a task to do an extensions update check once the extensions system
268 // is running. 290 // is running.
269 void DoDelayedInstallExtensions() { 291 void DoDelayedInstallExtensions() {
270 new FirstRunDelayedTasks(FirstRunDelayedTasks::INSTALL_EXTENSIONS); 292 new FirstRunDelayedTasks(FirstRunDelayedTasks::INSTALL_EXTENSIONS);
271 } 293 }
272 294
273 void DoDelayedInstallExtensionsIfNeeded( 295 void DoDelayedInstallExtensionsIfNeeded(
274 installer::MasterPreferences* install_prefs) { 296 installer::MasterPreferences* install_prefs) {
(...skipping 308 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 } 605 }
584 606
585 FilePath MasterPrefsPath() { 607 FilePath MasterPrefsPath() {
586 // The standard location of the master prefs is next to the chrome binary. 608 // The standard location of the master prefs is next to the chrome binary.
587 FilePath master_prefs; 609 FilePath master_prefs;
588 if (!PathService::Get(base::DIR_EXE, &master_prefs)) 610 if (!PathService::Get(base::DIR_EXE, &master_prefs))
589 return FilePath(); 611 return FilePath();
590 return master_prefs.AppendASCII(installer::kDefaultMasterPrefs); 612 return master_prefs.AppendASCII(installer::kDefaultMasterPrefs);
591 } 613 }
592 614
593 bool ProcessMasterPreferences(const FilePath& user_data_dir, 615 ProcessMasterPreferencesResult ProcessMasterPreferences(
594 MasterPrefs* out_prefs) { 616 const FilePath& user_data_dir,
617 MasterPrefs* out_prefs) {
595 DCHECK(!user_data_dir.empty()); 618 DCHECK(!user_data_dir.empty());
596 619
597 FilePath master_prefs_path; 620 FilePath master_prefs_path;
598 scoped_ptr<installer::MasterPreferences> 621 scoped_ptr<installer::MasterPreferences>
599 install_prefs(internal::LoadMasterPrefs(&master_prefs_path)); 622 install_prefs(internal::LoadMasterPrefs(&master_prefs_path));
600 if (!install_prefs.get()) 623 if (!install_prefs.get())
601 return true; 624 return SHOW_FIRST_RUN;
602 625
603 out_prefs->new_tabs = install_prefs->GetFirstRunTabs(); 626 out_prefs->new_tabs = install_prefs->GetFirstRunTabs();
604 627
605 internal::SetRLZPref(out_prefs, install_prefs.get()); 628 internal::SetRLZPref(out_prefs, install_prefs.get());
606 ShowPostInstallEULAIfNeeded(install_prefs.get()); 629
630 if (!ShowPostInstallEULAIfNeeded(install_prefs.get()))
631 return EULA_EXIT_NOW;
607 632
608 if (!internal::CopyPrefFile(user_data_dir, master_prefs_path)) 633 if (!internal::CopyPrefFile(user_data_dir, master_prefs_path))
609 return true; 634 return SHOW_FIRST_RUN;
610 635
611 DoDelayedInstallExtensionsIfNeeded(install_prefs.get()); 636 DoDelayedInstallExtensionsIfNeeded(install_prefs.get());
612 637
613 internal::SetupMasterPrefsFromInstallPrefs(out_prefs, 638 internal::SetupMasterPrefsFromInstallPrefs(out_prefs,
614 install_prefs.get()); 639 install_prefs.get());
615 640
616 // TODO(mirandac): Refactor skip-first-run-ui process into regular first run 641 // TODO(mirandac): Refactor skip-first-run-ui process into regular first run
617 // import process. http://crbug.com/49647 642 // import process. http://crbug.com/49647
618 // Note we are skipping all other master preferences if skip-first-run-ui 643 // Note we are skipping all other master preferences if skip-first-run-ui
619 // is *not* specified. (That is, we continue only if skipping first run ui.) 644 // is *not* specified. (That is, we continue only if skipping first run ui.)
620 if (!internal::SkipFirstRunUI(install_prefs.get())) 645 if (!internal::SkipFirstRunUI(install_prefs.get()))
621 return true; 646 return SHOW_FIRST_RUN;
622 647
623 // We need to be able to create the first run sentinel or else we cannot 648 // We need to be able to create the first run sentinel or else we cannot
624 // proceed because ImportSettings will launch the importer process which 649 // proceed because ImportSettings will launch the importer process which
625 // would end up here if the sentinel is not present. 650 // would end up here if the sentinel is not present.
626 if (!CreateSentinel()) 651 if (!CreateSentinel())
627 return false; 652 return SKIP_FIRST_RUN;
628 653
629 internal::SetShowWelcomePagePrefIfNeeded(install_prefs.get()); 654 internal::SetShowWelcomePagePrefIfNeeded(install_prefs.get());
630 internal::SetImportPreferencesAndLaunchImport(out_prefs, install_prefs.get()); 655 internal::SetImportPreferencesAndLaunchImport(out_prefs, install_prefs.get());
631 internal::SetDefaultBrowser(install_prefs.get()); 656 internal::SetDefaultBrowser(install_prefs.get());
632 657
633 return false; 658 return SKIP_FIRST_RUN;
634 } 659 }
635 660
636 } // namespace first_run 661 } // namespace first_run
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698