diff options
author | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-20 19:07:53 +0000 |
---|---|---|
committer | evan@chromium.org <evan@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2009-05-20 19:07:53 +0000 |
commit | 538d7b4b00f183f06223e5ab2ac4f641e054a345 (patch) | |
tree | 63af145e76a0a2e57034d3e1f063269c8d1ce890 /chrome/browser/first_run_win.cc | |
parent | f8ed9234ed347388a4091b0ef910a8f5dab56641 (diff) | |
download | chromium_src-538d7b4b00f183f06223e5ab2ac4f641e054a345.zip chromium_src-538d7b4b00f183f06223e5ab2ac4f641e054a345.tar.gz chromium_src-538d7b4b00f183f06223e5ab2ac4f641e054a345.tar.bz2 |
Revert r16502.
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@16503 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/browser/first_run_win.cc')
-rw-r--r-- | chrome/browser/first_run_win.cc | 667 |
1 files changed, 0 insertions, 667 deletions
diff --git a/chrome/browser/first_run_win.cc b/chrome/browser/first_run_win.cc deleted file mode 100644 index 3a24488..0000000 --- a/chrome/browser/first_run_win.cc +++ /dev/null @@ -1,667 +0,0 @@ -// Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "chrome/browser/first_run.h" - -#include <atlbase.h> -#include <atlcom.h> -#include <windows.h> -#include <shlobj.h> - -#include <sstream> - -#include "app/app_switches.h" -#include "app/resource_bundle.h" -#include "base/command_line.h" -#include "base/file_util.h" -#include "base/logging.h" -#include "base/object_watcher.h" -#include "base/path_service.h" -#include "base/process.h" -#include "base/process_util.h" -#include "base/registry.h" -#include "base/string_util.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_switches.h" -#include "chrome/common/pref_names.h" -#include "chrome/browser/browser_process.h" -#include "chrome/browser/hang_monitor/hung_window_detector.h" -#include "chrome/browser/importer/importer.h" -#include "chrome/browser/process_singleton.h" -#include "chrome/browser/profile.h" -#include "chrome/browser/profile_manager.h" -#include "chrome/browser/shell_integration.h" -#include "chrome/browser/views/first_run_view.h" -#include "chrome/common/chrome_constants.h" -#include "chrome/common/chrome_paths.h" -#include "chrome/common/pref_service.h" -#include "chrome/common/result_codes.h" -#include "chrome/installer/util/browser_distribution.h" -#include "chrome/installer/util/google_update_constants.h" -#include "chrome/installer/util/google_update_settings.h" -#include "chrome/installer/util/install_util.h" -#include "chrome/installer/util/master_preferences.h" -#include "chrome/installer/util/shell_util.h" -#include "chrome/installer/util/util_constants.h" -#include "google_update_idl.h" -#include "grit/locale_settings.h" -#include "views/widget/accelerator_handler.h" -#include "views/window/window.h" - -namespace { - -// The kSentinelFile file absence will tell us it is a first run. -const wchar_t kSentinelFile[] = L"First Run"; - -// Gives the full path to the sentinel file. The file might not exist. -bool GetFirstRunSentinelFilePath(std::wstring* path) { - std::wstring exe_path; - if (!PathService::Get(base::DIR_EXE, &exe_path)) - return false; - - std::wstring first_run_sentinel; - if (InstallUtil::IsPerUserInstall(exe_path.c_str())) { - first_run_sentinel = exe_path; - } else { - if (!PathService::Get(chrome::DIR_USER_DATA, &first_run_sentinel)) - return false; - } - - file_util::AppendToPath(&first_run_sentinel, kSentinelFile); - *path = first_run_sentinel; - return true; -} - -bool GetNewerChromeFile(std::wstring* path) { - if (!PathService::Get(base::DIR_EXE, path)) - return false; - file_util::AppendToPath(path, installer_util::kChromeNewExe); - return true; -} - -bool GetBackupChromeFile(std::wstring* path) { - if (!PathService::Get(base::DIR_EXE, path)) - return false; - file_util::AppendToPath(path, installer_util::kChromeOldExe); - return true; -} - -std::wstring GetDefaultPrefFilePath(bool create_profile_dir, - const std::wstring& user_data_dir) { - FilePath default_pref_dir = ProfileManager::GetDefaultProfileDir( - FilePath::FromWStringHack(user_data_dir)); - if (create_profile_dir) { - if (!file_util::PathExists(default_pref_dir)) { - if (!file_util::CreateDirectory(default_pref_dir)) - return std::wstring(); - } - } - return ProfileManager::GetDefaultProfilePath(default_pref_dir) - .ToWStringHack(); -} - -bool InvokeGoogleUpdateForRename() { - CComPtr<IProcessLauncher> ipl; - if (!FAILED(ipl.CoCreateInstance(__uuidof(ProcessLauncherClass)))) { - ULONG_PTR phandle = NULL; - DWORD id = GetCurrentProcessId(); - if (!FAILED(ipl->LaunchCmdElevated(google_update::kChromeGuid, - google_update::kRegRenameCmdField, - id, &phandle))) { - HANDLE handle = HANDLE(phandle); - DWORD exit_code; - ::GetExitCodeProcess(handle, &exit_code); - ::CloseHandle(handle); - if (exit_code == installer_util::RENAME_SUCCESSFUL) - return true; - } - } - return false; -} - -bool LaunchSetupWithParam(const std::wstring& param, const std::wstring& value, - int* ret_code) { - FilePath exe_path; - if (!PathService::Get(base::DIR_MODULE, &exe_path)) - return false; - exe_path = exe_path.Append(installer_util::kInstallerDir); - exe_path = exe_path.Append(installer_util::kSetupExe); - base::ProcessHandle ph; - CommandLine cl(exe_path.ToWStringHack()); - cl.AppendSwitchWithValue(param, value); - if (!base::LaunchApp(cl, false, false, &ph)) - return false; - DWORD wr = ::WaitForSingleObject(ph, INFINITE); - if (wr != WAIT_OBJECT_0) - return false; - return (TRUE == ::GetExitCodeProcess(ph, reinterpret_cast<DWORD*>(ret_code))); -} - -bool WriteEULAtoTempFile(FilePath* eula_path) { - std::string terms = - ResourceBundle::GetSharedInstance().GetDataResource(IDR_TERMS_HTML); - if (terms.empty()) - return false; - FilePath temp_dir; - if (!file_util::GetTempDir(&temp_dir)) - return false; - *eula_path = temp_dir.Append(L"chrome_eula_iframe.html"); - return (file_util::WriteFile(*eula_path, terms.c_str(), terms.size()) > 0); -} - -} // namespace - -bool FirstRun::IsChromeFirstRun() { - // A troolean, 0 means not yet set, 1 means set to true, 2 set to false. - static int first_run = 0; - if (first_run != 0) - return first_run == 1; - - std::wstring first_run_sentinel; - if (!GetFirstRunSentinelFilePath(&first_run_sentinel) || - file_util::PathExists(first_run_sentinel)) { - first_run = 2; - return false; - } - first_run = 1; - return true; -} - -bool FirstRun::CreateChromeDesktopShortcut() { - std::wstring chrome_exe; - if (!PathService::Get(base::FILE_EXE, &chrome_exe)) - return false; - BrowserDistribution *dist = BrowserDistribution::GetDistribution(); - if (!dist) - return false; - return ShellUtil::CreateChromeDesktopShortcut(chrome_exe, - dist->GetAppDescription(), ShellUtil::CURRENT_USER, - false, true); // create if doesn't exist. -} - -bool FirstRun::CreateChromeQuickLaunchShortcut() { - std::wstring chrome_exe; - if (!PathService::Get(base::FILE_EXE, &chrome_exe)) - return false; - return ShellUtil::CreateChromeQuickLaunchShortcut(chrome_exe, - ShellUtil::CURRENT_USER, // create only for current user. - true); // create if doesn't exist. -} - -bool FirstRun::RemoveSentinel() { - std::wstring first_run_sentinel; - if (!GetFirstRunSentinelFilePath(&first_run_sentinel)) - return false; - return file_util::Delete(first_run_sentinel, false); -} - -bool FirstRun::CreateSentinel() { - std::wstring first_run_sentinel; - if (!GetFirstRunSentinelFilePath(&first_run_sentinel)) - return false; - HANDLE file = ::CreateFileW(first_run_sentinel.c_str(), - FILE_READ_DATA | FILE_WRITE_DATA, - FILE_SHARE_READ | FILE_SHARE_WRITE, - NULL, CREATE_ALWAYS, 0, NULL); - if (INVALID_HANDLE_VALUE == file) - return false; - ::CloseHandle(file); - return true; -} - -bool FirstRun::ProcessMasterPreferences(const FilePath& user_data_dir, - const FilePath& master_prefs_path, - int* preference_details, - std::vector<std::wstring>* new_tabs) { - DCHECK(!user_data_dir.empty()); - if (preference_details) - *preference_details = 0; - - std::wstring master_prefs; - if (master_prefs_path.empty()) { - // The default location of the master prefs is next to the chrome exe. - std::wstring master_path; - if (!PathService::Get(base::DIR_EXE, &master_path)) - return true; - file_util::AppendToPath(&master_path, installer_util::kDefaultMasterPrefs); - master_prefs = master_path; - } else { - master_prefs = master_prefs_path.ToWStringHack(); - } - - int parse_result = installer_util::ParseDistributionPreferences(master_prefs); - if (preference_details) - *preference_details = parse_result; - - if (parse_result & installer_util::MASTER_PROFILE_ERROR) - return true; - - if (new_tabs) - *new_tabs = installer_util::ParseFirstRunTabs(master_prefs); - - if (parse_result & installer_util::MASTER_PROFILE_REQUIRE_EULA) { - // Show the post-installation EULA. This is done by setup.exe and the - // result determines if we continue or not. We wait here until the user - // dismisses the dialog. - - // The actual eula text is in a resource in chrome. We extract it to - // a text file so setup.exe can use it as an inner frame. - FilePath inner_html; - if (WriteEULAtoTempFile(&inner_html)) { - int retcode = 0; - const std::wstring& eula = installer_util::switches::kShowEula; - if (!LaunchSetupWithParam(eula, inner_html.ToWStringHack(), &retcode) || - (retcode == installer_util::EULA_REJECTED)) { - LOG(WARNING) << "EULA rejected. Fast exit."; - ::ExitProcess(1); - } - if (retcode == installer_util::EULA_ACCEPTED) { - LOG(INFO) << "EULA : no collection"; - GoogleUpdateSettings::SetCollectStatsConsent(false); - } else if (retcode == installer_util::EULA_ACCEPTED_OPT_IN) { - LOG(INFO) << "EULA : collection consent"; - GoogleUpdateSettings::SetCollectStatsConsent(true); - } - } - } - - if (parse_result & installer_util::MASTER_PROFILE_OEM_FIRST_RUN_BUBBLE) - FirstRun::SetOEMFirstRunBubblePref(); - - FilePath user_prefs = FilePath::FromWStringHack( - GetDefaultPrefFilePath(true, user_data_dir.ToWStringHack())); - if (user_prefs.empty()) - return true; - - // The master prefs are regular prefs so we can just copy the file - // to the default place and they just work. - if (!file_util::CopyFile(master_prefs, user_prefs.ToWStringHack())) - return true; - - if (!(parse_result & installer_util::MASTER_PROFILE_NO_FIRST_RUN_UI)) - return true; - - // From here on we won't show first run so we need to do the work to set the - // required state given that FirstRunView is not going to be called. - FirstRun::SetShowFirstRunBubblePref(); - - // We need to be able to create the first run sentinel or else we cannot - // proceed because ImportSettings will launch the importer process which - // would end up here if the sentinel is not present. - if (!FirstRun::CreateSentinel()) - return false; - - if (parse_result & installer_util::MASTER_PROFILE_SHOW_WELCOME) - FirstRun::SetShowWelcomePagePref(); - - int import_items = 0; - if (parse_result & installer_util::MASTER_PROFILE_IMPORT_SEARCH_ENGINE) - import_items += SEARCH_ENGINES; - if (parse_result & installer_util::MASTER_PROFILE_IMPORT_HISTORY) - import_items += HISTORY; - if (parse_result & installer_util::MASTER_PROFILE_IMPORT_BOOKMARKS) - import_items += FAVORITES; - - if (import_items) { - // There is something to import from the default browser. This launches - // the importer process and blocks until done or until it fails. - scoped_refptr<ImporterHost> importer_host = new ImporterHost(); - if (!FirstRun::ImportSettings(NULL, - importer_host->GetSourceProfileInfoAt(0).browser_type, - import_items, NULL)) { - LOG(WARNING) << "silent import failed"; - } - } - - if (parse_result & - installer_util::MASTER_PROFILE_MAKE_CHROME_DEFAULT_FOR_USER) - ShellIntegration::SetAsDefaultBrowser(); - - return false; -} - -bool Upgrade::IsBrowserAlreadyRunning() { - static HANDLE handle = NULL; - std::wstring exe; - PathService::Get(base::FILE_EXE, &exe); - std::replace(exe.begin(), exe.end(), '\\', '!'); - std::transform(exe.begin(), exe.end(), exe.begin(), tolower); - exe = L"Global\\" + exe; - if (handle != NULL) - CloseHandle(handle); - handle = CreateEvent(NULL, TRUE, TRUE, exe.c_str()); - int error = GetLastError(); - return (error == ERROR_ALREADY_EXISTS || error == ERROR_ACCESS_DENIED); -} - -bool Upgrade::RelaunchChromeBrowser(const CommandLine& command_line) { - ::SetEnvironmentVariable(google_update::kEnvProductVersionKey, NULL); - return base::LaunchApp(command_line.command_line_string(), - false, false, NULL); -} - -bool Upgrade::SwapNewChromeExeIfPresent() { - std::wstring new_chrome_exe; - if (!GetNewerChromeFile(&new_chrome_exe)) - return false; - if (!file_util::PathExists(new_chrome_exe)) - return false; - std::wstring curr_chrome_exe; - if (!PathService::Get(base::FILE_EXE, &curr_chrome_exe)) - return false; - - // First try to rename exe by launching rename command ourselves. - bool user_install = InstallUtil::IsPerUserInstall(curr_chrome_exe.c_str()); - HKEY reg_root = user_install ? HKEY_CURRENT_USER : HKEY_LOCAL_MACHINE; - BrowserDistribution *dist = BrowserDistribution::GetDistribution(); - RegKey key; - std::wstring rename_cmd; - if (key.Open(reg_root, dist->GetVersionKey().c_str(), KEY_READ) && - key.ReadValue(google_update::kRegRenameCmdField, &rename_cmd)) { - base::ProcessHandle handle; - if (base::LaunchApp(rename_cmd, true, true, &handle)) { - DWORD exit_code; - ::GetExitCodeProcess(handle, &exit_code); - ::CloseHandle(handle); - if (exit_code == installer_util::RENAME_SUCCESSFUL) - return true; - } - } - - // Rename didn't work so try to rename by calling Google Update - if (InvokeGoogleUpdateForRename()) - return true; - - // Rename still didn't work so just try to rename exe ourselves (for - // backward compatibility, can be deleted once the new process works). - std::wstring backup_exe; - if (!GetBackupChromeFile(&backup_exe)) - return false; - if (::ReplaceFileW(curr_chrome_exe.c_str(), new_chrome_exe.c_str(), - backup_exe.c_str(), REPLACEFILE_IGNORE_MERGE_ERRORS, - NULL, NULL)) { - return true; - } - return false; -} - -void OpenFirstRunDialog(Profile* profile, - ProcessSingleton* process_singleton) { - DCHECK(profile); - DCHECK(process_singleton); - - views::Window* first_run_ui = views::Window::CreateChromeWindow( - NULL, gfx::Rect(), new FirstRunView(profile)); - DCHECK(first_run_ui); - - // We need to avoid dispatching new tabs when we are doing the import - // because that will lead to data corruption or a crash. Lock() does that. - // If a CopyData message does come in while the First Run UI is visible, - // then we will attempt to set first_run_ui as the foreground window. - process_singleton->Lock(first_run_ui->GetNativeWindow()); - - first_run_ui->Show(); - - // We must now run a message loop (will be terminated when the First Run UI - // is closed) so that the window can receive messages and we block the - // browser window from showing up. We pass the accelerator handler here so - // that keyboard accelerators (Enter, Esc, etc) work in the dialog box. - MessageLoopForUI::current()->Run(g_browser_process->accelerator_handler()); - process_singleton->Unlock(); -} - -namespace { - -// This class is used by FirstRun::ImportSettings to determine when the import -// process has ended and what was the result of the operation as reported by -// the process exit code. This class executes in the context of the main chrome -// process. -class ImportProcessRunner : public base::ObjectWatcher::Delegate { - public: - // The constructor takes the importer process to watch and then it does a - // message loop blocking wait until the process ends. This object now owns - // the import_process handle. - explicit ImportProcessRunner(base::ProcessHandle import_process) - : import_process_(import_process), - exit_code_(ResultCodes::NORMAL_EXIT) { - watcher_.StartWatching(import_process, this); - MessageLoop::current()->Run(); - } - virtual ~ImportProcessRunner() { - ::CloseHandle(import_process_); - } - // Returns the child process exit code. There are 3 expected values: - // NORMAL_EXIT, IMPORTER_CANCEL or IMPORTER_HUNG. - int exit_code() const { - return exit_code_; - } - // The child process has terminated. Find the exit code and quit the loop. - virtual void OnObjectSignaled(HANDLE object) { - DCHECK(object == import_process_); - if (!::GetExitCodeProcess(import_process_, &exit_code_)) { - NOTREACHED(); - } - MessageLoop::current()->Quit(); - } - - private: - base::ObjectWatcher watcher_; - base::ProcessHandle import_process_; - DWORD exit_code_; -}; - -// Check every 3 seconds if the importer UI has hung. -const int kPollHangFrequency = 3000; - -// This class specializes on finding hung 'owned' windows. Unfortunately, the -// HungWindowDetector class cannot be used here because it assumes child -// windows and not owned top-level windows. -// This code is executed in the context of the main browser process and will -// terminate the importer process if it is hung. -class HungImporterMonitor : public WorkerThreadTicker::Callback { - public: - // The ctor takes the owner popup window and the process handle of the - // process to kill in case the popup or its owned active popup become - // unresponsive. - HungImporterMonitor(HWND owner_window, base::ProcessHandle import_process) - : owner_window_(owner_window), - import_process_(import_process), - ticker_(kPollHangFrequency) { - ticker_.RegisterTickHandler(this); - ticker_.Start(); - } - virtual ~HungImporterMonitor() { - ticker_.Stop(); - ticker_.UnregisterTickHandler(this); - } - - private: - virtual void OnTick() { - if (!import_process_) - return; - // We find the top active popup that we own, this will be either the - // owner_window_ itself or the dialog window of the other process. In - // both cases it is worth hung testing because both windows share the - // same message queue and at some point the other window could be gone - // while the other process still not pumping messages. - HWND active_window = ::GetLastActivePopup(owner_window_); - if (::IsHungAppWindow(active_window) || ::IsHungAppWindow(owner_window_)) { - ::TerminateProcess(import_process_, ResultCodes::IMPORTER_HUNG); - import_process_ = NULL; - } - } - - HWND owner_window_; - base::ProcessHandle import_process_; - WorkerThreadTicker ticker_; - DISALLOW_EVIL_CONSTRUCTORS(HungImporterMonitor); -}; - -// This class is used by FirstRun::ImportNow to get notified of the outcome of -// the import operation. It differs from ImportProcessRunner in that this -// class executes in the context of importing child process. -// The values that it handles are meant to be used as the process exit code. -class FirstRunImportObserver : public ImportObserver { - public: - FirstRunImportObserver() - : loop_running_(false), import_result_(ResultCodes::NORMAL_EXIT) { - } - int import_result() const { - return import_result_; - } - virtual void ImportCanceled() { - import_result_ = ResultCodes::IMPORTER_CANCEL; - Finish(); - } - virtual void ImportComplete() { - import_result_ = ResultCodes::NORMAL_EXIT; - Finish(); - } - - void RunLoop() { - loop_running_ = true; - MessageLoop::current()->Run(); - } - - private: - void Finish() { - if (loop_running_) - MessageLoop::current()->Quit(); - } - - bool loop_running_; - int import_result_; - DISALLOW_EVIL_CONSTRUCTORS(FirstRunImportObserver); -}; - -std::wstring EncodeImportParams(int browser_type, int options, HWND window) { - return StringPrintf(L"%d@%d@%d", browser_type, options, window); -} - -bool DecodeImportParams(const std::wstring& encoded, - int* browser_type, int* options, HWND* window) { - std::vector<std::wstring> v; - SplitString(encoded, L'@', &v); - if (v.size() != 3) - return false; - *browser_type = static_cast<int>(StringToInt64(v[0])); - *options = static_cast<int>(StringToInt64(v[1])); - *window = reinterpret_cast<HWND>(StringToInt64(v[2])); - return true; -} - -} // namespace - -bool FirstRun::ImportSettings(Profile* profile, int browser_type, - int items_to_import, HWND parent_window) { - const CommandLine& cmdline = *CommandLine::ForCurrentProcess(); - CommandLine import_cmd(cmdline.program()); - // Propagate user data directory switch. - if (cmdline.HasSwitch(switches::kUserDataDir)) { - import_cmd.AppendSwitchWithValue( - switches::kUserDataDir, - cmdline.GetSwitchValue(switches::kUserDataDir)); - } - - // Since ImportSettings is called before the local state is stored on disk - // we pass the language as an argument. GetApplicationLocale checks the - // current command line as fallback. - import_cmd.AppendSwitchWithValue( - switches::kLang, - g_browser_process->GetApplicationLocale()); - - import_cmd.CommandLine::AppendSwitchWithValue(switches::kImport, - EncodeImportParams(browser_type, items_to_import, parent_window)); - - // Time to launch the process that is going to do the import. - base::ProcessHandle import_process; - if (!base::LaunchApp(import_cmd, false, false, &import_process)) - return false; - - // Activate the importer monitor. It awakes periodically in another thread - // and checks that the importer UI is still pumping messages. - if (parent_window) - HungImporterMonitor hang_monitor(parent_window, import_process); - - // We block inside the import_runner ctor, pumping messages until the - // importer process ends. This can happen either by completing the import - // or by hang_monitor killing it. - ImportProcessRunner import_runner(import_process); - - // Import process finished. Reload the prefs, because importer may set - // the pref value. - if (profile) - profile->GetPrefs()->ReloadPersistentPrefs(); - - return (import_runner.exit_code() == ResultCodes::NORMAL_EXIT); -} - -int FirstRun::ImportNow(Profile* profile, const CommandLine& cmdline) { - std::wstring import_info = cmdline.GetSwitchValue(switches::kImport); - if (import_info.empty()) { - NOTREACHED(); - return false; - } - int browser_type = 0; - int items_to_import = 0; - HWND parent_window = NULL; - if (!DecodeImportParams(import_info, &browser_type, &items_to_import, - &parent_window)) { - NOTREACHED(); - return false; - } - scoped_refptr<ImporterHost> importer_host = new ImporterHost(); - FirstRunImportObserver observer; - - // If there is no parent window, we run in headless mode which amounts - // to having the windows hidden and if there is user action required the - // import is automatically canceled. - if (!parent_window) - importer_host->set_headless(); - - StartImportingWithUI( - parent_window, - items_to_import, - importer_host, - importer_host->GetSourceProfileInfoForBrowserType(browser_type), - profile, - &observer, - true); - observer.RunLoop(); - return observer.import_result(); -} - -bool FirstRun::SetShowFirstRunBubblePref() { - PrefService* local_state = g_browser_process->local_state(); - if (!local_state) - return false; - if (!local_state->IsPrefRegistered(prefs::kShouldShowFirstRunBubble)) { - local_state->RegisterBooleanPref(prefs::kShouldShowFirstRunBubble, false); - local_state->SetBoolean(prefs::kShouldShowFirstRunBubble, true); - } - return true; -} - -bool FirstRun::SetOEMFirstRunBubblePref() { - PrefService* local_state = g_browser_process->local_state(); - if (!local_state) - return false; - if (!local_state->IsPrefRegistered(prefs::kShouldUseOEMFirstRunBubble)) { - local_state->RegisterBooleanPref(prefs::kShouldUseOEMFirstRunBubble, - false); - local_state->SetBoolean(prefs::kShouldUseOEMFirstRunBubble, true); - } - return true; -} - -bool FirstRun::SetShowWelcomePagePref() { - PrefService* local_state = g_browser_process->local_state(); - if (!local_state) - return false; - if (!local_state->IsPrefRegistered(prefs::kShouldShowWelcomePage)) { - local_state->RegisterBooleanPref(prefs::kShouldShowWelcomePage, false); - local_state->SetBoolean(prefs::kShouldShowWelcomePage, true); - } - return true; -} |