Add new certificateProvider extension API.
[chromium-blink-merge.git] / chrome / browser / ui / app_list / search / people / people_provider.cc
blob1677b181a7470e580f44f10cb2e4717345daa972
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.
5 #include "chrome/browser/ui/app_list/search/people/people_provider.h"
7 #include <string>
9 #include "base/bind.h"
10 #include "base/callback.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "base/strings/utf_string_conversions.h"
13 #include "base/values.h"
14 #include "chrome/browser/browser_process.h"
15 #include "chrome/browser/profiles/profile.h"
16 #include "chrome/browser/search/search.h"
17 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
18 #include "chrome/browser/signin/signin_manager_factory.h"
19 #include "chrome/browser/ui/app_list/search/common/json_response_fetcher.h"
20 #include "chrome/browser/ui/app_list/search/people/people_result.h"
21 #include "chrome/browser/ui/app_list/search/people/person.h"
22 #include "components/signin/core/browser/profile_oauth2_token_service.h"
23 #include "components/signin/core/browser/signin_manager.h"
24 #include "google_apis/gaia/gaia_constants.h"
25 #include "net/base/url_util.h"
26 #include "url/gurl.h"
28 namespace app_list {
30 namespace {
32 const char kKeyItems[] = "items";
34 const char kAccessTokenField[] = "access_token";
35 const char kQueryField[] = "query";
36 const char kPeopleSearchUrl[] =
37 "https://www.googleapis.com/plus/v2whitelisted/people/autocomplete";
39 // OAuth2 scope for access to the Google+ People Search API.
40 const char kPeopleSearchOAuth2Scope[] =
41 "https://www.googleapis.com/auth/plus.peopleapi.readwrite";
43 } // namespace
45 PeopleProvider::PeopleProvider(Profile* profile,
46 AppListControllerDelegate* controller)
47 : WebserviceSearchProvider(profile),
48 OAuth2TokenService::Consumer("people_provider"),
49 controller_(controller),
50 people_search_url_(kPeopleSearchUrl),
51 skip_request_token_for_test_(false) {
52 oauth2_scope_.insert(kPeopleSearchOAuth2Scope);
55 PeopleProvider::~PeopleProvider() {}
57 void PeopleProvider::Start(bool /*is_voice_query*/,
58 const base::string16& query) {
59 ClearResults();
60 if (!IsValidQuery(query)) {
61 query_.clear();
62 return;
65 query_ = base::UTF16ToUTF8(query);
67 const CacheResult result = cache_->Get(WebserviceCache::PEOPLE, query_);
68 if (result.second) {
69 ProcessPeopleSearchResults(result.second);
70 if (!people_search_fetched_callback_.is_null())
71 people_search_fetched_callback_.Run();
72 if (result.first == FRESH)
73 return;
77 if (!people_search_) {
78 people_search_.reset(new JSONResponseFetcher(
79 base::Bind(&PeopleProvider::OnPeopleSearchFetched,
80 base::Unretained(this)),
81 profile_->GetRequestContext()));
84 if (!skip_request_token_for_test_) {
85 // We start with reqesting the access token. Once the token is fetched,
86 // we'll create the full query URL and fetch it.
87 StartThrottledQuery(base::Bind(&PeopleProvider::RequestAccessToken,
88 base::Unretained(this)));
89 } else {
90 // Running in a test, skip requesting the access token, straight away
91 // start our query.
92 StartThrottledQuery(base::Bind(&PeopleProvider::StartQuery,
93 base::Unretained(this)));
97 void PeopleProvider::Stop() {
98 if (people_search_)
99 people_search_->Stop();
102 void PeopleProvider::OnGetTokenSuccess(
103 const OAuth2TokenService::Request* request,
104 const std::string& access_token,
105 const base::Time& expiration_time) {
106 DCHECK_EQ(access_token_request_, request);
107 access_token_request_.reset();
108 access_token_ = access_token;
109 StartQuery();
112 void PeopleProvider::OnGetTokenFailure(
113 const OAuth2TokenService::Request* request,
114 const GoogleServiceAuthError& error) {
115 DCHECK_EQ(access_token_request_, request);
116 access_token_request_.reset();
119 void PeopleProvider::RequestAccessToken() {
120 // Only one active request at a time.
121 if (access_token_request_ != NULL)
122 return;
124 SigninManagerBase* signin_manager =
125 SigninManagerFactory::GetInstance()->GetForProfile(profile_);
126 if (signin_manager->IsAuthenticated()) {
127 ProfileOAuth2TokenService* token_service =
128 ProfileOAuth2TokenServiceFactory::GetForProfile(profile_);
129 access_token_request_ = token_service->StartRequest(
130 signin_manager->GetAuthenticatedAccountId(), oauth2_scope_, this);
134 GURL PeopleProvider::GetQueryUrl(const std::string& query) {
135 GURL people_search_url = people_search_url_;
136 people_search_url = net::AppendQueryParameter(people_search_url,
137 kAccessTokenField,
138 access_token_);
139 people_search_url = net::AppendQueryParameter(people_search_url,
140 kQueryField,
141 query);
143 return people_search_url;
146 void PeopleProvider::StartQuery() {
147 // |query_| can be NULL when the query is scheduled but then canceled.
148 if (!people_search_ || query_.empty())
149 return;
151 GURL url = GetQueryUrl(query_);
152 people_search_->Start(url);
155 void PeopleProvider::OnPeopleSearchFetched(
156 scoped_ptr<base::DictionaryValue> json) {
157 ProcessPeopleSearchResults(json.get());
158 cache_->Put(WebserviceCache::PEOPLE, query_, json.Pass());
160 if (!people_search_fetched_callback_.is_null())
161 people_search_fetched_callback_.Run();
164 void PeopleProvider::ProcessPeopleSearchResults(
165 const base::DictionaryValue* json) {
166 const base::ListValue* item_list = NULL;
167 if (!json ||
168 !json->GetList(kKeyItems, &item_list) ||
169 !item_list ||
170 item_list->empty()) {
171 return;
174 ClearResults();
175 for (base::ListValue::const_iterator it = item_list->begin();
176 it != item_list->end();
177 ++it) {
178 const base::DictionaryValue* dict;
179 if (!(*it)->GetAsDictionary(&dict))
180 continue;
182 scoped_ptr<SearchResult> result(CreateResult(*dict));
183 if (!result)
184 continue;
186 Add(result.Pass());
190 scoped_ptr<SearchResult> PeopleProvider::CreateResult(
191 const base::DictionaryValue& dict) {
192 scoped_ptr<SearchResult> result;
194 scoped_ptr<Person> person = Person::Create(dict);
195 if (!person)
196 return result.Pass();
198 result.reset(new PeopleResult(profile_, controller_, person.Pass()));
199 return result.Pass();
202 void PeopleProvider::SetupForTest(
203 const base::Closure& people_search_fetched_callback,
204 const GURL& people_search_url) {
205 people_search_fetched_callback_ = people_search_fetched_callback;
206 people_search_url_ = people_search_url;
207 skip_request_token_for_test_ = true;
210 } // namespace app_list