Upstream version 10.39.225.0
[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/signin/account_reconcilor_factory.h"
20 #include "chrome/browser/ui/browser.h"
21 #include "chrome/browser/ui/browser_dialogs.h"
22 #include "chrome/browser/ui/profile_chooser_constants.h"
23 #include "chrome/browser/ui/user_manager.h"
24 #include "chrome/common/chrome_switches.h"
25 #include "chrome/common/pref_names.h"
26 #include "chrome/common/url_constants.h"
27 #include "components/signin/core/browser/account_reconcilor.h"
28 #include "components/signin/core/common/profile_management_switches.h"
29 #include "content/public/browser/browser_thread.h"
30 #include "content/public/browser/user_metrics.h"
31
32 #if !defined(OS_IOS)
33 #include "chrome/browser/ui/browser_finder.h"
34 #include "chrome/browser/ui/browser_list.h"
35 #include "chrome/browser/ui/browser_list_observer.h"
36 #include "chrome/browser/ui/browser_window.h"
37 #include "chrome/browser/ui/startup/startup_browser_creator.h"
38 #endif  // !defined (OS_IOS)
39
40 using base::UserMetricsAction;
41 using content::BrowserThread;
42
43 namespace {
44
45 const char kNewProfileManagementExperimentInternalName[] =
46     "enable-new-profile-management";
47
48 // Handles running a callback when a new Browser for the given profile
49 // has been completely created.
50 class BrowserAddedForProfileObserver : public chrome::BrowserListObserver {
51  public:
52   BrowserAddedForProfileObserver(
53       Profile* profile,
54       ProfileManager::CreateCallback callback)
55       : profile_(profile),
56         callback_(callback) {
57     DCHECK(!callback_.is_null());
58     BrowserList::AddObserver(this);
59   }
60   virtual ~BrowserAddedForProfileObserver() {
61   }
62
63  private:
64   // Overridden from BrowserListObserver:
65   virtual void OnBrowserAdded(Browser* browser) OVERRIDE {
66     if (browser->profile() == profile_) {
67       BrowserList::RemoveObserver(this);
68       callback_.Run(profile_, Profile::CREATE_STATUS_INITIALIZED);
69       base::MessageLoop::current()->DeleteSoon(FROM_HERE, this);
70     }
71   }
72
73   // Profile for which the browser should be opened.
74   Profile* profile_;
75   ProfileManager::CreateCallback callback_;
76
77   DISALLOW_COPY_AND_ASSIGN(BrowserAddedForProfileObserver);
78 };
79
80 void OpenBrowserWindowForProfile(
81     ProfileManager::CreateCallback callback,
82     bool always_create,
83     bool is_new_profile,
84     chrome::HostDesktopType desktop_type,
85     Profile* profile,
86     Profile::CreateStatus status) {
87   DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));
88
89   if (status != Profile::CREATE_STATUS_INITIALIZED)
90     return;
91
92   chrome::startup::IsProcessStartup is_process_startup =
93       chrome::startup::IS_NOT_PROCESS_STARTUP;
94   chrome::startup::IsFirstRun is_first_run = chrome::startup::IS_NOT_FIRST_RUN;
95
96   // If this is a brand new profile, then start a first run window.
97   if (is_new_profile) {
98     is_process_startup = chrome::startup::IS_PROCESS_STARTUP;
99     is_first_run = chrome::startup::IS_FIRST_RUN;
100   }
101
102   // If |always_create| is false, and we have a |callback| to run, check
103   // whether a browser already exists so that we can run the callback. We don't
104   // want to rely on the observer listening to OnBrowserSetLastActive in this
105   // case, as you could manually activate an incorrect browser and trigger
106   // a false positive.
107   if (!always_create) {
108     Browser* browser = chrome::FindTabbedBrowser(profile, false, desktop_type);
109     if (browser) {
110       browser->window()->Activate();
111       if (!callback.is_null())
112         callback.Run(profile, Profile::CREATE_STATUS_INITIALIZED);
113       return;
114     }
115   }
116
117   // If there is a callback, create an observer to make sure it is only
118   // run when the browser has been completely created. This observer will
119   // delete itself once that happens. This should not leak, because we are
120   // passing |always_create| = true to FindOrCreateNewWindow below, which ends
121   // up calling LaunchBrowser and opens a new window. If for whatever reason
122   // that fails, either something has crashed, or the observer will be cleaned
123   // up when a different browser for this profile is opened.
124   if (!callback.is_null())
125     new BrowserAddedForProfileObserver(profile, callback);
126
127   // We already dealt with the case when |always_create| was false and a browser
128   // existed, which means that here a browser definitely needs to be created.
129   // Passing true for |always_create| means we won't duplicate the code that
130   // tries to find a browser.
131   profiles::FindOrCreateNewWindowForProfile(
132       profile,
133       is_process_startup,
134       is_first_run,
135       desktop_type,
136       true);
137 }
138
139 // Called after a |guest_profile| is available to be used by the user manager.
140 // Based on the value of |tutorial_mode| we determine a url to be displayed
141 // by the webui and run the |callback|, if it exists. After opening a profile,
142 // perform |profile_open_action|.
143 void OnUserManagerGuestProfileCreated(
144     const base::FilePath& profile_path_to_focus,
145     profiles::UserManagerTutorialMode tutorial_mode,
146     profiles::UserManagerProfileSelected profile_open_action,
147     const base::Callback<void(Profile*, const std::string&)>& callback,
148     Profile* guest_profile,
149     Profile::CreateStatus status) {
150   if (status != Profile::CREATE_STATUS_INITIALIZED || callback.is_null())
151     return;
152
153   // Tell the webui which user should be focused.
154   std::string page = chrome::kChromeUIUserManagerURL;
155
156   if (tutorial_mode == profiles::USER_MANAGER_TUTORIAL_OVERVIEW) {
157     page += profiles::kUserManagerDisplayTutorial;
158   } else if (!profile_path_to_focus.empty()) {
159     const ProfileInfoCache& cache =
160         g_browser_process->profile_manager()->GetProfileInfoCache();
161     size_t index = cache.GetIndexOfProfileWithPath(profile_path_to_focus);
162     if (index != std::string::npos) {
163       page += "#";
164       page += base::IntToString(index);
165     }
166   } else if (profile_open_action ==
167              profiles::USER_MANAGER_SELECT_PROFILE_TASK_MANAGER) {
168     page += profiles::kUserManagerSelectProfileTaskManager;
169   } else if (profile_open_action ==
170              profiles::USER_MANAGER_SELECT_PROFILE_ABOUT_CHROME) {
171     page += profiles::kUserManagerSelectProfileAboutChrome;
172   }
173   callback.Run(guest_profile, page);
174 }
175
176 // Updates Chrome services that require notification when
177 // the new_profile_management's status changes.
178 void UpdateServicesWithNewProfileManagementFlag(Profile* profile,
179                                                 bool new_flag_status) {
180   AccountReconcilor* account_reconcilor =
181       AccountReconcilorFactory::GetForProfile(profile);
182   account_reconcilor->OnNewProfileManagementFlagChanged(new_flag_status);
183 }
184
185 }  // namespace
186
187 namespace profiles {
188
189 // User Manager parameters are prefixed with hash.
190 const char kUserManagerDisplayTutorial[] = "#tutorial";
191 const char kUserManagerSelectProfileTaskManager[] = "#task-manager";
192 const char kUserManagerSelectProfileAboutChrome[] = "#about-chrome";
193
194 void FindOrCreateNewWindowForProfile(
195     Profile* profile,
196     chrome::startup::IsProcessStartup process_startup,
197     chrome::startup::IsFirstRun is_first_run,
198     chrome::HostDesktopType desktop_type,
199     bool always_create) {
200 #if defined(OS_IOS)
201   NOTREACHED();
202 #else
203   DCHECK(profile);
204
205   if (!always_create) {
206     Browser* browser = chrome::FindTabbedBrowser(profile, false, desktop_type);
207     if (browser) {
208       browser->window()->Activate();
209       return;
210     }
211   }
212
213   content::RecordAction(UserMetricsAction("NewWindow"));
214   CommandLine command_line(CommandLine::NO_PROGRAM);
215   int return_code;
216   StartupBrowserCreator browser_creator;
217   browser_creator.LaunchBrowser(command_line, profile, base::FilePath(),
218                                 process_startup, is_first_run, &return_code);
219 #endif  // defined(OS_IOS)
220 }
221
222 void SwitchToProfile(const base::FilePath& path,
223                      chrome::HostDesktopType desktop_type,
224                      bool always_create,
225                      ProfileManager::CreateCallback callback,
226                      ProfileMetrics::ProfileOpen metric) {
227   g_browser_process->profile_manager()->CreateProfileAsync(
228       path,
229       base::Bind(&OpenBrowserWindowForProfile,
230                  callback,
231                  always_create,
232                  false,
233                  desktop_type),
234       base::string16(),
235       base::string16(),
236       std::string());
237   ProfileMetrics::LogProfileSwitchUser(metric);
238 }
239
240 void SwitchToGuestProfile(chrome::HostDesktopType desktop_type,
241                           ProfileManager::CreateCallback callback) {
242   g_browser_process->profile_manager()->CreateProfileAsync(
243       ProfileManager::GetGuestProfilePath(),
244       base::Bind(&OpenBrowserWindowForProfile,
245                  callback,
246                  false,
247                  false,
248                  desktop_type),
249       base::string16(),
250       base::string16(),
251       std::string());
252   ProfileMetrics::LogProfileSwitchUser(ProfileMetrics::SWITCH_PROFILE_GUEST);
253 }
254
255 void CreateAndSwitchToNewProfile(chrome::HostDesktopType desktop_type,
256                                  ProfileManager::CreateCallback callback,
257                                  ProfileMetrics::ProfileAdd metric) {
258   ProfileInfoCache& cache =
259       g_browser_process->profile_manager()->GetProfileInfoCache();
260
261   int placeholder_avatar_index = profiles::GetPlaceholderAvatarIndex();
262   ProfileManager::CreateMultiProfileAsync(
263       cache.ChooseNameForNewProfile(placeholder_avatar_index),
264       base::UTF8ToUTF16(profiles::GetDefaultAvatarIconUrl(
265           placeholder_avatar_index)),
266       base::Bind(&OpenBrowserWindowForProfile,
267                  callback,
268                  true,
269                  true,
270                  desktop_type),
271       std::string());
272   ProfileMetrics::LogProfileAddNewUser(metric);
273 }
274
275 void GuestBrowserCloseSuccess(const base::FilePath& profile_path) {
276   UserManager::Show(profile_path,
277                     profiles::USER_MANAGER_NO_TUTORIAL,
278                     profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION);
279 }
280
281 void CloseGuestProfileWindows() {
282   ProfileManager* profile_manager = g_browser_process->profile_manager();
283   Profile* profile = profile_manager->GetProfileByPath(
284       ProfileManager::GetGuestProfilePath());
285
286   if (profile) {
287     BrowserList::CloseAllBrowsersWithProfile(
288         profile, base::Bind(&GuestBrowserCloseSuccess));
289   }
290 }
291
292 void LockBrowserCloseSuccess(const base::FilePath& profile_path) {
293   ProfileInfoCache* cache =
294       &g_browser_process->profile_manager()->GetProfileInfoCache();
295
296   cache->SetProfileSigninRequiredAtIndex(
297       cache->GetIndexOfProfileWithPath(profile_path), true);
298   UserManager::Show(profile_path,
299                     profiles::USER_MANAGER_NO_TUTORIAL,
300                     profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION);
301 }
302
303 void LockProfile(Profile* profile) {
304   DCHECK(profile);
305   if (profile) {
306     BrowserList::CloseAllBrowsersWithProfile(
307         profile, base::Bind(&LockBrowserCloseSuccess));
308   }
309 }
310
311 void CreateGuestProfileForUserManager(
312     const base::FilePath& profile_path_to_focus,
313     profiles::UserManagerTutorialMode tutorial_mode,
314     profiles::UserManagerProfileSelected profile_open_action,
315     const base::Callback<void(Profile*, const std::string&)>& callback) {
316   // Create the guest profile, if necessary, and open the User Manager
317   // from the guest profile.
318   g_browser_process->profile_manager()->CreateProfileAsync(
319       ProfileManager::GetGuestProfilePath(),
320       base::Bind(&OnUserManagerGuestProfileCreated,
321                  profile_path_to_focus,
322                  tutorial_mode,
323                  profile_open_action,
324                  callback),
325       base::string16(),
326       base::string16(),
327       std::string());
328 }
329
330 void ShowUserManagerMaybeWithTutorial(Profile* profile) {
331   // Guest users cannot appear in the User Manager, nor display a tutorial.
332   if (!profile || profile->IsGuestSession()) {
333     UserManager::Show(base::FilePath(),
334                       profiles::USER_MANAGER_NO_TUTORIAL,
335                       profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION);
336     return;
337   }
338   UserManager::Show(base::FilePath(),
339                     profiles::USER_MANAGER_TUTORIAL_OVERVIEW,
340                     profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION);
341 }
342
343 void EnableNewProfileManagementPreview(Profile* profile) {
344 #if defined(OS_ANDROID)
345   NOTREACHED();
346 #else
347   // TODO(rogerta): instead of setting experiment flags and command line
348   // args, we should set a profile preference.
349   const about_flags::Experiment experiment = {
350       kNewProfileManagementExperimentInternalName,
351       0,  // string id for title of experiment
352       0,  // string id for description of experiment
353       0,  // supported platforms
354       about_flags::Experiment::ENABLE_DISABLE_VALUE,
355       switches::kEnableNewProfileManagement,
356       "",  // not used with ENABLE_DISABLE_VALUE type
357       switches::kDisableNewProfileManagement,
358       "",  // not used with ENABLE_DISABLE_VALUE type
359       NULL,  // not used with ENABLE_DISABLE_VALUE type
360       3
361   };
362   about_flags::PrefServiceFlagsStorage flags_storage(
363       g_browser_process->local_state());
364   about_flags::SetExperimentEnabled(
365       &flags_storage,
366       experiment.NameForChoice(1),
367       true);
368
369   switches::EnableNewProfileManagementForTesting(
370       CommandLine::ForCurrentProcess());
371   UserManager::Show(base::FilePath(),
372                     profiles::USER_MANAGER_TUTORIAL_OVERVIEW,
373                     profiles::USER_MANAGER_SELECT_PROFILE_NO_ACTION);
374   UpdateServicesWithNewProfileManagementFlag(profile, true);
375 #endif
376 }
377
378 void DisableNewProfileManagementPreview(Profile* profile) {
379   about_flags::PrefServiceFlagsStorage flags_storage(
380       g_browser_process->local_state());
381   about_flags::SetExperimentEnabled(
382       &flags_storage,
383       kNewProfileManagementExperimentInternalName,
384       false);
385   chrome::AttemptRestart();
386   UpdateServicesWithNewProfileManagementFlag(profile, false);
387 }
388
389 void BubbleViewModeFromAvatarBubbleMode(
390     BrowserWindow::AvatarBubbleMode mode,
391     BubbleViewMode* bubble_view_mode,
392     TutorialMode* tutorial_mode) {
393   *tutorial_mode = TUTORIAL_MODE_NONE;
394   switch (mode) {
395     case BrowserWindow::AVATAR_BUBBLE_MODE_ACCOUNT_MANAGEMENT:
396       *bubble_view_mode = BUBBLE_VIEW_MODE_ACCOUNT_MANAGEMENT;
397       return;
398     case BrowserWindow::AVATAR_BUBBLE_MODE_SIGNIN:
399       *bubble_view_mode = BUBBLE_VIEW_MODE_GAIA_SIGNIN;
400       return;
401     case BrowserWindow::AVATAR_BUBBLE_MODE_ADD_ACCOUNT:
402       *bubble_view_mode = BUBBLE_VIEW_MODE_GAIA_ADD_ACCOUNT;
403       return;
404     case BrowserWindow::AVATAR_BUBBLE_MODE_REAUTH:
405       *bubble_view_mode = BUBBLE_VIEW_MODE_GAIA_REAUTH;
406       return;
407     case BrowserWindow::AVATAR_BUBBLE_MODE_CONFIRM_SIGNIN:
408       *bubble_view_mode = BUBBLE_VIEW_MODE_PROFILE_CHOOSER;
409       *tutorial_mode = TUTORIAL_MODE_CONFIRM_SIGNIN;
410       return;
411     case BrowserWindow::AVATAR_BUBBLE_MODE_SHOW_ERROR:
412       *bubble_view_mode = BUBBLE_VIEW_MODE_PROFILE_CHOOSER;
413       *tutorial_mode = TUTORIAL_MODE_SHOW_ERROR;
414       return;
415     default:
416       *bubble_view_mode = profiles::BUBBLE_VIEW_MODE_PROFILE_CHOOSER;
417   }
418 }
419
420 }  // namespace profiles