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

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: Updated comments/review feedback. 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
« no previous file with comments | « chrome/browser/background/background_mode_manager.cc ('k') | chrome/common/pref_names.h » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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..655b34c9c94c46a8fb44fc35354ea89dea700097 100644
--- a/chrome/browser/background/background_mode_manager_mac.mm
+++ b/chrome/browser/background/background_mode_manager_mac.mm
@@ -17,105 +17,135 @@
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() {
+void SetUserRemovedLoginItemPrefOnUIThread() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
PrefService* service = g_browser_process->local_state();
service->SetBoolean(prefs::kUserRemovedLoginItem, 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.
- 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
- 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 SetCreatedLoginItemPrefOnUIThread() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
+ PrefService* service = g_browser_process->local_state();
+ service->SetBoolean(prefs::kChromeCreatedLoginItem, true);
}
-void SetUserCreatedLoginItemPrefCallback() {
- PrefService* service = g_browser_process->local_state();
- service->SetBoolean(prefs::kUserCreatedLoginItem, true);
+void DisableLaunchOnStartupOnFileThread() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ // 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 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.
+void CheckForUserRemovedLoginItemOnFileThread() {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ if (!base::mac::CheckLoginItemStatus(NULL)) {
+ // There's no LoginItem, so set the kUserRemovedLoginItem pref.
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
- base::Bind(SetUserCreatedLoginItemPrefCallback));
- return;
+ base::Bind(SetUserRemovedLoginItemPrefOnUIThread));
}
+}
- if (should_add_login_item)
+void EnableLaunchOnStartupOnFileThread(bool need_migration) {
+ DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::FILE));
+ 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.
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(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.
-#if !defined(NDEBUG)
- else
- DCHECK(!login_item_removed); // Check for race condition (see above).
-#endif
+ BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
+ base::Bind(SetCreatedLoginItemPrefOnUIThread));
+ }
}
} // namespace
void BackgroundModeManager::EnableLaunchOnStartup(bool should_launch) {
- // This functionality is only defined for default profile, currently.
+ // 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 (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();
- // 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
+ // ever create another one.
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(
+ CheckForUserRemovedLoginItemOnFileThread));
+ } else {
+ bool need_migration = !service->GetBoolean(
+ prefs::kMigratedLoginItemPref);
+ service->SetBoolean(prefs::kMigratedLoginItemPref, true);
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(EnableLaunchOnStartupOnFileThread,
+ 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
+ // 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.
+ BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
+ base::Bind(
+ CheckForUserRemovedLoginItemOnFileThread));
+
// Call to the File thread to remove the login item since it requires
// accessing the disk.
BrowserThread::PostTask(BrowserThread::FILE, FROM_HERE,
- base::Bind(DisableLaunchOnStartupCallback));
+ base::Bind(DisableLaunchOnStartupOnFileThread));
}
}
« no previous file with comments | « chrome/browser/background/background_mode_manager.cc ('k') | chrome/common/pref_names.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698