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