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