root/chrome/browser/ui/app_list/search/people/people_result.cc

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. GetImageUrl
  2. weak_factory_
  3. Open
  4. InvokeAction
  5. Duplicate
  6. OnIconLoaded
  7. SetDefaultActions
  8. OpenChat
  9. SendEmail
  10. RefreshHangoutsExtensionId
  11. GetType

// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "chrome/browser/ui/app_list/search/people/people_result.h"

#include <vector>

#include "base/bind.h"
#include "base/memory/ref_counted.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
#include "chrome/browser/signin/signin_manager_factory.h"
#include "chrome/browser/ui/app_list/search/common/url_icon_source.h"
#include "chrome/browser/ui/app_list/search/people/person.h"
#include "chrome/browser/ui/browser_navigator.h"
#include "chrome/common/extensions/api/hangouts_private.h"
#include "components/signin/core/browser/profile_oauth2_token_service.h"
#include "components/signin/core/browser/signin_manager.h"
#include "content/public/browser/user_metrics.h"
#include "extensions/browser/event_router.h"
#include "extensions/browser/extension_system.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"

namespace OnHangoutRequested =
    extensions::api::hangouts_private::OnHangoutRequested;

using extensions::api::hangouts_private::User;
using extensions::api::hangouts_private::HangoutRequest;

namespace {

const int kIconSize = 32;
const char kImageSizePath[] = "s32-p/";
const char kEmailUrlPrefix[] = "mailto:";

const char* const kHangoutsExtensionIds[] = {
  "nckgahadagoaajjgafhacjanaoiihapd",
  "ljclpkphhpbpinifbeabbhlfddcpfdde",
  "ppleadejekpmccmnpjdimmlfljlkdfej",
  "eggnbpckecmjlblplehfpjjdhhidfdoj"
};

// Add a query parameter to specify the size to fetch the image in. The
// original profile image can be of an arbitrary size, we ask the server to
// crop it to a square 32x32 using its smart cropping algorithm.
GURL GetImageUrl(const GURL& url) {
  std::string image_filename = url.ExtractFileName();
  if (image_filename.empty())
    return url;

  return url.Resolve(kImageSizePath + image_filename);
}

}  // namespace

namespace app_list {

PeopleResult::PeopleResult(Profile* profile, scoped_ptr<Person> person)
    : profile_(profile), person_(person.Pass()), weak_factory_(this) {
  set_id(person_->id);
  set_title(base::UTF8ToUTF16(person_->display_name));
  set_relevance(person_->interaction_rank);
  set_details(base::UTF8ToUTF16(person_->email));

  RefreshHangoutsExtensionId();
  SetDefaultActions();

  image_ = gfx::ImageSkia(
      new UrlIconSource(base::Bind(&PeopleResult::OnIconLoaded,
                                   weak_factory_.GetWeakPtr()),
                        profile_->GetRequestContext(),
                        GetImageUrl(person_->image_url),
                        kIconSize,
                        IDR_PROFILE_PICTURE_LOADING),
      gfx::Size(kIconSize, kIconSize));
  SetIcon(image_);
}

PeopleResult::~PeopleResult() {
}

void PeopleResult::Open(int event_flags) {
  // Action 0 will always be our default action.
  InvokeAction(0, event_flags);
}

void PeopleResult::InvokeAction(int action_index, int event_flags) {
  if (hangouts_extension_id_.empty()) {
    // If the hangouts app is not available, the only option we are showing
    // to the user is 'Send Email'.
    SendEmail();
  } else {
    switch (action_index) {
      case 0:
        OpenChat();
        break;
      case 1:
        SendEmail();
        break;
      default:
        LOG(ERROR) << "Invalid people search action: " << action_index;
    }
  }
}

scoped_ptr<ChromeSearchResult> PeopleResult::Duplicate() {
  return scoped_ptr<ChromeSearchResult>(
      new PeopleResult(profile_, person_->Duplicate().Pass())).Pass();
}

void PeopleResult::OnIconLoaded() {
  // Remove the existing image reps since the icon data is loaded and they
  // need to be re-created.
  const std::vector<gfx::ImageSkiaRep>& image_reps = image_.image_reps();
  for (size_t i = 0; i < image_reps.size(); ++i)
    image_.RemoveRepresentation(image_reps[i].scale());

  SetIcon(image_);
}

void PeopleResult::SetDefaultActions() {
  Actions actions;

  ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
  if (!hangouts_extension_id_.empty()) {
    actions.push_back(Action(
        *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_CHAT),
        *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_CHAT_HOVER),
        *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_CHAT_PRESSED),
        l10n_util::GetStringUTF16(IDS_PEOPLE_SEARCH_ACTION_CHAT_TOOLTIP)));
  }
  actions.push_back(Action(
      *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL),
      *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL_HOVER),
      *bundle.GetImageSkiaNamed(IDR_PEOPLE_SEARCH_ACTION_EMAIL_PRESSED),
      l10n_util::GetStringUTF16(IDS_PEOPLE_SEARCH_ACTION_EMAIL_TOOLTIP)));
  SetActions(actions);
}

void PeopleResult::OpenChat() {
  HangoutRequest request;

  request.type = extensions::api::hangouts_private::HANGOUT_TYPE_CHAT;

  // from: the user this chat request is originating from.
  SigninManagerBase* signin_manager =
      SigninManagerFactory::GetInstance()->GetForProfile(profile_);
  DCHECK(signin_manager);
  request.from = signin_manager->GetAuthenticatedAccountId();

  // to: list of users with whom to start this hangout is with.
  linked_ptr<User> target(new User());
  target->id = person_->owner_id;
  request.to.push_back(target);

  scoped_ptr<extensions::Event> event(
      new extensions::Event(OnHangoutRequested::kEventName,
                            OnHangoutRequested::Create(request)));

  // TODO(rkc): Change this once we remove the hangoutsPrivate API.
  // See crbug.com/306672
  extensions::ExtensionSystem::Get(
      profile_)->event_router()->DispatchEventToExtension(
          hangouts_extension_id_, event.Pass());

  content::RecordAction(base::UserMetricsAction("PeopleSearch_OpenChat"));
}

void PeopleResult::SendEmail() {
  chrome::NavigateParams params(profile_,
                                GURL(kEmailUrlPrefix + person_->email),
                                content::PAGE_TRANSITION_LINK);
  // If no window exists, this will open a new window this one tab.
  params.disposition = NEW_FOREGROUND_TAB;
  chrome::Navigate(&params);
  content::RecordAction(base::UserMetricsAction("PeopleSearch_SendEmail"));
}

void PeopleResult::RefreshHangoutsExtensionId() {
  // TODO(rkc): Change this once we remove the hangoutsPrivate API.
  // See crbug.com/306672
  for (size_t i = 0; i < arraysize(kHangoutsExtensionIds); ++i) {
    if (extensions::ExtensionSystem::Get(
        profile_)->event_router()->ExtensionHasEventListener(
            kHangoutsExtensionIds[i], OnHangoutRequested::kEventName)) {
      hangouts_extension_id_ = kHangoutsExtensionIds[i];
      return;
    }
  }
  hangouts_extension_id_.clear();
}

ChromeSearchResultType PeopleResult::GetType() {
  return SEARCH_PEOPLE_SEARCH_RESULT;
}

}  // namespace app_list

/* [<][>][^][v][top][bottom][index][help] */