first_run.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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/importer/profile_writer.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/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 "googleurl/src/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 ProfileManager::GetDefaultProfileDir(user_data_dir); 172 if (create_profile_dir) { 173 if (!file_util::PathExists(default_pref_dir)) { 174 if (!file_util::CreateDirectory(default_pref_dir)) 175 return base::FilePath(); 176 } 177 } 178 return ProfileManager::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(ImporterHost* importer_host, 235 const importer::SourceProfile& source_profile, 236 Profile* target_profile, 237 uint16 items_to_import) { 238 ImportEndedObserver observer; 239 importer_host->SetObserver(&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 ImporterHost* 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 ImporterHost* 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 file_util::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} // namespace first_run 457 458namespace first_run { 459 460MasterPrefs::MasterPrefs() 461 : ping_delay(0), 462 homepage_defined(false), 463 do_import_items(0), 464 dont_import_items(0), 465 make_chrome_default(false), 466 suppress_first_run_default_browser_prompt(false) { 467} 468 469MasterPrefs::~MasterPrefs() {} 470 471bool IsChromeFirstRun() { 472 if (internal::first_run_ != internal::FIRST_RUN_UNKNOWN) 473 return internal::first_run_ == internal::FIRST_RUN_TRUE; 474 475 base::FilePath first_run_sentinel; 476 if (!internal::GetFirstRunSentinelFilePath(&first_run_sentinel) || 477 file_util::PathExists(first_run_sentinel)) { 478 internal::first_run_ = internal::FIRST_RUN_FALSE; 479 return false; 480 } 481 internal::first_run_ = internal::FIRST_RUN_TRUE; 482 return true; 483} 484 485bool CreateSentinel() { 486 base::FilePath first_run_sentinel; 487 if (!internal::GetFirstRunSentinelFilePath(&first_run_sentinel)) 488 return false; 489 return file_util::WriteFile(first_run_sentinel, "", 0) != -1; 490} 491 492std::string GetPingDelayPrefName() { 493 return base::StringPrintf("%s.%s", 494 installer::master_preferences::kDistroDict, 495 installer::master_preferences::kDistroPingDelay); 496} 497 498void RegisterUserPrefs(user_prefs::PrefRegistrySyncable* registry) { 499 registry->RegisterIntegerPref( 500 GetPingDelayPrefName().c_str(), 501 0, 502 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 503} 504 505bool RemoveSentinel() { 506 base::FilePath first_run_sentinel; 507 if (!internal::GetFirstRunSentinelFilePath(&first_run_sentinel)) 508 return false; 509 return file_util::Delete(first_run_sentinel, false); 510} 511 512bool SetShowFirstRunBubblePref(FirstRunBubbleOptions show_bubble_option) { 513 PrefService* local_state = g_browser_process->local_state(); 514 if (!local_state) 515 return false; 516 if (local_state->GetInteger( 517 prefs::kShowFirstRunBubbleOption) != FIRST_RUN_BUBBLE_SUPPRESS) { 518 // Set the new state as long as the bubble wasn't explicitly suppressed 519 // already. 520 local_state->SetInteger(prefs::kShowFirstRunBubbleOption, 521 show_bubble_option); 522 } 523 return true; 524} 525 526void SetShouldShowWelcomePage() { 527 g_should_show_welcome_page = true; 528} 529 530bool ShouldShowWelcomePage() { 531 bool retval = g_should_show_welcome_page; 532 g_should_show_welcome_page = false; 533 return retval; 534} 535 536void SetShouldDoPersonalDataManagerFirstRun() { 537 g_should_do_autofill_personal_data_manager_first_run = true; 538} 539 540bool ShouldDoPersonalDataManagerFirstRun() { 541 bool retval = g_should_do_autofill_personal_data_manager_first_run; 542 g_should_do_autofill_personal_data_manager_first_run = false; 543 return retval; 544} 545 546void LogFirstRunMetric(FirstRunBubbleMetric metric) { 547 UMA_HISTOGRAM_ENUMERATION("FirstRun.SearchEngineBubble", metric, 548 NUM_FIRST_RUN_BUBBLE_METRICS); 549} 550 551// static 552void FirstRunBubbleLauncher::ShowFirstRunBubbleSoon() { 553 SetShowFirstRunBubblePref(FIRST_RUN_BUBBLE_SHOW); 554 // This FirstRunBubbleLauncher instance will manage its own lifetime. 555 new FirstRunBubbleLauncher(); 556} 557 558FirstRunBubbleLauncher::FirstRunBubbleLauncher() { 559 registrar_.Add(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 560 content::NotificationService::AllSources()); 561} 562 563FirstRunBubbleLauncher::~FirstRunBubbleLauncher() {} 564 565void FirstRunBubbleLauncher::Observe( 566 int type, 567 const content::NotificationSource& source, 568 const content::NotificationDetails& details) { 569 DCHECK_EQ(type, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME); 570 Browser* browser = chrome::FindBrowserWithWebContents( 571 content::Source<content::WebContents>(source).ptr()); 572 if (!browser || !browser->is_type_tabbed()) 573 return; 574 575 // Check the preference to determine if the bubble should be shown. 576 PrefService* prefs = g_browser_process->local_state(); 577 if (!prefs || prefs->GetInteger( 578 prefs::kShowFirstRunBubbleOption) != FIRST_RUN_BUBBLE_SHOW) { 579 delete this; 580 return; 581 } 582 583 content::WebContents* contents = 584 browser->tab_strip_model()->GetActiveWebContents(); 585 586 // Suppress the first run bubble if a Gaia sign in page or the continue 587 // URL for the sign in page is showing. 588 if (SyncPromoUI::UseWebBasedSigninFlow()) { 589 if (gaia::IsGaiaSignonRealm(contents->GetURL().GetOrigin()) || 590 SyncPromoUI::IsContinueUrlForWebBasedSigninFlow(contents->GetURL())) { 591 return; 592 } 593 } 594 595 if (contents && contents->GetURL().SchemeIs(chrome::kChromeUIScheme)) { 596 // Suppress the first run bubble if the sync promo is showing. 597 if (contents->GetURL().host() == chrome::kChromeUISyncPromoHost) 598 return; 599 600 // Suppress the first run bubble if 'make chrome metro' flow is showing. 601 if (contents->GetURL().host() == chrome::kChromeUIMetroFlowHost) 602 return; 603 604 // Suppress the first run bubble if the NTP sync promo bubble is showing 605 // or if sign in is in progress. 606 if (contents->GetURL().host() == chrome::kChromeUINewTabHost) { 607 Profile* profile = 608 Profile::FromBrowserContext(contents->GetBrowserContext()); 609 SigninManagerBase* manager = 610 SigninManagerFactory::GetForProfile(profile); 611 bool signin_in_progress = manager && 612 (!manager->GetAuthenticatedUsername().empty() && 613 SigninTracker::GetSigninState(profile, NULL) != 614 SigninTracker::SIGNIN_COMPLETE); 615 bool is_promo_bubble_visible = 616 profile->GetPrefs()->GetBoolean(prefs::kSyncPromoShowNTPBubble); 617 618 if (is_promo_bubble_visible || signin_in_progress) 619 return; 620 } 621 } 622 623 // Suppress the first run bubble if a global error bubble is pending. 624 GlobalErrorService* global_error_service = 625 GlobalErrorServiceFactory::GetForProfile(browser->profile()); 626 if (global_error_service->GetFirstGlobalErrorWithBubbleView() != NULL) 627 return; 628 629 // Reset the preference and notifications to avoid showing the bubble again. 630 prefs->SetInteger(prefs::kShowFirstRunBubbleOption, 631 FIRST_RUN_BUBBLE_DONT_SHOW); 632 633 // Show the bubble now and destroy this bubble launcher. 634 browser->ShowFirstRunBubble(); 635 delete this; 636} 637 638void SetMasterPrefsPathForTesting(const base::FilePath& master_prefs) { 639 internal::master_prefs_path_for_testing.Get() = master_prefs; 640} 641 642ProcessMasterPreferencesResult ProcessMasterPreferences( 643 const base::FilePath& user_data_dir, 644 MasterPrefs* out_prefs) { 645 DCHECK(!user_data_dir.empty()); 646 647#if defined(OS_CHROMEOS) 648 // Chrome OS has its own out-of-box-experience code. Create the sentinel to 649 // mark the fact that we've run once but skip the full first-run flow. 650 CreateSentinel(); 651 return SKIP_FIRST_RUN_TASKS; 652#endif 653 654 base::FilePath master_prefs_path; 655 scoped_ptr<installer::MasterPreferences> 656 install_prefs(internal::LoadMasterPrefs(&master_prefs_path)); 657 658 // Default value in case master preferences is missing or corrupt, or 659 // ping_delay is missing. 660 out_prefs->ping_delay = 90; 661 if (install_prefs.get()) { 662 if (!internal::ShowPostInstallEULAIfNeeded(install_prefs.get())) 663 return EULA_EXIT_NOW; 664 665 if (!internal::CopyPrefFile(user_data_dir, master_prefs_path)) 666 DLOG(ERROR) << "Failed to copy master_preferences to user data dir."; 667 668 DoDelayedInstallExtensionsIfNeeded(install_prefs.get()); 669 670 internal::SetupMasterPrefsFromInstallPrefs(*install_prefs, out_prefs); 671 672 internal::SetDefaultBrowser(install_prefs.get()); 673 } 674 675 return DO_FIRST_RUN_TASKS; 676} 677 678void AutoImport( 679 Profile* profile, 680 bool homepage_defined, 681 int import_items, 682 int dont_import_items, 683 const std::string& import_bookmarks_path) { 684#if !defined(USE_AURA) 685 // Deletes itself. 686 ImporterHost* importer_host; 687 // TODO(csilv,mirandac): Out-of-process import has only been qualified on 688 // MacOS X and Windows, so we will only use it on those platforms. 689 // Linux still uses the in-process import (http://crbug.com/56816). 690#if defined(OS_MACOSX) || defined(OS_WIN) 691 importer_host = new ExternalProcessImporterHost; 692#else 693 importer_host = new ImporterHost; 694#endif 695 696 base::FilePath local_state_path; 697 PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path); 698 bool local_state_file_exists = file_util::PathExists(local_state_path); 699 700 scoped_refptr<ImporterList> importer_list(new ImporterList(NULL)); 701 importer_list->DetectSourceProfilesHack(); 702 703 // Do import if there is an available profile for us to import. 704 if (importer_list->count() > 0) { 705 // Don't show the warning dialog if import fails. 706 importer_host->set_headless(); 707 int items = 0; 708 709 if (internal::IsOrganicFirstRun()) { 710 // Home page is imported in organic builds only unless turned off or 711 // defined in master_preferences. 712 if (homepage_defined) { 713 dont_import_items |= importer::HOME_PAGE; 714 if (import_items & importer::HOME_PAGE) 715 import_items &= ~importer::HOME_PAGE; 716 } 717 // Search engines are not imported automatically in organic builds if the 718 // user already has a user preferences directory. 719 if (local_state_file_exists) { 720 dont_import_items |= importer::SEARCH_ENGINES; 721 if (import_items & importer::SEARCH_ENGINES) 722 import_items &= ~importer::SEARCH_ENGINES; 723 } 724 } 725 726 PrefService* user_prefs = profile->GetPrefs(); 727 728 SetImportItem(user_prefs, 729 prefs::kImportHistory, 730 import_items, 731 dont_import_items, 732 importer::HISTORY, 733 &items); 734 SetImportItem(user_prefs, 735 prefs::kImportHomepage, 736 import_items, 737 dont_import_items, 738 importer::HOME_PAGE, 739 &items); 740 SetImportItem(user_prefs, 741 prefs::kImportSearchEngine, 742 import_items, 743 dont_import_items, 744 importer::SEARCH_ENGINES, 745 &items); 746 SetImportItem(user_prefs, 747 prefs::kImportBookmarks, 748 import_items, 749 dont_import_items, 750 importer::FAVORITES, 751 &items); 752 753 importer::LogImporterUseToMetrics( 754 "AutoImport", importer_list->GetSourceProfileAt(0).importer_type); 755 756 ImportSettings(profile, importer_host, importer_list, items); 757 } 758 759 if (!import_bookmarks_path.empty()) { 760 // Deletes itself. 761 ImporterHost* file_importer_host; 762 // TODO(gab): Make Linux use OOP import as well (http://crbug.com/56816) and 763 // get rid of these ugly ifdefs. 764#if defined(OS_MACOSX) || defined(OS_WIN) 765 file_importer_host = new ExternalProcessImporterHost; 766#else 767 file_importer_host = new ImporterHost; 768#endif 769 file_importer_host->set_headless(); 770 771 ImportFromFile(profile, file_importer_host, import_bookmarks_path); 772 } 773 774 content::RecordAction(UserMetricsAction("FirstRunDef_Accept")); 775 776#endif // !defined(USE_AURA) 777 g_auto_import_state |= AUTO_IMPORT_CALLED; 778} 779 780void DoPostImportTasks(Profile* profile, bool make_chrome_default) { 781 if (make_chrome_default && 782 ShellIntegration::CanSetAsDefaultBrowser() == 783 ShellIntegration::SET_DEFAULT_UNATTENDED) { 784 ShellIntegration::SetAsDefaultBrowser(); 785 } 786 787 // Display the first run bubble if there is a default search provider. 788 TemplateURLService* template_url = 789 TemplateURLServiceFactory::GetForProfile(profile); 790 if (template_url && template_url->GetDefaultSearchProvider()) 791 FirstRunBubbleLauncher::ShowFirstRunBubbleSoon(); 792 SetShouldShowWelcomePage(); 793 SetShouldDoPersonalDataManagerFirstRun(); 794 795 internal::DoPostImportPlatformSpecificTasks(profile); 796} 797 798uint16 auto_import_state() { 799 return g_auto_import_state; 800} 801 802} // namespace first_run 803