OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2014 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_retriever.h> | |
6 | |
7 #include <base/json/json_reader.h> | |
8 #include <base/logging.h> | |
9 #include <base/values.h> | |
10 #include <net/base/load_flags.h> | |
11 #include <net/http/http_status_code.h> | |
12 #include <net/url_request/test_url_fetcher_factory.h> | |
Marc Treib
2015/09/03 09:04:36
Unneeded include
tache
2015/09/03 13:26:28
This is needed for FakeURLFetcher
Marc Treib
2015/09/03 13:54:55
Ah I see, sorry.
| |
13 #include <net/url_request/url_fetcher.h> | |
14 #include <net/url_request/url_fetcher_factory.h> | |
15 #include <net/url_request/url_request_context_getter.h> | |
16 #include <net/url_request/url_request_status.h> | |
17 | |
18 using net::FakeURLFetcher; | |
19 using net::URLFetcher; | |
20 using net::URLFetcherDelegate; | |
21 using net::URLRequestContextGetter; | |
22 using net::URLRequestStatus; | |
23 using net::URLFetcherFactory; | |
24 | |
25 namespace { | |
26 | |
27 const int kNumRetries = 1; | |
28 const char kIdInterests[] = "interest"; | |
29 const char kIdInterestName[] = "name"; | |
30 const char kIdInterestImageUrl[] = "imageUrl"; | |
31 const char kIdInterestRelevance[] = "relevance"; | |
32 | |
33 const char kInterestsUrl[] = "https://www.googleapis.com/TBD/v1/interests"; | |
34 | |
35 const char kFakeResponse[] = | |
36 "{" | |
37 " \"interest\": [" | |
38 " {\n" | |
39 " \"name\": \"Munich\",\n" | |
40 " \"imageUrl\": " | |
41 "\"https://usercontent.googleapis.com/freebase/v1/image/m/" | |
42 "02h6_6p?maxwidth=200&maxheight=200&mode=fill\"," | |
43 " \"relevance\": 0.85" | |
44 " }," | |
45 " {" | |
46 " \"name\": \"Defense of the Ancients\"," | |
47 " \"imageUrl\": " | |
48 "\"https://usercontent.googleapis.com/freebase/v1/image/m/" | |
49 "073pnt?maxwidth=200&maxheight=200&mode=fill\"," | |
50 " \"relevance\": 1" | |
51 " }," | |
52 " {" | |
53 " \"name\": \"Google\"," | |
54 " \"imageUrl\": " | |
55 "\"https://usercontent.googleapis.com/freebase/v1/image/m/" | |
56 "045c7b?maxwidth=200&maxheight=200&mode=fill&A\"," | |
57 " \"relevance\": 0.9" | |
58 " }," | |
59 " {" | |
60 " \"name\": \"Google Chrome\"," | |
61 " \"imageUrl\": " | |
62 "\"https://usercontent.googleapis.com/freebase/v1/image/m/" | |
63 "04j7cyf?maxwidth=200&maxheight=200&mode=fill\"," | |
64 " \"relevance\": 0.98" | |
65 " }" | |
66 " ]" | |
67 "}" | |
68 ""; | |
69 | |
70 std::vector<InterestsRetriever::Interest> EmptyResponse() { | |
71 return std::vector<InterestsRetriever::Interest>(); | |
72 } | |
73 | |
74 } // namespace | |
75 | |
76 InterestsRetriever::InterestsRetriever( | |
77 net::URLRequestContextGetter* url_request_context, const std::string& token, | |
Marc Treib
2015/09/03 09:04:36
Each param goes on its own line.
tache
2015/09/03 13:26:28
Done.
| |
78 const InterestsRetriever::InterestsCallback& callback, | |
79 URLFetcherFactory* url_fetcher_factory = NULL) | |
Marc Treib
2015/09/03 09:04:36
remove "= NULL"
tache
2015/09/03 13:26:28
Done.
| |
80 : url_request_context_(url_request_context), | |
81 token_(token), | |
82 callback_(callback), | |
83 url_fetcher_factory_(url_fetcher_factory) { | |
84 fetcher_ = CreateFetcher(); | |
85 | |
86 // Setup fetcher | |
87 fetcher_->SetRequestContext(url_request_context_); | |
88 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | |
89 net::LOAD_DO_NOT_SAVE_COOKIES); | |
90 fetcher_->SetAutomaticallyRetryOnNetworkChanges(kNumRetries); | |
91 | |
92 // Add oauth token | |
93 fetcher_->AddExtraRequestHeader(std::string("Authorization: Bearer ") + | |
94 token_); | |
95 | |
96 fetcher_->Start(); | |
97 } | |
98 | |
99 scoped_ptr<URLFetcher> InterestsRetriever::CreateFetcher() { | |
100 // The API is not accessible yet. So a static response is provided. | |
101 // return URLFetcher::Create(GURL(kInterestsUrl), URLFetcher::GET, this); | |
102 | |
103 // If a Factory is provided use it. This is needed for testing. | |
104 if (url_fetcher_factory_) { | |
Marc Treib
2015/09/03 09:04:36
Hm, this bothers me.. I dislike "if (testing)" con
tache
2015/09/03 13:26:28
Yes, this is only needed because of the fake respo
| |
105 return url_fetcher_factory_->CreateURLFetcher(0, GURL(kInterestsUrl), | |
106 URLFetcher::GET, this); | |
107 | |
108 } else { | |
109 return scoped_ptr<URLFetcher>(new FakeURLFetcher( | |
110 GURL(kInterestsUrl), this, std::string(kFakeResponse), net::HTTP_OK, | |
111 net::URLRequestStatus::SUCCESS)); | |
112 } | |
113 } | |
114 | |
115 void InterestsRetriever::OnURLFetchComplete(const net::URLFetcher* source) { | |
116 const URLRequestStatus& status = source->GetStatus(); | |
117 | |
118 std::string response_body; | |
119 source->GetResponseAsString(&response_body); | |
Marc Treib
2015/09/03 09:04:36
Move these two lines after the success check?
tache
2015/09/03 13:26:28
Done.
| |
120 | |
121 if (!status.is_success()) { | |
122 DLOG(WARNING) << "URL request failed!"; | |
123 callback_.Run(EmptyResponse()); | |
124 return; | |
125 } | |
126 | |
127 auto interests = ExtractInterests(response_body); | |
Marc Treib
2015/09/03 09:04:36
Inline the ExtractInterests call into the line bel
tache
2015/09/03 13:26:28
Done.
| |
128 callback_.Run(interests); | |
129 } | |
130 | |
131 std::vector<InterestsRetriever::Interest> InterestsRetriever::ExtractInterests( | |
132 const std::string& response) { | |
133 scoped_ptr<base::Value> value = base::JSONReader::Read(response); | |
134 | |
135 const base::DictionaryValue* dict = NULL; | |
Marc Treib
2015/09/03 09:04:37
nullptr :)
tache
2015/09/03 13:26:28
Done.
| |
136 if (!value || !value->GetAsDictionary(&dict)) { | |
137 DLOG(WARNING) << "ExtractInterests failed to parse global dictionary"; | |
138 return EmptyResponse(); | |
139 } | |
140 | |
141 const base::ListValue* interests_list = NULL; | |
142 std::vector<Interest> res; | |
143 | |
144 if (!dict->GetList(kIdInterests, &interests_list)) { | |
145 DLOG(WARNING) << "ExtractInterests failed to parse interests list"; | |
146 return EmptyResponse(); | |
147 } | |
148 | |
149 for (const base::Value* entry : *interests_list) { | |
150 const base::DictionaryValue* interest_dict = NULL; | |
151 if (!entry->GetAsDictionary(&interest_dict)) { | |
152 DLOG(WARNING) << "ExtractInterests failed to parse interest dictionary"; | |
153 return EmptyResponse(); | |
154 } | |
155 | |
156 std::string name; | |
157 if (!interest_dict->GetString(kIdInterestName, &name)) { | |
158 DLOG(WARNING) << "ExtractInterests failed to parse interest name"; | |
159 return EmptyResponse(); | |
160 } | |
161 | |
162 std::string image_url; | |
163 if (!interest_dict->GetString(kIdInterestImageUrl, &image_url)) { | |
Marc Treib
2015/09/03 09:04:36
I think it's okay if the image URL is missing? So
tache
2015/09/03 13:26:28
Done. I kept the warning, since atm there should a
Marc Treib
2015/09/03 13:54:55
Okay. Please add a comment though, otherwise the n
tache
2015/09/03 15:21:52
Done.
| |
164 DLOG(WARNING) << "ExtractInterests failed to parse interest image URL"; | |
165 return EmptyResponse(); | |
166 } | |
167 | |
168 double relevance; | |
169 if (!interest_dict->GetDouble(kIdInterestRelevance, &relevance)) { | |
170 DLOG(WARNING) << "ExtractInterests failed to parse interest relevance"; | |
171 return EmptyResponse(); | |
172 } | |
173 | |
174 res.push_back(Interest{name, image_url, relevance}); | |
Marc Treib
2015/09/03 09:04:36
We can't use uniform initialization yet - it needs
tache
2015/09/03 13:26:28
Done. Leaving it as is.
| |
175 } | |
176 | |
177 return res; | |
178 } | |
179 | |
180 InterestsRetriever::~InterestsRetriever() {} | |
181 | |
182 std::string InterestsRetriever::FakeResponse() { return kFakeResponse; } | |
OLD | NEW |