Upstream version 5.34.104.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / ui / sync / one_click_signin_helper.h
1 // Copyright (c) 2012 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 #ifndef CHROME_BROWSER_UI_SYNC_ONE_CLICK_SIGNIN_HELPER_H_
6 #define CHROME_BROWSER_UI_SYNC_ONE_CLICK_SIGNIN_HELPER_H_
7
8 #include <string>
9
10 #include "base/gtest_prod_util.h"
11 #include "base/memory/weak_ptr.h"
12 #include "chrome/browser/signin/signin_promo.h"
13 #include "chrome/browser/sync/profile_sync_service_observer.h"
14 #include "chrome/browser/ui/sync/one_click_signin_sync_starter.h"
15 #include "content/public/browser/navigation_controller.h"
16 #include "content/public/browser/web_contents_observer.h"
17 #include "content/public/browser/web_contents_user_data.h"
18 #include "google_apis/gaia/google_service_auth_error.h"
19
20 class Browser;
21 class GURL;
22 class PasswordManager;
23 class ProfileIOData;
24
25 namespace autofill {
26 struct PasswordForm;
27 }
28
29 namespace content {
30 class WebContents;
31 struct FrameNavigateParams;
32 struct LoadCommittedDetails;
33 }
34
35 namespace net {
36 class URLRequest;
37 }
38
39 // Per-tab one-click signin helper.  When a user signs in to a Google service
40 // and the profile is not yet connected to a Google account, will start the
41 // process of helping the user connect his profile with one click.  The process
42 // begins with an infobar and is followed with a confirmation dialog explaining
43 // more about what this means.
44 class OneClickSigninHelper
45     : public content::WebContentsObserver,
46       public content::WebContentsUserData<OneClickSigninHelper>,
47       public ProfileSyncServiceObserver {
48  public:
49   // Represents user's decision about sign in process.
50   enum AutoAccept {
51     // User decision not yet known.  Assume cancel.
52     AUTO_ACCEPT_NONE,
53
54     // User has explicitly accepted to sign in.  A bubble is shown with the
55     // option to start sync, configure it first, or abort.
56     AUTO_ACCEPT_ACCEPTED,
57
58     // User has explicitly accepted to sign in, but wants to configure sync
59     // settings before turning it on.
60     AUTO_ACCEPT_CONFIGURE,
61
62     // User has explicitly rejected to sign in.  Furthermore, the user does
63     // not want to be prompted to see the interstitial again in this profile.
64     AUTO_ACCEPT_REJECTED_FOR_PROFILE,
65
66     // This is an explicit sign in from either first run, NTP, wrench menu,
67     // or settings page.  The user will be signed in automatically with sync
68     // enabled using default settings.
69     AUTO_ACCEPT_EXPLICIT
70   };
71
72   // Return value of CanOfferOnIOThread().
73   enum Offer {
74     CAN_OFFER,
75     DONT_OFFER,
76     IGNORE_REQUEST
77   };
78
79   // Argument to CanOffer().
80   enum CanOfferFor {
81     CAN_OFFER_FOR_ALL,
82     CAN_OFFER_FOR_INTERSTITAL_ONLY,
83     CAN_OFFER_FOR_SECONDARY_ACCOUNT
84     // TODO(guohui): needs to handle adding secondary account through
85     // interstitial.
86   };
87
88   static void LogHistogramValue(signin::Source source, int action);
89
90   static void CreateForWebContentsWithPasswordManager(
91       content::WebContents* contents,
92       PasswordManager* password_manager);
93
94   // Returns true if the one-click signin feature can be offered at this time.
95   // If |email| is not empty, then the profile is checked to see if it's
96   // already connected to a google account or if the user has already rejected
97   // one-click sign-in with this email, in which cases a one click signin
98   // should not be offered.
99   //
100   // If |can_offer_for| is |CAN_OFFER_FOR_INTERSTITAL_ONLY|, then only do the
101   // checks that would affect the interstitial page.  Otherwise, do the checks
102   // that would affect the interstitial and the explicit sign ins.
103   //
104   // Returns in |error_message_id| an explanation as a string resource ID for
105   // why one-clicked cannot be offered.  |error_message_id| is valid only if
106   // the return value is false.  If no explanation is needed, |error_message_id|
107   // may be null.
108   static bool CanOffer(content::WebContents* web_contents,
109                        CanOfferFor can_offer_for,
110                        const std::string& email,
111                        std::string* error_message);
112
113   // Returns true if the one-click signin feature can be offered at this time.
114   // It can be offered if the io_data is not in an incognito window and if the
115   // origin of |url| is a valid Gaia sign in origin.  This function is meant
116   // to called only from the IO thread.
117   static Offer CanOfferOnIOThread(net::URLRequest* request,
118                                   ProfileIOData* io_data);
119
120   // Looks for the Google-Accounts-SignIn response header, and if found,
121   // tries to display an infobar in the tab contents identified by the
122   // child/route id.
123   static void ShowInfoBarIfPossible(net::URLRequest* request,
124                                     ProfileIOData* io_data,
125                                     int child_id,
126                                     int route_id);
127
128   // Handles cross account sign in error. If the supplied |email| does not match
129   // the last signed in email of the current profile, then Chrome will show a
130   // confirmation dialog before starting sync. It returns true if there is a
131   // cross ccount error, and false otherwise.
132   static bool HandleCrossAccountError(
133       content::WebContents* contents,
134       const std::string& session_index,
135       const std::string& email,
136       const std::string& password,
137       const std::string& oauth_code,
138       OneClickSigninHelper::AutoAccept auto_accept,
139       signin::Source source,
140       OneClickSigninSyncStarter::StartSyncMode start_mode,
141       OneClickSigninSyncStarter::Callback sync_callback);
142
143   static void RedirectToNtpOrAppsPage(
144       content::WebContents* contents, signin::Source source);
145
146   // If the |source| is not settings page/webstore, redirects to
147   // the NTP/Apps page.
148   static void RedirectToNtpOrAppsPageIfNecessary(
149       content::WebContents* contents, signin::Source source);
150
151   static void ShowSigninErrorBubble(Browser* browser, const std::string& error);
152
153   // Remove the item currently at the top of the history list if it's
154   // the Gaia redirect URL. Due to limitations of the NavigationController
155   // this cannot be done until a new page becomes "current".
156   static void RemoveSigninRedirectURLHistoryItem(
157       content::WebContents* web_contents);
158
159   static void LogConfirmHistogramValue(int action);
160
161  private:
162   friend class content::WebContentsUserData<OneClickSigninHelper>;
163   friend class OneClickSigninHelperTest;
164   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIncognitoTest,
165                            ShowInfoBarUIThreadIncognito);
166   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperTest,
167                            SigninFromWebstoreWithConfigSyncfirst);
168   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperTest,
169                            ShowSigninBubbleAfterSigninComplete);
170   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperTest, SigninCancelled);
171   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperTest, SigninFailed);
172   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperTest,
173                            CleanTransientStateOnNavigate);
174   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperTest,
175                            RemoveObserverFromProfileSyncService);
176   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest, CanOfferOnIOThread);
177   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest,
178                            CanOfferOnIOThreadIncognito);
179   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest,
180                            CanOfferOnIOThreadNoIOData);
181   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest,
182                            CanOfferOnIOThreadBadURL);
183   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest,
184                            CanOfferOnIOThreadDisabled);
185   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest,
186                            CanOfferOnIOThreadSignedIn);
187   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest,
188                            CanOfferOnIOThreadEmailNotAllowed);
189   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest,
190                            CanOfferOnIOThreadEmailAlreadyUsed);
191   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest,
192                            CreateTestProfileIOData);
193   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest,
194                            CanOfferOnIOThreadWithRejectedEmail);
195   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest,
196                            CanOfferOnIOThreadNoSigninCookies);
197   FRIEND_TEST_ALL_PREFIXES(OneClickSigninHelperIOTest,
198                            CanOfferOnIOThreadDisabledByPolicy);
199
200   // Maximum number of navigations away from the set of valid Gaia URLs before
201   // clearing the internal state of the helper.  This is necessary to support
202   // SAML-based accounts, but causes bug crbug.com/181163.
203   static const int kMaxNavigationsSince;
204
205   OneClickSigninHelper(content::WebContents* web_contents,
206                        PasswordManager* password_manager);
207
208   virtual ~OneClickSigninHelper();
209
210   // Returns true if the one-click signin feature can be offered at this time.
211   // It can be offered if the io_data is not in an incognito window and if the
212   // origin of |url| is a valid Gaia sign in origin.  This function is meant
213   // to called only from the IO thread.
214   static Offer CanOfferOnIOThreadImpl(const GURL& url,
215                                       base::SupportsUserData* request,
216                                       ProfileIOData* io_data);
217
218   // The portion of ShowInfoBarIfPossible() that needs to run on the UI thread.
219   // |session_index| and |email| are extracted from the Google-Accounts-SignIn
220   // header.  |auto_accept| is extracted from the Google-Chrome-SignIn header.
221   // |source| is used to determine which of the explicit sign in mechanism is
222   // being used.
223   //
224   // |continue_url| is where Gaia will continue to when the sign in process is
225   // done.  For explicit sign ins, this is a URL chrome controls. For one-click
226   // sign in, this could be any google property.  This URL is used to know
227   // when the sign process is over and to collect infomation from the user
228   // entered on the Gaia sign in page (for explicit sign ins).
229   static void ShowInfoBarUIThread(const std::string& session_index,
230                                   const std::string& email,
231                                   AutoAccept auto_accept,
232                                   signin::Source source,
233                                   const GURL& continue_url,
234                                   int child_id,
235                                   int route_id);
236
237   void RedirectToSignin();
238
239   // Clear all data member of the helper, except for the error.
240   void CleanTransientState();
241
242   // Unitests that use a TestingProfile should call this.
243   // Otherwise, clearing the pending e-mail crashes because the code expects
244   // a real ResourceContext rather than the MockResourceContext a
245   // TestingProfile provides.
246   void SetDoNotClearPendingEmailForTesting();
247
248   // In unit tests, disable starting the actual sync.
249   void set_do_not_start_sync_for_testing();
250
251   // Called when password has been submitted.
252   void PasswordSubmitted(const autofill::PasswordForm& form);
253
254   // content::WebContentsObserver overrides.
255   virtual void DidStartNavigationToPendingEntry(
256       const GURL& url,
257       content::NavigationController::ReloadType reload_type) OVERRIDE;
258   virtual void DidNavigateMainFrame(
259       const content::LoadCommittedDetails& details,
260       const content::FrameNavigateParams& params) OVERRIDE;
261   virtual void DidStopLoading(
262       content::RenderViewHost* render_view_host) OVERRIDE;
263   virtual void WebContentsDestroyed(content::WebContents* contents) OVERRIDE;
264
265   // ProfileSyncServiceObserver.
266   virtual void OnStateChanged() OVERRIDE;
267
268   OneClickSigninSyncStarter::Callback CreateSyncStarterCallback();
269
270   // Callback invoked when OneClickSigninSyncStarter completes sync setup.
271   void SyncSetupCompletedCallback(
272       OneClickSigninSyncStarter::SyncSetupResult result);
273
274   // Tracks if we are in the process of showing the signin or one click
275   // interstitial page. It's set to true the first time we load one of those
276   // pages and set to false when transient state is cleaned.
277   // Note: This should only be used for logging purposes.
278   bool showing_signin_;
279
280   // Information about the account that has just logged in.
281   std::string session_index_;
282   std::string email_;
283   std::string password_;
284   AutoAccept auto_accept_;
285   signin::Source source_;
286   bool switched_to_advanced_;
287   GURL continue_url_;
288   // The orignal continue URL after sync setup is complete.
289   GURL original_continue_url_;
290   std::string error_message_;
291
292   // Number of navigations since starting a sign in that is outside the
293   // the set of trusted Gaia URLs.  Sign in attempts that include visits to
294   // one more untrusted will cause a modal dialog to appear asking the user
295   // to confirm, similar to the interstitial flow.
296   int untrusted_navigations_since_signin_visit_;
297
298   // Whether a Gaia URL during the sign in process was not handled by the
299   // dedicated sign in process (e.g. SAML login, which redirects to a
300   // non-google-controlled domain).
301   // This is set to true if at least one such URL is detected.
302   bool untrusted_confirmation_required_;
303
304   // Allows unittests to avoid accessing the ResourceContext for clearing a
305   // pending e-mail.
306   bool do_not_clear_pending_email_;
307
308   // Allows unittest to avoid starting sync for real.
309   bool do_not_start_sync_for_testing_;
310
311   base::WeakPtrFactory<OneClickSigninHelper> weak_pointer_factory_;
312
313   DISALLOW_COPY_AND_ASSIGN(OneClickSigninHelper);
314 };
315
316 #endif  // CHROME_BROWSER_UI_SYNC_ONE_CLICK_SIGNIN_HELPER_H_