diff --git a/browser/brave_browser_main_parts.cc b/browser/brave_browser_main_parts.cc index 069500aac7d2..bec7a2c6f299 100644 --- a/browser/brave_browser_main_parts.cc +++ b/browser/brave_browser_main_parts.cc @@ -35,6 +35,7 @@ #include "content/public/browser/web_contents.h" #include "extensions/buildflags/buildflags.h" #include "media/base/media_switches.h" +#include "ui/views/login/login_screen_view.h" #if BUILDFLAG(ENABLE_SPEEDREADER) #include "brave/components/speedreader/speedreader_extended_info_handler.h" @@ -81,9 +82,6 @@ ChromeBrowserMainParts::ChromeBrowserMainParts(bool is_integration_test, ChromeBrowserMainParts::~ChromeBrowserMainParts() = default; int ChromeBrowserMainParts::PreMainMessageLoopRun() { - brave_component_updater::BraveOnDemandUpdater::GetInstance() - ->RegisterOnDemandUpdater( - &g_browser_process->component_updater()->GetOnDemandUpdater()); return ChromeBrowserMainParts_ChromiumImpl::PreMainMessageLoopRun(); } @@ -99,6 +97,20 @@ void ChromeBrowserMainParts::PreBrowserStart() { speedreader::SpeedreaderExtendedInfoHandler::Register(); #endif + brave_component_updater::BraveOnDemandUpdater::GetInstance() + ->RegisterOnDemandUpdater( + &g_browser_process->component_updater()->GetOnDemandUpdater()); + + // views::Widget* login_widget = new views::Widget(); + // views::Widget::InitParams params(views::Widget::InitParams::TYPE_WINDOW); + // params.bounds = gfx::Rect(100, 100, 400, 300); + // login_widget->Init(std::move(params)); + + // LoginScreenView* login_screen = new LoginScreenView(); + // login_widget->SetContentsView(login_screen); + + // login_widget->Show(); + ChromeBrowserMainParts_ChromiumImpl::PreBrowserStart(); } diff --git a/browser/brave_profile_prefs.cc b/browser/brave_profile_prefs.cc index 038d9bbf8c78..368b28ab2f3d 100644 --- a/browser/brave_profile_prefs.cc +++ b/browser/brave_profile_prefs.cc @@ -52,6 +52,7 @@ #include "brave/components/tor/buildflags/buildflags.h" #include "build/build_config.h" #include "chrome/browser/prefetch/pref_names.h" +#include "components/prefs/pref_service.h" #include "chrome/browser/prefs/session_startup_pref.h" #include "chrome/browser/preloading/preloading_prefs.h" #include "chrome/browser/ui/webui/new_tab_page/ntp_pref_names.h" @@ -151,6 +152,8 @@ void RegisterProfilePrefsForMigration( brave_wallet::RegisterProfilePrefsForMigration(registry); // Restore "Other Bookmarks" migration + registry->RegisterBooleanPref(kLoginState, false); + registry->RegisterBooleanPref(kOtherBookmarksMigrated, false); // Added 05/2021 @@ -499,4 +502,12 @@ void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry) { base::Value(false)); } +bool IsLoggedIn(PrefService* prefs) { + return prefs->GetBoolean(kLoginState); +} + +void SetLoggedIn(PrefService* prefs, bool logged_in) { + prefs->SetBoolean(kLoginState, logged_in); +} + } // namespace brave diff --git a/browser/brave_profile_prefs.h b/browser/brave_profile_prefs.h index a218ada9d606..323885094052 100644 --- a/browser/brave_profile_prefs.h +++ b/browser/brave_profile_prefs.h @@ -6,6 +6,8 @@ #ifndef BRAVE_BROWSER_BRAVE_PROFILE_PREFS_H_ #define BRAVE_BROWSER_BRAVE_PROFILE_PREFS_H_ +#include "components/prefs/pref_service.h" + namespace user_prefs { class PrefRegistrySyncable; } @@ -13,6 +15,8 @@ class PrefRegistrySyncable; namespace brave { void RegisterProfilePrefs(user_prefs::PrefRegistrySyncable* registry); +bool IsLoggedIn(PrefService* prefs); +void SetLoggedIn(PrefService* prefs, bool logged_in); } // namespace brave diff --git a/browser/ui/BUILD.gn b/browser/ui/BUILD.gn index ca2e002131cf..5b02c61302fc 100644 --- a/browser/ui/BUILD.gn +++ b/browser/ui/BUILD.gn @@ -326,6 +326,7 @@ source_set("ui") { "whats_new/pref_names.h", "whats_new/whats_new_util.cc", "whats_new/whats_new_util.h", + ] deps += [ @@ -534,6 +535,8 @@ source_set("ui") { "views/omnibox/brave_rounded_omnibox_results_frame.h", "views/omnibox/brave_search_conversion_promotion_view.cc", "views/omnibox/brave_search_conversion_promotion_view.h", + "views/login/login_screen_view.cc", + "views/login/login_screen_view.h", "views/overlay/brave_back_to_tab_label_button.cc", "views/overlay/brave_back_to_tab_label_button.h", "views/overlay/brave_video_overlay_window_views.cc", diff --git a/browser/ui/views/login/login_screen_view.cc b/browser/ui/views/login/login_screen_view.cc new file mode 100644 index 000000000000..e449860c706c --- /dev/null +++ b/browser/ui/views/login/login_screen_view.cc @@ -0,0 +1,126 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#include "brave/browser/ui/views/login/login_screen_view.h" + +#include "login_screen_view.h" +#include "ui/views/layout/box_layout.h" +#include "base/logging.h" +#include "base/task/sequenced_task_runner.h" +#include "base/task/single_thread_task_runner.h" +#include "ui/gfx/geometry/insets.h" + +LoginScreenView::LoginScreenView(Profile* profile, + base::OnceCallback on_login_success) + : profile_(profile->GetWeakPtr()), + username_field_(nullptr), + password_field_(nullptr), + login_button_(nullptr), + on_login_success_(std::move(on_login_success)) { + + DCHECK(profile) << "Profile cannot be null"; + CreateUI(); +} + +LoginScreenView::~LoginScreenView() { + LOG(INFO) << "LoginScreenView destroyed"; +} + +void LoginScreenView::CreateUI() { + SetLayoutManager(std::make_unique( + views::BoxLayout::Orientation::kVertical, + gfx::Insets(20), + 10)); + + auto* title = new views::Label(u"Ping Login"); + title->SetHorizontalAlignment(gfx::ALIGN_CENTER); + AddChildView(title); + + // Username section + auto* username_label = new views::Label(u"Username:"); + AddChildView(username_label); + + username_field_ = new views::Textfield(); + AddChildView(username_field_); + + // Password section + auto* password_label = new views::Label(u"Password:"); + AddChildView(password_label); + + password_field_ = new views::Textfield(); + password_field_->SetTextInputType(ui::TextInputType::TEXT_INPUT_TYPE_PASSWORD); + AddChildView(password_field_); + + // Login button + login_button_ = new views::MdTextButton( + base::BindRepeating(&LoginScreenView::OnLoginButtonPressed, + weak_ptr_factory_.GetWeakPtr()), + u"Login"); + login_button_->SetIsDefault(true); + AddChildView(login_button_); +} + +bool LoginScreenView::Cancel() { + // Closing the login dialog + CloseAndRunCallback(); + return true; +} + +bool LoginScreenView::Accept() { + // Returning false to prevent the default functionality of OK button + return false; +} + +void LoginScreenView::CloseAndRunCallback() { + LOG(INFO) << "Processing login success"; + + // Taking ownership of the callback before closing the widget + auto callback = std::move(on_login_success_); + auto* widget = GetWidget(); + + // Posting the task to ensure safe execution order + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce( + [](base::OnceCallback callback, + views::Widget* widget, + base::WeakPtr profile) { + if (!profile) { + LOG(ERROR) << "Profile no longer valid"; + return; + } + + LOG(INFO) << "Executing login callback"; + std::move(callback).Run(); + + LOG(INFO) << "Closing login dialog"; + if (widget) + widget->CloseNow(); + }, + std::move(callback), + widget, + profile_)); +} + +void LoginScreenView::OnLoginButtonPressed() { + if (!profile_) { + LOG(ERROR) << "Profile no longer valid during login"; + return; + } + + std::u16string username = username_field_->GetText(); + std::u16string password = password_field_->GetText(); + + LOG(INFO) << "Processing login attempt"; + + // Test authentication + if (username == u"admin" && password == u"password") { + LOG(INFO) << "Login credentials validated"; + CloseAndRunCallback(); + } else { + LOG(INFO) << "Login validation failed"; + // TODO: Adding user feedback + } +} \ No newline at end of file diff --git a/browser/ui/views/login/login_screen_view.h b/browser/ui/views/login/login_screen_view.h new file mode 100644 index 000000000000..f47f1e37ca28 --- /dev/null +++ b/browser/ui/views/login/login_screen_view.h @@ -0,0 +1,50 @@ +/* Copyright (c) 2022 The Brave Authors. All rights reserved. + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this file, + * You can obtain one at https://mozilla.org/MPL/2.0/. */ + +#ifndef BRAVE_BROWSER_UI_VIEWS_LOGIN_SCREEN_VIEW_H_ +#define BRAVE_BROWSER_UI_VIEWS_LOGIN_SCREEN_VIEW_H_ + +#include "base/memory/raw_ptr.h" +#include "base/memory/weak_ptr.h" +#include "ui/views/window/dialog_delegate.h" +#include "ui/views/controls/button/md_text_button.h" +#include "ui/views/controls/textfield/textfield.h" +#include "ui/views/controls/label.h" +#include "chrome/browser/profiles/profile.h" +#include "base/functional/callback.h" +#include "ui/views/window/dialog_delegate.h" + +class LoginScreenView : public views::DialogDelegateView { + public: + explicit LoginScreenView(Profile* profile, + base::OnceCallback on_login_success); + ~LoginScreenView() override; + + // Prevents copying and assignment of the dialog view + LoginScreenView(const LoginScreenView&) = delete; + LoginScreenView& operator=(const LoginScreenView&) = delete; + + bool Accept() override; + + bool Cancel() override; + + private: + void CreateUI(); + + void OnLoginButtonPressed(); + + void CloseAndRunCallback(); + + base::WeakPtr profile_; + raw_ptr username_field_; + raw_ptr password_field_; + raw_ptr login_button_; + base::OnceCallback on_login_success_; + + // For safe callback handling on the UI thread after the dialog is closed + base::WeakPtrFactory weak_ptr_factory_{this}; +}; + +#endif // BRAVE_BROWSER_UI_VIEWS_LOGIN_SCREEN_VIEW_H_ \ No newline at end of file diff --git a/chromium_src/chrome/browser/ui/startup/startup_browser_creator.cc b/chromium_src/chrome/browser/ui/startup/startup_browser_creator.cc index 8be50d2dcf50..44e9f2284ced 100644 --- a/chromium_src/chrome/browser/ui/startup/startup_browser_creator.cc +++ b/chromium_src/chrome/browser/ui/startup/startup_browser_creator.cc @@ -7,6 +7,14 @@ #include "brave/components/constants/brave_switches.h" #include "brave/components/tor/buildflags/buildflags.h" #include "chrome/browser/ui/startup/startup_browser_creator_impl.h" +#include "brave/browser/ui/views/login/login_screen_view.h" +#include "ui/views/widget/widget.h" +#include "base/memory/raw_ptr.h" +#include "base/run_loop.h" +#include "base/task/thread_pool.h" +#include "base/task/thread_pool/thread_pool_instance.h" +#include "base/task/sequenced_task_runner.h" +#include "base/threading/sequence_bound.h" #if BUILDFLAG(ENABLE_TOR) #include "brave/browser/tor/tor_profile_manager.h" @@ -18,6 +26,26 @@ static_assert(false, "LaunchModeRecorder, and remove this assert."); #endif // #ifdef LaunchModeRecorder +class BraveStartupBrowserCreatorImpl; + +// Launch parameters structure +struct LaunchParams { + // Using WeakPtr for safer profile access + base::WeakPtr profile; + chrome::startup::IsProcessStartup process_startup; + bool restore_tabbed_browser; + // Owned RunLoop instance for better lifetime management + std::unique_ptr run_loop; + + LaunchParams(Profile* p, + chrome::startup::IsProcessStartup ps, + bool rtb) + : profile(p->GetWeakPtr()), + process_startup(ps), + restore_tabbed_browser(rtb), + run_loop(std::make_unique()) {} +}; + class BraveStartupBrowserCreatorImpl final : public StartupBrowserCreatorImpl { public: BraveStartupBrowserCreatorImpl(const base::FilePath& cur_dir, @@ -32,8 +60,22 @@ class BraveStartupBrowserCreatorImpl final : public StartupBrowserCreatorImpl { void Launch(Profile* profile, chrome::startup::IsProcessStartup process_startup, bool restore_tabbed_browser); + + private: + + void LaunchWithAuth(std::shared_ptr params); + void OnLoginSuccess(std::shared_ptr params); + void FinishLaunch(std::shared_ptr params); + + // Thread safe flag to check if the user is logged in + static std::atomic is_logged_in_; + + // Using weak pointer factory for safe callback handling + base::WeakPtrFactory weak_ptr_factory_{this}; }; +std::atomic BraveStartupBrowserCreatorImpl::is_logged_in_(false); + BraveStartupBrowserCreatorImpl::BraveStartupBrowserCreatorImpl( const base::FilePath& cur_dir, const base::CommandLine& command_line, @@ -55,10 +97,17 @@ BraveStartupBrowserCreatorImpl::BraveStartupBrowserCreatorImpl( // // Note that if the --tor switch is used together with --silent-launch, Tor // won't be launched. + void BraveStartupBrowserCreatorImpl::Launch( Profile* profile, chrome::startup::IsProcessStartup process_startup, bool restore_tabbed_browser) { + + DCHECK(profile) << "Profile cannot be null"; + + LOG(INFO) << "Starting browser launch process"; + LOG(INFO) << "Current thread: " << base::PlatformThread::CurrentId(); + #if BUILDFLAG(ENABLE_TOR) if (StartupBrowserCreatorImpl::command_line_->HasSwitch(switches::kTor)) { // Call StartupBrowserCreatorImpl::Launch() with the Tor profile so that if @@ -69,8 +118,100 @@ void BraveStartupBrowserCreatorImpl::Launch( } #endif - StartupBrowserCreatorImpl::Launch(profile, process_startup, - restore_tabbed_browser); + auto params = std::make_shared( + profile, process_startup, restore_tabbed_browser); + + // Capturing the stack trace for debugging + base::debug::StackTrace stack_trace; + LOG(INFO) << "Launch stack trace: " << stack_trace.ToString(); + + LaunchWithAuth(params); + + // Only entering the RunLoop if authentication is needed + if (!is_logged_in_) { + LOG(INFO) << "Waiting for authentication..."; + params->run_loop->Run(); + LOG(INFO) << "Authentication complete"; + } +} + +void BraveStartupBrowserCreatorImpl::LaunchWithAuth( + std::shared_ptr params) { + + DCHECK(params); + DCHECK(params->profile.get()) << "Invalid profile in launch params"; + + if (!is_logged_in_) { + LOG(INFO) << "Starting authentication process"; + + // Creating the login callback + auto login_callback = base::BindOnce( + [](base::WeakPtr weak_this, + std::shared_ptr params) { + if (weak_this) { + // Posting to UI thread for safe execution + base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask( + FROM_HERE, + base::BindOnce( + &BraveStartupBrowserCreatorImpl::OnLoginSuccess, + weak_this, + params)); + } + }, + weak_ptr_factory_.GetWeakPtr(), + params); + + // Create and show login dialog + views::Widget* widget = views::DialogDelegate::CreateDialogWidget( + new LoginScreenView(params->profile.get(), std::move(login_callback)), + nullptr, + nullptr); + + LOG(INFO) << "Showing login dialog"; + widget->Show(); + } else { + // Already logged in, proceeding with launch + FinishLaunch(params); + } +} + +void BraveStartupBrowserCreatorImpl::OnLoginSuccess( + std::shared_ptr params) { + + LOG(INFO) << "Login success callback executed"; + + if (!params || !params->profile.get()) { + LOG(ERROR) << "Invalid launch parameters in OnLoginSuccess"; + return; + } + + is_logged_in_ = true; + FinishLaunch(params); +} + +void BraveStartupBrowserCreatorImpl::FinishLaunch( + std::shared_ptr params) { + + LOG(INFO) << "Starting browser launch"; + + if (!params || !params->profile.get()) { + LOG(ERROR) << "Invalid launch parameters in FinishLaunch"; + return; + } + + // Launching the browser with safe profile access + StartupBrowserCreatorImpl::Launch( + params->profile.get(), + params->process_startup, + params->restore_tabbed_browser); + + // Quitting the RunLoop if it exists + if (params->run_loop) { + LOG(INFO) << "Quitting launch RunLoop"; + params->run_loop->Quit(); + } + + LOG(INFO) << "Browser launch complete"; } #define StartupBrowserCreatorImpl BraveStartupBrowserCreatorImpl diff --git a/components/constants/pref_names.h b/components/constants/pref_names.h index 051eee42df44..11bdd2128d9a 100644 --- a/components/constants/pref_names.h +++ b/components/constants/pref_names.h @@ -135,6 +135,7 @@ inline constexpr char kNewTabPageShowTopSites[] = "brave.new_tab_page.show_top_sites"; inline constexpr char kOtherBookmarksMigrated[] = "brave.other_bookmarks_migrated"; +inline constexpr char kLoginState[] = "brave.login_state"; // Obsolete widget removal prefs #if !BUILDFLAG(IS_IOS) && !BUILDFLAG(IS_ANDROID)