people_result.cc revision f2477e01787aa58f445919b809d89e252beef54f
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/extensions/extension_system.h" 13#include "chrome/browser/profiles/profile.h" 14#include "chrome/browser/signin/profile_oauth2_token_service.h" 15#include "chrome/browser/signin/profile_oauth2_token_service_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 "content/public/browser/user_metrics.h" 21#include "extensions/browser/event_router.h" 22#include "grit/generated_resources.h" 23#include "grit/theme_resources.h" 24#include "ui/base/l10n/l10n_util.h" 25#include "ui/base/resource/resource_bundle.h" 26 27namespace OnHangoutRequested = 28 extensions::api::hangouts_private::OnHangoutRequested; 29 30using extensions::api::hangouts_private::User; 31using extensions::api::hangouts_private::HangoutRequest; 32 33namespace { 34 35const int kIconSize = 32; 36const char kImageSizePath[] = "s32-p/"; 37const char kEmailUrlPrefix[] = "mailto:"; 38 39const char* const kHangoutsExtensionIds[] = { 40 "nckgahadagoaajjgafhacjanaoiihapd", 41 "ljclpkphhpbpinifbeabbhlfddcpfdde", 42 "ppleadejekpmccmnpjdimmlfljlkdfej", 43 "eggnbpckecmjlblplehfpjjdhhidfdoj" 44}; 45 46// Add a query parameter to specify the size to fetch the image in. The 47// original profile image can be of an arbitrary size, we ask the server to 48// crop it to a square 32x32 using its smart cropping algorithm. 49GURL GetImageUrl(const GURL& url) { 50 std::string image_filename = url.ExtractFileName(); 51 if (image_filename.empty()) 52 return url; 53 54 return url.Resolve(kImageSizePath + image_filename); 55} 56 57} // namespace 58 59namespace app_list { 60 61PeopleResult::PeopleResult(Profile* profile, scoped_ptr<Person> person) 62 : profile_(profile), person_(person.Pass()), weak_factory_(this) { 63 set_id(person_->id); 64 set_title(UTF8ToUTF16(person_->display_name)); 65 set_relevance(person_->interaction_rank); 66 set_details(UTF8ToUTF16(person_->email)); 67 68 RefreshHangoutsExtensionId(); 69 SetDefaultActions(); 70 71 image_ = gfx::ImageSkia( 72 new UrlIconSource(base::Bind(&PeopleResult::OnIconLoaded, 73 weak_factory_.GetWeakPtr()), 74 profile_->GetRequestContext(), 75 GetImageUrl(person_->image_url), 76 kIconSize, 77 IDR_PROFILE_PICTURE_LOADING), 78 gfx::Size(kIconSize, kIconSize)); 79 SetIcon(image_); 80} 81 82PeopleResult::~PeopleResult() { 83} 84 85void PeopleResult::Open(int event_flags) { 86 // Action 0 will always be our default action. 87 InvokeAction(0, event_flags); 88} 89 90void PeopleResult::InvokeAction(int action_index, int event_flags) { 91 if (hangouts_extension_id_.empty()) { 92 // If the hangouts app is not available, the only option we are showing 93 // to the user is 'Send Email'. 94 SendEmail(); 95 } else { 96 switch (action_index) { 97 case 0: 98 OpenChat(); 99 break; 100 case 1: 101 SendEmail(); 102 break; 103 default: 104 LOG(ERROR) << "Invalid people search action: " << action_index; 105 } 106 } 107} 108 109scoped_ptr<ChromeSearchResult> PeopleResult::Duplicate() { 110 return scoped_ptr<ChromeSearchResult>( 111 new PeopleResult(profile_, person_->Duplicate().Pass())).Pass(); 112} 113 114void PeopleResult::OnIconLoaded() { 115 // Remove the existing image reps since the icon data is loaded and they 116 // need to be re-created. 117 const std::vector<gfx::ImageSkiaRep>& image_reps = image_.image_reps(); 118 for (size_t i = 0; i < image_reps.size(); ++i) 119 image_.RemoveRepresentation(image_reps[i].scale()); 120 121 SetIcon(image_); 122} 123 124void PeopleResult::SetDefaultActions() { 125 Actions actions; 126 127 ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 128 if (!hangouts_extension_id_.empty()) { 129 actions.push_back(Action( 130 *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_CHAT), 131 *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_CHAT_HOVER), 132 *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_CHAT_PRESSED), 133 l10n_util::GetStringUTF16(IDS_PEOPLE_SEARCH_ACTION_CHAT_TOOLTIP))); 134 } 135 actions.push_back(Action( 136 *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL), 137 *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL_HOVER), 138 *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL_PRESSED), 139 l10n_util::GetStringUTF16(IDS_PEOPLE_SEARCH_ACTION_EMAIL_TOOLTIP))); 140 SetActions(actions); 141} 142 143void PeopleResult::OpenChat() { 144 HangoutRequest request; 145 146 request.type = extensions::api::hangouts_private::HANGOUT_TYPE_CHAT; 147 148 // from: the user this chat request is originating from. 149 ProfileOAuth2TokenService* token_service = 150 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_); 151 DCHECK(token_service); 152 request.from = token_service->GetPrimaryAccountId(); 153 154 // to: list of users with whom to start this hangout is with. 155 linked_ptr<User> target(new User()); 156 target->id = person_->owner_id; 157 request.to.push_back(target); 158 159 scoped_ptr<extensions::Event> event( 160 new extensions::Event(OnHangoutRequested::kEventName, 161 OnHangoutRequested::Create(request))); 162 163 // TODO(rkc): Change this once we remove the hangoutsPrivate API. 164 // See crbug.com/306672 165 extensions::ExtensionSystem::Get( 166 profile_)->event_router()->DispatchEventToExtension( 167 hangouts_extension_id_, event.Pass()); 168 169 content::RecordAction(content::UserMetricsAction("PeopleSearch_OpenChat")); 170} 171 172void PeopleResult::SendEmail() { 173 chrome::NavigateParams params(profile_, 174 GURL(kEmailUrlPrefix + person_->email), 175 content::PAGE_TRANSITION_LINK); 176 // If no window exists, this will open a new window this one tab. 177 params.disposition = NEW_FOREGROUND_TAB; 178 chrome::Navigate(¶ms); 179 content::RecordAction(content::UserMetricsAction("PeopleSearch_SendEmail")); 180} 181 182void PeopleResult::RefreshHangoutsExtensionId() { 183 // TODO(rkc): Change this once we remove the hangoutsPrivate API. 184 // See crbug.com/306672 185 for (size_t i = 0; i < arraysize(kHangoutsExtensionIds); ++i) { 186 if (extensions::ExtensionSystem::Get( 187 profile_)->event_router()->ExtensionHasEventListener( 188 kHangoutsExtensionIds[i], OnHangoutRequested::kEventName)) { 189 hangouts_extension_id_ = kHangoutsExtensionIds[i]; 190 return; 191 } 192 } 193 hangouts_extension_id_.clear(); 194} 195 196ChromeSearchResultType PeopleResult::GetType() { 197 return SEARCH_PEOPLE_SEARCH_RESULT; 198} 199 200} // namespace app_list 201