172a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen// Copyright (c) 2011 The Chromium Authors. All rights reserved. 2bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Use of this source code is governed by a BSD-style license that can be 3bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// found in the LICENSE file. 4bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 5bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/first_run/first_run.h" 6bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 7bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <shlobj.h> 8ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include <windows.h> 9bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 10bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <set> 11bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include <sstream> 12bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 13bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/environment.h" 14bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/file_util.h" 15bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/path_service.h" 16bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/string_number_conversions.h" 17bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/string_split.h" 18ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "base/stringprintf.h" 19bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "base/utf_string_conversions.h" 203f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen#include "base/win/object_watcher.h" 21731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick#include "base/win/windows_version.h" 22ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/browser_process.h" 2321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/extensions/extension_service.h" 24bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/browser/extensions/extension_updater.h" 25ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/first_run/first_run_import_observer.h" 26ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/importer/importer_host.h" 27ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "chrome/browser/importer/importer_list.h" 28dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen#include "chrome/browser/importer/importer_progress_dialog.h" 2921d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen#include "chrome/browser/profiles/profile.h" 30bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/common/chrome_switches.h" 31bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/common/worker_thread_ticker.h" 32bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/installer/util/browser_distribution.h" 33bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/installer/util/google_update_constants.h" 34bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/installer/util/google_update_settings.h" 35bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/installer/util/install_util.h" 36bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/installer/util/shell_util.h" 37bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "chrome/installer/util/util_constants.h" 38ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/notification_service.h" 39ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen#include "content/common/result_codes.h" 40bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "google_update_idl.h" 41bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "grit/chromium_strings.h" 42bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "grit/generated_resources.h" 43bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "grit/locale_settings.h" 44bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen#include "grit/theme_resources.h" 4572a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/resource/resource_bundle.h" 4672a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen#include "ui/base/ui_base_switches.h" 47bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 48bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace { 49bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 50bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Helper class that performs delayed first-run tasks that need more of the 51bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// chrome infrastructure to be up and running before they can be attempted. 52bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenclass FirstRunDelayedTasks : public NotificationObserver { 53bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen public: 54bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen enum Tasks { 55bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NO_TASK, 56bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen INSTALL_EXTENSIONS 57bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen }; 58bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 59bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen explicit FirstRunDelayedTasks(Tasks task) { 60bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (task == INSTALL_EXTENSIONS) { 61bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen registrar_.Add(this, NotificationType::EXTENSIONS_READY, 62bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NotificationService::AllSources()); 63bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 64bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen registrar_.Add(this, NotificationType::BROWSER_CLOSED, 65bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NotificationService::AllSources()); 66bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 67bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 68bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen virtual void Observe(NotificationType type, 69bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const NotificationSource& source, 70bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const NotificationDetails& details) { 71bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // After processing the notification we always delete ourselves. 72bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (type.value == NotificationType::EXTENSIONS_READY) 7321d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen DoExtensionWork(Source<Profile>(source).ptr()->GetExtensionService()); 74bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen delete this; 75bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return; 76bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 77bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 78bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen private: 79bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Private ctor forces it to be created only in the heap. 80bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ~FirstRunDelayedTasks() {} 81bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 82bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // The extension work is to basically trigger an extension update check. 83bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // If the extension specified in the master pref is older than the live 84bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // extension it will get updated which is the same as get it installed. 8521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen void DoExtensionWork(ExtensionService* service) { 86bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!service) 87bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return; 88bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen service->updater()->CheckNow(); 89bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return; 90bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 91bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 92bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NotificationRegistrar registrar_; 93bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}; 94bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 95ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Creates the desktop shortcut to chrome for the current user. Returns 96ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// false if it fails. It will overwrite the shortcut if it exists. 97ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool CreateChromeDesktopShortcut() { 98ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FilePath chrome_exe; 99ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!PathService::Get(base::FILE_EXE, &chrome_exe)) 100ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 101ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 102ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!dist) 103ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 104ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return ShellUtil::CreateChromeDesktopShortcut( 105ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dist, 106ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen chrome_exe.value(), 107ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dist->GetAppDescription(), 108ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ShellUtil::CURRENT_USER, 109ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen false, 110ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen true); // create if doesn't exist. 111ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 112ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 113ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// Creates the quick launch shortcut to chrome for the current user. Returns 114ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen// false if it fails. It will overwrite the shortcut if it exists. 115ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool CreateChromeQuickLaunchShortcut() { 116ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FilePath chrome_exe; 117ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!PathService::Get(base::FILE_EXE, &chrome_exe)) 118ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return false; 119ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen BrowserDistribution* dist = BrowserDistribution::GetDistribution(); 120ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return ShellUtil::CreateChromeQuickLaunchShortcut( 121ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen dist, 122ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen chrome_exe.value(), 123ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen ShellUtil::CURRENT_USER, // create only for current user. 124ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen true); // create if doesn't exist. 125ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen} 126ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 127bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} // namespace 128bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 129bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool FirstRun::LaunchSetupWithParam(const std::string& param, 130bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const std::wstring& value, 131bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen int* ret_code) { 132bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen FilePath exe_path; 133bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!PathService::Get(base::DIR_MODULE, &exe_path)) 134bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 13521d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen exe_path = exe_path.Append(installer::kInstallerDir); 13621d179b334e59e9a3bfcaed4c4430bef1bc5759dKristian Monsen exe_path = exe_path.Append(installer::kSetupExe); 137bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen base::ProcessHandle ph; 138bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen CommandLine cl(exe_path); 139bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen cl.AppendSwitchNative(param, value); 140bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 141bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen CommandLine* browser_command_line = CommandLine::ForCurrentProcess(); 142bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (browser_command_line->HasSwitch(switches::kChromeFrame)) { 143bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen cl.AppendSwitch(switches::kChromeFrame); 144bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 145bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 146bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!base::LaunchApp(cl, false, false, &ph)) 147bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 148bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen DWORD wr = ::WaitForSingleObject(ph, INFINITE); 149bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (wr != WAIT_OBJECT_0) 150bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 151bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return (TRUE == ::GetExitCodeProcess(ph, reinterpret_cast<DWORD*>(ret_code))); 152bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 153bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 154bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool FirstRun::WriteEULAtoTempFile(FilePath* eula_path) { 155bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen base::StringPiece terms = 156bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ResourceBundle::GetSharedInstance().GetRawDataResource(IDR_TERMS_HTML); 157bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (terms.empty()) 158bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 159bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen FILE *file = file_util::CreateAndOpenTemporaryFile(eula_path); 160bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!file) 161bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 162bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool good = fwrite(terms.data(), terms.size(), 1, file) == 1; 163bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen fclose(file); 164bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return good; 165bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 166bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 167bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid FirstRun::DoDelayedInstallExtensions() { 168bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen new FirstRunDelayedTasks(FirstRunDelayedTasks::INSTALL_EXTENSIONS); 169bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 170bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 171bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsennamespace { 172bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 173bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// This class is used by FirstRun::ImportSettings to determine when the import 174bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// process has ended and what was the result of the operation as reported by 175bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// the process exit code. This class executes in the context of the main chrome 176bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// process. 1773f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsenclass ImportProcessRunner : public base::win::ObjectWatcher::Delegate { 178bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen public: 179bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // The constructor takes the importer process to watch and then it does a 180bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // message loop blocking wait until the process ends. This object now owns 181bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // the import_process handle. 182bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen explicit ImportProcessRunner(base::ProcessHandle import_process) 183bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen : import_process_(import_process), 184bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen exit_code_(ResultCodes::NORMAL_EXIT) { 185bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen watcher_.StartWatching(import_process, this); 186bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen MessageLoop::current()->Run(); 187bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 188bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen virtual ~ImportProcessRunner() { 189bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ::CloseHandle(import_process_); 190bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 191ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // Returns the child process exit code. There are 2 expected values: 192ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen // NORMAL_EXIT, or IMPORTER_HUNG. 193ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int exit_code() const { return exit_code_; } 194ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen 195bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // The child process has terminated. Find the exit code and quit the loop. 196bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen virtual void OnObjectSignaled(HANDLE object) { 197bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen DCHECK(object == import_process_); 198bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!::GetExitCodeProcess(import_process_, &exit_code_)) { 199bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NOTREACHED(); 200bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 201bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen MessageLoop::current()->Quit(); 202bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 203bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 204bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen private: 2053f50c38dc070f4bb515c1b64450dae14f316474eKristian Monsen base::win::ObjectWatcher watcher_; 206bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen base::ProcessHandle import_process_; 207bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen DWORD exit_code_; 208bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}; 209bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 210bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// Check every 3 seconds if the importer UI has hung. 211bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenconst int kPollHangFrequency = 3000; 212bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 213bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// This class specializes on finding hung 'owned' windows. Unfortunately, the 214bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// HungWindowDetector class cannot be used here because it assumes child 215bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// windows and not owned top-level windows. 216bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// This code is executed in the context of the main browser process and will 217bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// terminate the importer process if it is hung. 218bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenclass HungImporterMonitor : public WorkerThreadTicker::Callback { 219bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen public: 220bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // The ctor takes the owner popup window and the process handle of the 221bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // process to kill in case the popup or its owned active popup become 222bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // unresponsive. 223bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen HungImporterMonitor(HWND owner_window, base::ProcessHandle import_process) 224bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen : owner_window_(owner_window), 225bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen import_process_(import_process), 226bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ticker_(kPollHangFrequency) { 227bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ticker_.RegisterTickHandler(this); 228bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ticker_.Start(); 229bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 230bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen virtual ~HungImporterMonitor() { 231bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ticker_.Stop(); 232bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ticker_.UnregisterTickHandler(this); 233bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 234bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 235bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen private: 236bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen virtual void OnTick() { 237bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!import_process_) 238bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return; 239bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // We find the top active popup that we own, this will be either the 240bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // owner_window_ itself or the dialog window of the other process. In 241bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // both cases it is worth hung testing because both windows share the 242bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // same message queue and at some point the other window could be gone 243bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // while the other process still not pumping messages. 244bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen HWND active_window = ::GetLastActivePopup(owner_window_); 245bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (::IsHungAppWindow(active_window) || ::IsHungAppWindow(owner_window_)) { 246bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ::TerminateProcess(import_process_, ResultCodes::IMPORTER_HUNG); 247bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen import_process_ = NULL; 248bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 249bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 250bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 251bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen HWND owner_window_; 252bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen base::ProcessHandle import_process_; 253bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen WorkerThreadTicker ticker_; 254bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen DISALLOW_COPY_AND_ASSIGN(HungImporterMonitor); 255bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen}; 256bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 257ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenstd::string EncodeImportParams(int importer_type, 258ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int options, 259ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int skip_first_run_ui, 260ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HWND window) { 261ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return base::StringPrintf( 262ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen "%d@%d@%d@%d", importer_type, options, skip_first_run_ui, window); 263bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 264bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 265ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool DecodeImportParams(const std::string& encoded, 266ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int* importer_type, 267ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int* options, 268ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int* skip_first_run_ui, 269ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen HWND* window) { 270bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen std::vector<std::string> parts; 271731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick base::SplitString(encoded, '@', &parts); 272bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (parts.size() != 4) 273bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 274bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 275ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!base::StringToInt(parts[0], importer_type)) 276bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 277bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 278bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!base::StringToInt(parts[1], options)) 279bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 280bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 281bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!base::StringToInt(parts[2], skip_first_run_ui)) 282bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 283bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 284bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen int64 window_int; 285bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen base::StringToInt64(parts[3], &window_int); 286bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen *window = reinterpret_cast<HWND>(window_int); 287bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return true; 288bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 289bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 290bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} // namespace 291bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 292bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// static 293bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenvoid FirstRun::PlatformSetup() { 294ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen CreateChromeDesktopShortcut(); 295bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Windows 7 has deprecated the quick launch bar. 296731df977c0511bca2206b5f333555b1205ff1f43Iain Merrick if (base::win::GetVersion() < base::win::VERSION_WIN7) 297bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen CreateChromeQuickLaunchShortcut(); 298bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 299bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 300bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// static 301ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool FirstRun::IsOrganicFirstRun() { 302bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen std::wstring brand; 303bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen GoogleUpdateSettings::GetBrand(&brand); 304ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen return GoogleUpdateSettings::IsOrganicFirstRun(brand); 305bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 306bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 307bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// static 308ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsenbool FirstRun::ImportSettings(Profile* profile, 309ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int importer_type, 310bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen int items_to_import, 311bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const FilePath& import_bookmarks_path, 312bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen bool skip_first_run_ui, 313bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen HWND parent_window) { 314bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const CommandLine& cmdline = *CommandLine::ForCurrentProcess(); 315bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen CommandLine import_cmd(cmdline.GetProgram()); 316bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 317bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const char* kSwitchNames[] = { 318bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen switches::kUserDataDir, 319bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen switches::kChromeFrame, 320bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen switches::kCountry, 321bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen }; 322bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen import_cmd.CopySwitchesFrom(cmdline, kSwitchNames, arraysize(kSwitchNames)); 323bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 324bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Since ImportSettings is called before the local state is stored on disk 325bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // we pass the language as an argument. GetApplicationLocale checks the 326bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // current command line as fallback. 327bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen import_cmd.AppendSwitchASCII(switches::kLang, 328bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen g_browser_process->GetApplicationLocale()); 329bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 330bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (items_to_import) { 331bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen import_cmd.CommandLine::AppendSwitchASCII(switches::kImport, 332ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen EncodeImportParams(importer_type, items_to_import, 333bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen skip_first_run_ui ? 1 : 0, NULL)); 334bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 335bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 336bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!import_bookmarks_path.empty()) { 337bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen import_cmd.CommandLine::AppendSwitchPath( 338bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen switches::kImportFromFile, import_bookmarks_path); 339bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 340bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 341bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Time to launch the process that is going to do the import. 342bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen base::ProcessHandle import_process; 343bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (!base::LaunchApp(import_cmd, false, false, &import_process)) 344bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 345bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 346bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // We block inside the import_runner ctor, pumping messages until the 347bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // importer process ends. This can happen either by completing the import 348bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // or by hang_monitor killing it. 349bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen ImportProcessRunner import_runner(import_process); 350bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 351bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // Import process finished. Reload the prefs, because importer may set 352bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // the pref value. 353bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (profile) 354bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile->GetPrefs()->ReloadPersistentPrefs(); 355bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 356bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return (import_runner.exit_code() == ResultCodes::NORMAL_EXIT); 357bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 358bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 359bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen// static 360bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenbool FirstRun::ImportSettings(Profile* profile, 361bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen scoped_refptr<ImporterHost> importer_host, 36272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_refptr<ImporterList> importer_list, 363bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen int items_to_import) { 364bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return ImportSettings( 365bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile, 366ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen importer_list->GetSourceProfileAt(0).importer_type, 367bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen items_to_import, 368ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen FilePath(), 369ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen false, 370ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen NULL); 371bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 372bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 373bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsenint FirstRun::ImportFromBrowser(Profile* profile, 374bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen const CommandLine& cmdline) { 375bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen std::string import_info = cmdline.GetSwitchValueASCII(switches::kImport); 376bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (import_info.empty()) { 377bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NOTREACHED(); 378bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 379bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 380ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen int importer_type = 0; 381bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen int items_to_import = 0; 382bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen int skip_first_run_ui = 0; 383bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen HWND parent_window = NULL; 384ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen if (!DecodeImportParams(import_info, &importer_type, &items_to_import, 385bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen &skip_first_run_ui, &parent_window)) { 386bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen NOTREACHED(); 387bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen return false; 388bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen } 38972a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_refptr<ImporterHost> importer_host(new ImporterHost); 390dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen FirstRunImportObserver importer_observer; 391bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 39272a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen scoped_refptr<ImporterList> importer_list(new ImporterList); 39372a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen importer_list->DetectSourceProfilesHack(); 39472a454cd3513ac24fbdd0e0cb9ad70b86a99b801Kristian Monsen 395bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // If |skip_first_run_ui|, we run in headless mode. This means that if 396bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen // there is user action required the import is automatically canceled. 397bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen if (skip_first_run_ui > 0) 398bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen importer_host->set_headless(); 399bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen 400dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen importer::ShowImportProgressDialog( 401bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen parent_window, 402513209b27ff55e2841eac0e4120199c23acce758Ben Murdoch static_cast<uint16>(items_to_import), 403bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen importer_host, 404dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen &importer_observer, 405ddb351dbec246cf1fab5ec20d2d5520909041de1Kristian Monsen importer_list->GetSourceProfileForImporterType(importer_type), 406bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen profile, 407bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen true); 408dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen importer_observer.RunLoop(); 409dc0f95d653279beabeb9817299e2902918ba123eKristian Monsen return importer_observer.import_result(); 410bda42a81ee5f9b20d2bebedcf0bbef1e30e5b293Kristian Monsen} 411