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