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

Side by Side Diff: components/doodle/doodle_fetcher_impl.cc

Issue 2707293002: [Doodle] Split DoodleFetcher into interface + Impl (Closed)
Patch Set: review Created 3 years, 10 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
1 // Copyright 2017 The Chromium Authors. All rights reserved. 1 // Copyright 2017 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "components/doodle/doodle_fetcher.h" 5 #include "components/doodle/doodle_fetcher_impl.h"
6 6
7 #include <utility> 7 #include <utility>
8 8
9 #include "base/strings/string_number_conversions.h" 9 #include "base/strings/string_number_conversions.h"
10 #include "base/time/clock.h" 10 #include "base/time/clock.h"
11 #include "base/time/default_clock.h" 11 #include "base/time/default_clock.h"
12 #include "base/time/time.h" 12 #include "base/time/time.h"
13 #include "base/values.h" 13 #include "base/values.h"
14 #include "components/data_use_measurement/core/data_use_user_data.h" 14 #include "components/data_use_measurement/core/data_use_user_data.h"
15 #include "components/google/core/browser/google_url_tracker.h" 15 #include "components/google/core/browser/google_url_tracker.h"
(...skipping 51 matching lines...) Expand 10 before | Expand all | Expand 10 after
67 } // namespace 67 } // namespace
68 68
69 DoodleImage::DoodleImage() 69 DoodleImage::DoodleImage()
70 : height(0), width(0), is_animated_gif(false), is_cta(false) {} 70 : height(0), width(0), is_animated_gif(false), is_cta(false) {}
71 DoodleImage::~DoodleImage() = default; 71 DoodleImage::~DoodleImage() = default;
72 72
73 DoodleConfig::DoodleConfig() : doodle_type(DoodleType::UNKNOWN) {} 73 DoodleConfig::DoodleConfig() : doodle_type(DoodleType::UNKNOWN) {}
74 DoodleConfig::DoodleConfig(const DoodleConfig& config) = default; 74 DoodleConfig::DoodleConfig(const DoodleConfig& config) = default;
75 DoodleConfig::~DoodleConfig() = default; 75 DoodleConfig::~DoodleConfig() = default;
76 76
77 DoodleFetcher::DoodleFetcher( 77 DoodleFetcherImpl::DoodleFetcherImpl(
78 scoped_refptr<net::URLRequestContextGetter> download_context, 78 scoped_refptr<net::URLRequestContextGetter> download_context,
79 GoogleURLTracker* google_url_tracker, 79 GoogleURLTracker* google_url_tracker,
80 const ParseJSONCallback& json_parsing_callback) 80 const ParseJSONCallback& json_parsing_callback)
81 : download_context_(download_context), 81 : download_context_(download_context),
82 json_parsing_callback_(json_parsing_callback), 82 json_parsing_callback_(json_parsing_callback),
83 google_url_tracker_(google_url_tracker), 83 google_url_tracker_(google_url_tracker),
84 clock_(new base::DefaultClock()), 84 clock_(new base::DefaultClock()),
85 weak_ptr_factory_(this) { 85 weak_ptr_factory_(this) {
86 DCHECK(google_url_tracker_); 86 DCHECK(google_url_tracker_);
87 } 87 }
88 88
89 DoodleFetcher::~DoodleFetcher() = default; 89 DoodleFetcherImpl::~DoodleFetcherImpl() = default;
90 90
91 void DoodleFetcher::FetchDoodle(FinishedCallback callback) { 91 void DoodleFetcherImpl::FetchDoodle(FinishedCallback callback) {
92 if (IsFetchInProgress()) { 92 if (IsFetchInProgress()) {
93 callbacks_.push_back(std::move(callback)); 93 callbacks_.push_back(std::move(callback));
94 return; // The callback will be called for the existing request's results. 94 return; // The callback will be called for the existing request's results.
95 } 95 }
96 DCHECK(!fetcher_.get()); 96 DCHECK(!fetcher_.get());
97 callbacks_.push_back(std::move(callback)); 97 callbacks_.push_back(std::move(callback));
98 fetcher_ = URLFetcher::Create(GetGoogleBaseUrl().Resolve(kDoodleConfigPath), 98 fetcher_ = URLFetcher::Create(GetGoogleBaseUrl().Resolve(kDoodleConfigPath),
99 URLFetcher::GET, this); 99 URLFetcher::GET, this);
100 fetcher_->SetRequestContext(download_context_.get()); 100 fetcher_->SetRequestContext(download_context_.get());
101 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | 101 fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES |
102 net::LOAD_DO_NOT_SAVE_COOKIES | 102 net::LOAD_DO_NOT_SAVE_COOKIES |
103 net::LOAD_DO_NOT_SEND_AUTH_DATA); 103 net::LOAD_DO_NOT_SEND_AUTH_DATA);
104 fetcher_->SetAutomaticallyRetryOnNetworkChanges(1); 104 fetcher_->SetAutomaticallyRetryOnNetworkChanges(1);
105 data_use_measurement::DataUseUserData::AttachToFetcher( 105 data_use_measurement::DataUseUserData::AttachToFetcher(
106 fetcher_.get(), data_use_measurement::DataUseUserData::DOODLE); 106 fetcher_.get(), data_use_measurement::DataUseUserData::DOODLE);
107 fetcher_->Start(); 107 fetcher_->Start();
108 } 108 }
109 109
110 void DoodleFetcher::OnURLFetchComplete(const URLFetcher* source) { 110 void DoodleFetcherImpl::OnURLFetchComplete(const URLFetcher* source) {
111 DCHECK_EQ(fetcher_.get(), source); 111 DCHECK_EQ(fetcher_.get(), source);
112 std::unique_ptr<net::URLFetcher> free_fetcher = std::move(fetcher_); 112 std::unique_ptr<net::URLFetcher> free_fetcher = std::move(fetcher_);
113 113
114 std::string json_string; 114 std::string json_string;
115 if (!(source->GetStatus().is_success() && 115 if (!(source->GetStatus().is_success() &&
116 source->GetResponseCode() == net::HTTP_OK && 116 source->GetResponseCode() == net::HTTP_OK &&
117 source->GetResponseAsString(&json_string))) { 117 source->GetResponseAsString(&json_string))) {
118 RespondToAllCallbacks(DoodleState::DOWNLOAD_ERROR, base::nullopt); 118 RespondToAllCallbacks(DoodleState::DOWNLOAD_ERROR, base::nullopt);
119 return; 119 return;
120 } 120 }
121 121
122 json_parsing_callback_.Run( 122 json_parsing_callback_.Run(StripSafetyPreamble(std::move(json_string)),
123 StripSafetyPreamble(std::move(json_string)), 123 base::Bind(&DoodleFetcherImpl::OnJsonParsed,
124 base::Bind(&DoodleFetcher::OnJsonParsed, weak_ptr_factory_.GetWeakPtr()), 124 weak_ptr_factory_.GetWeakPtr()),
125 base::Bind(&DoodleFetcher::OnJsonParseFailed, 125 base::Bind(&DoodleFetcherImpl::OnJsonParseFailed,
126 weak_ptr_factory_.GetWeakPtr())); 126 weak_ptr_factory_.GetWeakPtr()));
127 } 127 }
128 128
129 void DoodleFetcher::OnJsonParsed(std::unique_ptr<base::Value> json) { 129 void DoodleFetcherImpl::OnJsonParsed(std::unique_ptr<base::Value> json) {
130 std::unique_ptr<base::DictionaryValue> config = 130 std::unique_ptr<base::DictionaryValue> config =
131 base::DictionaryValue::From(std::move(json)); 131 base::DictionaryValue::From(std::move(json));
132 if (!config.get()) { 132 if (!config.get()) {
133 DLOG(WARNING) << "Doodle JSON is not valid"; 133 DLOG(WARNING) << "Doodle JSON is not valid";
134 RespondToAllCallbacks(DoodleState::PARSING_ERROR, base::nullopt); 134 RespondToAllCallbacks(DoodleState::PARSING_ERROR, base::nullopt);
135 return; 135 return;
136 } 136 }
137 137
138 const base::DictionaryValue* ddljson = nullptr; 138 const base::DictionaryValue* ddljson = nullptr;
139 if (!config->GetDictionary("ddljson", &ddljson)) { 139 if (!config->GetDictionary("ddljson", &ddljson)) {
140 DLOG(WARNING) << "Doodle JSON reponse did not contain 'ddljson' key."; 140 DLOG(WARNING) << "Doodle JSON reponse did not contain 'ddljson' key.";
141 RespondToAllCallbacks(DoodleState::PARSING_ERROR, base::nullopt); 141 RespondToAllCallbacks(DoodleState::PARSING_ERROR, base::nullopt);
142 return; 142 return;
143 } 143 }
144 144
145 base::Optional<DoodleConfig> doodle = ParseDoodle(*ddljson); 145 base::Optional<DoodleConfig> doodle = ParseDoodle(*ddljson);
146 if (!doodle.has_value()) { 146 if (!doodle.has_value()) {
147 RespondToAllCallbacks(DoodleState::NO_DOODLE, base::nullopt); 147 RespondToAllCallbacks(DoodleState::NO_DOODLE, base::nullopt);
148 return; 148 return;
149 } 149 }
150 150
151 RespondToAllCallbacks(DoodleState::AVAILABLE, std::move(doodle)); 151 RespondToAllCallbacks(DoodleState::AVAILABLE, std::move(doodle));
152 } 152 }
153 153
154 void DoodleFetcher::OnJsonParseFailed(const std::string& error_message) { 154 void DoodleFetcherImpl::OnJsonParseFailed(const std::string& error_message) {
155 DLOG(WARNING) << "JSON parsing failed: " << error_message; 155 DLOG(WARNING) << "JSON parsing failed: " << error_message;
156 RespondToAllCallbacks(DoodleState::PARSING_ERROR, base::nullopt); 156 RespondToAllCallbacks(DoodleState::PARSING_ERROR, base::nullopt);
157 } 157 }
158 158
159 base::Optional<DoodleConfig> DoodleFetcher::ParseDoodle( 159 base::Optional<DoodleConfig> DoodleFetcherImpl::ParseDoodle(
160 const base::DictionaryValue& ddljson) const { 160 const base::DictionaryValue& ddljson) const {
161 DoodleConfig doodle; 161 DoodleConfig doodle;
162 if (!ParseImage(ddljson, "large_image", &doodle.large_image)) { 162 if (!ParseImage(ddljson, "large_image", &doodle.large_image)) {
163 return base::nullopt; 163 return base::nullopt;
164 } 164 }
165 ParseImage(ddljson, "transparent_large_image", 165 ParseImage(ddljson, "transparent_large_image",
166 &doodle.transparent_large_image); 166 &doodle.transparent_large_image);
167 ParseImage(ddljson, "large_cta_image", &doodle.large_cta_image); 167 ParseImage(ddljson, "large_cta_image", &doodle.large_cta_image);
168 ParseBaseInformation(ddljson, &doodle); 168 ParseBaseInformation(ddljson, &doodle);
169 return doodle; 169 return doodle;
170 } 170 }
171 171
172 bool DoodleFetcher::ParseImage(const base::DictionaryValue& image_parent, 172 bool DoodleFetcherImpl::ParseImage(const base::DictionaryValue& image_parent,
173 const std::string& image_name, 173 const std::string& image_name,
174 DoodleImage* image) const { 174 DoodleImage* image) const {
175 DCHECK(image); 175 DCHECK(image);
176 const base::DictionaryValue* image_dict = nullptr; 176 const base::DictionaryValue* image_dict = nullptr;
177 if (!image_parent.GetDictionary(image_name, &image_dict)) { 177 if (!image_parent.GetDictionary(image_name, &image_dict)) {
178 return false; 178 return false;
179 } 179 }
180 image->url = ParseRelativeUrl(*image_dict, "url"); 180 image->url = ParseRelativeUrl(*image_dict, "url");
181 if (!image->url.is_valid()) { 181 if (!image->url.is_valid()) {
182 DLOG(WARNING) << "Image URL for \"" << image_name << "\" is invalid."; 182 DLOG(WARNING) << "Image URL for \"" << image_name << "\" is invalid.";
183 return false; 183 return false;
184 } 184 }
185 image_dict->GetInteger("height", &image->height); 185 image_dict->GetInteger("height", &image->height);
186 image_dict->GetInteger("width", &image->width); 186 image_dict->GetInteger("width", &image->width);
187 image_dict->GetBoolean("is_animated_gif", &image->is_animated_gif); 187 image_dict->GetBoolean("is_animated_gif", &image->is_animated_gif);
188 image_dict->GetBoolean("is_cta", &image->is_cta); 188 image_dict->GetBoolean("is_cta", &image->is_cta);
189 return true; 189 return true;
190 } 190 }
191 191
192 void DoodleFetcher::ParseBaseInformation(const base::DictionaryValue& ddljson, 192 void DoodleFetcherImpl::ParseBaseInformation(
193 DoodleConfig* config) const { 193 const base::DictionaryValue& ddljson,
194 DoodleConfig* config) const {
194 config->search_url = ParseRelativeUrl(ddljson, "search_url"); 195 config->search_url = ParseRelativeUrl(ddljson, "search_url");
195 config->target_url = ParseRelativeUrl(ddljson, "target_url"); 196 config->target_url = ParseRelativeUrl(ddljson, "target_url");
196 config->fullpage_interactive_url = 197 config->fullpage_interactive_url =
197 ParseRelativeUrl(ddljson, "fullpage_interactive_url"); 198 ParseRelativeUrl(ddljson, "fullpage_interactive_url");
198 199
199 config->doodle_type = ParseDoodleType(ddljson); 200 config->doodle_type = ParseDoodleType(ddljson);
200 ddljson.GetString("alt_text", &config->alt_text); 201 ddljson.GetString("alt_text", &config->alt_text);
201 ddljson.GetString("interactive_html", &config->interactive_html); 202 ddljson.GetString("interactive_html", &config->interactive_html);
202 203
203 // The JSON doesn't guarantee the number to fit into an int. 204 // The JSON doesn't guarantee the number to fit into an int.
204 double ttl = 0; // Expires immediately if the parameter is missing. 205 double ttl = 0; // Expires immediately if the parameter is missing.
205 if (!ddljson.GetDouble("time_to_live_ms", &ttl) || ttl < 0) { 206 if (!ddljson.GetDouble("time_to_live_ms", &ttl) || ttl < 0) {
206 DLOG(WARNING) << "No valid Doodle image TTL present in ddljson!"; 207 DLOG(WARNING) << "No valid Doodle image TTL present in ddljson!";
207 ttl = 0; 208 ttl = 0;
208 } 209 }
209 if (ttl > kMaxTimeToLiveMS) { 210 if (ttl > kMaxTimeToLiveMS) {
210 ttl = kMaxTimeToLiveMS; 211 ttl = kMaxTimeToLiveMS;
211 DLOG(WARNING) << "Clamping Doodle image TTL to 30 days!"; 212 DLOG(WARNING) << "Clamping Doodle image TTL to 30 days!";
212 } 213 }
213 config->expiry_date = clock_->Now() + base::TimeDelta::FromMillisecondsD(ttl); 214 config->expiry_date = clock_->Now() + base::TimeDelta::FromMillisecondsD(ttl);
214 } 215 }
215 216
216 GURL DoodleFetcher::ParseRelativeUrl(const base::DictionaryValue& dict_value, 217 GURL DoodleFetcherImpl::ParseRelativeUrl(
217 const std::string& key) const { 218 const base::DictionaryValue& dict_value,
219 const std::string& key) const {
218 std::string str_url; 220 std::string str_url;
219 dict_value.GetString(key, &str_url); 221 dict_value.GetString(key, &str_url);
220 if (str_url.empty()) { 222 if (str_url.empty()) {
221 return GURL(); 223 return GURL();
222 } 224 }
223 return GetGoogleBaseUrl().Resolve(str_url); 225 return GetGoogleBaseUrl().Resolve(str_url);
224 } 226 }
225 227
226 void DoodleFetcher::RespondToAllCallbacks( 228 void DoodleFetcherImpl::RespondToAllCallbacks(
227 DoodleState state, 229 DoodleState state,
228 const base::Optional<DoodleConfig>& config) { 230 const base::Optional<DoodleConfig>& config) {
229 for (auto& callback : callbacks_) { 231 for (auto& callback : callbacks_) {
230 std::move(callback).Run(state, config); 232 std::move(callback).Run(state, config);
231 } 233 }
232 callbacks_.clear(); 234 callbacks_.clear();
233 } 235 }
234 236
235 GURL DoodleFetcher::GetGoogleBaseUrl() const { 237 GURL DoodleFetcherImpl::GetGoogleBaseUrl() const {
236 GURL cmd_line_url = google_util::CommandLineGoogleBaseURL(); 238 GURL cmd_line_url = google_util::CommandLineGoogleBaseURL();
237 if (cmd_line_url.is_valid()) { 239 if (cmd_line_url.is_valid()) {
238 return cmd_line_url; 240 return cmd_line_url;
239 } 241 }
240 return google_url_tracker_->google_url(); 242 return google_url_tracker_->google_url();
241 } 243 }
242 244
243 } // namespace doodle 245 } // namespace doodle
OLDNEW
« no previous file with comments | « components/doodle/doodle_fetcher_impl.h ('k') | components/doodle/doodle_fetcher_impl_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698