ca62eeafa2250d40c43e45cfb7e066c2241fa2f8
[platform/framework/web/crosswalk.git] / src / chrome / browser / profiles / profile_window.cc
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.
4
5 #include "chrome/browser/profiles/profile_window.h"
6
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"
26
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)
34
35 using base::UserMetricsAction;
36 using content::BrowserThread;
37
38 namespace {
39
40 const char kNewProfileManagementExperimentInternalName[] =
41     "enable-new-profile-management";
42
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);
54   }
55   virtual ~BrowserAddedForProfileObserver() {
56   }
57
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);
65     }
66   }
67
68   // Profile for which the browser should be opened.
69   Profile* profile_;
70   profiles::ProfileSwitchingDoneCallback callback_;
71
72   DISALLOW_COPY_AND_ASSIGN(BrowserAddedForProfileObserver);
73 };
74
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));
83
84   if (status != Profile::CREATE_STATUS_INITIALIZED)
85     return;
86
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;
90
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;
95   }
96
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;
109     }
110   }
111
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);
121
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);
132 }
133
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;
145
146   // Tell the webui which user should be focused.
147   std::string page = chrome::kChromeUIUserManagerURL;
148
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);
158     }
159   }
160
161   callback.Run(guest_profile, page);
162 }
163
164 }  // namespace
165
166 namespace profiles {
167
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);
178
179   if (!always_create) {
180     Browser* browser = chrome::FindTabbedBrowser(profile, false, desktop_type);
181     if (browser) {
182       browser->window()->Activate();
183       return;
184     }
185   }
186
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)
194 }
195
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);
212 }
213
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);
227 }
228
229 void CreateAndSwitchToNewProfile(chrome::HostDesktopType desktop_type,
230                                  ProfileSwitchingDoneCallback callback,
231                                  ProfileMetrics::ProfileAdd metric) {
232   ProfileInfoCache& cache =
233       g_browser_process->profile_manager()->GetProfileInfoCache();
234
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);
247 }
248
249 void CloseGuestProfileWindows() {
250   ProfileManager* profile_manager = g_browser_process->profile_manager();
251   Profile* profile = profile_manager->GetProfileByPath(
252       ProfileManager::GetGuestProfilePath());
253
254   if (profile) {
255     BrowserList::CloseAllBrowsersWithProfile(profile);
256   }
257 }
258
259 void LockProfile(Profile* profile) {
260   DCHECK(profile);
261   ProfileInfoCache& cache =
262       g_browser_process->profile_manager()->GetProfileInfoCache();
263
264   size_t index = cache.GetIndexOfProfileWithPath(profile->GetPath());
265   cache.SetProfileSigninRequiredAtIndex(index, true);
266   chrome::ShowUserManager(profile->GetPath());
267   BrowserList::CloseAllBrowsersWithProfile(profile);
268 }
269
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());
285 }
286
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;
292   }
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);
299
300   if (tutorial_shown) {
301     chrome::ShowUserManager(profile->GetPath());
302   } else {
303     chrome::ShowUserManagerWithTutorial(
304         profiles::USER_MANAGER_TUTORIAL_OVERVIEW);
305   }
306 }
307
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);
315
316   CommandLine::ForCurrentProcess()->AppendSwitch(
317       switches::kNewProfileManagement);
318   chrome::ShowUserManagerWithTutorial(profiles::USER_MANAGER_TUTORIAL_OVERVIEW);
319 }
320
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();
329 }
330
331 }  // namespace profiles