people_result.cc revision 0529e5d033099cbfc42635f6f6183833b09dff6e
169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal// Copyright 2013 The Chromium Authors. All rights reserved. 269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal// Use of this source code is governed by a BSD-style license that can be 369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal// found in the LICENSE file. 469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "chrome/browser/ui/app_list/search/people/people_result.h" 669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include <vector> 869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "base/bind.h" 1069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "base/memory/ref_counted.h" 1169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "base/strings/utf_string_conversions.h" 1269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "chrome/browser/profiles/profile.h" 1369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "chrome/browser/signin/profile_oauth2_token_service_factory.h" 1469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "chrome/browser/signin/signin_manager_factory.h" 1569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "chrome/browser/ui/app_list/search/common/url_icon_source.h" 1669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "chrome/browser/ui/app_list/search/people/person.h" 1769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "chrome/browser/ui/browser_navigator.h" 1869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "chrome/common/extensions/api/hangouts_private.h" 1969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "components/signin/core/browser/profile_oauth2_token_service.h" 2069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "components/signin/core/browser/signin_manager.h" 2169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "content/public/browser/user_metrics.h" 2269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "extensions/browser/event_router.h" 2369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "grit/generated_resources.h" 2469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "grit/theme_resources.h" 2569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "ui/base/l10n/l10n_util.h" 2669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal#include "ui/base/resource/resource_bundle.h" 2769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 2869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalnamespace OnHangoutRequested = 2969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal extensions::api::hangouts_private::OnHangoutRequested; 3069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalusing extensions::api::hangouts_private::User; 3269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalusing extensions::api::hangouts_private::HangoutRequest; 3369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalnamespace { 3569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 3669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalconst int kIconSize = 32; 3769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalconst char kImageSizePath[] = "s64-p/"; 3869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalconst char kEmailUrlPrefix[] = "mailto:"; 3969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalconst char* const kHangoutsExtensionIds[] = { 4169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "nckgahadagoaajjgafhacjanaoiihapd", 4269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "ljclpkphhpbpinifbeabbhlfddcpfdde", 4369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "ppleadejekpmccmnpjdimmlfljlkdfej", 4469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal "eggnbpckecmjlblplehfpjjdhhidfdoj" 4569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal}; 4669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 4769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal// Add a query parameter to specify the size to fetch the image in. The 4869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal// original profile image can be of an arbitrary size, we ask the server to 4969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal// crop it to a square 64x64 using its smart cropping algorithm. 5069e17611504376e4d4603925f8528dfc890fd2c6Luis SigalGURL GetImageUrl(const GURL& url) { 5169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal std::string image_filename = url.ExtractFileName(); 5269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (image_filename.empty()) 5369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return url; 5469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return url.Resolve(kImageSizePath + image_filename); 5669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 5769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 5869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} // namespace 5969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalnamespace app_list { 6169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6269e17611504376e4d4603925f8528dfc890fd2c6Luis SigalPeopleResult::PeopleResult(Profile* profile, scoped_ptr<Person> person) 6369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal : profile_(profile), person_(person.Pass()), weak_factory_(this) { 6469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal set_id(person_->id); 6569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal set_title(base::UTF8ToUTF16(person_->display_name)); 6669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal set_relevance(person_->interaction_rank); 6769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal set_details(base::UTF8ToUTF16(person_->email)); 6869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 6969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal RefreshHangoutsExtensionId(); 7069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SetDefaultActions(); 7169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 7269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal image_ = gfx::ImageSkia( 7369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new UrlIconSource(base::Bind(&PeopleResult::OnIconLoaded, 7469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal weak_factory_.GetWeakPtr()), 7569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal profile_->GetRequestContext(), 7669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal GetImageUrl(person_->image_url), 7769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal kIconSize, 7869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal IDR_PROFILE_PICTURE_LOADING), 7969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal gfx::Size(kIconSize, kIconSize)); 8069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SetIcon(image_); 8169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 8269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8369e17611504376e4d4603925f8528dfc890fd2c6Luis SigalPeopleResult::~PeopleResult() { 8469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 8569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 8669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalvoid PeopleResult::Open(int event_flags) { 8769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Action 0 will always be our default action. 8869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal InvokeAction(0, event_flags); 8969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 9069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 9169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalvoid PeopleResult::InvokeAction(int action_index, int event_flags) { 9269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (hangouts_extension_id_.empty()) { 9369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // If the hangouts app is not available, the only option we are showing 9469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // to the user is 'Send Email'. 9569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SendEmail(); 9669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } else { 9769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal switch (action_index) { 9869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 0: 9969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal OpenChat(); 10069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 10169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal case 1: 10269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SendEmail(); 10369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal break; 10469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal default: 10569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal LOG(ERROR) << "Invalid people search action: " << action_index; 10669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 10869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 10969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalscoped_ptr<ChromeSearchResult> PeopleResult::Duplicate() { 11169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal return scoped_ptr<ChromeSearchResult>( 11269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new PeopleResult(profile_, person_->Duplicate().Pass())).Pass(); 11369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 11469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 11569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalvoid PeopleResult::OnIconLoaded() { 11669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // Remove the existing image reps since the icon data is loaded and they 11769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // need to be re-created. 11869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal const std::vector<gfx::ImageSkiaRep>& image_reps = image_.image_reps(); 11969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (size_t i = 0; i < image_reps.size(); ++i) 12069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal image_.RemoveRepresentation(image_reps[i].scale()); 12169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SetIcon(image_); 12369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 12469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalvoid PeopleResult::SetDefaultActions() { 12669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal Actions actions; 12769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 12869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance(); 12969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (!hangouts_extension_id_.empty()) { 13069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal actions.push_back(Action( 13169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_CHAT), 13269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_CHAT_HOVER), 13369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_CHAT_PRESSED), 13469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal l10n_util::GetStringUTF16(IDS_PEOPLE_SEARCH_ACTION_CHAT_TOOLTIP))); 13569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal } 13669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal actions.push_back(Action( 13769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL), 13869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL_HOVER), 13969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL_PRESSED), 14069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal l10n_util::GetStringUTF16(IDS_PEOPLE_SEARCH_ACTION_EMAIL_TOOLTIP))); 14169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SetActions(actions); 14269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 14369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalvoid PeopleResult::OpenChat() { 14569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal HangoutRequest request; 14669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal request.type = extensions::api::hangouts_private::HANGOUT_TYPE_CHAT; 14869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 14969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // from: the user this chat request is originating from. 15069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SigninManagerBase* signin_manager = 15169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal SigninManagerFactory::GetInstance()->GetForProfile(profile_); 15269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal DCHECK(signin_manager); 15369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal request.from = signin_manager->GetAuthenticatedAccountId(); 15469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 15569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // to: list of users with whom to start this hangout is with. 15669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal linked_ptr<User> target(new User()); 15769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal target->id = person_->owner_id; 15869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal request.to.push_back(target); 15969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal scoped_ptr<extensions::Event> event( 16169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal new extensions::Event(OnHangoutRequested::kEventName, 16269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal OnHangoutRequested::Create(request))); 16369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // TODO(rkc): Change this once we remove the hangoutsPrivate API. 16569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // See crbug.com/306672 16669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal extensions::EventRouter::Get(profile_) 16769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal ->DispatchEventToExtension(hangouts_extension_id_, event.Pass()); 16869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 16969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal content::RecordAction(base::UserMetricsAction("PeopleSearch_OpenChat")); 17069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 17169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 17269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalvoid PeopleResult::SendEmail() { 17369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal chrome::NavigateParams params(profile_, 17469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal GURL(kEmailUrlPrefix + person_->email), 17569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal content::PAGE_TRANSITION_LINK); 17669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // If no window exists, this will open a new window this one tab. 17769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal params.disposition = NEW_FOREGROUND_TAB; 17869e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal chrome::Navigate(¶ms); 17969e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal content::RecordAction(base::UserMetricsAction("PeopleSearch_SendEmail")); 18069e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal} 18169e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal 18269e17611504376e4d4603925f8528dfc890fd2c6Luis Sigalvoid PeopleResult::RefreshHangoutsExtensionId() { 18369e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // TODO(rkc): Change this once we remove the hangoutsPrivate API. 18469e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal // See crbug.com/306672 18569e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal for (size_t i = 0; i < arraysize(kHangoutsExtensionIds); ++i) { 18669e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal if (extensions::EventRouter::Get(profile_)->ExtensionHasEventListener( 18769e17611504376e4d4603925f8528dfc890fd2c6Luis Sigal kHangoutsExtensionIds[i], OnHangoutRequested::kEventName)) { 188 hangouts_extension_id_ = kHangoutsExtensionIds[i]; 189 return; 190 } 191 } 192 hangouts_extension_id_.clear(); 193} 194 195ChromeSearchResultType PeopleResult::GetType() { 196 return SEARCH_PEOPLE_SEARCH_RESULT; 197} 198 199} // namespace app_list 200