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