summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorevan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-20 19:06:31 +0000
committerevan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2009-05-20 19:06:31 +0000
commitf8ed9234ed347388a4091b0ef910a8f5dab56641 (patch)
treee2430dc9ecfc7f425c7a24c38a746ff29e9aabb2
parent3404f0885a2b893d049b4fc920925d8b9a2330cb (diff)
downloadchromium_src-f8ed9234ed347388a4091b0ef910a8f5dab56641.zip
chromium_src-f8ed9234ed347388a4091b0ef910a8f5dab56641.tar.gz
chromium_src-f8ed9234ed347388a4091b0ef910a8f5dab56641.tar.bz2
Copy first_run.cc to first_run_win.cc for history preservation.
A subsequent change will modify these files. git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16502 0039d316-1c4b-4281-b951-d872f2087c98
-rw-r--r--chrome/browser/first_run_win.cc667
1 files changed, 667 insertions, 0 deletions
diff --git a/chrome/browser/first_run_win.cc b/chrome/browser/first_run_win.cc
new file mode 100644
index 0000000..3a24488
--- /dev/null
+++ b/chrome/browser/first_run_win.cc
@@ -0,0 +1,667 @@
+// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/first_run.h"
+
+#include <atlbase.h>
+#include <atlcom.h>
+#include <windows.h>
+#include <shlobj.h>
+
+#include <sstream>
+
+#include "app/app_switches.h"
+#include "app/resource_bundle.h"
+#include "base/command_line.h"
+#include "base/file_util.h"
+#include "base/logging.h"
+#include "base/object_watcher.h"
+#include "base/path_service.h"
+#include "base/process.h"
+#include "base/process_util.h"
+#include "base/registry.h"
+#include "base/string_util.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_switches.h"
+#include "chrome/common/pref_names.h"
+#include "chrome/browser/browser_process.h"
+#include "chrome/browser/hang_monitor/hung_window_detector.h"
+#include "chrome/browser/importer/importer.h"
+#include "chrome/browser/process_singleton.h"
+#include "chrome/browser/profile.h"
+#include "chrome/browser/profile_manager.h"
+#include "chrome/browser/shell_integration.h"
+#include "chrome/browser/views/first_run_view.h"
+#include "chrome/common/chrome_constants.h"
+#include "chrome/common/chrome_paths.h"
+#include "chrome/common/pref_service.h"
+#include "chrome/common/result_codes.h"
+#include "chrome/installer/util/browser_distribution.h"
+#include "chrome/installer/util/google_update_constants.h"
+#include "chrome/installer/util/google_update_settings.h"
+#include "chrome/installer/util/install_util.h"
+#include "chrome/installer/util/master_preferences.h"
+#include "chrome/installer/util/shell_util.h"
+#include "chrome/installer/util/util_constants.h"
+#include "google_update_idl.h"
+#include "grit/locale_settings.h"
+#include "views/widget/accelerator_handler.h"
+#include "views/window/window.h"
+
+namespace {
+
+// The kSentinelFile file absence will tell us it is a first run.
+const wchar_t kSentinelFile[] = L"First Run";
+
+// Gives the full path to the sentinel file. The file might not exist.
+bool GetFirstRunSentinelFilePath(std::wstring* path) {
+ std::wstring exe_path;
+ if (!PathService::Get(base::DIR_EXE, &exe_path))
+ return false;
+
+ std::wstring first_run_sentinel;
+ if (InstallUtil::IsPerUserInstall(exe_path.c_str())) {
+ first_run_sentinel = exe_path;
+ } else {
+ if (!PathService::Get(chrome::DIR_USER_DATA, &first_run_sentinel))
+ return false;
+ }
+
+ file_util::AppendToPath(&first_run_sentinel, kSentinelFile);
+ *path = first_run_sentinel;
+ return true;
+}
+
+bool GetNewerChromeFile(std::wstring* path) {
+ if (!PathService::Get(base::DIR_EXE, path))
+ return false;
+ file_util::AppendToPath(path, installer_util::kChromeNewExe);
+ return true;
+}
+
+bool GetBackupChromeFile(std::wstring* path) {
+ if (!PathService::Get(base::DIR_EXE, path))
+ return false;
+ file_util::AppendToPath(path, installer_util::kChromeOldExe);
+ return true;
+}
+
+std::wstring GetDefaultPrefFilePath(bool create_profile_dir,
+ const std::wstring& user_data_dir) {
+ FilePath default_pref_dir = ProfileManager::GetDefaultProfileDir(
+ FilePath::FromWStringHack(user_data_dir));
+ if (create_profile_dir) {
+ if (!file_util::PathExists(default_pref_dir)) {
+ if (!file_util::CreateDirectory(default_pref_dir))
+ return std::wstring();
+ }
+ }
+ return ProfileManager::GetDefaultProfilePath(default_pref_dir)
+ .ToWStringHack();
+}
+
+bool InvokeGoogleUpdateForRename() {
+ CComPtr<IProcessLauncher> ipl;
+ if (!FAILED(ipl.CoCreateInstance(__uuidof(ProcessLauncherClass)))) {
+ ULONG_PTR phandle = NULL;
+ DWORD id = GetCurrentProcessId();
+ if (!FAILED(ipl->LaunchCmdElevated(google_update::kChromeGuid,
+ google_update::kRegRenameCmdField,
+ id, &phandle))) {
+ HANDLE handle = HANDLE(phandle);
+ DWORD exit_code;
+ ::GetExitCodeProcess(handle, &exit_code);
+ ::CloseHandle(handle);
+ if (exit_code == installer_util::RENAME_SUCCESSFUL)
+ return true;
+ }
+ }
+ return false;
+}
+
+bool LaunchSetupWithParam(const std::wstring& param, const std::wstring& value,
+ int* ret_code) {
+ FilePath exe_path;
+ if (!PathService::Get(base::DIR_MODULE, &exe_path))
+ return false;
+ exe_path = exe_path.Append(installer_util::kInstallerDir);
+ exe_path = exe_path.Append(installer_util::kSetupExe);
+ base::ProcessHandle ph;
+ CommandLine cl(exe_path.ToWStringHack());
+ cl.AppendSwitchWithValue(param, value);
+ if (!base::LaunchApp(cl, false, false, &ph))
+ return false;
+ DWORD wr = ::WaitForSingleObject(ph, INFINITE);
+ if (wr != WAIT_OBJECT_0)
+ return false;
+ return (TRUE == ::GetExitCodeProcess(ph, reinterpret_cast<DWORD*>(ret_code)));
+}
+
+bool WriteEULAtoTempFile(FilePath* eula_path) {
+ std::string terms =
+ ResourceBundle::GetSharedInstance().GetDataResource(IDR_TERMS_HTML);
+ if (terms.empty())
+ return false;
+ FilePath temp_dir;
+ if (!file_util::GetTempDir(&temp_dir))
+ return false;
+ *eula_path = temp_dir.Append(L"chrome_eula_iframe.html");
+ return (file_util::WriteFile(*eula_path, terms.c_str(), terms.size()) > 0);
+}
+
+} // namespace
+
+bool FirstRun::IsChromeFirstRun() {
+ // A troolean, 0 means not yet set, 1 means set to true, 2 set to false.
+ static int first_run = 0;
+ if (first_run != 0)
+ return first_run == 1;
+
+ std::wstring first_run_sentinel;
+ if (!GetFirstRunSentinelFilePath(&first_run_sentinel) ||
+ file_util::PathExists(first_run_sentinel)) {
+ first_run = 2;
+ return false;
+ }
+ first_run = 1;
+ return true;
+}
+
+bool FirstRun::CreateChromeDesktopShortcut() {
+ std::wstring chrome_exe;
+ if (!PathService::Get(base::FILE_EXE, &chrome_exe))
+ return false;
+ BrowserDistribution *dist = BrowserDistribution::GetDistribution();
+ if (!dist)
+ return false;
+ return ShellUtil::CreateChromeDesktopShortcut(chrome_exe,
+ dist->GetAppDescription(), ShellUtil::CURRENT_USER,
+ false, true); // create if doesn't exist.
+}
+
+bool FirstRun::CreateChromeQuickLaunchShortcut() {
+ std::wstring chrome_exe;
+ if (!PathService::Get(base::FILE_EXE, &chrome_exe))
+ return false;
+ return ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe,
+ ShellUtil::CURRENT_USER, // create only for current user.
+ true); // create if doesn't exist.
+}
+
+bool FirstRun::RemoveSentinel() {
+ std::wstring first_run_sentinel;
+ if (!GetFirstRunSentinelFilePath(&first_run_sentinel))
+ return false;
+ return file_util::Delete(first_run_sentinel, false);
+}
+
+bool FirstRun::CreateSentinel() {
+ std::wstring first_run_sentinel;
+ if (!GetFirstRunSentinelFilePath(&first_run_sentinel))
+ return false;
+ HANDLE file = ::CreateFileW(first_run_sentinel.c_str(),
+ FILE_READ_DATA | FILE_WRITE_DATA,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL, CREATE_ALWAYS, 0, NULL);
+ if (INVALID_HANDLE_VALUE == file)
+ return false;
+ ::CloseHandle(file);
+ return true;
+}
+
+bool FirstRun::ProcessMasterPreferences(const FilePath& user_data_dir,
+ const FilePath& master_prefs_path,
+ int* preference_details,
+ std::vector<std::wstring>* new_tabs) {
+ DCHECK(!user_data_dir.empty());
+ if (preference_details)
+ *preference_details = 0;
+
+ std::wstring master_prefs;
+ if (master_prefs_path.empty()) {
+ // The default location of the master prefs is next to the chrome exe.
+ std::wstring master_path;
+ if (!PathService::Get(base::DIR_EXE, &master_path))
+ return true;
+ file_util::AppendToPath(&master_path, installer_util::kDefaultMasterPrefs);
+ master_prefs = master_path;
+ } else {
+ master_prefs = master_prefs_path.ToWStringHack();
+ }
+
+ int parse_result = installer_util::ParseDistributionPreferences(master_prefs);
+ if (preference_details)
+ *preference_details = parse_result;
+
+ if (parse_result & installer_util::MASTER_PROFILE_ERROR)
+ return true;
+
+ if (new_tabs)
+ *new_tabs = installer_util::ParseFirstRunTabs(master_prefs);
+
+ if (parse_result & installer_util::MASTER_PROFILE_REQUIRE_EULA) {
+ // Show the post-installation EULA. This is done by setup.exe and the
+ // result determines if we continue or not. We wait here until the user
+ // dismisses the dialog.
+
+ // The actual eula text is in a resource in chrome. We extract it to
+ // a text file so setup.exe can use it as an inner frame.
+ FilePath inner_html;
+ if (WriteEULAtoTempFile(&inner_html)) {
+ int retcode = 0;
+ const std::wstring& eula = installer_util::switches::kShowEula;
+ if (!LaunchSetupWithParam(eula, inner_html.ToWStringHack(), &retcode) ||
+ (retcode == installer_util::EULA_REJECTED)) {
+ LOG(WARNING) << "EULA rejected. Fast exit.";
+ ::ExitProcess(1);
+ }
+ if (retcode == installer_util::EULA_ACCEPTED) {
+ LOG(INFO) << "EULA : no collection";
+ GoogleUpdateSettings::SetCollectStatsConsent(false);
+ } else if (retcode == installer_util::EULA_ACCEPTED_OPT_IN) {
+ LOG(INFO) << "EULA : collection consent";
+ GoogleUpdateSettings::SetCollectStatsConsent(true);
+ }
+ }
+ }
+
+ if (parse_result & installer_util::MASTER_PROFILE_OEM_FIRST_RUN_BUBBLE)
+ FirstRun::SetOEMFirstRunBubblePref();
+
+ FilePath user_prefs = FilePath::FromWStringHack(
+ GetDefaultPrefFilePath(true, user_data_dir.ToWStringHack()));
+ if (user_prefs.empty())
+ return true;
+
+ // The master prefs are regular prefs so we can just copy the file
+ // to the default place and they just work.
+ if (!file_util::CopyFile(master_prefs, user_prefs.ToWStringHack()))
+ return true;
+
+ if (!(parse_result & installer_util::MASTER_PROFILE_NO_FIRST_RUN_UI))
+ return true;
+
+ // From here on we won't show first run so we need to do the work to set the
+ // required state given that FirstRunView is not going to be called.
+ FirstRun::SetShowFirstRunBubblePref();
+
+ // We need to be able to create the first run sentinel or else we cannot
+ // proceed because ImportSettings will launch the importer process which
+ // would end up here if the sentinel is not present.
+ if (!FirstRun::CreateSentinel())
+ return false;
+
+ if (parse_result & installer_util::MASTER_PROFILE_SHOW_WELCOME)
+ FirstRun::SetShowWelcomePagePref();
+
+ int import_items = 0;
+ if (parse_result & installer_util::MASTER_PROFILE_IMPORT_SEARCH_ENGINE)
+ import_items += SEARCH_ENGINES;
+ if (parse_result & installer_util::MASTER_PROFILE_IMPORT_HISTORY)
+ import_items += HISTORY;
+ if (parse_result & installer_util::MASTER_PROFILE_IMPORT_BOOKMARKS)
+ import_items += FAVORITES;
+
+ if (import_items) {
+ // There is something to import from the default browser. This launches
+ // the importer process and blocks until done or until it fails.
+ scoped_refptr<ImporterHost> importer_host = new ImporterHost();
+ if (!FirstRun::ImportSettings(NULL,
+ importer_host->GetSourceProfileInfoAt(0).browser_type,
+ import_items, NULL)) {
+ LOG(WARNING) << "silent import failed";
+ }
+ }
+
+ if (parse_result &
+ installer_util::MASTER_PROFILE_MAKE_CHROME_DEFAULT_FOR_USER)
+ ShellIntegration::SetAsDefaultBrowser();
+
+ return false;
+}
+
+bool Upgrade::IsBrowserAlreadyRunning() {
+ static HANDLE handle = NULL;
+ std::wstring exe;
+ PathService::Get(base::FILE_EXE, &exe);
+ std::replace(exe.begin(), exe.end(), '\\', '!');
+ std::transform(exe.begin(), exe.end(), exe.begin(), tolower);
+ exe = L"Global\\" + exe;
+ if (handle != NULL)
+ CloseHandle(handle);
+ handle = CreateEvent(NULL, TRUE, TRUE, exe.c_str());
+ int error = GetLastError();
+ return (error == ERROR_ALREADY_EXISTS || error == ERROR_ACCESS_DENIED);
+}
+
+bool Upgrade::RelaunchChromeBrowser(const CommandLine& command_line) {
+ ::SetEnvironmentVariable(google_update::kEnvProductVersionKey, NULL);
+ return base::LaunchApp(command_line.command_line_string(),
+ false, false, NULL);
+}
+
+bool Upgrade::SwapNewChromeExeIfPresent() {
+ std::wstring new_chrome_exe;
+ if (!GetNewerChromeFile(&new_chrome_exe))
+ return false;
+ if (!file_util::PathExists(new_chrome_exe))
+ return false;
+ std::wstring curr_chrome_exe;
+ if (!PathService::Get(base::FILE_EXE, &curr_chrome_exe))
+ return false;
+
+ // First try to rename exe by launching rename command ourselves.
+ bool user_install = InstallUtil::IsPerUserInstall(curr_chrome_exe.c_str());
+ HKEY reg_root = user_install ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE;
+ BrowserDistribution *dist = BrowserDistribution::GetDistribution();
+ RegKey key;
+ std::wstring rename_cmd;
+ if (key.Open(reg_root, dist->GetVersionKey().c_str(), KEY_READ) &&
+ key.ReadValue(google_update::kRegRenameCmdField, &rename_cmd)) {
+ base::ProcessHandle handle;
+ if (base::LaunchApp(rename_cmd, true, true, &handle)) {
+ DWORD exit_code;
+ ::GetExitCodeProcess(handle, &exit_code);
+ ::CloseHandle(handle);
+ if (exit_code == installer_util::RENAME_SUCCESSFUL)
+ return true;
+ }
+ }
+
+ // Rename didn't work so try to rename by calling Google Update
+ if (InvokeGoogleUpdateForRename())
+ return true;
+
+ // Rename still didn't work so just try to rename exe ourselves (for
+ // backward compatibility, can be deleted once the new process works).
+ std::wstring backup_exe;
+ if (!GetBackupChromeFile(&backup_exe))
+ return false;
+ if (::ReplaceFileW(curr_chrome_exe.c_str(), new_chrome_exe.c_str(),
+ backup_exe.c_str(), REPLACEFILE_IGNORE_MERGE_ERRORS,
+ NULL, NULL)) {
+ return true;
+ }
+ return false;
+}
+
+void OpenFirstRunDialog(Profile* profile,
+ ProcessSingleton* process_singleton) {
+ DCHECK(profile);
+ DCHECK(process_singleton);
+
+ views::Window* first_run_ui = views::Window::CreateChromeWindow(
+ NULL, gfx::Rect(), new FirstRunView(profile));
+ DCHECK(first_run_ui);
+
+ // We need to avoid dispatching new tabs when we are doing the import
+ // because that will lead to data corruption or a crash. Lock() does that.
+ // If a CopyData message does come in while the First Run UI is visible,
+ // then we will attempt to set first_run_ui as the foreground window.
+ process_singleton->Lock(first_run_ui->GetNativeWindow());
+
+ first_run_ui->Show();
+
+ // We must now run a message loop (will be terminated when the First Run UI
+ // is closed) so that the window can receive messages and we block the
+ // browser window from showing up. We pass the accelerator handler here so
+ // that keyboard accelerators (Enter, Esc, etc) work in the dialog box.
+ MessageLoopForUI::current()->Run(g_browser_process->accelerator_handler());
+ process_singleton->Unlock();
+}
+
+namespace {
+
+// This class is used by FirstRun::ImportSettings to determine when the import
+// process has ended and what was the result of the operation as reported by
+// the process exit code. This class executes in the context of the main chrome
+// process.
+class ImportProcessRunner : public base::ObjectWatcher::Delegate {
+ public:
+ // The constructor takes the importer process to watch and then it does a
+ // message loop blocking wait until the process ends. This object now owns
+ // the import_process handle.
+ explicit ImportProcessRunner(base::ProcessHandle import_process)
+ : import_process_(import_process),
+ exit_code_(ResultCodes::NORMAL_EXIT) {
+ watcher_.StartWatching(import_process, this);
+ MessageLoop::current()->Run();
+ }
+ virtual ~ImportProcessRunner() {
+ ::CloseHandle(import_process_);
+ }
+ // Returns the child process exit code. There are 3 expected values:
+ // NORMAL_EXIT, IMPORTER_CANCEL or IMPORTER_HUNG.
+ int exit_code() const {
+ return exit_code_;
+ }
+ // The child process has terminated. Find the exit code and quit the loop.
+ virtual void OnObjectSignaled(HANDLE object) {
+ DCHECK(object == import_process_);
+ if (!::GetExitCodeProcess(import_process_, &exit_code_)) {
+ NOTREACHED();
+ }
+ MessageLoop::current()->Quit();
+ }
+
+ private:
+ base::ObjectWatcher watcher_;
+ base::ProcessHandle import_process_;
+ DWORD exit_code_;
+};
+
+// Check every 3 seconds if the importer UI has hung.
+const int kPollHangFrequency = 3000;
+
+// This class specializes on finding hung 'owned' windows. Unfortunately, the
+// HungWindowDetector class cannot be used here because it assumes child
+// windows and not owned top-level windows.
+// This code is executed in the context of the main browser process and will
+// terminate the importer process if it is hung.
+class HungImporterMonitor : public WorkerThreadTicker::Callback {
+ public:
+ // The ctor takes the owner popup window and the process handle of the
+ // process to kill in case the popup or its owned active popup become
+ // unresponsive.
+ HungImporterMonitor(HWND owner_window, base::ProcessHandle import_process)
+ : owner_window_(owner_window),
+ import_process_(import_process),
+ ticker_(kPollHangFrequency) {
+ ticker_.RegisterTickHandler(this);
+ ticker_.Start();
+ }
+ virtual ~HungImporterMonitor() {
+ ticker_.Stop();
+ ticker_.UnregisterTickHandler(this);
+ }
+
+ private:
+ virtual void OnTick() {
+ if (!import_process_)
+ return;
+ // We find the top active popup that we own, this will be either the
+ // owner_window_ itself or the dialog window of the other process. In
+ // both cases it is worth hung testing because both windows share the
+ // same message queue and at some point the other window could be gone
+ // while the other process still not pumping messages.
+ HWND active_window = ::GetLastActivePopup(owner_window_);
+ if (::IsHungAppWindow(active_window) || ::IsHungAppWindow(owner_window_)) {
+ ::TerminateProcess(import_process_, ResultCodes::IMPORTER_HUNG);
+ import_process_ = NULL;
+ }
+ }
+
+ HWND owner_window_;
+ base::ProcessHandle import_process_;
+ WorkerThreadTicker ticker_;
+ DISALLOW_EVIL_CONSTRUCTORS(HungImporterMonitor);
+};
+
+// This class is used by FirstRun::ImportNow to get notified of the outcome of
+// the import operation. It differs from ImportProcessRunner in that this
+// class executes in the context of importing child process.
+// The values that it handles are meant to be used as the process exit code.
+class FirstRunImportObserver : public ImportObserver {
+ public:
+ FirstRunImportObserver()
+ : loop_running_(false), import_result_(ResultCodes::NORMAL_EXIT) {
+ }
+ int import_result() const {
+ return import_result_;
+ }
+ virtual void ImportCanceled() {
+ import_result_ = ResultCodes::IMPORTER_CANCEL;
+ Finish();
+ }
+ virtual void ImportComplete() {
+ import_result_ = ResultCodes::NORMAL_EXIT;
+ Finish();
+ }
+
+ void RunLoop() {
+ loop_running_ = true;
+ MessageLoop::current()->Run();
+ }
+
+ private:
+ void Finish() {
+ if (loop_running_)
+ MessageLoop::current()->Quit();
+ }
+
+ bool loop_running_;
+ int import_result_;
+ DISALLOW_EVIL_CONSTRUCTORS(FirstRunImportObserver);
+};
+
+std::wstring EncodeImportParams(int browser_type, int options, HWND window) {
+ return StringPrintf(L"%d@%d@%d", browser_type, options, window);
+}
+
+bool DecodeImportParams(const std::wstring& encoded,
+ int* browser_type, int* options, HWND* window) {
+ std::vector<std::wstring> v;
+ SplitString(encoded, L'@', &v);
+ if (v.size() != 3)
+ return false;
+ *browser_type = static_cast<int>(StringToInt64(v[0]));
+ *options = static_cast<int>(StringToInt64(v[1]));
+ *window = reinterpret_cast<HWND>(StringToInt64(v[2]));
+ return true;
+}
+
+} // namespace
+
+bool FirstRun::ImportSettings(Profile* profile, int browser_type,
+ int items_to_import, HWND parent_window) {
+ const CommandLine& cmdline = *CommandLine::ForCurrentProcess();
+ CommandLine import_cmd(cmdline.program());
+ // Propagate user data directory switch.
+ if (cmdline.HasSwitch(switches::kUserDataDir)) {
+ import_cmd.AppendSwitchWithValue(
+ switches::kUserDataDir,
+ cmdline.GetSwitchValue(switches::kUserDataDir));
+ }
+
+ // Since ImportSettings is called before the local state is stored on disk
+ // we pass the language as an argument. GetApplicationLocale checks the
+ // current command line as fallback.
+ import_cmd.AppendSwitchWithValue(
+ switches::kLang,
+ g_browser_process->GetApplicationLocale());
+
+ import_cmd.CommandLine::AppendSwitchWithValue(switches::kImport,
+ EncodeImportParams(browser_type, items_to_import, parent_window));
+
+ // Time to launch the process that is going to do the import.
+ base::ProcessHandle import_process;
+ if (!base::LaunchApp(import_cmd, false, false, &import_process))
+ return false;
+
+ // Activate the importer monitor. It awakes periodically in another thread
+ // and checks that the importer UI is still pumping messages.
+ if (parent_window)
+ HungImporterMonitor hang_monitor(parent_window, import_process);
+
+ // We block inside the import_runner ctor, pumping messages until the
+ // importer process ends. This can happen either by completing the import
+ // or by hang_monitor killing it.
+ ImportProcessRunner import_runner(import_process);
+
+ // Import process finished. Reload the prefs, because importer may set
+ // the pref value.
+ if (profile)
+ profile->GetPrefs()->ReloadPersistentPrefs();
+
+ return (import_runner.exit_code() == ResultCodes::NORMAL_EXIT);
+}
+
+int FirstRun::ImportNow(Profile* profile, const CommandLine& cmdline) {
+ std::wstring import_info = cmdline.GetSwitchValue(switches::kImport);
+ if (import_info.empty()) {
+ NOTREACHED();
+ return false;
+ }
+ int browser_type = 0;
+ int items_to_import = 0;
+ HWND parent_window = NULL;
+ if (!DecodeImportParams(import_info, &browser_type, &items_to_import,
+ &parent_window)) {
+ NOTREACHED();
+ return false;
+ }
+ scoped_refptr<ImporterHost> importer_host = new ImporterHost();
+ FirstRunImportObserver observer;
+
+ // If there is no parent window, we run in headless mode which amounts
+ // to having the windows hidden and if there is user action required the
+ // import is automatically canceled.
+ if (!parent_window)
+ importer_host->set_headless();
+
+ StartImportingWithUI(
+ parent_window,
+ items_to_import,
+ importer_host,
+ importer_host->GetSourceProfileInfoForBrowserType(browser_type),
+ profile,
+ &observer,
+ true);
+ observer.RunLoop();
+ return observer.import_result();
+}
+
+bool FirstRun::SetShowFirstRunBubblePref() {
+ PrefService* local_state = g_browser_process->local_state();
+ if (!local_state)
+ return false;
+ if (!local_state->IsPrefRegistered(prefs::kShouldShowFirstRunBubble)) {
+ local_state->RegisterBooleanPref(prefs::kShouldShowFirstRunBubble, false);
+ local_state->SetBoolean(prefs::kShouldShowFirstRunBubble, true);
+ }
+ return true;
+}
+
+bool FirstRun::SetOEMFirstRunBubblePref() {
+ PrefService* local_state = g_browser_process->local_state();
+ if (!local_state)
+ return false;
+ if (!local_state->IsPrefRegistered(prefs::kShouldUseOEMFirstRunBubble)) {
+ local_state->RegisterBooleanPref(prefs::kShouldUseOEMFirstRunBubble,
+ false);
+ local_state->SetBoolean(prefs::kShouldUseOEMFirstRunBubble, true);
+ }
+ return true;
+}
+
+bool FirstRun::SetShowWelcomePagePref() {
+ PrefService* local_state = g_browser_process->local_state();
+ if (!local_state)
+ return false;
+ if (!local_state->IsPrefRegistered(prefs::kShouldShowWelcomePage)) {
+ local_state->RegisterBooleanPref(prefs::kShouldShowWelcomePage, false);
+ local_state->SetBoolean(prefs::kShouldShowWelcomePage, true);
+ }
+ return true;
+}