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