root/chrome/browser/ui/app_list/search/search_controller.cc

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

DEFINITIONS

This source file includes following definitions.
  1. history_
  2. Init
  3. Start
  4. Stop
  5. OpenResult
  6. InvokeResultAction
  7. AddProvider
  8. OnResultsChanged
  9. OnSpeechRecognitionStateChanged

// 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/search_controller.h"

#include <algorithm>
#include <vector>

#include "base/bind.h"
#include "base/command_line.h"
#include "base/memory/scoped_ptr.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/app_list/search/app_search_provider.h"
#include "chrome/browser/ui/app_list/search/chrome_search_result.h"
#include "chrome/browser/ui/app_list/search/history.h"
#include "chrome/browser/ui/app_list/search/history_factory.h"
#include "chrome/browser/ui/app_list/search/omnibox_provider.h"
#include "chrome/browser/ui/app_list/search/people/people_provider.h"
#include "chrome/browser/ui/app_list/search/search_provider.h"
#include "chrome/browser/ui/app_list/search/webstore/webstore_provider.h"
#include "chrome/browser/ui/app_list/start_page_service.h"
#include "chrome/common/chrome_switches.h"
#include "content/public/browser/user_metrics.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "ui/app_list/search_box_model.h"
#include "ui/app_list/speech_ui_model.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"

namespace {
  const char kAppListSearchResultOpenTypeHistogram[] =
      "Apps.AppListSearchResultOpenType";
}

namespace app_list {

SearchController::SearchController(Profile* profile,
                                   SearchBoxModel* search_box,
                                   AppListModel::SearchResults* results,
                                   SpeechUIModel* speech_ui,
                                   AppListControllerDelegate* list_controller)
  : profile_(profile),
    search_box_(search_box),
    speech_ui_(speech_ui),
    list_controller_(list_controller),
    dispatching_query_(false),
    mixer_(new Mixer(results)),
    history_(HistoryFactory::GetForBrowserContext(profile)) {
  speech_ui_->AddObserver(this);
  Init();
}

SearchController::~SearchController() {
  speech_ui_->RemoveObserver(this);
}

void SearchController::Init() {
  ui::ResourceBundle& bundle = ui::ResourceBundle::GetSharedInstance();
  search_box_->SetIcon(*bundle.GetImageSkiaNamed(IDR_OMNIBOX_SEARCH));
  StartPageService* service = StartPageService::Get(profile_);
  if (service && service->GetSpeechRecognitionContents()) {
    search_box_->SetSpeechRecognitionButton(
        scoped_ptr<SearchBoxModel::SpeechButtonProperty>(
            new SearchBoxModel::SpeechButtonProperty(
                *bundle.GetImageSkiaNamed(IDR_OMNIBOX_MIC_SEARCH),
                l10n_util::GetStringUTF16(
                    IDS_APP_LIST_HOTWORD_LISTENING),
                *bundle.GetImageSkiaNamed(IDR_APP_LIST_MIC_HOTWORD_OFF),
                l10n_util::GetStringUTF16(
                    IDS_APP_LIST_START_SPEECH_RECOGNITION))));
  }
  OnSpeechRecognitionStateChanged(speech_ui_->state());

  mixer_->Init();

  AddProvider(Mixer::MAIN_GROUP, scoped_ptr<SearchProvider>(
      new AppSearchProvider(profile_, list_controller_)).Pass());
  AddProvider(Mixer::OMNIBOX_GROUP, scoped_ptr<SearchProvider>(
      new OmniboxProvider(profile_)).Pass());
  AddProvider(Mixer::WEBSTORE_GROUP, scoped_ptr<SearchProvider>(
      new WebstoreProvider(profile_, list_controller_)).Pass());
  if (!CommandLine::ForCurrentProcess()->HasSwitch(
            switches::kDisablePeopleSearch)) {
    AddProvider(Mixer::PEOPLE_GROUP, scoped_ptr<SearchProvider>(
        new PeopleProvider(profile_)).Pass());
  }
}

void SearchController::Start() {
  Stop();

  base::string16 query;
  base::TrimWhitespace(search_box_->text(), base::TRIM_ALL, &query);

  dispatching_query_ = true;
  for (Providers::iterator it = providers_.begin();
       it != providers_.end();
       ++it) {
    (*it)->Start(query);
  }
  dispatching_query_ = false;

  OnResultsChanged();

  // Maximum time (in milliseconds) to wait to the search providers to finish.
  const int kStopTimeMS = 1500;
  stop_timer_.Start(FROM_HERE,
                    base::TimeDelta::FromMilliseconds(kStopTimeMS),
                    base::Bind(&SearchController::Stop,
                               base::Unretained(this)));
}

void SearchController::Stop() {
  stop_timer_.Stop();

  for (Providers::iterator it = providers_.begin();
       it != providers_.end();
       ++it) {
    (*it)->Stop();
  }
}

void SearchController::OpenResult(SearchResult* result, int event_flags) {
  // Count AppList.Search here because it is composed of search + action.
  content::RecordAction(base::UserMetricsAction("AppList_Search"));

  ChromeSearchResult* chrome_result =
      static_cast<app_list::ChromeSearchResult*>(result);
  UMA_HISTOGRAM_ENUMERATION(kAppListSearchResultOpenTypeHistogram,
                            chrome_result->GetType(),
                            SEARCH_RESULT_TYPE_BOUNDARY);
  chrome_result->Open(event_flags);

  if (history_ && history_->IsReady()) {
    history_->AddLaunchEvent(base::UTF16ToUTF8(search_box_->text()),
                             chrome_result->id());
  }
}

void SearchController::InvokeResultAction(SearchResult* result,
                                          int action_index,
                                          int event_flags) {
  // TODO(xiyuan): Hook up with user learning.
  static_cast<app_list::ChromeSearchResult*>(result)->InvokeAction(
      action_index, event_flags);
}

void SearchController::AddProvider(Mixer::GroupId group,
                                   scoped_ptr<SearchProvider> provider) {
  provider->set_result_changed_callback(base::Bind(
      &SearchController::OnResultsChanged,
      base::Unretained(this)));
  mixer_->AddProviderToGroup(group, provider.get());
  providers_.push_back(provider.release());  // Takes ownership.
}

void SearchController::OnResultsChanged() {
  if (dispatching_query_)
    return;

  KnownResults known_results;
  if (history_ && history_->IsReady()) {
    history_->GetKnownResults(base::UTF16ToUTF8(search_box_->text()))
        ->swap(known_results);
  }

  mixer_->MixAndPublish(known_results);
}

void SearchController::OnSpeechRecognitionStateChanged(
    SpeechRecognitionState new_state) {
  search_box_->SetHintText(l10n_util::GetStringUTF16(
      (new_state == SPEECH_RECOGNITION_HOTWORD_LISTENING) ?
      IDS_SEARCH_BOX_HOTWORD_HINT : IDS_SEARCH_BOX_HINT));
}

}  // namespace app_list

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