search_controller.cc revision 90dce4d38c5ff5333bea97d859d4e484e27edf0c
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/search_controller.h" 6 7#include <algorithm> 8#include <vector> 9 10#include "base/bind.h" 11#include "base/command_line.h" 12#include "base/memory/scoped_ptr.h" 13#include "base/string_util.h" 14#include "base/utf_string_conversions.h" 15#include "chrome/browser/profiles/profile.h" 16#include "chrome/browser/ui/app_list/search/app_search_provider.h" 17#include "chrome/browser/ui/app_list/search/chrome_search_result.h" 18#include "chrome/browser/ui/app_list/search/history.h" 19#include "chrome/browser/ui/app_list/search/history_factory.h" 20#include "chrome/browser/ui/app_list/search/omnibox_provider.h" 21#include "chrome/browser/ui/app_list/search/search_provider.h" 22#include "chrome/browser/ui/app_list/search/webstore_provider.h" 23#include "content/public/browser/user_metrics.h" 24#include "grit/generated_resources.h" 25#include "grit/theme_resources.h" 26#include "ui/app_list/search_box_model.h" 27#include "ui/base/l10n/l10n_util.h" 28#include "ui/base/resource/resource_bundle.h" 29 30namespace app_list { 31 32SearchController::SearchController(Profile* profile, 33 SearchBoxModel* search_box, 34 AppListModel::SearchResults* results, 35 AppListControllerDelegate* list_controller) 36 : profile_(profile), 37 search_box_(search_box), 38 list_controller_(list_controller), 39 dispatching_query_(false), 40 mixer_(new Mixer(results)), 41 history_(HistoryFactory::GetForBrowserContext(profile)) { 42 Init(); 43} 44 45SearchController::~SearchController() {} 46 47void SearchController::Init() { 48 search_box_->SetHintText( 49 l10n_util::GetStringUTF16(IDS_SEARCH_BOX_HINT)); 50 search_box_->SetIcon(*ui::ResourceBundle::GetSharedInstance(). 51 GetImageSkiaNamed(IDR_OMNIBOX_SEARCH)); 52 53 mixer_->Init(); 54 55 AddProvider(Mixer::MAIN_GROUP, scoped_ptr<SearchProvider>( 56 new AppSearchProvider(profile_, list_controller_)).Pass()); 57 AddProvider(Mixer::OMNIBOX_GROUP, scoped_ptr<SearchProvider>( 58 new OmniboxProvider(profile_)).Pass()); 59 AddProvider(Mixer::WEBSTORE_GROUP, scoped_ptr<SearchProvider>( 60 new WebstoreProvider(profile_)).Pass()); 61} 62 63void SearchController::Start() { 64 Stop(); 65 66 string16 query; 67 TrimWhitespace(search_box_->text(), TRIM_ALL, &query); 68 69 dispatching_query_ = true; 70 for (Providers::iterator it = providers_.begin(); 71 it != providers_.end(); 72 ++it) { 73 (*it)->Start(query); 74 } 75 dispatching_query_ = false; 76 77 OnResultsChanged(); 78 79 // Maximum time (in milliseconds) to wait to the search providers to finish. 80 const int kStopTimeMS = 1500; 81 stop_timer_.Start(FROM_HERE, 82 base::TimeDelta::FromMilliseconds(kStopTimeMS), 83 base::Bind(&SearchController::Stop, 84 base::Unretained(this))); 85} 86 87void SearchController::Stop() { 88 stop_timer_.Stop(); 89 90 for (Providers::iterator it = providers_.begin(); 91 it != providers_.end(); 92 ++it) { 93 (*it)->Stop(); 94 } 95} 96 97void SearchController::OpenResult(SearchResult* result, int event_flags) { 98 // Count AppList.Search here because it is composed of search + action. 99 content::RecordAction(content::UserMetricsAction("AppList_Search")); 100 101 ChromeSearchResult* chrome_result = 102 static_cast<app_list::ChromeSearchResult*>(result); 103 chrome_result->Open(event_flags); 104 105 if (history_ && history_->IsReady()) { 106 history_->AddLaunchEvent(UTF16ToUTF8(search_box_->text()), 107 chrome_result->id()); 108 } 109} 110 111void SearchController::InvokeResultAction(SearchResult* result, 112 int action_index, 113 int event_flags) { 114 // TODO(xiyuan): Hook up with user learning. 115 static_cast<app_list::ChromeSearchResult*>(result)->InvokeAction( 116 action_index, event_flags); 117} 118 119void SearchController::AddProvider(Mixer::GroupId group, 120 scoped_ptr<SearchProvider> provider) { 121 provider->set_result_changed_callback(base::Bind( 122 &SearchController::OnResultsChanged, 123 base::Unretained(this))); 124 mixer_->AddProviderToGroup(group, provider.get()); 125 providers_.push_back(provider.release()); // Takes ownership. 126} 127 128void SearchController::OnResultsChanged() { 129 if (dispatching_query_) 130 return; 131 132 KnownResults known_results; 133 if (history_ && history_->IsReady()) { 134 history_->GetKnownResults(UTF16ToUTF8(search_box_->text())) 135 ->swap(known_results); 136 } 137 138 mixer_->MixAndPublish(known_results); 139} 140 141} // namespace app_list 142