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_brand.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/pref_registry/pref_registry_syncable.h" 57 #include "components/signin/core/browser/signin_manager.h" 58 #include "components/signin/core/browser/signin_tracker.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 68 using base::UserMetricsAction; 69 70 namespace { 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. 75 uint16 g_auto_import_state = first_run::AUTO_IMPORT_NONE; 76 77 // Flags for functions of similar name. 78 bool g_should_show_welcome_page = false; 79 bool 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. 85 class 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. 119 class 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. 163 void DoDelayedInstallExtensions() { 164 new FirstRunDelayedTasks(FirstRunDelayedTasks::INSTALL_EXTENSIONS); 165 } 166 167 void 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. 178 void 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 { 218 // no policy (recommended or managed) is set 219 if (should_import) 220 *items |= import_type; 221 } 222 223 user_prefs->ClearPref(pref_path); 224 } 225 226 // Launches the import, via |importer_host|, from |source_profile| into 227 // |target_profile| for the items specified in the |items_to_import| bitfield. 228 // This may be done in a separate process depending on the platform, but it will 229 // always block until done. 230 void ImportFromSourceProfile(ExternalProcessImporterHost* importer_host, 231 const importer::SourceProfile& source_profile, 232 Profile* target_profile, 233 uint16 items_to_import) { 234 ImportEndedObserver observer; 235 importer_host->set_observer(&observer); 236 importer_host->StartImportSettings(source_profile, 237 target_profile, 238 items_to_import, 239 new ProfileWriter(target_profile)); 240 // If the import process has not errored out, block on it. 241 if (!observer.ended()) { 242 base::RunLoop loop; 243 observer.set_callback_for_import_end(loop.QuitClosure()); 244 loop.Run(); 245 observer.set_callback_for_import_end(base::Closure()); 246 } 247 } 248 249 // Imports bookmarks from an html file whose path is provided by 250 // |import_bookmarks_path|. 251 void ImportFromFile(Profile* profile, 252 ExternalProcessImporterHost* file_importer_host, 253 const std::string& import_bookmarks_path) { 254 importer::SourceProfile source_profile; 255 source_profile.importer_type = importer::TYPE_BOOKMARKS_FILE; 256 257 const base::FilePath::StringType& import_bookmarks_path_str = 258 #if defined(OS_WIN) 259 base::UTF8ToUTF16(import_bookmarks_path); 260 #else 261 import_bookmarks_path; 262 #endif 263 source_profile.source_path = base::FilePath(import_bookmarks_path_str); 264 265 ImportFromSourceProfile(file_importer_host, source_profile, profile, 266 importer::FAVORITES); 267 g_auto_import_state |= first_run::AUTO_IMPORT_BOOKMARKS_FILE_IMPORTED; 268 } 269 270 // Imports settings from the first profile in |importer_list|. 271 void ImportSettings(Profile* profile, 272 ExternalProcessImporterHost* importer_host, 273 scoped_ptr<ImporterList> importer_list, 274 int items_to_import) { 275 const importer::SourceProfile& source_profile = 276 importer_list->GetSourceProfileAt(0); 277 278 // Ensure that importers aren't requested to import items that they do not 279 // support. If there is no overlap, skip. 280 items_to_import &= source_profile.services_supported; 281 if (items_to_import == 0) 282 return; 283 284 ImportFromSourceProfile(importer_host, source_profile, profile, 285 items_to_import); 286 g_auto_import_state |= first_run::AUTO_IMPORT_PROFILE_IMPORTED; 287 } 288 289 GURL UrlFromString(const std::string& in) { 290 return GURL(in); 291 } 292 293 void ConvertStringVectorToGURLVector( 294 const std::vector<std::string>& src, 295 std::vector<GURL>* ret) { 296 ret->resize(src.size()); 297 std::transform(src.begin(), src.end(), ret->begin(), &UrlFromString); 298 } 299 300 // Show the first run search engine bubble at the first appropriate opportunity. 301 // This bubble may be delayed by other UI, like global errors and sync promos. 302 class FirstRunBubbleLauncher : public content::NotificationObserver { 303 public: 304 // Show the bubble at the first appropriate opportunity. This function 305 // instantiates a FirstRunBubbleLauncher, which manages its own lifetime. 306 static void ShowFirstRunBubbleSoon(); 307 308 private: 309 FirstRunBubbleLauncher(); 310 virtual ~FirstRunBubbleLauncher(); 311 312 // content::NotificationObserver: 313 virtual void Observe(int type, 314 const content::NotificationSource& source, 315 const content::NotificationDetails& details) OVERRIDE; 316 317 content::NotificationRegistrar registrar_; 318 319 DISALLOW_COPY_AND_ASSIGN(FirstRunBubbleLauncher); 320 }; 321 322 // static 323 void FirstRunBubbleLauncher::ShowFirstRunBubbleSoon() { 324 SetShowFirstRunBubblePref(first_run::FIRST_RUN_BUBBLE_SHOW); 325 // This FirstRunBubbleLauncher instance will manage its own lifetime. 326 new FirstRunBubbleLauncher(); 327 } 328 329 FirstRunBubbleLauncher::FirstRunBubbleLauncher() { 330 registrar_.Add(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 331 content::NotificationService::AllSources()); 332 333 // This notification is required to observe the switch between the sync setup 334 // page and the general settings page. 335 registrar_.Add(this, chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED, 336 content::NotificationService::AllSources()); 337 } 338 339 FirstRunBubbleLauncher::~FirstRunBubbleLauncher() {} 340 341 void FirstRunBubbleLauncher::Observe( 342 int type, 343 const content::NotificationSource& source, 344 const content::NotificationDetails& details) { 345 DCHECK(type == content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME || 346 type == chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED); 347 348 Browser* browser = chrome::FindBrowserWithWebContents( 349 content::Source<content::WebContents>(source).ptr()); 350 if (!browser || !browser->is_type_tabbed()) 351 return; 352 353 // Check the preference to determine if the bubble should be shown. 354 PrefService* prefs = g_browser_process->local_state(); 355 if (!prefs || prefs->GetInteger(prefs::kShowFirstRunBubbleOption) != 356 first_run::FIRST_RUN_BUBBLE_SHOW) { 357 delete this; 358 return; 359 } 360 361 content::WebContents* contents = 362 browser->tab_strip_model()->GetActiveWebContents(); 363 364 // Suppress the first run bubble if a Gaia sign in page, the continue 365 // URL for the sign in page or the sync setup page is showing. 366 if (contents && 367 (contents->GetURL().GetOrigin().spec() == 368 chrome::kChromeUIChromeSigninURL || 369 gaia::IsGaiaSignonRealm(contents->GetURL().GetOrigin()) || 370 signin::IsContinueUrlForWebBasedSigninFlow(contents->GetURL()) || 371 (contents->GetURL() == 372 chrome::GetSettingsUrl(chrome::kSyncSetupSubPage)))) { 373 return; 374 } 375 376 if (contents && contents->GetURL().SchemeIs(content::kChromeUIScheme)) { 377 // Suppress the first run bubble if 'make chrome metro' flow is showing. 378 if (contents->GetURL().host() == chrome::kChromeUIMetroFlowHost) 379 return; 380 381 // Suppress the first run bubble if the NTP sync promo bubble is showing 382 // or if sign in is in progress. 383 if (contents->GetURL().host() == chrome::kChromeUINewTabHost) { 384 Profile* profile = 385 Profile::FromBrowserContext(contents->GetBrowserContext()); 386 SigninManagerBase* manager = 387 SigninManagerFactory::GetForProfile(profile); 388 bool signin_in_progress = manager && manager->AuthInProgress(); 389 bool is_promo_bubble_visible = 390 profile->GetPrefs()->GetBoolean(prefs::kSignInPromoShowNTPBubble); 391 392 if (is_promo_bubble_visible || signin_in_progress) 393 return; 394 } 395 } 396 397 // Suppress the first run bubble if a global error bubble is pending. 398 GlobalErrorService* global_error_service = 399 GlobalErrorServiceFactory::GetForProfile(browser->profile()); 400 if (global_error_service->GetFirstGlobalErrorWithBubbleView() != NULL) 401 return; 402 403 // Reset the preference and notifications to avoid showing the bubble again. 404 prefs->SetInteger(prefs::kShowFirstRunBubbleOption, 405 first_run::FIRST_RUN_BUBBLE_DONT_SHOW); 406 407 // Show the bubble now and destroy this bubble launcher. 408 browser->ShowFirstRunBubble(); 409 delete this; 410 } 411 412 static base::LazyInstance<base::FilePath> master_prefs_path_for_testing 413 = LAZY_INSTANCE_INITIALIZER; 414 415 // Loads master preferences from the master preference file into the installer 416 // master preferences. Returns the pointer to installer::MasterPreferences 417 // object if successful; otherwise, returns NULL. 418 installer::MasterPreferences* LoadMasterPrefs() { 419 base::FilePath master_prefs_path; 420 if (!master_prefs_path_for_testing.Get().empty()) 421 master_prefs_path = master_prefs_path_for_testing.Get(); 422 else 423 master_prefs_path = base::FilePath(first_run::internal::MasterPrefsPath()); 424 if (master_prefs_path.empty()) 425 return NULL; 426 installer::MasterPreferences* install_prefs = 427 new installer::MasterPreferences(master_prefs_path); 428 if (!install_prefs->read_from_file()) { 429 delete install_prefs; 430 return NULL; 431 } 432 433 return install_prefs; 434 } 435 436 // Makes chrome the user's default browser according to policy or 437 // |make_chrome_default_for_user| if no policy is set. 438 void ProcessDefaultBrowserPolicy(bool make_chrome_default_for_user) { 439 // Only proceed if chrome can be made default unattended. The interactive case 440 // (Windows 8+) is handled by the first run default browser prompt. 441 if (ShellIntegration::CanSetAsDefaultBrowser() == 442 ShellIntegration::SET_DEFAULT_UNATTENDED) { 443 // The policy has precedence over the user's choice. 444 if (g_browser_process->local_state()->IsManagedPreference( 445 prefs::kDefaultBrowserSettingEnabled)) { 446 if (g_browser_process->local_state()->GetBoolean( 447 prefs::kDefaultBrowserSettingEnabled)) { 448 ShellIntegration::SetAsDefaultBrowser(); 449 } 450 } else if (make_chrome_default_for_user) { 451 ShellIntegration::SetAsDefaultBrowser(); 452 } 453 } 454 } 455 456 } // namespace 457 458 namespace first_run { 459 namespace internal { 460 461 FirstRunState g_first_run = FIRST_RUN_UNKNOWN; 462 463 void SetupMasterPrefsFromInstallPrefs( 464 const installer::MasterPreferences& install_prefs, 465 MasterPrefs* out_prefs) { 466 ConvertStringVectorToGURLVector( 467 install_prefs.GetFirstRunTabs(), &out_prefs->new_tabs); 468 469 install_prefs.GetInt(installer::master_preferences::kDistroPingDelay, 470 &out_prefs->ping_delay); 471 472 bool value = false; 473 if (install_prefs.GetBool( 474 installer::master_preferences::kDistroImportSearchPref, &value)) { 475 if (value) { 476 out_prefs->do_import_items |= importer::SEARCH_ENGINES; 477 } else { 478 out_prefs->dont_import_items |= importer::SEARCH_ENGINES; 479 } 480 } 481 482 // If we're suppressing the first-run bubble, set that preference now. 483 // Otherwise, wait until the user has completed first run to set it, so the 484 // user is guaranteed to see the bubble iff he or she has completed the first 485 // run process. 486 if (install_prefs.GetBool( 487 installer::master_preferences::kDistroSuppressFirstRunBubble, 488 &value) && value) 489 SetShowFirstRunBubblePref(FIRST_RUN_BUBBLE_SUPPRESS); 490 491 if (install_prefs.GetBool( 492 installer::master_preferences::kDistroImportHistoryPref, 493 &value)) { 494 if (value) { 495 out_prefs->do_import_items |= importer::HISTORY; 496 } else { 497 out_prefs->dont_import_items |= importer::HISTORY; 498 } 499 } 500 501 std::string not_used; 502 out_prefs->homepage_defined = install_prefs.GetString( 503 prefs::kHomePage, ¬_used); 504 505 if (install_prefs.GetBool( 506 installer::master_preferences::kDistroImportHomePagePref, 507 &value)) { 508 if (value) { 509 out_prefs->do_import_items |= importer::HOME_PAGE; 510 } else { 511 out_prefs->dont_import_items |= importer::HOME_PAGE; 512 } 513 } 514 515 // Bookmarks are never imported unless specifically turned on. 516 if (install_prefs.GetBool( 517 installer::master_preferences::kDistroImportBookmarksPref, 518 &value)) { 519 if (value) 520 out_prefs->do_import_items |= importer::FAVORITES; 521 else 522 out_prefs->dont_import_items |= importer::FAVORITES; 523 } 524 525 if (install_prefs.GetBool( 526 installer::master_preferences::kMakeChromeDefaultForUser, 527 &value) && value) { 528 out_prefs->make_chrome_default_for_user = true; 529 } 530 531 if (install_prefs.GetBool( 532 installer::master_preferences::kSuppressFirstRunDefaultBrowserPrompt, 533 &value) && value) { 534 out_prefs->suppress_first_run_default_browser_prompt = true; 535 } 536 537 install_prefs.GetString( 538 installer::master_preferences::kDistroImportBookmarksFromFilePref, 539 &out_prefs->import_bookmarks_path); 540 541 out_prefs->variations_seed = install_prefs.GetVariationsSeed(); 542 out_prefs->variations_seed_signature = 543 install_prefs.GetVariationsSeedSignature(); 544 545 install_prefs.GetString( 546 installer::master_preferences::kDistroSuppressDefaultBrowserPromptPref, 547 &out_prefs->suppress_default_browser_prompt_for_version); 548 } 549 550 bool GetFirstRunSentinelFilePath(base::FilePath* path) { 551 base::FilePath user_data_dir; 552 if (!PathService::Get(chrome::DIR_USER_DATA, &user_data_dir)) 553 return false; 554 *path = user_data_dir.Append(chrome::kFirstRunSentinel); 555 return true; 556 } 557 558 bool CreateSentinel() { 559 base::FilePath first_run_sentinel; 560 return GetFirstRunSentinelFilePath(&first_run_sentinel) && 561 base::WriteFile(first_run_sentinel, "", 0) != -1; 562 } 563 564 // -- Platform-specific functions -- 565 566 #if !defined(OS_LINUX) && !defined(OS_BSD) 567 bool IsOrganicFirstRun() { 568 std::string brand; 569 google_brand::GetBrand(&brand); 570 return google_brand::IsOrganicFirstRun(brand); 571 } 572 #endif 573 574 } // namespace internal 575 576 MasterPrefs::MasterPrefs() 577 : ping_delay(0), 578 homepage_defined(false), 579 do_import_items(0), 580 dont_import_items(0), 581 make_chrome_default_for_user(false), 582 suppress_first_run_default_browser_prompt(false) { 583 } 584 585 MasterPrefs::~MasterPrefs() {} 586 587 bool IsChromeFirstRun() { 588 if (internal::g_first_run == internal::FIRST_RUN_UNKNOWN) { 589 internal::g_first_run = internal::FIRST_RUN_FALSE; 590 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 591 if (command_line->HasSwitch(switches::kForceFirstRun) || 592 (!command_line->HasSwitch(switches::kNoFirstRun) && 593 !internal::IsFirstRunSentinelPresent())) { 594 internal::g_first_run = internal::FIRST_RUN_TRUE; 595 } 596 } 597 return internal::g_first_run == internal::FIRST_RUN_TRUE; 598 } 599 600 #if defined(OS_MACOSX) 601 bool IsFirstRunSuppressed(const CommandLine& command_line) { 602 return command_line.HasSwitch(switches::kNoFirstRun); 603 } 604 #endif 605 606 void CreateSentinelIfNeeded() { 607 if (IsChromeFirstRun()) 608 internal::CreateSentinel(); 609 } 610 611 std::string GetPingDelayPrefName() { 612 return base::StringPrintf("%s.%s", 613 installer::master_preferences::kDistroDict, 614 installer::master_preferences::kDistroPingDelay); 615 } 616 617 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { 618 registry->RegisterIntegerPref( 619 GetPingDelayPrefName().c_str(), 620 0, 621 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 622 } 623 624 bool 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 638 void SetShouldShowWelcomePage() { 639 g_should_show_welcome_page = true; 640 } 641 642 bool ShouldShowWelcomePage() { 643 bool retval = g_should_show_welcome_page; 644 g_should_show_welcome_page = false; 645 return retval; 646 } 647 648 void SetShouldDoPersonalDataManagerFirstRun() { 649 g_should_do_autofill_personal_data_manager_first_run = true; 650 } 651 652 bool 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 658 void LogFirstRunMetric(FirstRunBubbleMetric metric) { 659 UMA_HISTOGRAM_ENUMERATION("FirstRun.SearchEngineBubble", metric, 660 NUM_FIRST_RUN_BUBBLE_METRICS); 661 } 662 663 void SetMasterPrefsPathForTesting(const base::FilePath& master_prefs) { 664 master_prefs_path_for_testing.Get() = master_prefs; 665 } 666 667 ProcessMasterPreferencesResult 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 695 void 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 // It may be possible to do the if block below asynchronously. In which case, 706 // get rid of this RunLoop. http://crbug.com/366116. 707 base::RunLoop run_loop; 708 scoped_ptr<ImporterList> importer_list(new ImporterList()); 709 importer_list->DetectSourceProfiles( 710 g_browser_process->GetApplicationLocale(), 711 false, // include_interactive_profiles? 712 run_loop.QuitClosure()); 713 run_loop.Run(); 714 715 // Do import if there is an available profile for us to import. 716 if (importer_list->count() > 0) { 717 if (internal::IsOrganicFirstRun()) { 718 // Home page is imported in organic builds only unless turned off or 719 // defined in master_preferences. 720 if (homepage_defined) { 721 dont_import_items |= importer::HOME_PAGE; 722 if (import_items & importer::HOME_PAGE) 723 import_items &= ~importer::HOME_PAGE; 724 } 725 // Search engines are not imported automatically in organic builds if the 726 // user already has a user preferences directory. 727 if (local_state_file_exists) { 728 dont_import_items |= importer::SEARCH_ENGINES; 729 if (import_items & importer::SEARCH_ENGINES) 730 import_items &= ~importer::SEARCH_ENGINES; 731 } 732 } 733 734 PrefService* user_prefs = profile->GetPrefs(); 735 int items = 0; 736 737 SetImportItem(user_prefs, 738 prefs::kImportHistory, 739 import_items, 740 dont_import_items, 741 importer::HISTORY, 742 &items); 743 SetImportItem(user_prefs, 744 prefs::kImportHomepage, 745 import_items, 746 dont_import_items, 747 importer::HOME_PAGE, 748 &items); 749 SetImportItem(user_prefs, 750 prefs::kImportSearchEngine, 751 import_items, 752 dont_import_items, 753 importer::SEARCH_ENGINES, 754 &items); 755 SetImportItem(user_prefs, 756 prefs::kImportBookmarks, 757 import_items, 758 dont_import_items, 759 importer::FAVORITES, 760 &items); 761 762 // Deletes itself. 763 ExternalProcessImporterHost* importer_host = 764 new ExternalProcessImporterHost; 765 766 // Don't show the warning dialog if import fails. 767 importer_host->set_headless(); 768 769 importer::LogImporterUseToMetrics( 770 "AutoImport", importer_list->GetSourceProfileAt(0).importer_type); 771 772 ImportSettings(profile, importer_host, importer_list.Pass(), items); 773 } 774 775 if (!import_bookmarks_path.empty()) { 776 // Deletes itself. 777 ExternalProcessImporterHost* file_importer_host = 778 new ExternalProcessImporterHost; 779 file_importer_host->set_headless(); 780 781 ImportFromFile(profile, file_importer_host, import_bookmarks_path); 782 } 783 784 content::RecordAction(UserMetricsAction("FirstRunDef_Accept")); 785 786 g_auto_import_state |= AUTO_IMPORT_CALLED; 787 } 788 789 void DoPostImportTasks(Profile* profile, bool make_chrome_default_for_user) { 790 // Only set default browser after import as auto import relies on the current 791 // default browser to know what to import from. 792 ProcessDefaultBrowserPolicy(make_chrome_default_for_user); 793 794 // Display the first run bubble if there is a default search provider. 795 TemplateURLService* template_url = 796 TemplateURLServiceFactory::GetForProfile(profile); 797 if (template_url && template_url->GetDefaultSearchProvider()) 798 FirstRunBubbleLauncher::ShowFirstRunBubbleSoon(); 799 SetShouldShowWelcomePage(); 800 SetShouldDoPersonalDataManagerFirstRun(); 801 802 internal::DoPostImportPlatformSpecificTasks(profile); 803 } 804 805 uint16 auto_import_state() { 806 return g_auto_import_state; 807 } 808 809 } // namespace first_run 810