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/ui/app_list/search/people/people_result.h"
10 #include "base/memory/ref_counted.h"
11 #include "base/strings/utf_string_conversions.h"
12 #include "chrome/browser/profiles/profile.h"
13 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
14 #include "chrome/browser/signin/signin_manager.h"
15 #include "chrome/browser/signin/signin_manager_factory.h"
16 #include "chrome/browser/ui/app_list/search/common/url_icon_source.h"
17 #include "chrome/browser/ui/app_list/search/people/person.h"
18 #include "chrome/browser/ui/browser_navigator.h"
19 #include "chrome/common/extensions/api/hangouts_private.h"
20 #include "components/signin/core/browser/profile_oauth2_token_service.h"
21 #include "content/public/browser/user_metrics.h"
22 #include "extensions/browser/event_router.h"
23 #include "extensions/browser/extension_system.h"
24 #include "grit/generated_resources.h"
25 #include "grit/theme_resources.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/resource/resource_bundle.h"
29 namespace OnHangoutRequested =
30 extensions::api::hangouts_private::OnHangoutRequested;
32 using extensions::api::hangouts_private::User;
33 using extensions::api::hangouts_private::HangoutRequest;
37 const int kIconSize = 32;
38 const char kImageSizePath[] = "s32-p/";
39 const char kEmailUrlPrefix[] = "mailto:";
41 const char* const kHangoutsExtensionIds[] = {
42 "nckgahadagoaajjgafhacjanaoiihapd",
43 "ljclpkphhpbpinifbeabbhlfddcpfdde",
44 "ppleadejekpmccmnpjdimmlfljlkdfej",
45 "eggnbpckecmjlblplehfpjjdhhidfdoj"
48 // Add a query parameter to specify the size to fetch the image in. The
49 // original profile image can be of an arbitrary size, we ask the server to
50 // crop it to a square 32x32 using its smart cropping algorithm.
51 GURL GetImageUrl(const GURL& url) {
52 std::string image_filename = url.ExtractFileName();
53 if (image_filename.empty())
56 return url.Resolve(kImageSizePath + image_filename);
63 PeopleResult::PeopleResult(Profile* profile, scoped_ptr<Person> person)
64 : profile_(profile), person_(person.Pass()), weak_factory_(this) {
66 set_title(base::UTF8ToUTF16(person_->display_name));
67 set_relevance(person_->interaction_rank);
68 set_details(base::UTF8ToUTF16(person_->email));
70 RefreshHangoutsExtensionId();
73 image_ = gfx::ImageSkia(
74 new UrlIconSource(base::Bind(&PeopleResult::OnIconLoaded,
75 weak_factory_.GetWeakPtr()),
76 profile_->GetRequestContext(),
77 GetImageUrl(person_->image_url),
79 IDR_PROFILE_PICTURE_LOADING),
80 gfx::Size(kIconSize, kIconSize));
84 PeopleResult::~PeopleResult() {
87 void PeopleResult::Open(int event_flags) {
88 // Action 0 will always be our default action.
89 InvokeAction(0, event_flags);
92 void PeopleResult::InvokeAction(int action_index, int event_flags) {
93 if (hangouts_extension_id_.empty()) {
94 // If the hangouts app is not available, the only option we are showing
95 // to the user is 'Send Email'.
98 switch (action_index) {
106 LOG(ERROR) << "Invalid people search action: " << action_index;
111 scoped_ptr<ChromeSearchResult> PeopleResult::Duplicate() {
112 return scoped_ptr<ChromeSearchResult>(
113 new PeopleResult(profile_, person_->Duplicate().Pass())).Pass();
116 void PeopleResult::OnIconLoaded() {
117 // Remove the existing image reps since the icon data is loaded and they
118 // need to be re-created.
119 const std::vector<gfx::ImageSkiaRep>& image_reps = image_.image_reps();
120 for (size_t i = 0; i < image_reps.size(); ++i)
121 image_.RemoveRepresentation(image_reps[i].scale());
126 void PeopleResult::SetDefaultActions() {
129 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
130 if (!hangouts_extension_id_.empty()) {
131 actions.push_back(Action(
132 *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_CHAT),
133 *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_CHAT_HOVER),
134 *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_CHAT_PRESSED),
135 l10n_util::GetStringUTF16(IDS_PEOPLE_SEARCH_ACTION_CHAT_TOOLTIP)));
137 actions.push_back(Action(
138 *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL),
139 *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL_HOVER),
140 *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL_PRESSED),
141 l10n_util::GetStringUTF16(IDS_PEOPLE_SEARCH_ACTION_EMAIL_TOOLTIP)));
145 void PeopleResult::OpenChat() {
146 HangoutRequest request;
148 request.type = extensions::api::hangouts_private::HANGOUT_TYPE_CHAT;
150 // from: the user this chat request is originating from.
151 SigninManagerBase* signin_manager =
152 SigninManagerFactory::GetInstance()->GetForProfile(profile_);
153 DCHECK(signin_manager);
154 request.from = signin_manager->GetAuthenticatedAccountId();
156 // to: list of users with whom to start this hangout is with.
157 linked_ptr<User> target(new User());
158 target->id = person_->owner_id;
159 request.to.push_back(target);
161 scoped_ptr<extensions::Event> event(
162 new extensions::Event(OnHangoutRequested::kEventName,
163 OnHangoutRequested::Create(request)));
165 // TODO(rkc): Change this once we remove the hangoutsPrivate API.
166 // See crbug.com/306672
167 extensions::ExtensionSystem::Get(
168 profile_)->event_router()->DispatchEventToExtension(
169 hangouts_extension_id_, event.Pass());
171 content::RecordAction(base::UserMetricsAction("PeopleSearch_OpenChat"));
174 void PeopleResult::SendEmail() {
175 chrome::NavigateParams params(profile_,
176 GURL(kEmailUrlPrefix + person_->email),
177 content::PAGE_TRANSITION_LINK);
178 // If no window exists, this will open a new window this one tab.
179 params.disposition = NEW_FOREGROUND_TAB;
180 chrome::Navigate(¶ms);
181 content::RecordAction(base::UserMetricsAction("PeopleSearch_SendEmail"));
184 void PeopleResult::RefreshHangoutsExtensionId() {
185 // TODO(rkc): Change this once we remove the hangoutsPrivate API.
186 // See crbug.com/306672
187 for (size_t i = 0; i < arraysize(kHangoutsExtensionIds); ++i) {
188 if (extensions::ExtensionSystem::Get(
189 profile_)->event_router()->ExtensionHasEventListener(
190 kHangoutsExtensionIds[i], OnHangoutRequested::kEventName)) {
191 hangouts_extension_id_ = kHangoutsExtensionIds[i];
195 hangouts_extension_id_.clear();
198 ChromeSearchResultType PeopleResult::GetType() {
199 return SEARCH_PEOPLE_SEARCH_RESULT;
202 } // namespace app_list