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/json/json_file_value_serializer.h" 14 #include "base/lazy_instance.h" 15 #include "base/memory/ref_counted.h" 16 #include "base/message_loop/message_loop.h" 17 #include "base/metrics/histogram.h" 18 #include "base/path_service.h" 19 #include "base/prefs/pref_service.h" 20 #include "base/strings/stringprintf.h" 21 #include "base/strings/utf_string_conversions.h" 22 #include "build/build_config.h" 23 #include "chrome/browser/browser_process.h" 24 #include "chrome/browser/chrome_notification_types.h" 25 #include "chrome/browser/extensions/extension_service.h" 26 #include "chrome/browser/extensions/updater/extension_updater.h" 27 #include "chrome/browser/first_run/first_run_internal.h" 28 #include "chrome/browser/google/google_util.h" 29 #include "chrome/browser/importer/external_process_importer_host.h" 30 #include "chrome/browser/importer/importer_list.h" 31 #include "chrome/browser/importer/importer_progress_observer.h" 32 #include "chrome/browser/importer/importer_uma.h" 33 #include "chrome/browser/importer/profile_writer.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 65 using content::UserMetricsAction; 66 67 namespace { 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. 72 uint16 g_auto_import_state = first_run::AUTO_IMPORT_NONE; 73 74 // Flags for functions of similar name. 75 bool g_should_show_welcome_page = false; 76 bool 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. 82 class 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. 115 class 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. 159 void DoDelayedInstallExtensions() { 160 new FirstRunDelayedTasks(FirstRunDelayedTasks::INSTALL_EXTENSIONS); 161 } 162 163 void DoDelayedInstallExtensionsIfNeeded( 164 installer::MasterPreferences* install_prefs) { 165 DictionaryValue* extensions = 0; 166 if (install_prefs->GetExtensionsBlock(&extensions)) { 167 VLOG(1) << "Extensions block found in master preferences"; 168 DoDelayedInstallExtensions(); 169 } 170 } 171 172 base::FilePath GetDefaultPrefFilePath(bool create_profile_dir, 173 const base::FilePath& user_data_dir) { 174 base::FilePath default_pref_dir = 175 profiles::GetDefaultProfileDir(user_data_dir); 176 if (create_profile_dir) { 177 if (!base::PathExists(default_pref_dir)) { 178 if (!base::CreateDirectory(default_pref_dir)) 179 return base::FilePath(); 180 } 181 } 182 return profiles::GetProfilePrefsPath(default_pref_dir); 183 } 184 185 // Sets the |items| bitfield according to whether the import data specified by 186 // |import_type| should be be auto imported or not. 187 void SetImportItem(PrefService* user_prefs, 188 const char* pref_path, 189 int import_items, 190 int dont_import_items, 191 importer::ImportItem import_type, 192 int* items) { 193 // Work out whether an item is to be imported according to what is specified 194 // in master preferences. 195 bool should_import = false; 196 bool master_pref_set = 197 ((import_items | dont_import_items) & import_type) != 0; 198 bool master_pref = ((import_items & ~dont_import_items) & import_type) != 0; 199 200 if (import_type == importer::HISTORY || 201 (import_type != importer::FAVORITES && 202 first_run::internal::IsOrganicFirstRun())) { 203 // History is always imported unless turned off in master_preferences. 204 // Search engines and home page are imported in organic builds only 205 // unless turned off in master_preferences. 206 should_import = !master_pref_set || master_pref; 207 } else { 208 // Bookmarks are never imported, unless turned on in master_preferences. 209 // Search engine and home page import behaviour is similar in non organic 210 // builds. 211 should_import = master_pref_set && master_pref; 212 } 213 214 // If an import policy is set, import items according to policy. If no master 215 // preference is set, but a corresponding recommended policy is set, import 216 // item according to recommended policy. If both a master preference and a 217 // recommended policy is set, the master preference wins. If neither 218 // recommended nor managed policies are set, import item according to what we 219 // worked out above. 220 if (master_pref_set) 221 user_prefs->SetBoolean(pref_path, should_import); 222 223 if (!user_prefs->FindPreference(pref_path)->IsDefaultValue()) { 224 if (user_prefs->GetBoolean(pref_path)) 225 *items |= import_type; 226 } else { // no policy (recommended or managed) is set 227 if (should_import) 228 *items |= import_type; 229 } 230 231 user_prefs->ClearPref(pref_path); 232 } 233 234 // Launches the import, via |importer_host|, from |source_profile| into 235 // |target_profile| for the items specified in the |items_to_import| bitfield. 236 // This may be done in a separate process depending on the platform, but it will 237 // always block until done. 238 void ImportFromSourceProfile(ExternalProcessImporterHost* importer_host, 239 const importer::SourceProfile& source_profile, 240 Profile* target_profile, 241 uint16 items_to_import) { 242 ImportEndedObserver observer; 243 importer_host->set_observer(&observer); 244 importer_host->StartImportSettings(source_profile, 245 target_profile, 246 items_to_import, 247 new ProfileWriter(target_profile)); 248 // If the import process has not errored out, block on it. 249 if (!observer.ended()) { 250 observer.set_should_quit_message_loop(); 251 base::MessageLoop::current()->Run(); 252 } 253 } 254 255 // Imports bookmarks from an html file whose path is provided by 256 // |import_bookmarks_path|. 257 void ImportFromFile(Profile* profile, 258 ExternalProcessImporterHost* file_importer_host, 259 const std::string& import_bookmarks_path) { 260 importer::SourceProfile source_profile; 261 source_profile.importer_type = importer::TYPE_BOOKMARKS_FILE; 262 263 const base::FilePath::StringType& import_bookmarks_path_str = 264 #if defined(OS_WIN) 265 UTF8ToUTF16(import_bookmarks_path); 266 #else 267 import_bookmarks_path; 268 #endif 269 source_profile.source_path = base::FilePath(import_bookmarks_path_str); 270 271 ImportFromSourceProfile(file_importer_host, source_profile, profile, 272 importer::FAVORITES); 273 g_auto_import_state |= first_run::AUTO_IMPORT_BOOKMARKS_FILE_IMPORTED; 274 } 275 276 // Imports settings from the first profile in |importer_list|. 277 void ImportSettings(Profile* profile, 278 ExternalProcessImporterHost* importer_host, 279 scoped_refptr<ImporterList> importer_list, 280 int items_to_import) { 281 const importer::SourceProfile& source_profile = 282 importer_list->GetSourceProfileAt(0); 283 284 // Ensure that importers aren't requested to import items that they do not 285 // support. If there is no overlap, skip. 286 items_to_import &= source_profile.services_supported; 287 if (items_to_import == 0) 288 return; 289 290 ImportFromSourceProfile(importer_host, source_profile, profile, 291 items_to_import); 292 g_auto_import_state |= first_run::AUTO_IMPORT_PROFILE_IMPORTED; 293 } 294 295 GURL UrlFromString(const std::string& in) { 296 return GURL(in); 297 } 298 299 void ConvertStringVectorToGURLVector( 300 const std::vector<std::string>& src, 301 std::vector<GURL>* ret) { 302 ret->resize(src.size()); 303 std::transform(src.begin(), src.end(), ret->begin(), &UrlFromString); 304 } 305 306 // Show the first run search engine bubble at the first appropriate opportunity. 307 // This bubble may be delayed by other UI, like global errors and sync promos. 308 class FirstRunBubbleLauncher : public content::NotificationObserver { 309 public: 310 // Show the bubble at the first appropriate opportunity. This function 311 // instantiates a FirstRunBubbleLauncher, which manages its own lifetime. 312 static void ShowFirstRunBubbleSoon(); 313 314 private: 315 FirstRunBubbleLauncher(); 316 virtual ~FirstRunBubbleLauncher(); 317 318 // content::NotificationObserver: 319 virtual void Observe(int type, 320 const content::NotificationSource& source, 321 const content::NotificationDetails& details) OVERRIDE; 322 323 content::NotificationRegistrar registrar_; 324 325 DISALLOW_COPY_AND_ASSIGN(FirstRunBubbleLauncher); 326 }; 327 328 // static 329 void FirstRunBubbleLauncher::ShowFirstRunBubbleSoon() { 330 SetShowFirstRunBubblePref(first_run::FIRST_RUN_BUBBLE_SHOW); 331 // This FirstRunBubbleLauncher instance will manage its own lifetime. 332 new FirstRunBubbleLauncher(); 333 } 334 335 FirstRunBubbleLauncher::FirstRunBubbleLauncher() { 336 registrar_.Add(this, content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME, 337 content::NotificationService::AllSources()); 338 339 // This notification is required to observe the switch between the sync setup 340 // page and the general settings page. 341 registrar_.Add(this, chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED, 342 content::NotificationService::AllSources()); 343 } 344 345 FirstRunBubbleLauncher::~FirstRunBubbleLauncher() {} 346 347 void FirstRunBubbleLauncher::Observe( 348 int type, 349 const content::NotificationSource& source, 350 const content::NotificationDetails& details) { 351 DCHECK(type == content::NOTIFICATION_LOAD_COMPLETED_MAIN_FRAME || 352 type == chrome::NOTIFICATION_WEB_CONTENT_SETTINGS_CHANGED); 353 354 Browser* browser = chrome::FindBrowserWithWebContents( 355 content::Source<content::WebContents>(source).ptr()); 356 if (!browser || !browser->is_type_tabbed()) 357 return; 358 359 // Check the preference to determine if the bubble should be shown. 360 PrefService* prefs = g_browser_process->local_state(); 361 if (!prefs || prefs->GetInteger(prefs::kShowFirstRunBubbleOption) != 362 first_run::FIRST_RUN_BUBBLE_SHOW) { 363 delete this; 364 return; 365 } 366 367 content::WebContents* contents = 368 browser->tab_strip_model()->GetActiveWebContents(); 369 370 // Suppress the first run bubble if a Gaia sign in page, the continue 371 // URL for the sign in page or the sync setup page is showing. 372 if (contents && 373 (gaia::IsGaiaSignonRealm(contents->GetURL().GetOrigin()) || 374 signin::IsContinueUrlForWebBasedSigninFlow(contents->GetURL()) || 375 contents->GetURL() == GURL(std::string(chrome::kChromeUISettingsURL) + 376 chrome::kSyncSetupSubPage))) { 377 return; 378 } 379 380 if (contents && contents->GetURL().SchemeIs(chrome::kChromeUIScheme)) { 381 // Suppress the first run bubble if 'make chrome metro' flow is showing. 382 if (contents->GetURL().host() == chrome::kChromeUIMetroFlowHost) 383 return; 384 385 // Suppress the first run bubble if the NTP sync promo bubble is showing 386 // or if sign in is in progress. 387 if (contents->GetURL().host() == chrome::kChromeUINewTabHost) { 388 Profile* profile = 389 Profile::FromBrowserContext(contents->GetBrowserContext()); 390 SigninManagerBase* manager = 391 SigninManagerFactory::GetForProfile(profile); 392 bool signin_in_progress = manager && manager->AuthInProgress(); 393 bool is_promo_bubble_visible = 394 profile->GetPrefs()->GetBoolean(prefs::kSignInPromoShowNTPBubble); 395 396 if (is_promo_bubble_visible || signin_in_progress) 397 return; 398 } 399 } 400 401 // Suppress the first run bubble if a global error bubble is pending. 402 GlobalErrorService* global_error_service = 403 GlobalErrorServiceFactory::GetForProfile(browser->profile()); 404 if (global_error_service->GetFirstGlobalErrorWithBubbleView() != NULL) 405 return; 406 407 // Reset the preference and notifications to avoid showing the bubble again. 408 prefs->SetInteger(prefs::kShowFirstRunBubbleOption, 409 first_run::FIRST_RUN_BUBBLE_DONT_SHOW); 410 411 // Show the bubble now and destroy this bubble launcher. 412 browser->ShowFirstRunBubble(); 413 delete this; 414 } 415 416 static base::LazyInstance<base::FilePath> master_prefs_path_for_testing 417 = LAZY_INSTANCE_INITIALIZER; 418 419 // Loads master preferences from the master preference file into the installer 420 // master preferences. Returns the pointer to installer::MasterPreferences 421 // object if successful; otherwise, returns NULL. 422 installer::MasterPreferences* LoadMasterPrefs() { 423 base::FilePath master_prefs_path; 424 if (!master_prefs_path_for_testing.Get().empty()) 425 master_prefs_path = master_prefs_path_for_testing.Get(); 426 else 427 master_prefs_path = base::FilePath(first_run::internal::MasterPrefsPath()); 428 if (master_prefs_path.empty()) 429 return NULL; 430 installer::MasterPreferences* install_prefs = 431 new installer::MasterPreferences(master_prefs_path); 432 if (!install_prefs->read_from_file()) { 433 delete install_prefs; 434 return NULL; 435 } 436 437 return install_prefs; 438 } 439 440 // Makes chrome the user's default browser according to policy or 441 // |make_chrome_default_for_user| if no policy is set. 442 void ProcessDefaultBrowserPolicy(bool make_chrome_default_for_user) { 443 // Only proceed if chrome can be made default unattended. The interactive case 444 // (Windows 8+) is handled by the first run default browser prompt. 445 if (ShellIntegration::CanSetAsDefaultBrowser() == 446 ShellIntegration::SET_DEFAULT_UNATTENDED) { 447 // The policy has precedence over the user's choice. 448 if (g_browser_process->local_state()->IsManagedPreference( 449 prefs::kDefaultBrowserSettingEnabled)) { 450 if (g_browser_process->local_state()->GetBoolean( 451 prefs::kDefaultBrowserSettingEnabled)) { 452 ShellIntegration::SetAsDefaultBrowser(); 453 } 454 } else if (make_chrome_default_for_user) { 455 ShellIntegration::SetAsDefaultBrowser(); 456 } 457 } 458 } 459 460 } // namespace 461 462 namespace first_run { 463 namespace internal { 464 465 FirstRunState first_run_ = FIRST_RUN_UNKNOWN; 466 467 bool GeneratePrefFile(const base::FilePath& user_data_dir, 468 const installer::MasterPreferences& master_prefs) { 469 base::FilePath user_prefs = GetDefaultPrefFilePath(true, user_data_dir); 470 if (user_prefs.empty()) 471 return false; 472 473 const base::DictionaryValue& master_prefs_dict = 474 master_prefs.master_dictionary(); 475 476 JSONFileValueSerializer serializer(user_prefs); 477 478 // Call Serialize (which does IO) on the main thread, which would _normally_ 479 // be verboten. In this case however, we require this IO to synchronously 480 // complete before Chrome can start (as master preferences seed the Local 481 // State and Preferences files). This won't trip ThreadIORestrictions as they 482 // won't have kicked in yet on the main thread. 483 return serializer.Serialize(master_prefs_dict); 484 } 485 486 void SetupMasterPrefsFromInstallPrefs( 487 const installer::MasterPreferences& install_prefs, 488 MasterPrefs* out_prefs) { 489 ConvertStringVectorToGURLVector( 490 install_prefs.GetFirstRunTabs(), &out_prefs->new_tabs); 491 492 install_prefs.GetInt(installer::master_preferences::kDistroPingDelay, 493 &out_prefs->ping_delay); 494 495 bool value = false; 496 if (install_prefs.GetBool( 497 installer::master_preferences::kDistroImportSearchPref, &value)) { 498 if (value) { 499 out_prefs->do_import_items |= importer::SEARCH_ENGINES; 500 } else { 501 out_prefs->dont_import_items |= importer::SEARCH_ENGINES; 502 } 503 } 504 505 // If we're suppressing the first-run bubble, set that preference now. 506 // Otherwise, wait until the user has completed first run to set it, so the 507 // user is guaranteed to see the bubble iff he or she has completed the first 508 // run process. 509 if (install_prefs.GetBool( 510 installer::master_preferences::kDistroSuppressFirstRunBubble, 511 &value) && value) 512 SetShowFirstRunBubblePref(FIRST_RUN_BUBBLE_SUPPRESS); 513 514 if (install_prefs.GetBool( 515 installer::master_preferences::kDistroImportHistoryPref, 516 &value)) { 517 if (value) { 518 out_prefs->do_import_items |= importer::HISTORY; 519 } else { 520 out_prefs->dont_import_items |= importer::HISTORY; 521 } 522 } 523 524 std::string not_used; 525 out_prefs->homepage_defined = install_prefs.GetString( 526 prefs::kHomePage, ¬_used); 527 528 if (install_prefs.GetBool( 529 installer::master_preferences::kDistroImportHomePagePref, 530 &value)) { 531 if (value) { 532 out_prefs->do_import_items |= importer::HOME_PAGE; 533 } else { 534 out_prefs->dont_import_items |= importer::HOME_PAGE; 535 } 536 } 537 538 // Bookmarks are never imported unless specifically turned on. 539 if (install_prefs.GetBool( 540 installer::master_preferences::kDistroImportBookmarksPref, 541 &value)) { 542 if (value) 543 out_prefs->do_import_items |= importer::FAVORITES; 544 else 545 out_prefs->dont_import_items |= importer::FAVORITES; 546 } 547 548 if (install_prefs.GetBool( 549 installer::master_preferences::kMakeChromeDefaultForUser, 550 &value) && value) { 551 out_prefs->make_chrome_default_for_user = true; 552 } 553 554 if (install_prefs.GetBool( 555 installer::master_preferences::kSuppressFirstRunDefaultBrowserPrompt, 556 &value) && value) { 557 out_prefs->suppress_first_run_default_browser_prompt = true; 558 } 559 560 install_prefs.GetString( 561 installer::master_preferences::kDistroImportBookmarksFromFilePref, 562 &out_prefs->import_bookmarks_path); 563 564 out_prefs->variations_seed = install_prefs.GetVariationsSeed(); 565 566 install_prefs.GetString( 567 installer::master_preferences::kDistroSuppressDefaultBrowserPromptPref, 568 &out_prefs->suppress_default_browser_prompt_for_version); 569 } 570 571 bool CreateSentinel() { 572 base::FilePath first_run_sentinel; 573 if (!internal::GetFirstRunSentinelFilePath(&first_run_sentinel)) 574 return false; 575 return file_util::WriteFile(first_run_sentinel, "", 0) != -1; 576 } 577 578 // -- Platform-specific functions -- 579 580 #if !defined(OS_LINUX) && !defined(OS_BSD) 581 bool IsOrganicFirstRun() { 582 std::string brand; 583 google_util::GetBrand(&brand); 584 return google_util::IsOrganicFirstRun(brand); 585 } 586 #endif 587 588 } // namespace internal 589 590 MasterPrefs::MasterPrefs() 591 : ping_delay(0), 592 homepage_defined(false), 593 do_import_items(0), 594 dont_import_items(0), 595 make_chrome_default_for_user(false), 596 suppress_first_run_default_browser_prompt(false) { 597 } 598 599 MasterPrefs::~MasterPrefs() {} 600 601 bool IsChromeFirstRun() { 602 if (internal::first_run_ != internal::FIRST_RUN_UNKNOWN) 603 return internal::first_run_ == internal::FIRST_RUN_TRUE; 604 605 internal::first_run_ = internal::FIRST_RUN_FALSE; 606 607 base::FilePath first_run_sentinel; 608 const CommandLine* command_line = CommandLine::ForCurrentProcess(); 609 if (command_line->HasSwitch(switches::kForceFirstRun)) { 610 internal::first_run_ = internal::FIRST_RUN_TRUE; 611 } else if (command_line->HasSwitch(switches::kCancelFirstRun)) { 612 internal::first_run_ = internal::FIRST_RUN_CANCEL; 613 } else if (!command_line->HasSwitch(switches::kNoFirstRun) && 614 internal::GetFirstRunSentinelFilePath(&first_run_sentinel) && 615 !base::PathExists(first_run_sentinel)) { 616 internal::first_run_ = internal::FIRST_RUN_TRUE; 617 } 618 619 return internal::first_run_ == internal::FIRST_RUN_TRUE; 620 } 621 622 bool IsFirstRunSuppressed(const CommandLine& command_line) { 623 return command_line.HasSwitch(switches::kCancelFirstRun) || 624 command_line.HasSwitch(switches::kNoFirstRun); 625 } 626 627 void CreateSentinelIfNeeded() { 628 if (IsChromeFirstRun() || 629 internal::first_run_ == internal::FIRST_RUN_CANCEL) { 630 internal::CreateSentinel(); 631 } 632 } 633 634 std::string GetPingDelayPrefName() { 635 return base::StringPrintf("%s.%s", 636 installer::master_preferences::kDistroDict, 637 installer::master_preferences::kDistroPingDelay); 638 } 639 640 void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { 641 registry->RegisterIntegerPref( 642 GetPingDelayPrefName().c_str(), 643 0, 644 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF); 645 } 646 647 bool RemoveSentinel() { 648 base::FilePath first_run_sentinel; 649 if (!internal::GetFirstRunSentinelFilePath(&first_run_sentinel)) 650 return false; 651 return base::DeleteFile(first_run_sentinel, false); 652 } 653 654 bool SetShowFirstRunBubblePref(FirstRunBubbleOptions show_bubble_option) { 655 PrefService* local_state = g_browser_process->local_state(); 656 if (!local_state) 657 return false; 658 if (local_state->GetInteger( 659 prefs::kShowFirstRunBubbleOption) != FIRST_RUN_BUBBLE_SUPPRESS) { 660 // Set the new state as long as the bubble wasn't explicitly suppressed 661 // already. 662 local_state->SetInteger(prefs::kShowFirstRunBubbleOption, 663 show_bubble_option); 664 } 665 return true; 666 } 667 668 void SetShouldShowWelcomePage() { 669 g_should_show_welcome_page = true; 670 } 671 672 bool ShouldShowWelcomePage() { 673 bool retval = g_should_show_welcome_page; 674 g_should_show_welcome_page = false; 675 return retval; 676 } 677 678 void SetShouldDoPersonalDataManagerFirstRun() { 679 g_should_do_autofill_personal_data_manager_first_run = true; 680 } 681 682 bool ShouldDoPersonalDataManagerFirstRun() { 683 bool retval = g_should_do_autofill_personal_data_manager_first_run; 684 g_should_do_autofill_personal_data_manager_first_run = false; 685 return retval; 686 } 687 688 void LogFirstRunMetric(FirstRunBubbleMetric metric) { 689 UMA_HISTOGRAM_ENUMERATION("FirstRun.SearchEngineBubble", metric, 690 NUM_FIRST_RUN_BUBBLE_METRICS); 691 } 692 693 void SetMasterPrefsPathForTesting(const base::FilePath& master_prefs) { 694 master_prefs_path_for_testing.Get() = master_prefs; 695 } 696 697 ProcessMasterPreferencesResult ProcessMasterPreferences( 698 const base::FilePath& user_data_dir, 699 MasterPrefs* out_prefs) { 700 DCHECK(!user_data_dir.empty()); 701 702 scoped_ptr<installer::MasterPreferences> install_prefs(LoadMasterPrefs()); 703 704 // Default value in case master preferences is missing or corrupt, or 705 // ping_delay is missing. 706 out_prefs->ping_delay = 90; 707 if (install_prefs.get()) { 708 if (!internal::ShowPostInstallEULAIfNeeded(install_prefs.get())) 709 return EULA_EXIT_NOW; 710 711 if (!internal::GeneratePrefFile(user_data_dir, *install_prefs.get())) 712 DLOG(ERROR) << "Failed to generate master_preferences in user data dir."; 713 714 DoDelayedInstallExtensionsIfNeeded(install_prefs.get()); 715 716 internal::SetupMasterPrefsFromInstallPrefs(*install_prefs, out_prefs); 717 } 718 719 return FIRST_RUN_PROCEED; 720 } 721 722 void AutoImport( 723 Profile* profile, 724 bool homepage_defined, 725 int import_items, 726 int dont_import_items, 727 const std::string& import_bookmarks_path) { 728 base::FilePath local_state_path; 729 PathService::Get(chrome::FILE_LOCAL_STATE, &local_state_path); 730 bool local_state_file_exists = base::PathExists(local_state_path); 731 732 scoped_refptr<ImporterList> importer_list(new ImporterList()); 733 importer_list->DetectSourceProfilesHack( 734 g_browser_process->GetApplicationLocale(), false); 735 736 // Do import if there is an available profile for us to import. 737 if (importer_list->count() > 0) { 738 if (internal::IsOrganicFirstRun()) { 739 // Home page is imported in organic builds only unless turned off or 740 // defined in master_preferences. 741 if (homepage_defined) { 742 dont_import_items |= importer::HOME_PAGE; 743 if (import_items & importer::HOME_PAGE) 744 import_items &= ~importer::HOME_PAGE; 745 } 746 // Search engines are not imported automatically in organic builds if the 747 // user already has a user preferences directory. 748 if (local_state_file_exists) { 749 dont_import_items |= importer::SEARCH_ENGINES; 750 if (import_items & importer::SEARCH_ENGINES) 751 import_items &= ~importer::SEARCH_ENGINES; 752 } 753 } 754 755 PrefService* user_prefs = profile->GetPrefs(); 756 int items = 0; 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 // Deletes itself. 784 ExternalProcessImporterHost* importer_host = 785 new ExternalProcessImporterHost; 786 787 // Don't show the warning dialog if import fails. 788 importer_host->set_headless(); 789 790 importer::LogImporterUseToMetrics( 791 "AutoImport", importer_list->GetSourceProfileAt(0).importer_type); 792 793 ImportSettings(profile, importer_host, importer_list, items); 794 } 795 796 if (!import_bookmarks_path.empty()) { 797 // Deletes itself. 798 ExternalProcessImporterHost* file_importer_host = 799 new ExternalProcessImporterHost; 800 file_importer_host->set_headless(); 801 802 ImportFromFile(profile, file_importer_host, import_bookmarks_path); 803 } 804 805 content::RecordAction(UserMetricsAction("FirstRunDef_Accept")); 806 807 g_auto_import_state |= AUTO_IMPORT_CALLED; 808 } 809 810 void DoPostImportTasks(Profile* profile, bool make_chrome_default_for_user) { 811 // Only set default browser after import as auto import relies on the current 812 // default browser to know what to import from. 813 ProcessDefaultBrowserPolicy(make_chrome_default_for_user); 814 815 // Display the first run bubble if there is a default search provider. 816 TemplateURLService* template_url = 817 TemplateURLServiceFactory::GetForProfile(profile); 818 if (template_url && template_url->GetDefaultSearchProvider()) 819 FirstRunBubbleLauncher::ShowFirstRunBubbleSoon(); 820 SetShouldShowWelcomePage(); 821 SetShouldDoPersonalDataManagerFirstRun(); 822 823 internal::DoPostImportPlatformSpecificTasks(profile); 824 } 825 826 uint16 auto_import_state() { 827 return g_auto_import_state; 828 } 829 830 } // namespace first_run 831