1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160
|
// Copyright (c) 2011 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 "base/bind.h"
#include "base/command_line.h"
#include "base/mac/mac_util.h"
#include "base/prefs/pref_service.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 "chrome/grit/generated_resources.h"
#include "content/public/browser/browser_thread.h"
#include "ui/base/l10n/l10n_util.h"
using content::BrowserThread;
namespace {
void SetUserRemovedLoginItemPrefOnUIThread() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
PrefService* service = g_browser_process->local_state();
service->SetBoolean(prefs::kUserRemovedLoginItem, true);
}
void SetCreatedLoginItemPrefOnUIThread() {
DCHECK(content::BrowserThread::CurrentlyOn(content::BrowserThread::UI));
PrefService* service = g_browser_process->local_state();
service->SetBoolean(prefs::kChromeCreatedLoginItem, 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 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(SetUserRemovedLoginItemPrefOnUIThread));
}
}
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.
BrowserThread::PostTask(BrowserThread::UI, FROM_HERE,
base::Bind(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.
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 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(DisableLaunchOnStartupOnFileThread));
}
}
void BackgroundModeManager::DisplayAppInstalledNotification(
const extensions::Extension* extension) {
// TODO(atwilson): Display a platform-appropriate notification here.
// http://crbug.com/74970
}
base::string16 BackgroundModeManager::GetPreferencesMenuLabel() {
return l10n_util::GetStringUTF16(IDS_OPTIONS);
}
|