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.
5 #include "chrome/browser/ui/webui/ntp/ntp_login_handler.h"
10 #include "base/bind_helpers.h"
11 #include "base/metrics/histogram.h"
12 #include "base/prefs/pref_notifier.h"
13 #include "base/prefs/pref_service.h"
14 #include "base/strings/utf_string_conversions.h"
15 #include "base/values.h"
16 #include "chrome/browser/browser_process.h"
17 #include "chrome/browser/chrome_notification_types.h"
18 #include "chrome/browser/profiles/profile.h"
19 #include "chrome/browser/profiles/profile_info_cache.h"
20 #include "chrome/browser/profiles/profile_manager.h"
21 #include "chrome/browser/profiles/profile_metrics.h"
22 #include "chrome/browser/signin/signin_manager.h"
23 #include "chrome/browser/signin/signin_manager_factory.h"
24 #include "chrome/browser/signin/signin_promo.h"
25 #include "chrome/browser/sync/profile_sync_service.h"
26 #include "chrome/browser/sync/profile_sync_service_factory.h"
27 #include "chrome/browser/ui/browser.h"
28 #include "chrome/browser/ui/browser_finder.h"
29 #include "chrome/browser/ui/browser_window.h"
30 #include "chrome/browser/ui/chrome_pages.h"
31 #include "chrome/browser/ui/webui/ntp/new_tab_ui.h"
32 #include "chrome/browser/web_resource/promo_resource_service.h"
33 #include "chrome/common/pref_names.h"
34 #include "chrome/common/url_constants.h"
35 #include "content/public/browser/notification_details.h"
36 #include "content/public/browser/notification_service.h"
37 #include "content/public/browser/web_contents.h"
38 #include "content/public/browser/web_ui.h"
39 #include "content/public/common/page_zoom.h"
40 #include "grit/chromium_strings.h"
41 #include "grit/generated_resources.h"
42 #include "net/base/escape.h"
43 #include "skia/ext/image_operations.h"
44 #include "ui/base/l10n/l10n_util.h"
45 #include "ui/base/webui/web_ui_util.h"
46 #include "ui/gfx/canvas.h"
47 #include "ui/gfx/image/image.h"
49 using content::OpenURLParams
;
50 using content::Referrer
;
54 SkBitmap
GetGAIAPictureForNTP(const gfx::Image
& image
) {
55 // This value must match the width and height value of login-status-icon
57 const int kLength
= 27;
58 SkBitmap bmp
= skia::ImageOperations::Resize(*image
.ToSkBitmap(),
59 skia::ImageOperations::RESIZE_BEST
, kLength
, kLength
);
61 gfx::Canvas
canvas(gfx::Size(kLength
, kLength
), 1.0f
, false);
62 canvas
.DrawImageInt(gfx::ImageSkia::CreateFrom1xBitmap(bmp
), 0, 0);
64 // Draw a gray border on the inside of the icon.
65 SkColor color
= SkColorSetARGB(83, 0, 0, 0);
66 canvas
.DrawRect(gfx::Rect(0, 0, kLength
- 1, kLength
- 1), color
);
68 return canvas
.ExtractImageRep().sk_bitmap();
71 // Puts the |content| into a span with the given CSS class.
72 base::string16
CreateSpanWithClass(const base::string16
& content
,
73 const std::string
& css_class
) {
74 return base::ASCIIToUTF16("<span class='" + css_class
+ "'>") +
75 net::EscapeForHTML(content
) + base::ASCIIToUTF16("</span>");
80 NTPLoginHandler::NTPLoginHandler() {
83 NTPLoginHandler::~NTPLoginHandler() {
86 void NTPLoginHandler::RegisterMessages() {
87 PrefService
* pref_service
= Profile::FromWebUI(web_ui())->GetPrefs();
88 username_pref_
.Init(prefs::kGoogleServicesUsername
,
90 base::Bind(&NTPLoginHandler::UpdateLogin
,
91 base::Unretained(this)));
92 signin_allowed_pref_
.Init(prefs::kSigninAllowed
,
94 base::Bind(&NTPLoginHandler::UpdateLogin
,
95 base::Unretained(this)));
97 registrar_
.Add(this, chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED
,
98 content::NotificationService::AllSources());
100 web_ui()->RegisterMessageCallback("initializeSyncLogin",
101 base::Bind(&NTPLoginHandler::HandleInitializeSyncLogin
,
102 base::Unretained(this)));
103 web_ui()->RegisterMessageCallback("showSyncLoginUI",
104 base::Bind(&NTPLoginHandler::HandleShowSyncLoginUI
,
105 base::Unretained(this)));
106 web_ui()->RegisterMessageCallback("loginMessageSeen",
107 base::Bind(&NTPLoginHandler::HandleLoginMessageSeen
,
108 base::Unretained(this)));
109 web_ui()->RegisterMessageCallback("showAdvancedLoginUI",
110 base::Bind(&NTPLoginHandler::HandleShowAdvancedLoginUI
,
111 base::Unretained(this)));
114 void NTPLoginHandler::Observe(int type
,
115 const content::NotificationSource
& source
,
116 const content::NotificationDetails
& details
) {
117 if (type
== chrome::NOTIFICATION_PROFILE_CACHED_INFO_CHANGED
) {
124 void NTPLoginHandler::HandleInitializeSyncLogin(const base::ListValue
* args
) {
128 void NTPLoginHandler::HandleShowSyncLoginUI(const base::ListValue
* args
) {
129 Profile
* profile
= Profile::FromWebUI(web_ui());
130 std::string username
= profile
->GetPrefs()->GetString(
131 prefs::kGoogleServicesUsername
);
132 content::WebContents
* web_contents
= web_ui()->GetWebContents();
133 Browser
* browser
= chrome::FindBrowserWithWebContents(web_contents
);
137 if (username
.empty()) {
138 #if !defined(OS_ANDROID)
139 // The user isn't signed in, show the sign in promo.
140 if (signin::ShouldShowPromo(profile
)) {
141 signin::Source source
=
142 (web_contents
->GetURL().spec() == chrome::kChromeUIAppsURL
) ?
143 signin::SOURCE_APPS_PAGE_LINK
:
144 signin::SOURCE_NTP_LINK
;
145 chrome::ShowBrowserSignin(browser
, source
);
146 RecordInHistogram(NTP_SIGN_IN_PROMO_CLICKED
);
149 } else if (args
->GetSize() == 4) {
150 // The user is signed in, show the profiles menu.
155 bool success
= args
->GetDouble(0, &x
);
157 success
= args
->GetDouble(1, &y
);
159 success
= args
->GetDouble(2, &width
);
161 success
= args
->GetDouble(3, &height
);
164 double zoom
= content::ZoomLevelToZoomFactor(web_contents
->GetZoomLevel());
165 gfx::Rect
rect(x
* zoom
, y
* zoom
, width
* zoom
, height
* zoom
);
167 browser
->window()->ShowAvatarBubble(web_ui()->GetWebContents(), rect
);
168 ProfileMetrics::LogProfileOpenMethod(ProfileMetrics::NTP_AVATAR_BUBBLE
);
172 void NTPLoginHandler::RecordInHistogram(int type
) {
173 // Invalid type to record.
174 if (type
< NTP_SIGN_IN_PROMO_VIEWED
||
175 type
> NTP_SIGN_IN_PROMO_CLICKED
) {
178 UMA_HISTOGRAM_ENUMERATION("SyncPromo.NTPPromo", type
,
179 NTP_SIGN_IN_PROMO_BUCKET_BOUNDARY
);
183 void NTPLoginHandler::HandleLoginMessageSeen(const base::ListValue
* args
) {
184 Profile::FromWebUI(web_ui())->GetPrefs()->SetBoolean(
185 prefs::kSignInPromoShowNTPBubble
, false);
186 NewTabUI
* ntp_ui
= NewTabUI::FromWebUIController(web_ui()->GetController());
187 // When instant extended is enabled, there may not be a NewTabUI object.
189 ntp_ui
->set_showing_sync_bubble(true);
192 void NTPLoginHandler::HandleShowAdvancedLoginUI(const base::ListValue
* args
) {
194 chrome::FindBrowserWithWebContents(web_ui()->GetWebContents());
196 chrome::ShowBrowserSignin(browser
, signin::SOURCE_NTP_LINK
);
199 void NTPLoginHandler::UpdateLogin() {
200 Profile
* profile
= Profile::FromWebUI(web_ui());
201 std::string username
= profile
->GetPrefs()->GetString(
202 prefs::kGoogleServicesUsername
);
204 base::string16 header
, sub_header
;
205 std::string icon_url
;
206 if (!username
.empty()) {
207 ProfileInfoCache
& cache
=
208 g_browser_process
->profile_manager()->GetProfileInfoCache();
209 size_t profile_index
= cache
.GetIndexOfProfileWithPath(profile
->GetPath());
210 if (profile_index
!= std::string::npos
) {
211 // Only show the profile picture and full name for the single profile
212 // case. In the multi-profile case the profile picture is visible in the
213 // title bar and the full name can be ambiguous.
214 if (cache
.GetNumberOfProfiles() == 1) {
215 base::string16 name
= cache
.GetGAIANameOfProfileAtIndex(profile_index
);
217 header
= CreateSpanWithClass(name
, "profile-name");
218 const gfx::Image
* image
=
219 cache
.GetGAIAPictureOfProfileAtIndex(profile_index
);
221 icon_url
= webui::GetBitmapDataUrl(GetGAIAPictureForNTP(*image
));
223 if (header
.empty()) {
224 header
= CreateSpanWithClass(base::UTF8ToUTF16(username
),
229 #if !defined(OS_ANDROID) && !defined(OS_CHROMEOS)
230 // Android uses a custom sign in promo. Don't call the function
231 // signin::ShouldShowPromo() since it does a bunch of checks that are not
232 // required here. We only want to suppress this login status for users that
233 // are not allowed to sign in. Chromeos does not show this status header
235 SigninManager
* signin
= SigninManagerFactory::GetForProfile(
236 profile
->GetOriginalProfile());
237 if (!profile
->IsManaged() && signin
->IsSigninAllowed()) {
238 base::string16 signed_in_link
= l10n_util::GetStringUTF16(
239 IDS_SYNC_PROMO_NOT_SIGNED_IN_STATUS_LINK
);
240 signed_in_link
= CreateSpanWithClass(signed_in_link
, "link-span");
241 header
= l10n_util::GetStringFUTF16(
242 IDS_SYNC_PROMO_NOT_SIGNED_IN_STATUS_HEADER
,
243 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME
));
244 sub_header
= l10n_util::GetStringFUTF16(
245 IDS_SYNC_PROMO_NOT_SIGNED_IN_STATUS_SUB_HEADER
, signed_in_link
);
246 // Record that the user was shown the promo.
247 RecordInHistogram(NTP_SIGN_IN_PROMO_VIEWED
);
252 base::StringValue
header_value(header
);
253 base::StringValue
sub_header_value(sub_header
);
254 base::StringValue
icon_url_value(icon_url
);
255 base::FundamentalValue
is_user_signed_in(!username
.empty());
256 web_ui()->CallJavascriptFunction("ntp.updateLogin",
257 header_value
, sub_header_value
, icon_url_value
, is_user_signed_in
);
261 bool NTPLoginHandler::ShouldShow(Profile
* profile
) {
262 #if defined(OS_CHROMEOS)
263 // For now we don't care about showing sync status on Chrome OS. The promo
264 // UI and the avatar menu don't exist on that platform.
267 SigninManager
* signin
= SigninManagerFactory::GetForProfile(profile
);
268 return !profile
->IsOffTheRecord() && signin
&& signin
->IsSigninAllowed();
273 void NTPLoginHandler::GetLocalizedValues(Profile
* profile
,
274 base::DictionaryValue
* values
) {
275 PrefService
* prefs
= profile
->GetPrefs();
276 bool hide_sync
= !prefs
->GetBoolean(prefs::kSignInPromoShowNTPBubble
);
278 base::string16 message
= hide_sync
? base::string16() :
279 l10n_util::GetStringFUTF16(IDS_SYNC_PROMO_NTP_BUBBLE_MESSAGE
,
280 l10n_util::GetStringUTF16(IDS_SHORT_PRODUCT_NAME
));
282 values
->SetString("login_status_message", message
);
283 values
->SetString("login_status_url",
284 hide_sync
? std::string() : chrome::kSyncLearnMoreURL
);
285 values
->SetString("login_status_advanced",
286 hide_sync
? base::string16() :
287 l10n_util::GetStringUTF16(IDS_SYNC_PROMO_NTP_BUBBLE_ADVANCED
));
288 values
->SetString("login_status_dismiss",
289 hide_sync
? base::string16() :
290 l10n_util::GetStringUTF16(IDS_SYNC_PROMO_NTP_BUBBLE_OK
));