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