first_run.cc revision 2a99a7e74a7f215066514fe81d2bfa6639d9eddd
1// Copyright (c) 2012 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/first_run/first_run.h"
6
7#include <algorithm>
8
9#include "base/command_line.h"
10#include "base/compiler_specific.h"
11#include "base/file_util.h"
12#include "base/lazy_instance.h"
13#include "base/metrics/histogram.h"
14#include "base/path_service.h"
15#include "base/prefs/pref_service.h"
16#include "base/stringprintf.h"
17#include "base/utf_string_conversions.h"
18#include "build/build_config.h"
19#include "chrome/browser/browser_process.h"
20#include "chrome/browser/extensions/extension_service.h"
21#include "chrome/browser/extensions/updater/extension_updater.h"
22#include "chrome/browser/first_run/first_run_dialog.h"
23#include "chrome/browser/first_run/first_run_import_observer.h"
24#include "chrome/browser/first_run/first_run_internal.h"
25#include "chrome/browser/google/google_util.h"
26#include "chrome/browser/importer/external_process_importer_host.h"
27#include "chrome/browser/importer/importer_host.h"
28#include "chrome/browser/importer/importer_list.h"
29#include "chrome/browser/importer/importer_progress_dialog.h"
30#include "chrome/browser/importer/importer_progress_observer.h"
31#include "chrome/browser/process_singleton.h"
32#include "chrome/browser/profiles/profile_manager.h"
33#include "chrome/browser/search_engines/template_url_service.h"
34#include "chrome/browser/search_engines/template_url_service_factory.h"
35#include "chrome/browser/shell_integration.h"
36#include "chrome/browser/ui/browser.h"
37#include "chrome/browser/ui/browser_finder.h"
38#include "chrome/browser/ui/global_error/global_error_service.h"
39#include "chrome/browser/ui/global_error/global_error_service_factory.h"
40#include "chrome/browser/ui/tabs/tab_strip_model.h"
41#include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
42#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h"
43#include "chrome/common/chrome_notification_types.h"
44#include "chrome/common/chrome_paths.h"
45#include "chrome/common/chrome_switches.h"
46#include "chrome/common/pref_names.h"
47#include "chrome/common/startup_metric_utils.h"
48#include "chrome/common/url_constants.h"
49#include "chrome/installer/util/master_preferences.h"
50#include "chrome/installer/util/master_preferences_constants.h"
51#include "chrome/installer/util/util_constants.h"
52#include "components/user_prefs/pref_registry_syncable.h"
53#include "content/public/browser/notification_service.h"
54#include "content/public/browser/notification_types.h"
55#include "content/public/browser/user_metrics.h"
56#include "content/public/browser/web_contents.h"
57#include "google_apis/gaia/gaia_auth_util.h"
58#include "googleurl/src/gurl.h"
59
60using content::UserMetricsAction;
61
62namespace {
63
64// Flags for functions of similar name.
65bool should_show_welcome_page_ = false;
66bool should_do_autofill_personal_data_manager_first_run_ = false;
67
68// Flags indicating whether a first-run profile auto import was performed, and
69// whether the importer process exited successfully.
70bool did_perform_profile_import = false;
71bool profile_import_exited_successfully = false;
72
73// Helper class that performs delayed first-run tasks that need more of the
74// chrome infrastructure to be up and running before they can be attempted.
75class FirstRunDelayedTasks : public content::NotificationObserver {
76 public:
77  enum Tasks {
78    NO_TASK,
79    INSTALL_EXTENSIONS
80  };
81
82  explicit FirstRunDelayedTasks(Tasks task) {
83    if (task == INSTALL_EXTENSIONS) {
84      registrar_.Add(this, chrome::NOTIFICATION_EXTENSIONS_READY,
85                     content::NotificationService::AllSources());
86    }
87    registrar_.Add(this, chrome::NOTIFICATION_BROWSER_CLOSED,
88                   content::NotificationService::AllSources());
89  }
90
91  virtual void Observe(int type,
92                       const content::NotificationSource& source,
93                       const content::NotificationDetails& details) OVERRIDE {
94    // After processing the notification we always delete ourselves.
95    if (type == chrome::NOTIFICATION_EXTENSIONS_READY) {
96      DoExtensionWork(
97          content::Source<Profile>(source).ptr()->GetExtensionService());
98    }
99    delete this;
100  }
101
102 private:
103  // Private ctor forces it to be created only in the heap.
104  virtual ~FirstRunDelayedTasks() {}
105
106  // The extension work is to basically trigger an extension update check.
107  // If the extension specified in the master pref is older than the live
108  // extension it will get updated which is the same as get it installed.
109  void DoExtensionWork(ExtensionService* service) {
110    if (service)
111      service->updater()->CheckNow(extensions::ExtensionUpdater::CheckParams());
112  }
113
114  content::NotificationRegistrar registrar_;
115};
116
117// Installs a task to do an extensions update check once the extensions system
118// is running.
119void DoDelayedInstallExtensions() {
120  new FirstRunDelayedTasks(FirstRunDelayedTasks::INSTALL_EXTENSIONS);
121}
122
123void DoDelayedInstallExtensionsIfNeeded(
124    installer::MasterPreferences* install_prefs) {
125  DictionaryValue* extensions = 0;
126  if (install_prefs->GetExtensionsBlock(&extensions)) {
127    VLOG(1) << "Extensions block found in master preferences";
128    DoDelayedInstallExtensions();
129  }
130}
131
132base::FilePath GetDefaultPrefFilePath(bool create_profile_dir,
133                                      const base::FilePath& user_data_dir) {
134  base::FilePath default_pref_dir =
135      ProfileManager::GetDefaultProfileDir(user_data_dir);
136  if (create_profile_dir) {
137    if (!file_util::PathExists(default_pref_dir)) {
138      if (!file_util::CreateDirectory(default_pref_dir))
139        return base::FilePath();
140    }
141  }
142  return ProfileManager::GetProfilePrefsPath(default_pref_dir);
143}
144
145// Sets the |items| bitfield according to whether the import data specified by
146// |import_type| should be be auto imported or not.
147void SetImportItem(PrefService* user_prefs,
148                   const char* pref_path,
149                   int import_items,
150                   int dont_import_items,
151                   importer::ImportItem import_type,
152                   int& items) {
153  // Work out whether an item is to be imported according to what is specified
154  // in master preferences.
155  bool should_import = false;
156  bool master_pref_set =
157      ((import_items | dont_import_items) & import_type) != 0;
158  bool master_pref = ((import_items & ~dont_import_items) & import_type) != 0;
159
160  if (import_type == importer::HISTORY ||
161      ((import_type != importer::FAVORITES) &&
162      first_run::internal::IsOrganicFirstRun())) {
163    // History is always imported unless turned off in master_preferences.
164    // Search engines are only imported in certain builds unless overridden
165    // in master_preferences.Home page is imported in organic builds only unless
166    // turned off in master_preferences.
167    should_import = !master_pref_set || master_pref;
168  } else {
169    // Bookmarks are never imported, unless turned on in master_preferences.
170    // Search engine and home page import behaviour is similar in non organic
171    // builds.
172    should_import = master_pref_set && master_pref;
173  }
174
175  // If an import policy is set, import items according to policy. If no master
176  // preference is set, but a corresponding recommended policy is set, import
177  // item according to recommended policy. If both a master preference and a
178  // recommended policy is set, the master preference wins. If neither
179  // recommended nor managed policies are set, import item according to what we
180  // worked out above.
181  if (master_pref_set)
182    user_prefs->SetBoolean(pref_path, should_import);
183
184  if (!user_prefs->FindPreference(pref_path)->IsDefaultValue()) {
185    if (user_prefs->GetBoolean(pref_path))
186      items |= import_type;
187  } else { // no policy (recommended or managed) is set
188    if (should_import)
189      items |= import_type;
190  }
191
192  user_prefs->ClearPref(pref_path);
193}
194
195// Imports bookmarks from an html file. The path to the file is provided in
196// the command line.
197int ImportFromFile(Profile* profile, const CommandLine& cmdline) {
198  base::FilePath file_path =
199      cmdline.GetSwitchValuePath(switches::kImportFromFile);
200  if (file_path.empty()) {
201    NOTREACHED();
202    return false;
203  }
204  scoped_refptr<ImporterHost> importer_host(new ImporterHost);
205  importer_host->set_headless();
206
207  importer::SourceProfile source_profile;
208  source_profile.importer_type = importer::TYPE_BOOKMARKS_FILE;
209  source_profile.source_path = file_path;
210
211  FirstRunImportObserver importer_observer;
212  importer::ShowImportProgressDialog(importer::FAVORITES,
213                                     importer_host,
214                                     &importer_observer,
215                                     source_profile,
216                                     profile,
217                                     true);
218
219  importer_observer.RunLoop();
220  return importer_observer.import_result();
221}
222
223GURL UrlFromString(const std::string& in) {
224  return GURL(in);
225}
226
227void ConvertStringVectorToGURLVector(
228    const std::vector<std::string>& src,
229    std::vector<GURL>* ret) {
230  ret->resize(src.size());
231  std::transform(src.begin(), src.end(), ret->begin(), &UrlFromString);
232}
233
234}  // namespace
235
236namespace first_run {
237namespace internal {
238
239FirstRunState first_run_ = FIRST_RUN_UNKNOWN;
240
241static base::LazyInstance<base::FilePath> master_prefs_path_for_testing
242    = LAZY_INSTANCE_INITIALIZER;
243
244installer::MasterPreferences*
245    LoadMasterPrefs(base::FilePath* master_prefs_path) {
246  if (!master_prefs_path_for_testing.Get().empty())
247    *master_prefs_path = master_prefs_path_for_testing.Get();
248  else
249    *master_prefs_path = base::FilePath(MasterPrefsPath());
250  if (master_prefs_path->empty())
251    return NULL;
252  installer::MasterPreferences* install_prefs =
253      new installer::MasterPreferences(*master_prefs_path);
254  if (!install_prefs->read_from_file()) {
255    delete install_prefs;
256    return NULL;
257  }
258
259  return install_prefs;
260}
261
262bool CopyPrefFile(const base::FilePath& user_data_dir,
263                  const base::FilePath& master_prefs_path) {
264  base::FilePath user_prefs = GetDefaultPrefFilePath(true, user_data_dir);
265  if (user_prefs.empty())
266    return false;
267
268  // The master prefs are regular prefs so we can just copy the file
269  // to the default place and they just work.
270  return file_util::CopyFile(master_prefs_path, user_prefs);
271}
272
273void SetupMasterPrefsFromInstallPrefs(
274    const installer::MasterPreferences& install_prefs,
275    MasterPrefs* out_prefs) {
276  bool value = false;
277  if (install_prefs.GetBool(
278          installer::master_preferences::kDistroImportSearchPref, &value)) {
279    if (value) {
280      out_prefs->do_import_items |= importer::SEARCH_ENGINES;
281    } else {
282      out_prefs->dont_import_items |= importer::SEARCH_ENGINES;
283    }
284  }
285
286  // If we're suppressing the first-run bubble, set that preference now.
287  // Otherwise, wait until the user has completed first run to set it, so the
288  // user is guaranteed to see the bubble iff he or she has completed the first
289  // run process.
290  if (install_prefs.GetBool(
291          installer::master_preferences::kDistroSuppressFirstRunBubble,
292          &value) && value)
293    SetShowFirstRunBubblePref(FIRST_RUN_BUBBLE_SUPPRESS);
294
295  if (install_prefs.GetBool(
296          installer::master_preferences::kDistroImportHistoryPref,
297          &value)) {
298    if (value) {
299      out_prefs->do_import_items |= importer::HISTORY;
300    } else {
301      out_prefs->dont_import_items |= importer::HISTORY;
302    }
303  }
304
305  std::string not_used;
306  out_prefs->homepage_defined = install_prefs.GetString(
307      prefs::kHomePage, &not_used);
308
309  if (install_prefs.GetBool(
310          installer::master_preferences::kDistroImportHomePagePref,
311          &value)) {
312    if (value) {
313      out_prefs->do_import_items |= importer::HOME_PAGE;
314    } else {
315      out_prefs->dont_import_items |= importer::HOME_PAGE;
316    }
317  }
318
319  // Bookmarks are never imported unless specifically turned on.
320  if (install_prefs.GetBool(
321          installer::master_preferences::kDistroImportBookmarksPref,
322          &value)) {
323    if (value)
324      out_prefs->do_import_items |= importer::FAVORITES;
325    else
326      out_prefs->dont_import_items |= importer::FAVORITES;
327  }
328
329  if (install_prefs.GetBool(
330          installer::master_preferences::kMakeChromeDefaultForUser,
331          &value) && value) {
332    out_prefs->make_chrome_default = true;
333  }
334
335  if (install_prefs.GetBool(
336          installer::master_preferences::kSuppressFirstRunDefaultBrowserPrompt,
337          &value) && value) {
338    out_prefs->suppress_first_run_default_browser_prompt = true;
339  }
340
341  out_prefs->variations_seed = install_prefs.GetVariationsSeed();
342}
343
344void SetDefaultBrowser(installer::MasterPreferences* install_prefs){
345  // Even on the first run we only allow for the user choice to take effect if
346  // no policy has been set by the admin.
347  if (!g_browser_process->local_state()->IsManagedPreference(
348          prefs::kDefaultBrowserSettingEnabled)) {
349    bool value = false;
350    if (install_prefs->GetBool(
351            installer::master_preferences::kMakeChromeDefaultForUser,
352            &value) && value) {
353      ShellIntegration::SetAsDefaultBrowser();
354    }
355  } else {
356    if (g_browser_process->local_state()->GetBoolean(
357            prefs::kDefaultBrowserSettingEnabled)) {
358      ShellIntegration::SetAsDefaultBrowser();
359    }
360  }
361}
362
363void SetRLZPref(first_run::MasterPrefs* out_prefs,
364                installer::MasterPreferences* install_prefs) {
365  if (!install_prefs->GetInt(installer::master_preferences::kDistroPingDelay,
366                    &out_prefs->ping_delay)) {
367    // Default value in case master preferences is missing or corrupt,
368    // or ping_delay is missing.
369    out_prefs->ping_delay = 90;
370  }
371}
372
373// -- Platform-specific functions --
374
375#if !defined(OS_LINUX) && !defined(OS_BSD)
376bool IsOrganicFirstRun() {
377  std::string brand;
378  google_util::GetBrand(&brand);
379  return google_util::IsOrganicFirstRun(brand);
380}
381#endif
382
383int ImportBookmarkFromFileIfNeeded(Profile* profile,
384                                   const CommandLine& cmdline) {
385  int return_code = true;
386  if (cmdline.HasSwitch(switches::kImportFromFile)) {
387    // Silently import preset bookmarks from file.
388    // This is an OEM scenario.
389    return_code = ImportFromFile(profile, cmdline);
390  }
391  return return_code;
392}
393
394}  // namespace internal
395}  // namespace first_run
396
397namespace first_run {
398
399MasterPrefs::MasterPrefs()
400    : ping_delay(0),
401      homepage_defined(false),
402      do_import_items(0),
403      dont_import_items(0),
404      make_chrome_default(false),
405      suppress_first_run_default_browser_prompt(false) {
406}
407
408MasterPrefs::~MasterPrefs() {}
409
410bool IsChromeFirstRun() {
411  if (internal::first_run_ != internal::FIRST_RUN_UNKNOWN)
412    return internal::first_run_ == internal::FIRST_RUN_TRUE;
413
414  base::FilePath first_run_sentinel;
415  if (!internal::GetFirstRunSentinelFilePath(&first_run_sentinel) ||
416      file_util::PathExists(first_run_sentinel)) {
417    internal::first_run_ = internal::FIRST_RUN_FALSE;
418    return false;
419  }
420  internal::first_run_ = internal::FIRST_RUN_TRUE;
421  return true;
422}
423
424bool CreateSentinel() {
425  base::FilePath first_run_sentinel;
426  if (!internal::GetFirstRunSentinelFilePath(&first_run_sentinel))
427    return false;
428  return file_util::WriteFile(first_run_sentinel, "", 0) != -1;
429}
430
431std::string GetPingDelayPrefName() {
432  return base::StringPrintf("%s.%s",
433                            installer::master_preferences::kDistroDict,
434                            installer::master_preferences::kDistroPingDelay);
435}
436
437void RegisterUserPrefs(PrefRegistrySyncable* registry) {
438  registry->RegisterIntegerPref(GetPingDelayPrefName().c_str(),
439                                0,
440                                PrefRegistrySyncable::UNSYNCABLE_PREF);
441}
442
443bool RemoveSentinel() {
444  base::FilePath first_run_sentinel;
445  if (!internal::GetFirstRunSentinelFilePath(&first_run_sentinel))
446    return false;
447  return file_util::Delete(first_run_sentinel, false);
448}
449
450bool SetShowFirstRunBubblePref(FirstRunBubbleOptions show_bubble_option) {
451  PrefService* local_state = g_browser_process->local_state();
452  if (!local_state)
453    return false;
454  if (local_state->GetInteger(
455          prefs::kShowFirstRunBubbleOption) != FIRST_RUN_BUBBLE_SUPPRESS) {
456    // Set the new state as long as the bubble wasn't explicitly suppressed
457    // already.
458    local_state->SetInteger(prefs::kShowFirstRunBubbleOption,
459                            show_bubble_option);
460  }
461  return true;
462}
463
464void SetShouldShowWelcomePage() {
465  should_show_welcome_page_ = true;
466}
467
468bool ShouldShowWelcomePage() {
469  bool retval = should_show_welcome_page_;
470  should_show_welcome_page_ = false;
471  return retval;
472}
473
474void SetShouldDoPersonalDataManagerFirstRun() {
475  should_do_autofill_personal_data_manager_first_run_ = true;
476}
477
478bool ShouldDoPersonalDataManagerFirstRun() {
479  bool retval = should_do_autofill_personal_data_manager_first_run_;
480  should_do_autofill_personal_data_manager_first_run_ = false;
481  return retval;
482}
483
484void LogFirstRunMetric(FirstRunBubbleMetric metric) {
485  UMA_HISTOGRAM_ENUMERATION("FirstRun.SearchEngineBubble", metric,
486                            NUM_FIRST_RUN_BUBBLE_METRICS);
487}
488
489namespace {
490CommandLine* GetExtraArgumentsInstance() {
491  CR_DEFINE_STATIC_LOCAL(CommandLine, arguments, (CommandLine::NoProgram()));
492  return &arguments;
493}
494}  // namespace
495
496void SetExtraArgumentsForImportProcess(const CommandLine& arguments) {
497  GetExtraArgumentsInstance()->AppendArguments(arguments, false);
498}
499
500const CommandLine& GetExtraArgumentsForImportProcess() {
501  return *GetExtraArgumentsInstance();
502}
503
504// static
505void FirstRunBubbleLauncher::ShowFirstRunBubbleSoon() {
506  SetShowFirstRunBubblePref(FIRST_RUN_BUBBLE_SHOW);
507  // This FirstRunBubbleLauncher instance will manage its own lifetime.
508  new FirstRunBubbleLauncher();
509}
510
511FirstRunBubbleLauncher::FirstRunBubbleLauncher() {
512  registrar_.Add(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME,
513                 content::NotificationService::AllSources());
514}
515
516FirstRunBubbleLauncher::~FirstRunBubbleLauncher() {}
517
518void FirstRunBubbleLauncher::Observe(
519    int type,
520    const content::NotificationSource& source,
521    const content::NotificationDetails& details) {
522  DCHECK_EQ(type, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME);
523  Browser* browser = chrome::FindBrowserWithWebContents(
524      content::Source<content::WebContents>(source).ptr());
525  if (!browser || !browser->is_type_tabbed())
526    return;
527
528  // Check the preference to determine if the bubble should be shown.
529  PrefService* prefs = g_browser_process->local_state();
530  if (!prefs || prefs->GetInteger(
531          prefs::kShowFirstRunBubbleOption) != FIRST_RUN_BUBBLE_SHOW) {
532    delete this;
533    return;
534  }
535
536  content::WebContents* contents =
537      browser->tab_strip_model()->GetActiveWebContents();
538
539  // Suppress the first run bubble if a Gaia sign in page is showing.
540  if (SyncPromoUI::UseWebBasedSigninFlow() &&
541      gaia::IsGaiaSignonRealm(contents->GetURL().GetOrigin())) {
542      return;
543  }
544
545  if (contents && contents->GetURL().SchemeIs(chrome::kChromeUIScheme)) {
546    // Suppress the first run bubble if the sync promo is showing.
547    if (contents->GetURL().host() == chrome::kChromeUISyncPromoHost)
548      return;
549
550    // Suppress the first run bubble if 'make chrome metro' flow is showing.
551    if (contents->GetURL().host() == chrome::kChromeUIMetroFlowHost)
552      return;
553
554    // Suppress the first run bubble if the NTP sync promo bubble is showing.
555    if (contents->GetURL().host() == chrome::kChromeUINewTabHost) {
556      NewTabUI* new_tab_ui =
557          NewTabUI::FromWebUIController(contents->GetWebUI()->GetController());
558      if (new_tab_ui && new_tab_ui->showing_sync_bubble())
559        return;
560    }
561  }
562
563  // Suppress the first run bubble if a global error bubble is pending.
564  GlobalErrorService* global_error_service =
565      GlobalErrorServiceFactory::GetForProfile(browser->profile());
566  if (global_error_service->GetFirstGlobalErrorWithBubbleView() != NULL)
567    return;
568
569  // Reset the preference and notifications to avoid showing the bubble again.
570  prefs->SetInteger(prefs::kShowFirstRunBubbleOption,
571                    FIRST_RUN_BUBBLE_DONT_SHOW);
572
573  // Show the bubble now and destroy this bubble launcher.
574  browser->ShowFirstRunBubble();
575  delete this;
576}
577
578void SetMasterPrefsPathForTesting(const base::FilePath& master_prefs) {
579  internal::master_prefs_path_for_testing.Get() = master_prefs;
580}
581
582ProcessMasterPreferencesResult ProcessMasterPreferences(
583    const base::FilePath& user_data_dir,
584    MasterPrefs* out_prefs) {
585  DCHECK(!user_data_dir.empty());
586
587#if defined(OS_CHROMEOS)
588  // Chrome OS has its own out-of-box-experience code.  Create the sentinel to
589  // mark the fact that we've run once but skip the full first-run flow.
590  CreateSentinel();
591  return SKIP_FIRST_RUN_TASKS;
592#endif
593
594  base::FilePath master_prefs_path;
595  scoped_ptr<installer::MasterPreferences>
596      install_prefs(internal::LoadMasterPrefs(&master_prefs_path));
597  if (!install_prefs.get())
598    return DO_FIRST_RUN_TASKS;
599
600  ConvertStringVectorToGURLVector(
601      install_prefs->GetFirstRunTabs(), &out_prefs->new_tabs);
602
603  internal::SetRLZPref(out_prefs, install_prefs.get());
604
605  if (!internal::ShowPostInstallEULAIfNeeded(install_prefs.get()))
606    return EULA_EXIT_NOW;
607
608  if (!internal::CopyPrefFile(user_data_dir, master_prefs_path))
609    DLOG(ERROR) << "Failed to copy master_preferences to user data dir.";
610
611  DoDelayedInstallExtensionsIfNeeded(install_prefs.get());
612
613  internal::SetupMasterPrefsFromInstallPrefs(*install_prefs, out_prefs);
614
615  internal::SetImportPreferencesAndLaunchImport(out_prefs, install_prefs.get());
616  internal::SetDefaultBrowser(install_prefs.get());
617
618  return DO_FIRST_RUN_TASKS;
619}
620
621void AutoImport(
622    Profile* profile,
623    bool homepage_defined,
624    int import_items,
625    int dont_import_items,
626    ProcessSingleton* process_singleton) {
627#if !defined(USE_AURA)
628  // We need to avoid dispatching new tabs when we are importing because
629  // that will lead to data corruption or a crash. Because there is no UI for
630  // the import process, we pass NULL as the window to bring to the foreground
631  // when a CopyData message comes in; this causes the message to be silently
632  // discarded, which is the correct behavior during the import process.
633  process_singleton->Lock(NULL);
634
635  scoped_refptr<ImporterHost> importer_host;
636  // TODO(csilv,mirandac): Out-of-process import has only been qualified on
637  // MacOS X, so we will only use it on that platform since it is required.
638  // Remove this conditional logic once oop import is qualified for
639  // Linux/Windows. http://crbug.com/22142
640#if defined(OS_MACOSX)
641  importer_host = new ExternalProcessImporterHost;
642#else
643  importer_host = new ImporterHost;
644#endif
645
646  base::FilePath local_state_path;
647  PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
648  bool local_state_file_exists = file_util::PathExists(local_state_path);
649
650  scoped_refptr<ImporterList> importer_list(new ImporterList(NULL));
651  importer_list->DetectSourceProfilesHack();
652
653  // Do import if there is an available profile for us to import.
654  if (importer_list->count() > 0) {
655    // Don't show the warning dialog if import fails.
656    importer_host->set_headless();
657    int items = 0;
658
659    if (internal::IsOrganicFirstRun()) {
660      // Home page is imported in organic builds only unless turned off or
661      // defined in master_preferences.
662      if (homepage_defined) {
663        dont_import_items |= importer::HOME_PAGE;
664        if (import_items & importer::HOME_PAGE)
665          import_items &= ~importer::HOME_PAGE;
666      }
667      // Search engines are not imported automatically in organic builds if the
668      // user already has a user preferences directory.
669      if (local_state_file_exists) {
670        dont_import_items |= importer::SEARCH_ENGINES;
671        if (import_items & importer::SEARCH_ENGINES)
672          import_items &= ~importer::SEARCH_ENGINES;
673      }
674    }
675
676    PrefService* user_prefs = profile->GetPrefs();
677
678    SetImportItem(user_prefs,
679                  prefs::kImportHistory,
680                  import_items,
681                  dont_import_items,
682                  importer::HISTORY,
683                  items);
684    SetImportItem(user_prefs,
685                  prefs::kImportHomepage,
686                  import_items,
687                  dont_import_items,
688                  importer::HOME_PAGE,
689                  items);
690    SetImportItem(user_prefs,
691                  prefs::kImportSearchEngine,
692                  import_items,
693                  dont_import_items,
694                  importer::SEARCH_ENGINES,
695                  items);
696    SetImportItem(user_prefs,
697                  prefs::kImportBookmarks,
698                  import_items,
699                  dont_import_items,
700                  importer::FAVORITES,
701                  items);
702
703    profile_import_exited_successfully =
704        internal::ImportSettings(profile, importer_host, importer_list, items);
705    DCHECK(profile_import_exited_successfully);
706  }
707
708  content::RecordAction(UserMetricsAction("FirstRunDef_Accept"));
709
710  process_singleton->Unlock();
711  first_run::CreateSentinel();
712#endif  // !defined(USE_AURA)
713  did_perform_profile_import = true;
714}
715
716void DoPostImportTasks(Profile* profile, bool make_chrome_default) {
717  if (make_chrome_default &&
718      ShellIntegration::CanSetAsDefaultBrowser() ==
719          ShellIntegration::SET_DEFAULT_UNATTENDED) {
720    ShellIntegration::SetAsDefaultBrowser();
721  }
722
723#if !defined(USE_AURA)
724  base::FilePath local_state_path;
725  PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path);
726  bool local_state_file_exists = file_util::PathExists(local_state_path);
727
728  // Launch the first run dialog only for certain builds, and only if the user
729  // has not already set preferences.
730  if (internal::IsOrganicFirstRun() && !local_state_file_exists) {
731    startup_metric_utils::SetNonBrowserUIDisplayed();
732    ShowFirstRunDialog(profile);
733  }
734  // Display the first run bubble if there is a default search provider.
735  TemplateURLService* template_url =
736      TemplateURLServiceFactory::GetForProfile(profile);
737  if (template_url && template_url->GetDefaultSearchProvider())
738    FirstRunBubbleLauncher::ShowFirstRunBubbleSoon();
739  SetShouldShowWelcomePage();
740  SetShouldDoPersonalDataManagerFirstRun();
741#endif  // !defined(USE_AURA)
742
743  internal::DoPostImportPlatformSpecificTasks();
744}
745
746bool DidPerformProfileImport(bool* exited_successfully) {
747  if (exited_successfully)
748    *exited_successfully = profile_import_exited_successfully;
749  return did_perform_profile_import;
750}
751
752}  // namespace first_run
753