first_run.cc revision b2df76ea8fec9e32f6f3718986dba0d95315b29c
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/files/file_path.h" 13#include "base/lazy_instance.h" 14#include "base/metrics/histogram.h" 15#include "base/path_service.h" 16#include "base/prefs/pref_service.h" 17#include "base/stringprintf.h" 18#include "base/utf_string_conversions.h" 19#include "build/build_config.h" 20#include "chrome/browser/browser_process.h" 21#include "chrome/browser/extensions/extension_service.h" 22#include "chrome/browser/extensions/updater/extension_updater.h" 23#include "chrome/browser/first_run/first_run_internal.h" 24#include "chrome/browser/google/google_util.h" 25#include "chrome/browser/importer/external_process_importer_host.h" 26#include "chrome/browser/importer/importer_host.h" 27#include "chrome/browser/importer/importer_list.h" 28#include "chrome/browser/importer/importer_progress_observer.h" 29#include "chrome/browser/importer/importer_type.h" 30#include "chrome/browser/profiles/profile_manager.h" 31#include "chrome/browser/search_engines/template_url_service.h" 32#include "chrome/browser/search_engines/template_url_service_factory.h" 33#include "chrome/browser/shell_integration.h" 34#include "chrome/browser/signin/signin_manager.h" 35#include "chrome/browser/signin/signin_manager_factory.h" 36#include "chrome/browser/signin/signin_tracker.h" 37#include "chrome/browser/ui/browser.h" 38#include "chrome/browser/ui/browser_finder.h" 39#include "chrome/browser/ui/global_error/global_error_service.h" 40#include "chrome/browser/ui/global_error/global_error_service_factory.h" 41#include "chrome/browser/ui/tabs/tab_strip_model.h" 42#include "chrome/browser/ui/webui/ntp/new_tab_ui.h" 43#include "chrome/browser/ui/webui/sync_promo/sync_promo_ui.h" 44#include "chrome/common/chrome_notification_types.h" 45#include "chrome/common/chrome_paths.h" 46#include "chrome/common/chrome_switches.h" 47#include "chrome/common/pref_names.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 g_should_show_welcome_page = false; 66bool g_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 and home page are imported in organic builds only 165 // unless turned off in master_preferences. 166 should_import = !master_pref_set || master_pref; 167 } else { 168 // Bookmarks are never imported, unless turned on in master_preferences. 169 // Search engine and home page import behaviour is similar in non organic 170 // builds. 171 should_import = master_pref_set && master_pref; 172 } 173 174 // If an import policy is set, import items according to policy. If no master 175 // preference is set, but a corresponding recommended policy is set, import 176 // item according to recommended policy. If both a master preference and a 177 // recommended policy is set, the master preference wins. If neither 178 // recommended nor managed policies are set, import item according to what we 179 // worked out above. 180 if (master_pref_set) 181 user_prefs->SetBoolean(pref_path, should_import); 182 183 if (!user_prefs->FindPreference(pref_path)->IsDefaultValue()) { 184 if (user_prefs->GetBoolean(pref_path)) 185 *items |= import_type; 186 } else { // no policy (recommended or managed) is set 187 if (should_import) 188 *items |= import_type; 189 } 190 191 user_prefs->ClearPref(pref_path); 192} 193 194// Imports bookmarks from an html file. The path to the file is provided in 195// the command line. 196void ImportFromFile(Profile* profile, const CommandLine& cmdline) { 197 base::FilePath file_path = 198 cmdline.GetSwitchValuePath(switches::kImportFromFile); 199 if (file_path.empty()) { 200 NOTREACHED(); 201 return; 202 } 203 204 // Deletes itself. 205 ImporterHost* importer_host = new ImporterHost; 206 importer_host->set_headless(); 207 208 importer::SourceProfile source_profile; 209 source_profile.importer_type = importer::TYPE_BOOKMARKS_FILE; 210 source_profile.source_path = file_path; 211 212 first_run::internal::ImportEndedObserver observer; 213 importer_host->SetObserver(&observer); 214 importer_host->StartImportSettings( 215 source_profile, profile, importer::FAVORITES, new ProfileWriter(profile)); 216 // If the import process has not errored out, block on it. 217 if (!observer.ended()) { 218 observer.set_should_quit_message_loop(); 219 MessageLoop::current()->Run(); 220 } 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 244// TODO(gab): This will go back inline above when it is moved to first_run.cc 245// (see TODO above), but needs to be separate for now to satisfy clang error: 246// "[chromium-style] virtual methods with non-empty bodies shouldn't be declared 247// inline". 248void ImportEndedObserver::ImportEnded() { 249 ended_ = true; 250 if (should_quit_message_loop_) 251 MessageLoop::current()->Quit(); 252} 253 254installer::MasterPreferences* 255 LoadMasterPrefs(base::FilePath* master_prefs_path) { 256 if (!master_prefs_path_for_testing.Get().empty()) 257 *master_prefs_path = master_prefs_path_for_testing.Get(); 258 else 259 *master_prefs_path = base::FilePath(MasterPrefsPath()); 260 if (master_prefs_path->empty()) 261 return NULL; 262 installer::MasterPreferences* install_prefs = 263 new installer::MasterPreferences(*master_prefs_path); 264 if (!install_prefs->read_from_file()) { 265 delete install_prefs; 266 return NULL; 267 } 268 269 return install_prefs; 270} 271 272bool CopyPrefFile(const base::FilePath& user_data_dir, 273 const base::FilePath& master_prefs_path) { 274 base::FilePath user_prefs = GetDefaultPrefFilePath(true, user_data_dir); 275 if (user_prefs.empty()) 276 return false; 277 278 // The master prefs are regular prefs so we can just copy the file 279 // to the default place and they just work. 280 return file_util::CopyFile(master_prefs_path, user_prefs); 281} 282 283void SetupMasterPrefsFromInstallPrefs( 284 const installer::MasterPreferences& install_prefs, 285 MasterPrefs* out_prefs) { 286 ConvertStringVectorToGURLVector( 287 install_prefs.GetFirstRunTabs(), &out_prefs->new_tabs); 288 289 install_prefs.GetInt(installer::master_preferences::kDistroPingDelay, 290 &out_prefs->ping_delay); 291 292 bool value = false; 293 if (install_prefs.GetBool( 294 installer::master_preferences::kDistroImportSearchPref, &value)) { 295 if (value) { 296 out_prefs->do_import_items |= importer::SEARCH_ENGINES; 297 } else { 298 out_prefs->dont_import_items |= importer::SEARCH_ENGINES; 299 } 300 } 301 302 // If we're suppressing the first-run bubble, set that preference now. 303 // Otherwise, wait until the user has completed first run to set it, so the 304 // user is guaranteed to see the bubble iff he or she has completed the first 305 // run process. 306 if (install_prefs.GetBool( 307 installer::master_preferences::kDistroSuppressFirstRunBubble, 308 &value) && value) 309 SetShowFirstRunBubblePref(FIRST_RUN_BUBBLE_SUPPRESS); 310 311 if (install_prefs.GetBool( 312 installer::master_preferences::kDistroImportHistoryPref, 313 &value)) { 314 if (value) { 315 out_prefs->do_import_items |= importer::HISTORY; 316 } else { 317 out_prefs->dont_import_items |= importer::HISTORY; 318 } 319 } 320 321 std::string not_used; 322 out_prefs->homepage_defined = install_prefs.GetString( 323 prefs::kHomePage, ¬_used); 324 325 if (install_prefs.GetBool( 326 installer::master_preferences::kDistroImportHomePagePref, 327 &value)) { 328 if (value) { 329 out_prefs->do_import_items |= importer::HOME_PAGE; 330 } else { 331 out_prefs->dont_import_items |= importer::HOME_PAGE; 332 } 333 } 334 335 // Bookmarks are never imported unless specifically turned on. 336 if (install_prefs.GetBool( 337 installer::master_preferences::kDistroImportBookmarksPref, 338 &value)) { 339 if (value) 340 out_prefs->do_import_items |= importer::FAVORITES; 341 else 342 out_prefs->dont_import_items |= importer::FAVORITES; 343 } 344 345 if (install_prefs.GetBool( 346 installer::master_preferences::kMakeChromeDefaultForUser, 347 &value) && value) { 348 out_prefs->make_chrome_default = true; 349 } 350 351 if (install_prefs.GetBool( 352 installer::master_preferences::kSuppressFirstRunDefaultBrowserPrompt, 353 &value) && value) { 354 out_prefs->suppress_first_run_default_browser_prompt = true; 355 } 356 357 out_prefs->variations_seed = install_prefs.GetVariationsSeed(); 358 359 install_prefs.GetString( 360 installer::master_preferences::kDistroSuppressDefaultBrowserPromptPref, 361 &out_prefs->suppress_default_browser_prompt_for_version); 362} 363 364void SetDefaultBrowser(installer::MasterPreferences* install_prefs){ 365 // Even on the first run we only allow for the user choice to take effect if 366 // no policy has been set by the admin. 367 if (!g_browser_process->local_state()->IsManagedPreference( 368 prefs::kDefaultBrowserSettingEnabled)) { 369 bool value = false; 370 if (install_prefs->GetBool( 371 installer::master_preferences::kMakeChromeDefaultForUser, 372 &value) && value) { 373 ShellIntegration::SetAsDefaultBrowser(); 374 } 375 } else { 376 if (g_browser_process->local_state()->GetBoolean( 377 prefs::kDefaultBrowserSettingEnabled)) { 378 ShellIntegration::SetAsDefaultBrowser(); 379 } 380 } 381} 382 383// -- Platform-specific functions -- 384 385#if !defined(OS_LINUX) && !defined(OS_BSD) 386bool IsOrganicFirstRun() { 387 std::string brand; 388 google_util::GetBrand(&brand); 389 return google_util::IsOrganicFirstRun(brand); 390} 391#endif 392 393int ImportBookmarkFromFileIfNeeded(Profile* profile, 394 const CommandLine& cmdline) { 395 if (cmdline.HasSwitch(switches::kImportFromFile)) { 396 // Silently import preset bookmarks from file. 397 // This is an OEM scenario. 398 ImportFromFile(profile, cmdline); 399 } 400 // ImportBookmarkFromFileIfNeeded() will go away as part of 401 // http://crbug.com/219419, so it is fine to hardcode |true| for now. 402 return true; 403} 404 405} // namespace internal 406} // namespace first_run 407 408namespace first_run { 409 410MasterPrefs::MasterPrefs() 411 : ping_delay(0), 412 homepage_defined(false), 413 do_import_items(0), 414 dont_import_items(0), 415 make_chrome_default(false), 416 suppress_first_run_default_browser_prompt(false) { 417} 418 419MasterPrefs::~MasterPrefs() {} 420 421bool IsChromeFirstRun() { 422 if (internal::first_run_ != internal::FIRST_RUN_UNKNOWN) 423 return internal::first_run_ == internal::FIRST_RUN_TRUE; 424 425 base::FilePath first_run_sentinel; 426 if (!internal::GetFirstRunSentinelFilePath(&first_run_sentinel) || 427 file_util::PathExists(first_run_sentinel)) { 428 internal::first_run_ = internal::FIRST_RUN_FALSE; 429 return false; 430 } 431 internal::first_run_ = internal::FIRST_RUN_TRUE; 432 return true; 433} 434 435bool CreateSentinel() { 436 base::FilePath first_run_sentinel; 437 if (!internal::GetFirstRunSentinelFilePath(&first_run_sentinel)) 438 return false; 439 return file_util::WriteFile(first_run_sentinel, "", 0) != -1; 440} 441 442std::string GetPingDelayPrefName() { 443 return base::StringPrintf("%s.%s", 444 installer::master_preferences::kDistroDict, 445 installer::master_preferences::kDistroPingDelay); 446} 447 448void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry) { 449 registry->RegisterIntegerPref( 450 GetPingDelayPrefName().c_str(), 451 0, 452 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 453} 454 455bool RemoveSentinel() { 456 base::FilePath first_run_sentinel; 457 if (!internal::GetFirstRunSentinelFilePath(&first_run_sentinel)) 458 return false; 459 return file_util::Delete(first_run_sentinel, false); 460} 461 462bool SetShowFirstRunBubblePref(FirstRunBubbleOptions show_bubble_option) { 463 PrefService* local_state = g_browser_process->local_state(); 464 if (!local_state) 465 return false; 466 if (local_state->GetInteger( 467 prefs::kShowFirstRunBubbleOption) != FIRST_RUN_BUBBLE_SUPPRESS) { 468 // Set the new state as long as the bubble wasn't explicitly suppressed 469 // already. 470 local_state->SetInteger(prefs::kShowFirstRunBubbleOption, 471 show_bubble_option); 472 } 473 return true; 474} 475 476void SetShouldShowWelcomePage() { 477 g_should_show_welcome_page = true; 478} 479 480bool ShouldShowWelcomePage() { 481 bool retval = g_should_show_welcome_page; 482 g_should_show_welcome_page = false; 483 return retval; 484} 485 486void SetShouldDoPersonalDataManagerFirstRun() { 487 g_should_do_autofill_personal_data_manager_first_run = true; 488} 489 490bool ShouldDoPersonalDataManagerFirstRun() { 491 bool retval = g_should_do_autofill_personal_data_manager_first_run; 492 g_should_do_autofill_personal_data_manager_first_run = false; 493 return retval; 494} 495 496void LogFirstRunMetric(FirstRunBubbleMetric metric) { 497 UMA_HISTOGRAM_ENUMERATION("FirstRun.SearchEngineBubble", metric, 498 NUM_FIRST_RUN_BUBBLE_METRICS); 499} 500 501namespace { 502CommandLine* GetExtraArgumentsInstance() { 503 CR_DEFINE_STATIC_LOCAL(CommandLine, arguments, (CommandLine::NoProgram())); 504 return &arguments; 505} 506} // namespace 507 508void SetExtraArgumentsForImportProcess(const CommandLine& arguments) { 509 GetExtraArgumentsInstance()->AppendArguments(arguments, false); 510} 511 512const CommandLine& GetExtraArgumentsForImportProcess() { 513 return *GetExtraArgumentsInstance(); 514} 515 516// static 517void FirstRunBubbleLauncher::ShowFirstRunBubbleSoon() { 518 SetShowFirstRunBubblePref(FIRST_RUN_BUBBLE_SHOW); 519 // This FirstRunBubbleLauncher instance will manage its own lifetime. 520 new FirstRunBubbleLauncher(); 521} 522 523FirstRunBubbleLauncher::FirstRunBubbleLauncher() { 524 registrar_.Add(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 525 content::NotificationService::AllSources()); 526} 527 528FirstRunBubbleLauncher::~FirstRunBubbleLauncher() {} 529 530void FirstRunBubbleLauncher::Observe( 531 int type, 532 const content::NotificationSource& source, 533 const content::NotificationDetails& details) { 534 DCHECK_EQ(type, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME); 535 Browser* browser = chrome::FindBrowserWithWebContents( 536 content::Source<content::WebContents>(source).ptr()); 537 if (!browser || !browser->is_type_tabbed()) 538 return; 539 540 // Check the preference to determine if the bubble should be shown. 541 PrefService* prefs = g_browser_process->local_state(); 542 if (!prefs || prefs->GetInteger( 543 prefs::kShowFirstRunBubbleOption) != FIRST_RUN_BUBBLE_SHOW) { 544 delete this; 545 return; 546 } 547 548 content::WebContents* contents = 549 browser->tab_strip_model()->GetActiveWebContents(); 550 551 // Suppress the first run bubble if a Gaia sign in page or the continue 552 // URL for the sign in page is showing. 553 if (SyncPromoUI::UseWebBasedSigninFlow()) { 554 if (gaia::IsGaiaSignonRealm(contents->GetURL().GetOrigin()) || 555 SyncPromoUI::IsContinueUrlForWebBasedSigninFlow(contents->GetURL())) { 556 return; 557 } 558 } 559 560 if (contents && contents->GetURL().SchemeIs(chrome::kChromeUIScheme)) { 561 // Suppress the first run bubble if the sync promo is showing. 562 if (contents->GetURL().host() == chrome::kChromeUISyncPromoHost) 563 return; 564 565 // Suppress the first run bubble if 'make chrome metro' flow is showing. 566 if (contents->GetURL().host() == chrome::kChromeUIMetroFlowHost) 567 return; 568 569 // Suppress the first run bubble if the NTP sync promo bubble is showing 570 // or if sign in is in progress. 571 if (contents->GetURL().host() == chrome::kChromeUINewTabHost) { 572 Profile* profile = 573 Profile::FromBrowserContext(contents->GetBrowserContext()); 574 SigninManagerBase* manager = 575 SigninManagerFactory::GetForProfile(profile); 576 bool signin_in_progress = manager && 577 (!manager->GetAuthenticatedUsername().empty() && 578 SigninTracker::GetSigninState(profile, NULL) != 579 SigninTracker::SIGNIN_COMPLETE); 580 bool is_promo_bubble_visible = 581 profile->GetPrefs()->GetBoolean(prefs::kSyncPromoShowNTPBubble); 582 583 if (is_promo_bubble_visible || signin_in_progress) 584 return; 585 } 586 } 587 588 // Suppress the first run bubble if a global error bubble is pending. 589 GlobalErrorService* global_error_service = 590 GlobalErrorServiceFactory::GetForProfile(browser->profile()); 591 if (global_error_service->GetFirstGlobalErrorWithBubbleView() != NULL) 592 return; 593 594 // Reset the preference and notifications to avoid showing the bubble again. 595 prefs->SetInteger(prefs::kShowFirstRunBubbleOption, 596 FIRST_RUN_BUBBLE_DONT_SHOW); 597 598 // Show the bubble now and destroy this bubble launcher. 599 browser->ShowFirstRunBubble(); 600 delete this; 601} 602 603void SetMasterPrefsPathForTesting(const base::FilePath& master_prefs) { 604 internal::master_prefs_path_for_testing.Get() = master_prefs; 605} 606 607ProcessMasterPreferencesResult ProcessMasterPreferences( 608 const base::FilePath& user_data_dir, 609 MasterPrefs* out_prefs) { 610 DCHECK(!user_data_dir.empty()); 611 612#if defined(OS_CHROMEOS) 613 // Chrome OS has its own out-of-box-experience code. Create the sentinel to 614 // mark the fact that we've run once but skip the full first-run flow. 615 CreateSentinel(); 616 return SKIP_FIRST_RUN_TASKS; 617#endif 618 619 base::FilePath master_prefs_path; 620 scoped_ptr<installer::MasterPreferences> 621 install_prefs(internal::LoadMasterPrefs(&master_prefs_path)); 622 623 // Default value in case master preferences is missing or corrupt, or 624 // ping_delay is missing. 625 out_prefs->ping_delay = 90; 626 if (install_prefs.get()) { 627 if (!internal::ShowPostInstallEULAIfNeeded(install_prefs.get())) 628 return EULA_EXIT_NOW; 629 630 if (!internal::CopyPrefFile(user_data_dir, master_prefs_path)) 631 DLOG(ERROR) << "Failed to copy master_preferences to user data dir."; 632 633 DoDelayedInstallExtensionsIfNeeded(install_prefs.get()); 634 635 internal::SetupMasterPrefsFromInstallPrefs(*install_prefs, out_prefs); 636 637 internal::SetImportPreferencesAndLaunchImport(out_prefs, 638 install_prefs.get()); 639 640 internal::SetDefaultBrowser(install_prefs.get()); 641 } 642 643 return DO_FIRST_RUN_TASKS; 644} 645 646void AutoImport( 647 Profile* profile, 648 bool homepage_defined, 649 int import_items, 650 int dont_import_items) { 651#if !defined(USE_AURA) 652 // Deletes itself. 653 ImporterHost* importer_host; 654 // TODO(csilv,mirandac): Out-of-process import has only been qualified on 655 // MacOS X, so we will only use it on that platform since it is required. 656 // Remove this conditional logic once oop import is qualified for 657 // Linux/Windows. http://crbug.com/22142 658#if defined(OS_MACOSX) 659 importer_host = new ExternalProcessImporterHost; 660#else 661 importer_host = new ImporterHost; 662#endif 663 664 base::FilePath local_state_path; 665 PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path); 666 bool local_state_file_exists = file_util::PathExists(local_state_path); 667 668 scoped_refptr<ImporterList> importer_list(new ImporterList(NULL)); 669 importer_list->DetectSourceProfilesHack(); 670 671 // Do import if there is an available profile for us to import. 672 if (importer_list->count() > 0) { 673 // Don't show the warning dialog if import fails. 674 importer_host->set_headless(); 675 int items = 0; 676 677 if (internal::IsOrganicFirstRun()) { 678 // Home page is imported in organic builds only unless turned off or 679 // defined in master_preferences. 680 if (homepage_defined) { 681 dont_import_items |= importer::HOME_PAGE; 682 if (import_items & importer::HOME_PAGE) 683 import_items &= ~importer::HOME_PAGE; 684 } 685 // Search engines are not imported automatically in organic builds if the 686 // user already has a user preferences directory. 687 if (local_state_file_exists) { 688 dont_import_items |= importer::SEARCH_ENGINES; 689 if (import_items & importer::SEARCH_ENGINES) 690 import_items &= ~importer::SEARCH_ENGINES; 691 } 692 } 693 694 PrefService* user_prefs = profile->GetPrefs(); 695 696 SetImportItem(user_prefs, 697 prefs::kImportHistory, 698 import_items, 699 dont_import_items, 700 importer::HISTORY, 701 &items); 702 SetImportItem(user_prefs, 703 prefs::kImportHomepage, 704 import_items, 705 dont_import_items, 706 importer::HOME_PAGE, 707 &items); 708 SetImportItem(user_prefs, 709 prefs::kImportSearchEngine, 710 import_items, 711 dont_import_items, 712 importer::SEARCH_ENGINES, 713 &items); 714 SetImportItem(user_prefs, 715 prefs::kImportBookmarks, 716 import_items, 717 dont_import_items, 718 importer::FAVORITES, 719 &items); 720 721 importer::LogImporterUseToMetrics( 722 "AutoImport", importer_list->GetSourceProfileAt(0).importer_type); 723 724 profile_import_exited_successfully = 725 internal::ImportSettings(profile, importer_host, importer_list, items); 726 DCHECK(profile_import_exited_successfully); 727 } 728 729 content::RecordAction(UserMetricsAction("FirstRunDef_Accept")); 730 731#endif // !defined(USE_AURA) 732 did_perform_profile_import = true; 733} 734 735void DoPostImportTasks(Profile* profile, bool make_chrome_default) { 736 if (make_chrome_default && 737 ShellIntegration::CanSetAsDefaultBrowser() == 738 ShellIntegration::SET_DEFAULT_UNATTENDED) { 739 ShellIntegration::SetAsDefaultBrowser(); 740 } 741 742 // Display the first run bubble if there is a default search provider. 743 TemplateURLService* template_url = 744 TemplateURLServiceFactory::GetForProfile(profile); 745 if (template_url && template_url->GetDefaultSearchProvider()) 746 FirstRunBubbleLauncher::ShowFirstRunBubbleSoon(); 747 SetShouldShowWelcomePage(); 748 SetShouldDoPersonalDataManagerFirstRun(); 749 750 internal::DoPostImportPlatformSpecificTasks(profile); 751} 752 753bool DidPerformProfileImport(bool* exited_successfully) { 754 if (exited_successfully) 755 *exited_successfully = profile_import_exited_successfully; 756 return did_perform_profile_import; 757} 758 759} // namespace first_run 760