| OLD | NEW |
| 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2010 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "chrome/browser/first_run.h" | 5 #include "chrome/browser/first_run.h" |
| 6 | 6 |
| 7 #include <windows.h> | 7 #include <windows.h> |
| 8 #include <shellapi.h> | 8 #include <shellapi.h> |
| 9 #include <shlobj.h> | 9 #include <shlobj.h> |
| 10 | 10 |
| 11 #include <set> | 11 #include <set> |
| 12 #include <sstream> | 12 #include <sstream> |
| 13 | 13 |
| 14 // TODO(port): trim this include list once first run has been refactored fully. | 14 // TODO(port): trim this include list once first run has been refactored fully. |
| 15 #include "app/app_switches.h" | 15 #include "app/app_switches.h" |
| 16 #include "app/l10n_util.h" | 16 #include "app/l10n_util.h" |
| 17 #include "app/l10n_util_win.h" | 17 #include "app/l10n_util_win.h" |
| 18 #include "app/resource_bundle.h" | 18 #include "app/resource_bundle.h" |
| 19 #include "base/command_line.h" | 19 #include "base/command_line.h" |
| 20 #include "base/file_util.h" | 20 #include "base/file_util.h" |
| 21 #include "base/logging.h" | 21 #include "base/logging.h" |
| 22 #include "base/object_watcher.h" | 22 #include "base/object_watcher.h" |
| 23 #include "base/path_service.h" | 23 #include "base/path_service.h" |
| 24 #include "base/process.h" | 24 #include "base/process.h" |
| 25 #include "base/process_util.h" | 25 #include "base/process_util.h" |
| 26 #include "base/registry.h" | 26 #include "base/registry.h" |
| 27 #include "base/scoped_comptr_win.h" | 27 #include "base/scoped_comptr_win.h" |
| 28 #include "base/string_util.h" | 28 #include "base/string_util.h" |
| 29 #include "base/win_util.h" |
| 29 #include "chrome/common/chrome_constants.h" | 30 #include "chrome/common/chrome_constants.h" |
| 30 #include "chrome/common/chrome_switches.h" | 31 #include "chrome/common/chrome_switches.h" |
| 31 #include "chrome/common/notification_registrar.h" | 32 #include "chrome/common/notification_registrar.h" |
| 32 #include "chrome/common/notification_service.h" | 33 #include "chrome/common/notification_service.h" |
| 33 #include "chrome/common/notification_type.h" | 34 #include "chrome/common/notification_type.h" |
| 34 #include "chrome/common/pref_names.h" | 35 #include "chrome/common/pref_names.h" |
| 35 #include "chrome/browser/browser_process.h" | 36 #include "chrome/browser/browser_process.h" |
| 36 #include "chrome/browser/extensions/extensions_service.h" | 37 #include "chrome/browser/extensions/extensions_service.h" |
| 37 #include "chrome/browser/extensions/extension_updater.h" | 38 #include "chrome/browser/extensions/extension_updater.h" |
| 38 #include "chrome/browser/hang_monitor/hung_window_detector.h" | 39 #include "chrome/browser/hang_monitor/hung_window_detector.h" |
| 39 #include "chrome/browser/importer/importer.h" | 40 #include "chrome/browser/importer/importer.h" |
| 40 #include "chrome/browser/importer/importer_data_types.h" | 41 #include "chrome/browser/importer/importer_data_types.h" |
| 42 #include "chrome/browser/metrics/user_metrics.h" |
| 41 #include "chrome/browser/pref_service.h" | 43 #include "chrome/browser/pref_service.h" |
| 42 #include "chrome/browser/process_singleton.h" | 44 #include "chrome/browser/process_singleton.h" |
| 43 #include "chrome/browser/profile.h" | 45 #include "chrome/browser/profile.h" |
| 44 #include "chrome/browser/profile_manager.h" | 46 #include "chrome/browser/profile_manager.h" |
| 45 #include "chrome/browser/shell_integration.h" | 47 #include "chrome/browser/shell_integration.h" |
| 46 #include "chrome/browser/views/first_run_view.h" | 48 #include "chrome/browser/views/first_run_search_engine_view.h" |
| 47 #include "chrome/common/chrome_paths.h" | 49 #include "chrome/common/chrome_paths.h" |
| 48 #include "chrome/common/result_codes.h" | 50 #include "chrome/common/result_codes.h" |
| 49 #include "chrome/installer/util/browser_distribution.h" | 51 #include "chrome/installer/util/browser_distribution.h" |
| 50 #include "chrome/installer/util/google_update_constants.h" | 52 #include "chrome/installer/util/google_update_constants.h" |
| 51 #include "chrome/installer/util/google_update_settings.h" | 53 #include "chrome/installer/util/google_update_settings.h" |
| 52 #include "chrome/installer/util/install_util.h" | 54 #include "chrome/installer/util/install_util.h" |
| 53 #include "chrome/installer/util/master_preferences.h" | 55 #include "chrome/installer/util/master_preferences.h" |
| 54 #include "chrome/installer/util/shell_util.h" | 56 #include "chrome/installer/util/shell_util.h" |
| 55 #include "chrome/installer/util/util_constants.h" | 57 #include "chrome/installer/util/util_constants.h" |
| 56 #include "google_update_idl.h" | 58 #include "google_update_idl.h" |
| 57 #include "grit/app_resources.h" | 59 #include "grit/app_resources.h" |
| 58 #include "grit/chromium_strings.h" | 60 #include "grit/chromium_strings.h" |
| 59 #include "grit/generated_resources.h" | 61 #include "grit/generated_resources.h" |
| 60 #include "grit/locale_settings.h" | 62 #include "grit/locale_settings.h" |
| 61 #include "grit/theme_resources.h" | 63 #include "grit/theme_resources.h" |
| 62 #include "views/background.h" | 64 #include "views/background.h" |
| 63 #include "views/controls/button/image_button.h" | 65 #include "views/controls/button/image_button.h" |
| 64 #include "views/controls/button/native_button.h" | 66 #include "views/controls/button/native_button.h" |
| 65 #include "views/controls/button/radio_button.h" | 67 #include "views/controls/button/radio_button.h" |
| 66 #include "views/controls/image_view.h" | 68 #include "views/controls/image_view.h" |
| 67 #include "views/controls/label.h" | 69 #include "views/controls/label.h" |
| 68 #include "views/controls/link.h" | 70 #include "views/controls/link.h" |
| 69 #include "views/focus/accelerator_handler.h" | 71 #include "views/focus/accelerator_handler.h" |
| 70 #include "views/grid_layout.h" | 72 #include "views/grid_layout.h" |
| 71 #include "views/standard_layout.h" | 73 #include "views/standard_layout.h" |
| 72 #include "views/widget/root_view.h" | 74 #include "views/widget/root_view.h" |
| 73 #include "views/widget/widget_win.h" | 75 #include "views/widget/widget_win.h" |
| 74 #include "views/window/window.h" | 76 #include "views/window/window.h" |
| 77 #include "views/window/window_delegate.h" |
| 78 #include "views/window/window_win.h" |
| 75 | 79 |
| 76 namespace { | 80 namespace { |
| 77 | 81 |
| 78 bool GetNewerChromeFile(FilePath* path) { | 82 bool GetNewerChromeFile(FilePath* path) { |
| 79 if (!PathService::Get(base::DIR_EXE, path)) | 83 if (!PathService::Get(base::DIR_EXE, path)) |
| 80 return false; | 84 return false; |
| 81 *path = path->Append(installer_util::kChromeNewExe); | 85 *path = path->Append(installer_util::kChromeNewExe); |
| 82 return true; | 86 return true; |
| 83 } | 87 } |
| 84 | 88 |
| (...skipping 252 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 337 if (installer_util::GetDistroBooleanPreference(prefs.get(), | 341 if (installer_util::GetDistroBooleanPreference(prefs.get(), |
| 338 installer_util::master_preferences:: | 342 installer_util::master_preferences:: |
| 339 kSearchEngineExperimentRandomizePref, | 343 kSearchEngineExperimentRandomizePref, |
| 340 &value) && value) { | 344 &value) && value) { |
| 341 out_prefs->randomize_search_engine_experiment = true; | 345 out_prefs->randomize_search_engine_experiment = true; |
| 342 } | 346 } |
| 343 // Set the first run bubble to minimal. | 347 // Set the first run bubble to minimal. |
| 344 FirstRun::SetMinimalFirstRunBubblePref(); | 348 FirstRun::SetMinimalFirstRunBubblePref(); |
| 345 } | 349 } |
| 346 | 350 |
| 351 // History is imported automatically, unless turned off in master_prefs. |
| 352 if (installer_util::GetDistroBooleanPreference(prefs.get(), |
| 353 installer_util::master_preferences::kDistroImportHistoryPref, &value) |
| 354 && !value) { |
| 355 out_prefs->dont_import_items |= importer::HISTORY; |
| 356 } |
| 357 |
| 358 // Home page is imported automatically only in organic builds, and can be |
| 359 // turned off in master_prefs. |
| 360 if (installer_util::GetDistroBooleanPreference(prefs.get(), |
| 361 installer_util::master_preferences::kDistroImportHomePagePref, &value) |
| 362 && !value) { |
| 363 out_prefs->dont_import_items |= importer::HOME_PAGE; |
| 364 } |
| 365 |
| 366 // Bookmarks are never imported unless specifically turned on. |
| 367 if (installer_util::GetDistroBooleanPreference(prefs.get(), |
| 368 installer_util::master_preferences::kDistroImportBookmarksPref, &value) |
| 369 && value) { |
| 370 out_prefs->do_import_items |= importer::FAVORITES; |
| 371 } |
| 372 |
| 347 // Note we are skipping all other master preferences if skip-first-run-ui | 373 // Note we are skipping all other master preferences if skip-first-run-ui |
| 348 // is *not* specified. | 374 // is *not* specified. (That is, we continue only if skipping first run ui.) |
| 349 if (!installer_util::GetDistroBooleanPreference(prefs.get(), | 375 if (!installer_util::GetDistroBooleanPreference(prefs.get(), |
| 350 installer_util::master_preferences::kDistroSkipFirstRunPref, &value) || | 376 installer_util::master_preferences::kDistroSkipFirstRunPref, &value) || |
| 351 !value) | 377 !value) |
| 352 return true; | 378 return true; |
| 353 | 379 |
| 354 // From here on we won't show first run so we need to do the work to show the | 380 // From here on we won't show first run so we need to do the work to show the |
| 355 // bubble anyway, unless it's already been explicitly suppressed. | 381 // bubble anyway, unless it's already been explicitly suppressed. |
| 356 FirstRun::SetShowFirstRunBubblePref(true); | 382 FirstRun::SetShowFirstRunBubblePref(true); |
| 357 | 383 |
| 358 // We need to be able to create the first run sentinel or else we cannot | 384 // We need to be able to create the first run sentinel or else we cannot |
| 359 // proceed because ImportSettings will launch the importer process which | 385 // proceed because ImportSettings will launch the importer process which |
| 360 // would end up here if the sentinel is not present. | 386 // would end up here if the sentinel is not present. |
| 361 if (!FirstRun::CreateSentinel()) | 387 if (!FirstRun::CreateSentinel()) |
| 362 return false; | 388 return false; |
| 363 | 389 |
| 364 if (installer_util::GetDistroBooleanPreference(prefs.get(), | 390 if (installer_util::GetDistroBooleanPreference(prefs.get(), |
| 365 installer_util::master_preferences::kDistroShowWelcomePage, &value) && | 391 installer_util::master_preferences::kDistroShowWelcomePage, &value) && |
| 366 value) | 392 value) |
| 367 FirstRun::SetShowWelcomePagePref(); | 393 FirstRun::SetShowWelcomePagePref(); |
| 368 | 394 |
| 369 if (installer_util::GetDistroBooleanPreference(prefs.get(), | |
| 370 installer_util::master_preferences::kDistroImportHistoryPref, &value) && | |
| 371 value) | |
| 372 import_items += importer::HISTORY; | |
| 373 if (installer_util::GetDistroBooleanPreference(prefs.get(), | |
| 374 installer_util::master_preferences::kDistroImportBookmarksPref, &value) && | |
| 375 value) | |
| 376 import_items += importer::FAVORITES; | |
| 377 if (installer_util::GetDistroBooleanPreference(prefs.get(), | |
| 378 installer_util::master_preferences::kDistroImportHomePagePref, &value) && | |
| 379 value) | |
| 380 import_items += importer::HOME_PAGE; | |
| 381 | |
| 382 std::wstring import_bookmarks_path; | 395 std::wstring import_bookmarks_path; |
| 383 installer_util::GetDistroStringPreference(prefs.get(), | 396 installer_util::GetDistroStringPreference(prefs.get(), |
| 384 installer_util::master_preferences::kDistroImportBookmarksFromFilePref, | 397 installer_util::master_preferences::kDistroImportBookmarksFromFilePref, |
| 385 &import_bookmarks_path); | 398 &import_bookmarks_path); |
| 386 | 399 |
| 387 if (import_items || !import_bookmarks_path.empty()) { | 400 if (import_items || !import_bookmarks_path.empty()) { |
| 388 // There is something to import from the default browser. This launches | 401 // There is something to import from the default browser. This launches |
| 389 // the importer process and blocks until done or until it fails. | 402 // the importer process and blocks until done or until it fails. |
| 390 scoped_refptr<ImporterHost> importer_host = new ImporterHost(); | 403 scoped_refptr<ImporterHost> importer_host = new ImporterHost(); |
| 391 if (!FirstRun::ImportSettings(NULL, | 404 if (!FirstRun::ImportSettings(NULL, |
| (...skipping 91 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 483 } | 496 } |
| 484 | 497 |
| 485 // static | 498 // static |
| 486 bool Upgrade::IsUpdatePendingRestart() { | 499 bool Upgrade::IsUpdatePendingRestart() { |
| 487 FilePath new_chrome_exe; | 500 FilePath new_chrome_exe; |
| 488 if (!GetNewerChromeFile(&new_chrome_exe)) | 501 if (!GetNewerChromeFile(&new_chrome_exe)) |
| 489 return false; | 502 return false; |
| 490 return file_util::PathExists(new_chrome_exe); | 503 return file_util::PathExists(new_chrome_exe); |
| 491 } | 504 } |
| 492 | 505 |
| 493 bool OpenFirstRunDialog(Profile* profile, | |
| 494 bool homepage_defined, | |
| 495 int import_items, | |
| 496 int dont_import_items, | |
| 497 bool search_engine_experiment, | |
| 498 bool randomize_search_engine_experiment, | |
| 499 ProcessSingleton* process_singleton) { | |
| 500 DCHECK(profile); | |
| 501 DCHECK(process_singleton); | |
| 502 | |
| 503 // We need the FirstRunView to outlive its parent, as we retrieve the accept | |
| 504 // state from it after the dialog has been closed. | |
| 505 scoped_ptr<FirstRunView> first_run_view( | |
| 506 new FirstRunView(profile, | |
| 507 homepage_defined, | |
| 508 import_items, | |
| 509 dont_import_items, | |
| 510 search_engine_experiment, | |
| 511 randomize_search_engine_experiment)); | |
| 512 first_run_view->set_parent_owned(false); | |
| 513 views::Window* first_run_ui = views::Window::CreateChromeWindow( | |
| 514 NULL, gfx::Rect(), first_run_view.get()); | |
| 515 DCHECK(first_run_ui); | |
| 516 | |
| 517 // We need to avoid dispatching new tabs when we are doing the import | |
| 518 // because that will lead to data corruption or a crash. Lock() does that. | |
| 519 // If a CopyData message does come in while the First Run UI is visible, | |
| 520 // then we will attempt to set first_run_ui as the foreground window. | |
| 521 process_singleton->Lock(first_run_ui->GetNativeWindow()); | |
| 522 | |
| 523 first_run_ui->Show(); | |
| 524 | |
| 525 // We must now run a message loop (will be terminated when the First Run UI | |
| 526 // is closed) so that the window can receive messages and we block the | |
| 527 // browser window from showing up. We pass the accelerator handler here so | |
| 528 // that keyboard accelerators (Enter, Esc, etc) work in the dialog box. | |
| 529 views::AcceleratorHandler accelerator_handler; | |
| 530 MessageLoopForUI::current()->Run(&accelerator_handler); | |
| 531 process_singleton->Unlock(); | |
| 532 | |
| 533 return first_run_view->accepted(); | |
| 534 } | |
| 535 | |
| 536 namespace { | 506 namespace { |
| 537 | 507 |
| 538 // This class is used by FirstRun::ImportSettings to determine when the import | 508 // This class is used by FirstRun::ImportSettings to determine when the import |
| 539 // process has ended and what was the result of the operation as reported by | 509 // process has ended and what was the result of the operation as reported by |
| 540 // the process exit code. This class executes in the context of the main chrome | 510 // the process exit code. This class executes in the context of the main chrome |
| 541 // process. | 511 // process. |
| 542 class ImportProcessRunner : public base::ObjectWatcher::Delegate { | 512 class ImportProcessRunner : public base::ObjectWatcher::Delegate { |
| 543 public: | 513 public: |
| 544 // The constructor takes the importer process to watch and then it does a | 514 // The constructor takes the importer process to watch and then it does a |
| 545 // message loop blocking wait until the process ends. This object now owns | 515 // message loop blocking wait until the process ends. This object now owns |
| (...skipping 90 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 636 | 606 |
| 637 if (!StringToInt(v[1], options)) | 607 if (!StringToInt(v[1], options)) |
| 638 return false; | 608 return false; |
| 639 | 609 |
| 640 *window = reinterpret_cast<HWND>(StringToInt64(v[2])); | 610 *window = reinterpret_cast<HWND>(StringToInt64(v[2])); |
| 641 return true; | 611 return true; |
| 642 } | 612 } |
| 643 | 613 |
| 644 } // namespace | 614 } // namespace |
| 645 | 615 |
| 616 void FirstRun::AutoImport(Profile* profile, |
| 617 bool homepage_defined, |
| 618 int import_items, |
| 619 int dont_import_items, |
| 620 bool search_engine_experiment, |
| 621 bool randomize_search_engine_experiment, |
| 622 ProcessSingleton* process_singleton) { |
| 623 FirstRun::CreateChromeDesktopShortcut(); |
| 624 // Windows 7 has deprecated the quick launch bar. |
| 625 if (win_util::GetWinVersion() < win_util::WINVERSION_WIN7) |
| 626 CreateChromeQuickLaunchShortcut(); |
| 627 |
| 628 scoped_refptr<ImporterHost> importer_host; |
| 629 importer_host = new ImporterHost(); |
| 630 int items = 0; |
| 631 // History and home page are always imported unless turned off in |
| 632 // master_preferences. |
| 633 if (!(dont_import_items & importer::HISTORY)) |
| 634 items = items | importer::HISTORY; |
| 635 if (!((dont_import_items & importer::HOME_PAGE) || homepage_defined)) |
| 636 items = items | importer::HOME_PAGE; |
| 637 |
| 638 // Search engine and bookmarks are never imported unless turned on |
| 639 // in master_preferences. |
| 640 if (import_items & importer::SEARCH_ENGINES) |
| 641 items = items | importer::SEARCH_ENGINES; |
| 642 if (import_items & importer::FAVORITES) |
| 643 items = items | importer::FAVORITES; |
| 644 // We need to avoid dispatching new tabs when we are importing because |
| 645 // that will lead to data corruption or a crash. Because there is no UI for |
| 646 // the import process, we pass NULL as the window to bring to the foreground |
| 647 // when a CopyData message comes in; this causes the message to be silently |
| 648 // discarded, which is the correct behavior during the import process. |
| 649 process_singleton->Lock(NULL); |
| 650 |
| 651 // Index 0 is the default browser. |
| 652 FirstRun::ImportSettings(profile, |
| 653 importer_host->GetSourceProfileInfoAt(0).browser_type, items, NULL); |
| 654 UserMetrics::RecordAction(UserMetricsAction("FirstRunDef_Accept")); |
| 655 |
| 656 // Launch the search engine dialog only if build is organic. |
| 657 std::wstring brand; |
| 658 GoogleUpdateSettings::GetBrand(&brand); |
| 659 if (GoogleUpdateSettings::IsOrganic(brand)) { |
| 660 // The home page string may be set in the preferences, but the user should |
| 661 // initially use Chrome with the NTP as home page in organic builds. |
| 662 profile->GetPrefs()->SetBoolean(prefs::kHomePageIsNewTabPage, true); |
| 663 |
| 664 // Search engine dialog is shown in organic builds unless overridden by |
| 665 // master_preferences. |
| 666 if (!(import_items & importer::SEARCH_ENGINES)) { |
| 667 views::Window* search_engine_dialog = views::Window::CreateChromeWindow( |
| 668 NULL, |
| 669 gfx::Rect(), |
| 670 new FirstRunSearchEngineView(profile, |
| 671 randomize_search_engine_experiment)); |
| 672 DCHECK(search_engine_dialog); |
| 673 |
| 674 search_engine_dialog->Show(); |
| 675 views::AcceleratorHandler accelerator_handler; |
| 676 MessageLoopForUI::current()->Run(&accelerator_handler); |
| 677 search_engine_dialog->Close(); |
| 678 } |
| 679 } |
| 680 |
| 681 process_singleton->Unlock(); |
| 682 FirstRun::CreateSentinel(); |
| 683 } |
| 684 |
| 646 bool FirstRun::ImportSettings(Profile* profile, int browser_type, | 685 bool FirstRun::ImportSettings(Profile* profile, int browser_type, |
| 647 int items_to_import, | 686 int items_to_import, |
| 648 const std::wstring& import_bookmarks_path, | 687 const std::wstring& import_bookmarks_path, |
| 649 HWND parent_window) { | 688 HWND parent_window) { |
| 650 const CommandLine& cmdline = *CommandLine::ForCurrentProcess(); | 689 const CommandLine& cmdline = *CommandLine::ForCurrentProcess(); |
| 651 CommandLine import_cmd(cmdline.GetProgram()); | 690 CommandLine import_cmd(cmdline.GetProgram()); |
| 652 // Propagate user data directory switch. | 691 // Propagate user data directory switch. |
| 653 if (cmdline.HasSwitch(switches::kUserDataDir)) { | 692 if (cmdline.HasSwitch(switches::kUserDataDir)) { |
| 654 import_cmd.AppendSwitchWithValue( | 693 import_cmd.AppendSwitchWithValue( |
| 655 switches::kUserDataDir, | 694 switches::kUserDataDir, |
| (...skipping 373 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1029 | 1068 |
| 1030 Upgrade::TryResult Upgrade::ShowTryChromeDialog(size_t version) { | 1069 Upgrade::TryResult Upgrade::ShowTryChromeDialog(size_t version) { |
| 1031 if (version > 10000) { | 1070 if (version > 10000) { |
| 1032 // This is a test value. We want to make sure we exercise | 1071 // This is a test value. We want to make sure we exercise |
| 1033 // returning this early. See EarlyReturnTest test harness. | 1072 // returning this early. See EarlyReturnTest test harness. |
| 1034 return Upgrade::TD_NOT_NOW; | 1073 return Upgrade::TD_NOT_NOW; |
| 1035 } | 1074 } |
| 1036 TryChromeDialog td; | 1075 TryChromeDialog td; |
| 1037 return td.ShowModal(); | 1076 return td.ShowModal(); |
| 1038 } | 1077 } |
| OLD | NEW |