Don't add Chromium as a login item
"Background mode" is about allowing background apps to continue running
even when Chromium is closed. What does "closed" mean, though? On
Windows, an app is "closed" if it has no windows open, so on Windows,
background mode keeps the actual chrome.exe running with just an
indication in the system tray.
This has always mapped imperfectly to the Mac, where apps cannot run
without an active Dock icon, yet can remain running without any windows
open. With this mismatch, early on, background mode was implemented on
the Mac to add a login item if an extension was marked as requesting
background mode.
However, using a login item in this way does not significantly improve
the experience of background mode. In addition, the state of the world
has also changed:
- For many years now, macOS has automatically resumed apps that were
running prior to shutdown. This means that the system is, in many
cases, automatically restarting Chromium anyway.
- macOS Ventura adds more restrictions in the area of adding code to
run at startup/login, so this isn't a place that is desirable to be in
anyway.
And finally, given the age of the bug and its number of stars, it's
not clear that this code worked well in the first place.
Given all that, the decision was made to remove the "background mode =
create login item" code on the Mac.
Fixed: 140017
Change-Id: I01b0f20e0bbd3b30bdfd82a9eabfb6ae20437ef0
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/3997795
Reviewed-by: Devlin Cronin <[email protected]>
Reviewed-by: Mark Mentovai <[email protected]>
Commit-Queue: Avi Drissman <[email protected]>
Cr-Commit-Position: refs/heads/main@{#1066674}
diff --git a/chrome/browser/BUILD.gn b/chrome/browser/BUILD.gn
index c501302..314156e 100644
--- a/chrome/browser/BUILD.gn
+++ b/chrome/browser/BUILD.gn
@@ -6850,7 +6850,7 @@
sources += [ "background/background_mode_manager_win.cc" ]
}
if (is_mac) {
- sources += [ "background/background_mode_manager_mac.mm" ]
+ sources += [ "background/background_mode_manager_mac.cc" ]
}
if (is_chromeos_ash) {
sources += [ "background/background_mode_manager_chromeos.cc" ]
diff --git a/chrome/browser/background/background_mode_manager.cc b/chrome/browser/background/background_mode_manager.cc
index cbf9b5d..9894507 100644
--- a/chrome/browser/background/background_mode_manager.cc
+++ b/chrome/browser/background/background_mode_manager.cc
@@ -24,7 +24,6 @@
#include "base/metrics/user_metrics.h"
#include "base/one_shot_event.h"
#include "base/strings/utf_string_conversions.h"
-#include "base/task/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
#include "build/chromeos_buildflags.h"
@@ -372,11 +371,6 @@
// static
void BackgroundModeManager::RegisterPrefs(PrefRegistrySimple* registry) {
-#if BUILDFLAG(IS_MAC)
- registry->RegisterBooleanPref(prefs::kUserRemovedLoginItem, false);
- registry->RegisterBooleanPref(prefs::kChromeCreatedLoginItem, false);
- registry->RegisterBooleanPref(prefs::kMigratedLoginItemPref, false);
-#endif
registry->RegisterBooleanPref(prefs::kBackgroundModeEnabled, true);
}
@@ -874,6 +868,8 @@
EnableLaunchOnStartup(*launch_on_startup_enabled_);
}
+namespace {
+
// Gets the image for the status tray icon, at the correct size for the current
// platform and display settings.
gfx::ImageSkia GetStatusTrayIcon() {
@@ -906,6 +902,8 @@
#endif
}
+} // namespace
+
void BackgroundModeManager::CreateStatusTrayIcon() {
// Only need status icons on windows/linux. ChromeOS doesn't allow exiting
// Chrome and Mac can use the dock icon instead.
diff --git a/chrome/browser/background/background_mode_manager_mac.cc b/chrome/browser/background/background_mode_manager_mac.cc
new file mode 100644
index 0000000..71669968
--- /dev/null
+++ b/chrome/browser/background/background_mode_manager_mac.cc
@@ -0,0 +1,25 @@
+// Copyright 2011 The Chromium Authors
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/browser/background/background_mode_manager.h"
+
+#include "base/task/sequenced_task_runner.h"
+#include "base/task/thread_pool.h"
+
+void BackgroundModeManager::EnableLaunchOnStartup(bool should_launch) {
+ // The Mac does not support forcing a launch on startup.
+}
+
+void BackgroundModeManager::DisplayClientInstalledNotification(
+ const std::u16string& name) {
+ // TODO(http://crbug.com/74970): Display a platform-appropriate notification
+ // here.
+}
+
+scoped_refptr<base::SequencedTaskRunner>
+BackgroundModeManager::CreateTaskRunner() {
+ return base::ThreadPool::CreateSequencedTaskRunner(
+ {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
+ base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
+}
diff --git a/chrome/browser/background/background_mode_manager_mac.mm b/chrome/browser/background/background_mode_manager_mac.mm
deleted file mode 100644
index 53aea51e..0000000
--- a/chrome/browser/background/background_mode_manager_mac.mm
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright 2011 The Chromium Authors
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/bind.h"
-#include "base/command_line.h"
-#include "base/mac/mac_util.h"
-#include "base/task/sequenced_task_runner.h"
-#include "base/task/thread_pool.h"
-#include "base/threading/scoped_blocking_call.h"
-#include "chrome/browser/background/background_mode_manager.h"
-#include "chrome/browser/browser_process.h"
-#include "chrome/common/chrome_switches.h"
-#include "chrome/common/pref_names.h"
-#include "components/prefs/pref_service.h"
-#include "content/public/browser/browser_task_traits.h"
-#include "content/public/browser/browser_thread.h"
-
-using content::BrowserThread;
-
-namespace {
-void SetUserRemovedLoginItemPrefOnUIThread() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- PrefService* service = g_browser_process->local_state();
- service->SetBoolean(prefs::kUserRemovedLoginItem, true);
-}
-
-void SetCreatedLoginItemPrefOnUIThread() {
- DCHECK_CURRENTLY_ON(content::BrowserThread::UI);
- PrefService* service = g_browser_process->local_state();
- service->SetBoolean(prefs::kChromeCreatedLoginItem, true);
-}
-
-void DisableLaunchOnStartupOnWorkerThread() {
- base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
- base::BlockingType::MAY_BLOCK);
- // If the LoginItem is not hidden, it means it's user created, so don't
- // delete it.
- bool is_hidden = false;
- if (base::mac::CheckLoginItemStatus(&is_hidden) && is_hidden)
- base::mac::RemoveFromLoginItems();
-}
-
-void CheckForUserRemovedLoginItemOnWorkerThread() {
- base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
- base::BlockingType::MAY_BLOCK);
- if (!base::mac::CheckLoginItemStatus(NULL)) {
- // There's no LoginItem, so set the kUserRemovedLoginItem pref.
- content::GetUIThreadTaskRunner({})->PostTask(
- FROM_HERE, base::BindOnce(SetUserRemovedLoginItemPrefOnUIThread));
- }
-}
-
-void EnableLaunchOnStartupOnWorkerThread(bool need_migration) {
- base::ScopedBlockingCall scoped_blocking_call(FROM_HERE,
- base::BlockingType::MAY_BLOCK);
- if (need_migration) {
- // This is the first time running Chrome since the kChromeCreatedLoginItem
- // pref was added. Initialize the status of this pref based on whether
- // there is already a hidden login item.
- bool is_hidden = false;
- if (base::mac::CheckLoginItemStatus(&is_hidden)) {
- if (is_hidden) {
- // We already have a hidden login item, so set the kChromeCreatedLoginItem
- // flag.
- content::GetUIThreadTaskRunner({})->PostTask(
- FROM_HERE, base::BindOnce(SetCreatedLoginItemPrefOnUIThread));
- }
- // LoginItem already exists - just exit.
- return;
- }
- }
-
- // Check if Chrome is already a Login Item - if not, create one.
- if (!base::mac::CheckLoginItemStatus(NULL)) {
- // Call back to the UI thread to set our preference so we know that Chrome
- // created the login item (which means we are allowed to delete it later).
- // There's a race condition here if the user disables launch on startup
- // before our callback is run, but the user can manually disable
- // "Open At Login" via the dock if this happens.
- base::mac::AddToLoginItems(true); // Hide on startup.
- content::GetUIThreadTaskRunner({})->PostTask(
- FROM_HERE, base::BindOnce(SetCreatedLoginItemPrefOnUIThread));
- }
-}
-
-} // namespace
-
-void BackgroundModeManager::EnableLaunchOnStartup(bool should_launch) {
- // LoginItems are associated with an executable, not with a specific
- // user-data-dir, so only mess with the LoginItem when running with the
- // default user-data-dir. So if a user is running multiple instances of
- // Chrome with different user-data-dirs, they won't conflict in their
- // use of LoginItems.
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserDataDir))
- return;
-
- // There are a few cases we need to handle:
- //
- // 1) Chrome is transitioning to "launch on startup" state, and there's no
- // login item currently. We create a new item if the kUserRemovedLoginItem
- // and kChromeCreatedLoginItem flags are already false, and set the
- // kChromeCreatedLoginItem flag to true. If kChromeCreatedLoginItem is
- // already set (meaning that we created a login item that has since been
- // deleted) then we will set the kUserRemovedLoginItem so we do not create
- // login items in the future.
- //
- // 2) Chrome is transitioning to the "do not launch on startup" state. If
- // the kChromeCreatedLoginItem flag is false, we do nothing. Otherwise, we
- // will delete the login item if it's present, and not we will set
- // kUserRemovedLoginItem to true to prevent future login items from being
- // created.
- if (should_launch) {
- PrefService* service = g_browser_process->local_state();
- // If the user removed the login item, don't ever create another one.
- if (service->GetBoolean(prefs::kUserRemovedLoginItem))
- return;
-
- if (service->GetBoolean(prefs::kChromeCreatedLoginItem)) {
- DCHECK(service->GetBoolean(prefs::kMigratedLoginItemPref));
- // If we previously created a login item, we don't need to create
- // a new one - just check to see if the user removed it so we don't
- // ever create another one.
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(CheckForUserRemovedLoginItemOnWorkerThread));
- } else {
- bool need_migration = !service->GetBoolean(
- prefs::kMigratedLoginItemPref);
- service->SetBoolean(prefs::kMigratedLoginItemPref, true);
- task_runner_->PostTask(
- FROM_HERE,
- base::BindOnce(EnableLaunchOnStartupOnWorkerThread, need_migration));
- }
- } else {
- PrefService* service = g_browser_process->local_state();
- // If Chrome didn't create any login items, just exit.
- if (!service->GetBoolean(prefs::kChromeCreatedLoginItem))
- return;
-
- // Clear the pref now that we're removing the login item.
- service->ClearPref(prefs::kChromeCreatedLoginItem);
-
- // If the user removed our login item, note this so we don't ever create
- // another one.
- task_runner_->PostTask(
- FROM_HERE, base::BindOnce(CheckForUserRemovedLoginItemOnWorkerThread));
-
- // Call to the File thread to remove the login item since it requires
- // accessing the disk.
- task_runner_->PostTask(
- FROM_HERE, base::BindOnce(DisableLaunchOnStartupOnWorkerThread));
- }
-}
-
-void BackgroundModeManager::DisplayClientInstalledNotification(
- const std::u16string& name) {
- // TODO(atwilson): Display a platform-appropriate notification here.
- // http://crbug.com/74970
-}
-
-scoped_refptr<base::SequencedTaskRunner>
-BackgroundModeManager::CreateTaskRunner() {
- return base::ThreadPool::CreateSequencedTaskRunner(
- {base::MayBlock(), base::TaskPriority::BEST_EFFORT,
- base::TaskShutdownBehavior::BLOCK_SHUTDOWN});
-}
diff --git a/chrome/browser/prefs/browser_prefs.cc b/chrome/browser/prefs/browser_prefs.cc
index 67fc241..c6fc5783 100644
--- a/chrome/browser/prefs/browser_prefs.cc
+++ b/chrome/browser/prefs/browser_prefs.cc
@@ -775,6 +775,15 @@
"ash.launcher.suggested_content_info_dismissed";
#endif
+#if BUILDFLAG(ENABLE_BACKGROUND_MODE) && BUILDFLAG(IS_MAC)
+// Deprecated 11/2022.
+const char kUserRemovedLoginItem[] = "background_mode.user_removed_login_item";
+const char kChromeCreatedLoginItem[] =
+ "background_mode.chrome_created_login_item";
+const char kMigratedLoginItemPref[] =
+ "background_mode.migrated_login_item_pref";
+#endif
+
// Register local state used only for migration (clearing or moving to a new
// key).
void RegisterLocalStatePrefsForMigration(PrefRegistrySimple* registry) {
@@ -837,6 +846,13 @@
// Deprecated 09/2022
registry->RegisterDictionaryPref(kUsersLastInputMethod);
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+
+// Deprecated 11/2022.
+#if BUILDFLAG(ENABLE_BACKGROUND_MODE) && BUILDFLAG(IS_MAC)
+ registry->RegisterBooleanPref(kUserRemovedLoginItem, false);
+ registry->RegisterBooleanPref(kChromeCreatedLoginItem, false);
+ registry->RegisterBooleanPref(kMigratedLoginItemPref, false);
+#endif // BUILDFLAG(IS_CHROMEOS_ASH)
}
// Register prefs used only for migration (clearing or moving to a new key).
@@ -1743,6 +1759,13 @@
local_state->ClearPref(kUsersLastInputMethod);
#endif // BUILDFLAG(IS_CHROMEOS_ASH)
+#if BUILDFLAG(ENABLE_BACKGROUND_MODE) && BUILDFLAG(IS_MAC)
+ // Added 11/2022.
+ local_state->ClearPref(kUserRemovedLoginItem);
+ local_state->ClearPref(kChromeCreatedLoginItem);
+ local_state->ClearPref(kMigratedLoginItemPref);
+#endif
+
// Please don't delete the following line. It is used by PRESUBMIT.py.
// END_MIGRATE_OBSOLETE_LOCAL_STATE_PREFS