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