[Metrics] Make MetricsStateManager take a callback param to check if UMA is enabled.
[chromium-blink-merge.git] / chrome / browser / signin / signin_promo.cc
blob91de1f9458035da5b836b1203cd9dae65fbe694e
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/signin/signin_promo.h"
7 #include "base/prefs/pref_service.h"
8 #include "base/strings/string_number_conversions.h"
9 #include "base/strings/string_util.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/browser_process.h"
13 #include "chrome/browser/first_run/first_run.h"
14 #include "chrome/browser/google/google_util.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/profiles/profile_info_cache.h"
17 #include "chrome/browser/profiles/profile_manager.h"
18 #include "chrome/browser/signin/signin_manager_factory.h"
19 #include "chrome/browser/sync/profile_sync_service.h"
20 #include "chrome/browser/sync/profile_sync_service_factory.h"
21 #include "chrome/browser/ui/webui/options/core_options_handler.h"
22 #include "chrome/browser/ui/webui/theme_source.h"
23 #include "chrome/common/net/url_util.h"
24 #include "chrome/common/pref_names.h"
25 #include "chrome/common/url_constants.h"
26 #include "components/pref_registry/pref_registry_syncable.h"
27 #include "components/signin/core/browser/signin_manager.h"
28 #include "components/signin/core/common/profile_management_switches.h"
29 #include "content/public/browser/url_data_source.h"
30 #include "content/public/browser/web_contents.h"
31 #include "content/public/browser/web_ui.h"
32 #include "content/public/browser/web_ui_data_source.h"
33 #include "google_apis/gaia/gaia_urls.h"
34 #include "grit/browser_resources.h"
35 #include "grit/generated_resources.h"
36 #include "grit/theme_resources.h"
37 #include "net/base/escape.h"
38 #include "net/base/network_change_notifier.h"
39 #include "net/base/url_util.h"
40 #include "ui/base/l10n/l10n_util.h"
41 #include "url/gurl.h"
43 using content::WebContents;
44 using net::GetValueForKeyInQuery;
46 namespace {
48 const char kSignInPromoQueryKeyAutoClose[] = "auto_close";
49 const char kSignInPromoQueryKeyContinue[] = "continue";
50 const char kSignInPromoQueryKeySource[] = "source";
51 const char kSignInPromoQueryKeyConstrained[] = "constrained";
53 // Gaia cannot support about:blank as a continue URL, so using a hosted blank
54 // page instead.
55 const char kSignInLandingUrlPrefix[] =
56 "https://www.google.com/intl/%s/chrome/blank.html";
58 // The maximum number of times we want to show the sign in promo at startup.
59 const int kSignInPromoShowAtStartupMaximum = 10;
61 // Forces the web based signin flow when set.
62 bool g_force_web_based_signin_flow = false;
64 // Checks we want to show the sign in promo for the given brand.
65 bool AllowPromoAtStartupForCurrentBrand() {
66 std::string brand;
67 google_util::GetBrand(&brand);
69 if (brand.empty())
70 return true;
72 if (google_util::IsInternetCafeBrandCode(brand))
73 return false;
75 // Enable for both organic and distribution.
76 return true;
79 // Returns true if a user has seen the sign in promo at startup previously.
80 bool HasShownPromoAtStartup(Profile* profile) {
81 return profile->GetPrefs()->HasPrefPath(prefs::kSignInPromoStartupCount);
84 // Returns true if the user has previously skipped the sign in promo.
85 bool HasUserSkippedPromo(Profile* profile) {
86 return profile->GetPrefs()->GetBoolean(prefs::kSignInPromoUserSkipped);
89 } // namespace
91 namespace signin {
93 bool ShouldShowPromo(Profile* profile) {
94 #if defined(OS_CHROMEOS)
95 // There's no need to show the sign in promo on cros since cros users are
96 // already logged in.
97 return false;
98 #else
100 // Don't bother if we don't have any kind of network connection.
101 if (net::NetworkChangeNotifier::IsOffline())
102 return false;
104 // Don't show for managed profiles.
105 if (profile->IsManaged())
106 return false;
108 // Display the signin promo if the user is not signed in.
109 SigninManager* signin = SigninManagerFactory::GetForProfile(
110 profile->GetOriginalProfile());
111 return !signin->AuthInProgress() && signin->IsSigninAllowed() &&
112 signin->GetAuthenticatedUsername().empty();
113 #endif
116 bool ShouldShowPromoAtStartup(Profile* profile, bool is_new_profile) {
117 DCHECK(profile);
119 // Don't show if the profile is an incognito.
120 if (profile->IsOffTheRecord())
121 return false;
123 if (!ShouldShowPromo(profile))
124 return false;
126 if (!is_new_profile) {
127 if (!HasShownPromoAtStartup(profile))
128 return false;
131 if (HasUserSkippedPromo(profile))
132 return false;
134 // For Chinese users skip the sign in promo.
135 if (g_browser_process->GetApplicationLocale() == "zh-CN")
136 return false;
138 PrefService* prefs = profile->GetPrefs();
139 int show_count = prefs->GetInteger(prefs::kSignInPromoStartupCount);
140 if (show_count >= kSignInPromoShowAtStartupMaximum)
141 return false;
143 // This pref can be set in the master preferences file to allow or disallow
144 // showing the sign in promo at startup.
145 if (prefs->HasPrefPath(prefs::kSignInPromoShowOnFirstRunAllowed))
146 return prefs->GetBoolean(prefs::kSignInPromoShowOnFirstRunAllowed);
148 // For now don't show the promo for some brands.
149 if (!AllowPromoAtStartupForCurrentBrand())
150 return false;
152 // Default to show the promo for Google Chrome builds.
153 #if defined(GOOGLE_CHROME_BUILD)
154 return true;
155 #else
156 return false;
157 #endif
160 void DidShowPromoAtStartup(Profile* profile) {
161 int show_count = profile->GetPrefs()->GetInteger(
162 prefs::kSignInPromoStartupCount);
163 show_count++;
164 profile->GetPrefs()->SetInteger(prefs::kSignInPromoStartupCount, show_count);
167 void SetUserSkippedPromo(Profile* profile) {
168 profile->GetPrefs()->SetBoolean(prefs::kSignInPromoUserSkipped, true);
171 GURL GetLandingURL(const char* option, int value) {
172 const std::string& locale = g_browser_process->GetApplicationLocale();
173 std::string url = base::StringPrintf(kSignInLandingUrlPrefix, locale.c_str());
174 base::StringAppendF(&url, "?%s=%d", option, value);
175 return GURL(url);
178 GURL GetPromoURL(Source source, bool auto_close) {
179 return GetPromoURL(source, auto_close, false /* is_constrained */);
182 GURL GetPromoURL(Source source, bool auto_close, bool is_constrained) {
183 return GetPromoURLWithContinueURL(source, auto_close, is_constrained, GURL());
186 GURL GetPromoURLWithContinueURL(Source source,
187 bool auto_close,
188 bool is_constrained,
189 GURL continue_url) {
190 DCHECK_NE(SOURCE_UNKNOWN, source);
192 if (!switches::IsEnableWebBasedSignin()) {
193 std::string url(chrome::kChromeUIChromeSigninURL);
194 base::StringAppendF(&url, "?%s=%d", kSignInPromoQueryKeySource, source);
195 if (auto_close)
196 base::StringAppendF(&url, "&%s=1", kSignInPromoQueryKeyAutoClose);
197 if (is_constrained)
198 base::StringAppendF(&url, "&%s=1", kSignInPromoQueryKeyConstrained);
199 if (!continue_url.is_empty()) {
200 DCHECK(continue_url.is_valid());
201 std::string escaped_continue_url =
202 net::EscapeQueryParamValue(continue_url.spec(), false);
203 base::StringAppendF(&url,
204 "&%s=%s",
205 kSignInPromoQueryKeyContinue,
206 escaped_continue_url.c_str());
208 return GURL(url);
211 // Build a Gaia-based URL that can be used to sign the user into chrome.
212 // There are required request parameters:
214 // - tell Gaia which service the user is signing into. In this case,
215 // a chrome sign in uses the service "chromiumsync"
216 // - provide a continue URL. This is the URL that Gaia will redirect to
217 // once the sign is complete.
219 // The continue URL includes a source parameter that can be extracted using
220 // the function GetSourceForSignInPromoURL() below. This is used to know
221 // which of the chrome sign in access points was used to sign the user in.
222 // It is also parsed for the |auto_close| flag, which indicates that the tab
223 // must be closed after sync setup is successful.
224 // See OneClickSigninHelper for details.
225 std::string query_string = "?service=chromiumsync&sarp=1";
227 DCHECK(continue_url.is_empty());
228 std::string continue_url_str = GetLandingURL(kSignInPromoQueryKeySource,
229 static_cast<int>(source)).spec();
230 if (auto_close) {
231 base::StringAppendF(
232 &continue_url_str, "&%s=1", kSignInPromoQueryKeyAutoClose);
235 base::StringAppendF(
236 &query_string,
237 "&%s=%s",
238 kSignInPromoQueryKeyContinue,
239 net::EscapeQueryParamValue(continue_url_str, false).c_str());
241 return GaiaUrls::GetInstance()->service_login_url().Resolve(query_string);
244 GURL GetReauthURL(Profile* profile, const std::string& account_id) {
245 if (switches::IsEnableWebBasedSignin()) {
246 return net::AppendQueryParameter(
247 signin::GetPromoURL(signin::SOURCE_SETTINGS, true),
248 "Email",
249 account_id);
252 const std::string primary_account_id =
253 SigninManagerFactory::GetForProfile(profile)->
254 GetAuthenticatedAccountId();
255 signin::Source source = account_id == primary_account_id ?
256 signin::SOURCE_SETTINGS : signin::SOURCE_AVATAR_BUBBLE_ADD_ACCOUNT;
258 GURL url = signin::GetPromoURL(source, true);
259 url = net::AppendQueryParameter(url, "email", account_id);
260 url = net::AppendQueryParameter(url, "validateEmail", "1");
261 return net::AppendQueryParameter(url, "readOnlyEmail", "1");
264 GURL GetNextPageURLForPromoURL(const GURL& url) {
265 std::string value;
266 if (GetValueForKeyInQuery(url, kSignInPromoQueryKeyContinue, &value)) {
267 GURL continue_url = GURL(value);
268 if (continue_url.is_valid())
269 return continue_url;
272 return GURL();
275 Source GetSourceForPromoURL(const GURL& url) {
276 std::string value;
277 if (GetValueForKeyInQuery(url, kSignInPromoQueryKeySource, &value)) {
278 int source = 0;
279 if (base::StringToInt(value, &source) && source >= SOURCE_START_PAGE &&
280 source < SOURCE_UNKNOWN) {
281 return static_cast<Source>(source);
284 return SOURCE_UNKNOWN;
287 bool IsAutoCloseEnabledInURL(const GURL& url) {
288 std::string value;
289 if (GetValueForKeyInQuery(url, kSignInPromoQueryKeyAutoClose, &value)) {
290 int enabled = 0;
291 if (base::StringToInt(value, &enabled) && enabled == 1)
292 return true;
294 return false;
297 bool IsContinueUrlForWebBasedSigninFlow(const GURL& url) {
298 GURL::Replacements replacements;
299 replacements.ClearQuery();
300 const std::string& locale = g_browser_process->GetApplicationLocale();
301 GURL continue_url =
302 GURL(base::StringPrintf(kSignInLandingUrlPrefix, locale.c_str()));
303 return (
304 google_util::IsGoogleDomainUrl(
305 url,
306 google_util::ALLOW_SUBDOMAIN,
307 google_util::DISALLOW_NON_STANDARD_PORTS) &&
308 url.ReplaceComponents(replacements).path() ==
309 continue_url.ReplaceComponents(replacements).path());
312 void ForceWebBasedSigninFlowForTesting(bool force) {
313 g_force_web_based_signin_flow = force;
316 void RegisterProfilePrefs(
317 user_prefs::PrefRegistrySyncable* registry) {
318 registry->RegisterIntegerPref(
319 prefs::kSignInPromoStartupCount,
321 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
322 registry->RegisterBooleanPref(
323 prefs::kSignInPromoUserSkipped,
324 false,
325 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
326 registry->RegisterBooleanPref(
327 prefs::kSignInPromoShowOnFirstRunAllowed,
328 true,
329 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
330 registry->RegisterBooleanPref(
331 prefs::kSignInPromoShowNTPBubble,
332 false,
333 user_prefs::PrefRegistrySyncable::UNSYNCABLE_PREF);
336 } // namespace signin