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_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 DisableLaunchOnStartupOnFileThread() {
DCHECK_CURRENTLY_ON(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_CURRENTLY_ON(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_CURRENTLY_ON(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);
}
|