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