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