Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(134)

Side by Side Diff: chrome/browser/interests/interests_fetcher.cc

Issue 1384973002: Add InterestsFetcher which retrieves a user's interests from the server. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Created 5 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2015 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/interests/interests_fetcher.h"
6
7 #include "base/command_line.h"
8 #include "base/json/json_reader.h"
9 #include "base/logging.h"
10 #include "base/strings/stringprintf.h"
11 #include "base/values.h"
12 #include "chrome/browser/signin/profile_oauth2_token_service_factory.h"
13 #include "chrome/browser/signin/signin_manager_factory.h"
14 #include "chrome/common/chrome_switches.h"
15 #include "components/signin/core/browser/profile_oauth2_token_service.h"
16 #include "net/base/load_flags.h"
17 #include "net/http/http_status_code.h"
18 #include "net/url_request/url_fetcher.h"
19 #include "net/url_request/url_request_context_getter.h"
20 #include "net/url_request/url_request_status.h"
21
22 namespace {
23
24 const int kNumRetries = 1;
25 const char kIdInterests[] = "interests";
26 const char kIdInterestName[] = "name";
27 const char kIdInterestImageUrl[] = "imageUrl";
28 const char kIdInterestRelevance[] = "relevance";
29
30 const char kApiScope[] = "https://www.googleapis.com/auth/googlenow";
31
32 const char kAuthorizationHeaderFormat[] = "Authorization: Bearer %s";
33
34 std::vector<InterestsFetcher::Interest> EmptyResponse() {
35 return std::vector<InterestsFetcher::Interest>();
36 }
37
38 GURL GetInterestsURL() {
39 const base::CommandLine* command_line =
40 base::CommandLine::ForCurrentProcess();
41 GURL interests_url(
42 command_line->GetSwitchValueASCII(switches::kInterestsURL));
Bernhard Bauer 2015/10/06 08:56:10 You can inline the constructor (`return GURL(...);
PEConn 2015/10/06 10:11:44 Done.
43 return interests_url;
44 }
45
46 } // namespace
47
48 InterestsFetcher::Interest::Interest(const std::string& name,
49 const GURL& image_url, float relevance)
Bernhard Bauer 2015/10/06 08:56:10 The items in argument lists go either all on the s
PEConn 2015/10/06 10:11:44 Done.
50 : name(name), image_url(image_url), relevance(relevance) {}
51
52 InterestsFetcher::Interest::~Interest() {}
53
54 bool InterestsFetcher::Interest::operator==(const Interest& interest) const {
55 return name == interest.name &&
56 image_url == interest.image_url &&
57 relevance == interest.relevance;
58 }
59
60 InterestsFetcher::InterestsFetcher(
61 OAuth2TokenService* oauth2_token_service,
62 const std::string& account_id,
63 net::URLRequestContextGetter* url_request_context)
64 : OAuth2TokenService::Consumer("interests_fetcher"),
65 account_id_(account_id),
66 url_request_context_(url_request_context),
67 access_token_expired_(false),
68 token_service_(oauth2_token_service) {
69 }
70
71 InterestsFetcher::~InterestsFetcher() {}
72
73 // static
74 scoped_ptr<InterestsFetcher>
75 InterestsFetcher::CreateFromProfile(Profile* profile) {
76 ProfileOAuth2TokenService* token_service =
77 ProfileOAuth2TokenServiceFactory::GetForProfile(profile);
78
79 SigninManagerBase* signin = SigninManagerFactory::GetForProfile(profile);
80
81 return make_scoped_ptr(new InterestsFetcher(
82 token_service,
83 signin->GetAuthenticatedAccountId(),
84 profile->GetRequestContext()));
85 }
86
87 void InterestsFetcher::FetchInterests(
88 const InterestsFetcher::InterestsCallback& callback) {
89 DCHECK(callback_.is_null());
90 callback_ = callback;
91 StartOAuth2Request();
92 }
93
94 void InterestsFetcher::OnURLFetchComplete(const net::URLFetcher* source) {
95 const net::URLRequestStatus& status = source->GetStatus();
96 if (!status.is_success()) {
97 VLOG(2) << "Network error " << status.error();
98 callback_.Run(EmptyResponse());
99 return;
100 }
101
102 int response_code = source->GetResponseCode();
103 // If we get an authorization error, refresh token and retry once.
104 if (response_code == net::HTTP_UNAUTHORIZED && !access_token_expired_) {
105 access_token_expired_ = true;
106 token_service_->InvalidateAccessToken(account_id_, GetApiScopes(),
107 access_token_);
108 StartOAuth2Request();
109 return;
110 }
111
112 if (response_code != net::HTTP_OK) {
113 VLOG(2) << "HTTP error " << response_code;
114 callback_.Run(EmptyResponse());
115 return;
116 }
117
118 std::string response_body;
119 source->GetResponseAsString(&response_body);
120
121 callback_.Run(ExtractInterests(response_body));
122 }
123
124 void InterestsFetcher::OnGetTokenSuccess(
125 const OAuth2TokenService::Request* request,
126 const std::string& access_token,
127 const base::Time& expiration_time) {
128 access_token_ = access_token;
129
130 fetcher_ = CreateFetcher();
131 fetcher_->SetRequestContext(url_request_context_);
132 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
133 net::LOAD_DO_NOT_SAVE_COOKIES);
134 fetcher_->SetAutomaticallyRetryOnNetworkChanges(kNumRetries);
135
136 fetcher_->AddExtraRequestHeader(
137 base::StringPrintf(kAuthorizationHeaderFormat, access_token_.c_str()));
138
139 fetcher_->Start();
140 }
141
142 void InterestsFetcher::OnGetTokenFailure(
143 const OAuth2TokenService::Request* request,
144 const GoogleServiceAuthError& error) {
145 DLOG(WARNING) << error.ToString();
146
147 callback_.Run(EmptyResponse());
148 }
149
150 void InterestsFetcher::StartOAuth2Request(){
151 oauth_request_ =
152 token_service_->StartRequest(account_id_, GetApiScopes(), this);
153 }
154
155 OAuth2TokenService::ScopeSet InterestsFetcher::GetApiScopes() {
156 OAuth2TokenService::ScopeSet scopes;
157 scopes.insert(kApiScope);
158 return scopes;
159 }
160
161 scoped_ptr<net::URLFetcher> InterestsFetcher::CreateFetcher() {
162 return net::URLFetcher::Create(0, GetInterestsURL(), net::URLFetcher::GET,
163 this);
164 }
165
166 std::vector<InterestsFetcher::Interest> InterestsFetcher::ExtractInterests(
167 const std::string& response) {
168 scoped_ptr<base::Value> value = base::JSONReader::Read(response);
169
170 const base::DictionaryValue* dict = nullptr;
171 if (!value || !value->GetAsDictionary(&dict)) {
172 DLOG(WARNING) << "ExtractInterests failed to parse global dictionary";
173 return EmptyResponse();
174 }
175
176 const base::ListValue* interests_list = nullptr;
177 std::vector<Interest> res;
Bernhard Bauer 2015/10/06 08:56:10 If you move this to the beginning, you can just re
PEConn 2015/10/06 10:11:44 I think EmptyResponse makes things a bit more read
178
179 if (!dict->GetList(kIdInterests, &interests_list)) {
180 DLOG(WARNING) << "ExtractInterests failed to parse interests list";
181 return EmptyResponse();
182 }
183
184 for (const base::Value* entry : *interests_list) {
185 const base::DictionaryValue* interest_dict = nullptr;
186 if (!entry->GetAsDictionary(&interest_dict)) {
187 DLOG(WARNING) << "ExtractInterests failed to parse interest dictionary";
188 return EmptyResponse();
189 }
190
191 std::string name;
192 if (!interest_dict->GetString(kIdInterestName, &name)) {
193 DLOG(WARNING) << "ExtractInterests failed to parse interest name";
194 return EmptyResponse();
195 }
196
197 std::string image_url;
198 if (!interest_dict->GetString(kIdInterestImageUrl, &image_url)) {
199 // image_url is allowed to be missing.
200 //
201 // However this is still logged as a warning, since, currently, the server
202 // should always provide an image_url.
203 DLOG(WARNING) << "ExtractInterests failed to parse interest image URL";
204 }
205
206 double relevance;
207 if (!interest_dict->GetDouble(kIdInterestRelevance, &relevance)) {
208 DLOG(WARNING) << "ExtractInterests failed to parse interest relevance";
209 return EmptyResponse();
210 }
211
212 res.push_back(Interest{name, GURL(image_url), relevance});
213 }
214
215 return res;
216 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698