Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(565)

Unified Diff: chrome/browser/background/background_mode_manager_mac.mm

Issue 13982009: Fix issue with login items getting recreated. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Created 7 years, 8 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/background/background_mode_manager_mac.mm
diff --git a/chrome/browser/background/background_mode_manager_mac.mm b/chrome/browser/background/background_mode_manager_mac.mm
index 3f764b693e75151fdce1177ef4f0166745ca7437..232f482fbfceb164dd1fe88ec355dfdff3ba3671 100644
--- a/chrome/browser/background/background_mode_manager_mac.mm
+++ b/chrome/browser/background/background_mode_manager_mac.mm
@@ -17,69 +17,63 @@
using content::BrowserThread;
namespace {
-#if !defined(NDEBUG)
-// The code to remove a login item has a potential race (because the code to
-// set and check the kUserRemovedLoginItem pref runs on the UI thread, while
-// the code that checks for a login item runs on the IO thread). We add this
-// flag which should always match the value of the pref to see if we ever hit
-// this race in practice.
-static bool login_item_removed = false;
-#endif
-
void SetUserRemovedLoginItemPrefCallback() {
PrefService* service = g_browser_process->local_state();
service->SetBoolean(prefs::kUserRemovedLoginItem, true);
}
+void SetCreatedLoginItemPrefCallback() {
+ PrefService* service = g_browser_process->local_state();
+ service->SetBoolean(prefs::kChromeCreatedLoginItem, true);
+}
+
void DisableLaunchOnStartupCallback() {
- // Check if Chrome is not a login Item, or is a Login Item but w/o 'hidden'
- // flag - most likely user has modified the setting, don't override it.
+ // 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)) {
- // No login item - this means the user must have already removed it, so
- // call back to the UI thread to set a preference so we don't try to
- // recreate it the next time they enable/install a background app.
-#if !defined(NDEBUG)
- login_item_removed = true;
-#endif
+ if (base::mac::CheckLoginItemStatus(&is_hidden) && is_hidden)
+ base::mac::RemoveFromLoginItems();
+}
+
+void CheckForUserRemovedLoginItem() {
+ if (!base::mac::CheckLoginItemStatus(NULL)) {
+ // There's no LoginItem, so set the kUserRemovedLoginItem pref.
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(SetUserRemovedLoginItemPrefCallback));
- return;
}
-
- // If the login item does not have the "hidden" flag set, just leave it there
- // since it means the user must have created it.
- if (!is_hidden)
- return;
-
- // Remove the login item we created.
- base::mac::RemoveFromLoginItems();
}
-void SetUserCreatedLoginItemPrefCallback() {
- PrefService* service = g_browser_process->local_state();
- service->SetBoolean(prefs::kUserCreatedLoginItem, true);
-}
-
-void EnableLaunchOnStartupCallback(bool should_add_login_item) {
- // Check if Chrome is already a Login Item (avoid overriding user choice).
- if (base::mac::CheckLoginItemStatus(NULL)) {
- // Call back to the UI thread to set our preference so we don't delete the
- // user's login item when we disable launch on startup. 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.
- BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(SetUserCreatedLoginItemPrefCallback));
- return;
+void EnableLaunchOnStartupCallback(bool need_migration) {
+ if (need_migration) {
+ DLOG(ERROR) << "MIGRATING";
+ // 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)) {
+ DLOG(ERROR) << "FOUND LOGIN ITEM - hidden = " << is_hidden;
+ if (is_hidden) {
+ // We already have a hidden login item, so set the kChromeCreatedLoginItem
+ // flag.
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(SetCreatedLoginItemPrefCallback));
+ }
+ // LoginItem already exists - just exit.
+ return;
+ }
}
- if (should_add_login_item)
+ // 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.
-#if !defined(NDEBUG)
- else
- DCHECK(!login_item_removed); // Check for race condition (see above).
-#endif
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(SetCreatedLoginItemPrefCallback));
+ }
}
} // namespace
@@ -89,29 +83,56 @@ void BackgroundModeManager::EnableLaunchOnStartup(bool should_launch) {
if (CommandLine::ForCurrentProcess()->HasSwitch(switches::kUserDataDir))
sail 2013/04/11 16:12:29 The user data directory has nothing to do with def
Andrew T Wilson (Slow) 2013/04/12 09:52:21 Yeah, the comment was wrong (predated multi-profil
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();
- // Create a login item if the user did not remove our login item
- // previously. We call out to the FILE thread either way since we
- // want to check for a user-created login item.
- bool should_add_login_item =
- !service->GetBoolean(prefs::kUserRemovedLoginItem);
- BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(EnableLaunchOnStartupCallback,
- should_add_login_item));
+ // 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
+ // every create another one.
sail 2013/04/11 16:12:29 typo? "don't every"
Andrew T Wilson (Slow) 2013/04/12 09:52:21 Done.
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(CheckForUserRemovedLoginItem));
+ } else {
+ bool need_migration = !service->GetBoolean(
+ prefs::kMigratedLoginItemPref);
+ service->SetBoolean(prefs::kMigratedLoginItemPref, true);
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(EnableLaunchOnStartupCallback,
+ need_migration));
+ }
} else {
PrefService* service = g_browser_process->local_state();
- if (service->GetBoolean(prefs::kUserCreatedLoginItem)) {
- // We didn't create the login item, so nothing to do here. Clear our
- // prefs so if the user removes the login item before installing a
- // background app, we will revert to the default behavior.
- service->ClearPref(prefs::kUserCreatedLoginItem);
- service->ClearPref(prefs::kUserRemovedLoginItem);
-#if !defined(NDEBUG)
- login_item_removed = false;
-#endif
+ // We didn't create any login items, so 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.
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(CheckForUserRemovedLoginItem));
+
// Call to the File thread to remove the login item since it requires
// accessing the disk.
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,

Powered by Google App Engine
This is Rietveld 408576698