Temporarily re-enabling SizeAfterPrefChange test with traces (this time for Linux...
[chromium-blink-merge.git] / chrome / browser / profiles / profile_window.cc
blobca62eeafa2250d40c43e45cfb7e066c2241fa2f8
1 // Copyright 2013 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
5 #include "chrome/browser/profiles/profile_window.h"
7 #include "base/command_line.h"
8 #include "base/files/file_path.h"
9 #include "base/prefs/pref_service.h"
10 #include "base/strings/string_number_conversions.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/about_flags.h"
13 #include "chrome/browser/browser_process.h"
14 #include "chrome/browser/lifetime/application_lifetime.h"
15 #include "chrome/browser/pref_service_flags_storage.h"
16 #include "chrome/browser/profiles/profile.h"
17 #include "chrome/browser/profiles/profile_avatar_icon_util.h"
18 #include "chrome/browser/profiles/profile_manager.h"
19 #include "chrome/browser/ui/browser.h"
20 #include "chrome/browser/ui/browser_dialogs.h"
21 #include "chrome/common/chrome_switches.h"
22 #include "chrome/common/pref_names.h"
23 #include "chrome/common/url_constants.h"
24 #include "content/public/browser/browser_thread.h"
25 #include "content/public/browser/user_metrics.h"
27 #if !defined(OS_IOS)
28 #include "chrome/browser/ui/browser_finder.h"
29 #include "chrome/browser/ui/browser_list.h"
30 #include "chrome/browser/ui/browser_list_observer.h"
31 #include "chrome/browser/ui/browser_window.h"
32 #include "chrome/browser/ui/startup/startup_browser_creator.h"
33 #endif // !defined (OS_IOS)
35 using base::UserMetricsAction;
36 using content::BrowserThread;
38 namespace {
40 const char kNewProfileManagementExperimentInternalName[] =
41 "enable-new-profile-management";
43 // Handles running a callback when a new Browser for the given profile
44 // has been completely created.
45 class BrowserAddedForProfileObserver : public chrome::BrowserListObserver {
46 public:
47 BrowserAddedForProfileObserver(
48 Profile* profile,
49 profiles::ProfileSwitchingDoneCallback callback)
50 : profile_(profile),
51 callback_(callback) {
52 DCHECK(!callback_.is_null());
53 BrowserList::AddObserver(this);
55 virtual ~BrowserAddedForProfileObserver() {
58 private:
59 // Overridden from BrowserListObserver:
60 virtual void OnBrowserAdded(Browser* browser) OVERRIDE {
61 if (browser->profile() == profile_) {
62 BrowserList::RemoveObserver(this);
63 callback_.Run();
64 base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
68 // Profile for which the browser should be opened.
69 Profile* profile_;
70 profiles::ProfileSwitchingDoneCallback callback_;
72 DISALLOW_COPY_AND_ASSIGN(BrowserAddedForProfileObserver);
75 void OpenBrowserWindowForProfile(
76 profiles::ProfileSwitchingDoneCallback callback,
77 bool always_create,
78 bool is_new_profile,
79 chrome::HostDesktopType desktop_type,
80 Profile* profile,
81 Profile::CreateStatus status) {
82 DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
84 if (status != Profile::CREATE_STATUS_INITIALIZED)
85 return;
87 chrome::startup::IsProcessStartup is_process_startup =
88 chrome::startup::IS_NOT_PROCESS_STARTUP;
89 chrome::startup::IsFirstRun is_first_run = chrome::startup::IS_NOT_FIRST_RUN;
91 // If this is a brand new profile, then start a first run window.
92 if (is_new_profile) {
93 is_process_startup = chrome::startup::IS_PROCESS_STARTUP;
94 is_first_run = chrome::startup::IS_FIRST_RUN;
97 // If |always_create| is false, and we have a |callback| to run, check
98 // whether a browser already exists so that we can run the callback. We don't
99 // want to rely on the observer listening to OnBrowserSetLastActive in this
100 // case, as you could manually activate an incorrect browser and trigger
101 // a false positive.
102 if (!always_create) {
103 Browser* browser = chrome::FindTabbedBrowser(profile, false, desktop_type);
104 if (browser) {
105 browser->window()->Activate();
106 if (!callback.is_null())
107 callback.Run();
108 return;
112 // If there is a callback, create an observer to make sure it is only
113 // run when the browser has been completely created. This observer will
114 // delete itself once that happens. This should not leak, because we are
115 // passing |always_create| = true to FindOrCreateNewWindow below, which ends
116 // up calling LaunchBrowser and opens a new window. If for whatever reason
117 // that fails, either something has crashed, or the observer will be cleaned
118 // up when a different browser for this profile is opened.
119 if (!callback.is_null())
120 new BrowserAddedForProfileObserver(profile, callback);
122 // We already dealt with the case when |always_create| was false and a browser
123 // existed, which means that here a browser definitely needs to be created.
124 // Passing true for |always_create| means we won't duplicate the code that
125 // tries to find a browser.
126 profiles::FindOrCreateNewWindowForProfile(
127 profile,
128 is_process_startup,
129 is_first_run,
130 desktop_type,
131 true);
134 // Called after a |guest_profile| is available to be used by the user manager.
135 // Based on the value of |tutorial_mode| we determine a url to be displayed
136 // by the webui and run the |callback|, if it exists.
137 void OnUserManagerGuestProfileCreated(
138 const base::FilePath& profile_path_to_focus,
139 profiles::UserManagerTutorialMode tutorial_mode,
140 const base::Callback<void(Profile*, const std::string&)>& callback,
141 Profile* guest_profile,
142 Profile::CreateStatus status) {
143 if (status != Profile::CREATE_STATUS_INITIALIZED || callback.is_null())
144 return;
146 // Tell the webui which user should be focused.
147 std::string page = chrome::kChromeUIUserManagerURL;
149 if (tutorial_mode == profiles::USER_MANAGER_TUTORIAL_OVERVIEW) {
150 page += "#tutorial";
151 } else if (!profile_path_to_focus.empty()) {
152 const ProfileInfoCache& cache =
153 g_browser_process->profile_manager()->GetProfileInfoCache();
154 size_t index = cache.GetIndexOfProfileWithPath(profile_path_to_focus);
155 if (index != std::string::npos) {
156 page += "#";
157 page += base::IntToString(index);
161 callback.Run(guest_profile, page);
164 } // namespace
166 namespace profiles {
168 void FindOrCreateNewWindowForProfile(
169 Profile* profile,
170 chrome::startup::IsProcessStartup process_startup,
171 chrome::startup::IsFirstRun is_first_run,
172 chrome::HostDesktopType desktop_type,
173 bool always_create) {
174 #if defined(OS_IOS)
175 NOTREACHED();
176 #else
177 DCHECK(profile);
179 if (!always_create) {
180 Browser* browser = chrome::FindTabbedBrowser(profile, false, desktop_type);
181 if (browser) {
182 browser->window()->Activate();
183 return;
187 content::RecordAction(UserMetricsAction("NewWindow"));
188 CommandLine command_line(CommandLine::NO_PROGRAM);
189 int return_code;
190 StartupBrowserCreator browser_creator;
191 browser_creator.LaunchBrowser(command_line, profile, base::FilePath(),
192 process_startup, is_first_run, &return_code);
193 #endif // defined(OS_IOS)
196 void SwitchToProfile(const base::FilePath& path,
197 chrome::HostDesktopType desktop_type,
198 bool always_create,
199 ProfileSwitchingDoneCallback callback,
200 ProfileMetrics::ProfileOpen metric) {
201 g_browser_process->profile_manager()->CreateProfileAsync(
202 path,
203 base::Bind(&OpenBrowserWindowForProfile,
204 callback,
205 always_create,
206 false,
207 desktop_type),
208 base::string16(),
209 base::string16(),
210 std::string());
211 ProfileMetrics::LogProfileSwitchUser(metric);
214 void SwitchToGuestProfile(chrome::HostDesktopType desktop_type,
215 ProfileSwitchingDoneCallback callback) {
216 g_browser_process->profile_manager()->CreateProfileAsync(
217 ProfileManager::GetGuestProfilePath(),
218 base::Bind(&OpenBrowserWindowForProfile,
219 callback,
220 false,
221 false,
222 desktop_type),
223 base::string16(),
224 base::string16(),
225 std::string());
226 ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::SWITCH_PROFILE_GUEST);
229 void CreateAndSwitchToNewProfile(chrome::HostDesktopType desktop_type,
230 ProfileSwitchingDoneCallback callback,
231 ProfileMetrics::ProfileAdd metric) {
232 ProfileInfoCache& cache =
233 g_browser_process->profile_manager()->GetProfileInfoCache();
235 int placeholder_avatar_index = profiles::GetPlaceholderAvatarIndex();
236 ProfileManager::CreateMultiProfileAsync(
237 cache.ChooseNameForNewProfile(placeholder_avatar_index),
238 base::UTF8ToUTF16(profiles::GetDefaultAvatarIconUrl(
239 placeholder_avatar_index)),
240 base::Bind(&OpenBrowserWindowForProfile,
241 callback,
242 true,
243 true,
244 desktop_type),
245 std::string());
246 ProfileMetrics::LogProfileAddNewUser(metric);
249 void CloseGuestProfileWindows() {
250 ProfileManager* profile_manager = g_browser_process->profile_manager();
251 Profile* profile = profile_manager->GetProfileByPath(
252 ProfileManager::GetGuestProfilePath());
254 if (profile) {
255 BrowserList::CloseAllBrowsersWithProfile(profile);
259 void LockProfile(Profile* profile) {
260 DCHECK(profile);
261 ProfileInfoCache& cache =
262 g_browser_process->profile_manager()->GetProfileInfoCache();
264 size_t index = cache.GetIndexOfProfileWithPath(profile->GetPath());
265 cache.SetProfileSigninRequiredAtIndex(index, true);
266 chrome::ShowUserManager(profile->GetPath());
267 BrowserList::CloseAllBrowsersWithProfile(profile);
270 void CreateGuestProfileForUserManager(
271 const base::FilePath& profile_path_to_focus,
272 profiles::UserManagerTutorialMode tutorial_mode,
273 const base::Callback<void(Profile*, const std::string&)>& callback) {
274 // Create the guest profile, if necessary, and open the User Manager
275 // from the guest profile.
276 g_browser_process->profile_manager()->CreateProfileAsync(
277 ProfileManager::GetGuestProfilePath(),
278 base::Bind(&OnUserManagerGuestProfileCreated,
279 profile_path_to_focus,
280 tutorial_mode,
281 callback),
282 base::string16(),
283 base::string16(),
284 std::string());
287 void ShowUserManagerMaybeWithTutorial(Profile* profile) {
288 // Guest users cannot appear in the User Manager, nor display a tutorial.
289 if (!profile || profile->IsGuestSession()) {
290 chrome::ShowUserManager(base::FilePath());
291 return;
293 // Show the tutorial if the profile has not shown it before.
294 PrefService* pref_service = profile->GetPrefs();
295 bool tutorial_shown = pref_service->GetBoolean(
296 prefs::kProfileUserManagerTutorialShown);
297 if (!tutorial_shown)
298 pref_service->SetBoolean(prefs::kProfileUserManagerTutorialShown, true);
300 if (tutorial_shown) {
301 chrome::ShowUserManager(profile->GetPath());
302 } else {
303 chrome::ShowUserManagerWithTutorial(
304 profiles::USER_MANAGER_TUTORIAL_OVERVIEW);
308 void EnableNewProfileManagementPreview() {
309 about_flags::PrefServiceFlagsStorage flags_storage(
310 g_browser_process->local_state());
311 about_flags::SetExperimentEnabled(
312 &flags_storage,
313 kNewProfileManagementExperimentInternalName,
314 true);
316 CommandLine::ForCurrentProcess()->AppendSwitch(
317 switches::kNewProfileManagement);
318 chrome::ShowUserManagerWithTutorial(profiles::USER_MANAGER_TUTORIAL_OVERVIEW);
321 void DisableNewProfileManagementPreview() {
322 about_flags::PrefServiceFlagsStorage flags_storage(
323 g_browser_process->local_state());
324 about_flags::SetExperimentEnabled(
325 &flags_storage,
326 kNewProfileManagementExperimentInternalName,
327 false);
328 chrome::AttemptRestart();
331 } // namespace profiles