people_result.cc revision effb81e5f8246d0db0270817048dc992db66e9fb
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/ui/app_list/search/people/people_result.h" 6 7#include <vector> 8 9#include "base/bind.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" 28 29namespace OnHangoutRequested = 30 extensions::api::hangouts_private::OnHangoutRequested; 31 32using extensions::api::hangouts_private::User; 33using extensions::api::hangouts_private::HangoutRequest; 34 35namespace { 36 37const int kIconSize = 32; 38const char kImageSizePath[] = "s32-p/"; 39const char kEmailUrlPrefix[] = "mailto:"; 40 41const char* const kHangoutsExtensionIds[] = { 42 "nckgahadagoaajjgafhacjanaoiihapd", 43 "ljclpkphhpbpinifbeabbhlfddcpfdde", 44 "ppleadejekpmccmnpjdimmlfljlkdfej", 45 "eggnbpckecmjlblplehfpjjdhhidfdoj" 46}; 47 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. 51GURL GetImageUrl(const GURL& url) { 52 std::string image_filename = url.ExtractFileName(); 53 if (image_filename.empty()) 54 return url; 55 56 return url.Resolve(kImageSizePath + image_filename); 57} 58 59} // namespace 60 61namespace app_list { 62 63PeopleResult::PeopleResult(Profile* profile, scoped_ptr<Person> person) 64 : profile_(profile), person_(person.Pass()), weak_factory_(this) { 65 set_id(person_->id); 66 set_title(base::UTF8ToUTF16(person_->display_name)); 67 set_relevance(person_->interaction_rank); 68 set_details(base::UTF8ToUTF16(person_->email)); 69 70 RefreshHangoutsExtensionId(); 71 SetDefaultActions(); 72 73 image_ = gfx::ImageSkia( 74 new UrlIconSource(base::Bind(&PeopleResult::OnIconLoaded, 75 weak_factory_.GetWeakPtr()), 76 profile_->GetRequestContext(), 77 GetImageUrl(person_->image_url), 78 kIconSize, 79 IDR_PROFILE_PICTURE_LOADING), 80 gfx::Size(kIconSize, kIconSize)); 81 SetIcon(image_); 82} 83 84PeopleResult::~PeopleResult() { 85} 86 87void PeopleResult::Open(int event_flags) { 88 // Action 0 will always be our default action. 89 InvokeAction(0, event_flags); 90} 91 92void 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'. 96 SendEmail(); 97 } else { 98 switch (action_index) { 99 case 0: 100 OpenChat(); 101 break; 102 case 1: 103 SendEmail(); 104 break; 105 default: 106 LOG(ERROR) << "Invalid people search action: " << action_index; 107 } 108 } 109} 110 111scoped_ptr<ChromeSearchResult> PeopleResult::Duplicate() { 112 return scoped_ptr<ChromeSearchResult>( 113 new PeopleResult(profile_, person_->Duplicate().Pass())).Pass(); 114} 115 116void 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()); 122 123 SetIcon(image_); 124} 125 126void PeopleResult::SetDefaultActions() { 127 Actions actions; 128 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))); 136 } 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))); 142 SetActions(actions); 143} 144 145void PeopleResult::OpenChat() { 146 HangoutRequest request; 147 148 request.type = extensions::api::hangouts_private::HANGOUT_TYPE_CHAT; 149 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(); 155 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); 160 161 scoped_ptr<extensions::Event> event( 162 new extensions::Event(OnHangoutRequested::kEventName, 163 OnHangoutRequested::Create(request))); 164 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()); 170 171 content::RecordAction(base::UserMetricsAction("PeopleSearch_OpenChat")); 172} 173 174void 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")); 182} 183 184void 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]; 192 return; 193 } 194 } 195 hangouts_extension_id_.clear(); 196} 197 198ChromeSearchResultType PeopleResult::GetType() { 199 return SEARCH_PEOPLE_SEARCH_RESULT; 200} 201 202} // namespace app_list 203