Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright 2016 The Chromium Authors. All rights reserved. | 1 // Copyright 2016 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/ntp_snippets/ntp_snippets_fetcher.h" | 5 #include "components/ntp_snippets/ntp_snippets_fetcher.h" |
| 6 | 6 |
| 7 #include <stdlib.h> | |
| 8 | |
| 7 #include "base/command_line.h" | 9 #include "base/command_line.h" |
| 8 #include "base/files/file_path.h" | 10 #include "base/files/file_path.h" |
| 9 #include "base/files/file_util.h" | 11 #include "base/files/file_util.h" |
| 10 #include "base/metrics/sparse_histogram.h" | 12 #include "base/metrics/sparse_histogram.h" |
| 11 #include "base/path_service.h" | 13 #include "base/path_service.h" |
| 12 #include "base/strings/string_number_conversions.h" | 14 #include "base/strings/string_number_conversions.h" |
| 13 #include "base/strings/string_util.h" | 15 #include "base/strings/string_util.h" |
| 14 #include "base/strings/stringprintf.h" | 16 #include "base/strings/stringprintf.h" |
| 15 #include "base/values.h" | 17 #include "base/values.h" |
| 16 #include "components/data_use_measurement/core/data_use_user_data.h" | 18 #include "components/data_use_measurement/core/data_use_user_data.h" |
| 19 #include "components/ntp_snippets/ntp_snippets_constants.h" | |
| 17 #include "components/ntp_snippets/switches.h" | 20 #include "components/ntp_snippets/switches.h" |
| 21 #include "components/signin/core/browser/profile_oauth2_token_service.h" | |
| 22 #include "components/signin/core/browser/signin_manager.h" | |
| 23 #include "components/signin/core/browser/signin_manager_base.h" | |
| 24 #include "components/variations/variations_associated_data.h" | |
| 18 #include "google_apis/google_api_keys.h" | 25 #include "google_apis/google_api_keys.h" |
| 19 #include "net/base/load_flags.h" | 26 #include "net/base/load_flags.h" |
| 20 #include "net/http/http_request_headers.h" | 27 #include "net/http/http_request_headers.h" |
| 21 #include "net/http/http_response_headers.h" | 28 #include "net/http/http_response_headers.h" |
| 22 #include "net/http/http_status_code.h" | 29 #include "net/http/http_status_code.h" |
| 23 #include "net/url_request/url_fetcher.h" | 30 #include "net/url_request/url_fetcher.h" |
| 31 #include "third_party/icu/source/common/unicode/uloc.h" | |
| 32 #include "third_party/icu/source/common/unicode/utypes.h" | |
| 24 | 33 |
| 25 using net::URLFetcher; | 34 using net::URLFetcher; |
| 26 using net::URLRequestContextGetter; | 35 using net::URLRequestContextGetter; |
| 27 using net::HttpRequestHeaders; | 36 using net::HttpRequestHeaders; |
| 28 using net::URLRequestStatus; | 37 using net::URLRequestStatus; |
| 29 | 38 |
| 30 namespace ntp_snippets { | 39 namespace ntp_snippets { |
| 31 | 40 |
| 32 namespace { | 41 namespace { |
| 33 | 42 |
| 34 const char kStatusMessageEmptyHosts[] = "Cannot fetch for empty hosts list."; | 43 const char kStatusMessageEmptyHosts[] = "Cannot fetch for empty hosts list."; |
| 35 const char kStatusMessageURLRequestErrorFormat[] = "URLRequestStatus error %d"; | 44 const char kStatusMessageURLRequestErrorFormat[] = "URLRequestStatus error %d"; |
| 36 const char kStatusMessageHTTPErrorFormat[] = "HTTP error %d"; | 45 const char kStatusMessageHTTPErrorFormat[] = "HTTP error %d"; |
| 37 const char kStatusMessageJsonErrorFormat[] = "Received invalid JSON (error %s)"; | 46 const char kStatusMessageJsonErrorFormat[] = "Received invalid JSON (error %s)"; |
| 38 const char kStatusMessageInvalidList[] = "Invalid / empty list."; | 47 const char kStatusMessageInvalidList[] = "Invalid / empty list."; |
| 39 | 48 |
| 40 const char kContentSnippetsServerFormat[] = | 49 const char kApiScope[] = "https://www.googleapis.com/auth/webhistory"; |
| 41 "https://chromereader-pa.googleapis.com/v1/fetch?key=%s"; | 50 const char kSnippetsServer[] = |
| 51 "https://chromereader-pa.googleapis.com/v1/fetch"; | |
| 52 const char kSnippetsServerNonAuthorizedFormat[] = "%s?key=%s"; | |
| 53 const char kAuthorizationRequestHeaderFormat[] = "Bearer %s"; | |
| 54 | |
| 55 // Variation parameter for the variant of fetching to use. | |
| 56 const char kVariantName[] = "fetching_variant"; | |
| 57 | |
| 58 // Constants listing possible values of the "fetching_variant" parameter. | |
| 59 const char kVariantRestrictedString[] = "restricted"; | |
| 60 const char kVariantPersonalizedString[] = "personalized"; | |
| 61 const char kVariantRestrictedPersonalizedString[] = "restricted_personalized"; | |
| 42 | 62 |
| 43 const char kRequestParameterFormat[] = | 63 const char kRequestParameterFormat[] = |
| 44 "{" | 64 "{" |
| 45 " \"response_detail_level\": \"STANDARD\"," | 65 " \"response_detail_level\": \"STANDARD\"," |
| 66 "%s" // If authenticated - an obfuscated Gaia ID will be inserted here. | |
| 46 " \"advanced_options\": {" | 67 " \"advanced_options\": {" |
| 47 " \"local_scoring_params\": {" | 68 " \"local_scoring_params\": {" |
| 48 " \"content_params\": {" | 69 " \"content_params\": {" |
| 49 " \"only_return_personalized_results\": false" | 70 " \"only_return_personalized_results\": false" |
| 71 "%s" // If authenticated - user segment (lang code) will be inserted here. | |
| 50 " }," | 72 " }," |
| 51 " \"content_restricts\": {" | 73 " \"content_restricts\": {" |
| 52 " \"type\": \"METADATA\"," | 74 " \"type\": \"METADATA\"," |
| 53 " \"value\": \"TITLE\"" | 75 " \"value\": \"TITLE\"" |
| 54 " }," | 76 " }," |
| 55 " \"content_restricts\": {" | 77 " \"content_restricts\": {" |
| 56 " \"type\": \"METADATA\"," | 78 " \"type\": \"METADATA\"," |
| 57 " \"value\": \"SNIPPET\"" | 79 " \"value\": \"SNIPPET\"" |
| 58 " }," | 80 " }," |
| 59 " \"content_restricts\": {" | 81 " \"content_restricts\": {" |
| 60 " \"type\": \"METADATA\"," | 82 " \"type\": \"METADATA\"," |
| 61 " \"value\": \"THUMBNAIL\"" | 83 " \"value\": \"THUMBNAIL\"" |
| 62 " }" | 84 " }" |
| 63 "%s" | 85 "%s" // If host restricted - host restrictions will be inserted here. |
| 64 " }," | 86 " }," |
| 65 " \"global_scoring_params\": {" | 87 " \"global_scoring_params\": {" |
| 66 " \"num_to_return\": %i" | 88 " \"num_to_return\": %i," |
| 89 " \"sort_type\": 1" | |
| 67 " }" | 90 " }" |
| 68 " }" | 91 " }" |
| 69 "}"; | 92 "}"; |
| 70 | 93 |
| 94 const char kGaiaIdFormat[] = " \"obfuscated_gaia_id\": \"%s\","; | |
| 95 const char kUserSegmentFormat[] = " ,\"user_segment\": \"%s\""; | |
| 71 const char kHostRestrictFormat[] = | 96 const char kHostRestrictFormat[] = |
| 72 " ,\"content_selectors\": {" | 97 " ,\"content_selectors\": {" |
| 73 " \"type\": \"HOST_RESTRICT\"," | 98 " \"type\": \"HOST_RESTRICT\"," |
| 74 " \"value\": \"%s\"" | 99 " \"value\": \"%s\"" |
| 75 " }"; | 100 " }"; |
| 76 | 101 |
| 77 } // namespace | 102 } // namespace |
| 78 | 103 |
| 79 NTPSnippetsFetcher::NTPSnippetsFetcher( | 104 NTPSnippetsFetcher::NTPSnippetsFetcher( |
| 105 SigninManagerBase* signin_manager, | |
| 106 OAuth2TokenService* token_service, | |
| 80 scoped_refptr<URLRequestContextGetter> url_request_context_getter, | 107 scoped_refptr<URLRequestContextGetter> url_request_context_getter, |
| 81 const ParseJSONCallback& parse_json_callback, | 108 const ParseJSONCallback& parse_json_callback, |
| 82 bool is_stable_channel) | 109 bool is_stable_channel) |
| 83 : url_request_context_getter_(url_request_context_getter), | 110 : OAuth2TokenService::Consumer("ntp_snippets"), |
| 111 signin_manager_(signin_manager), | |
| 112 token_service_(token_service), | |
| 113 waiting_for_refresh_token_(false), | |
| 114 url_request_context_getter_(url_request_context_getter), | |
| 84 parse_json_callback_(parse_json_callback), | 115 parse_json_callback_(parse_json_callback), |
| 85 is_stable_channel_(is_stable_channel), | 116 is_stable_channel_(is_stable_channel), |
| 86 weak_ptr_factory_(this) {} | 117 weak_ptr_factory_(this) { |
| 118 // Parse the variation parameters and set the defaults if missing. | |
| 119 std::string variant = variations::GetVariationParamValue( | |
| 120 ntp_snippets::kStudyName, kVariantName); | |
| 121 if (variant == kVariantRestrictedString) { | |
| 122 variant_ = Variant::kRestricted; | |
| 123 } else if (variant == kVariantPersonalizedString) { | |
| 124 variant_ = Variant::kPersonalized; | |
| 125 } else { | |
| 126 variant_ = Variant::kRestrictedPersonalized; | |
| 127 LOG_IF(WARNING, !variant.empty() && variant != | |
|
Marc Treib
2016/05/10 08:42:20
nitty nit: Break after the "&&", and align to the"
jkrcal
2016/05/10 09:10:07
git cl format did it differently but it is better
| |
| 128 kVariantRestrictedPersonalizedString) | |
| 129 << "Unknown fetching variant provided: " << variant; | |
| 130 } | |
| 131 } | |
| 87 | 132 |
| 88 NTPSnippetsFetcher::~NTPSnippetsFetcher() {} | 133 NTPSnippetsFetcher::~NTPSnippetsFetcher() { |
| 134 if (waiting_for_refresh_token_) | |
| 135 token_service_->RemoveObserver(this); | |
| 136 } | |
| 89 | 137 |
| 90 void NTPSnippetsFetcher::SetCallback( | 138 void NTPSnippetsFetcher::SetCallback( |
| 91 const SnippetsAvailableCallback& callback) { | 139 const SnippetsAvailableCallback& callback) { |
| 92 snippets_available_callback_ = callback; | 140 snippets_available_callback_ = callback; |
| 93 } | 141 } |
| 94 | 142 |
| 95 void NTPSnippetsFetcher::FetchSnippetsFromHosts( | 143 void NTPSnippetsFetcher::FetchSnippetsFromHosts( |
| 96 const std::set<std::string>& hosts, int count) { | 144 const std::set<std::string>& hosts, |
| 97 std::string host_restricts; | 145 const std::string& language_code, |
| 98 if (!base::CommandLine::ForCurrentProcess()->HasSwitch( | 146 int count) { |
| 99 switches::kDontRestrict)) { | 147 hosts_ = hosts; |
| 100 if (hosts.empty()) { | 148 |
| 101 if (!snippets_available_callback_.is_null()) { | 149 if (UseHostRestriction() && hosts_.empty()) { |
| 102 snippets_available_callback_.Run(NTPSnippet::PtrVector(), | 150 if (!snippets_available_callback_.is_null()) { |
| 103 kStatusMessageEmptyHosts); | 151 snippets_available_callback_.Run(NTPSnippet::PtrVector(), |
| 104 } | 152 kStatusMessageEmptyHosts); |
| 105 return; | |
| 106 } | 153 } |
| 107 for (const std::string& host : hosts) | 154 return; |
| 108 host_restricts += base::StringPrintf(kHostRestrictFormat, host.c_str()); | |
| 109 } | 155 } |
| 110 const std::string& key = is_stable_channel_ | 156 |
| 111 ? google_apis::GetAPIKey() | 157 // Translate the BCP 47 |language_code| into a posix locale string. |
| 112 : google_apis::GetNonStableAPIKey(); | 158 char locale[ULOC_FULLNAME_CAPACITY]; |
| 113 std::string url = | 159 UErrorCode error; |
| 114 base::StringPrintf(kContentSnippetsServerFormat, key.c_str()); | 160 uloc_forLanguageTag(language_code.c_str(), locale, ULOC_FULLNAME_CAPACITY, |
| 115 url_fetcher_ = URLFetcher::Create(GURL(url), URLFetcher::POST, this); | 161 nullptr, &error); |
| 162 DLOG_IF(WARNING, U_ZERO_ERROR != error) << | |
| 163 "Error in translating language code to a locale string: " << error; | |
| 164 locale_ = locale; | |
| 165 | |
| 166 count_to_fetch_ = count; | |
| 167 | |
| 168 bool use_authentication = UseAuthentication(); | |
| 169 | |
| 170 if (use_authentication && signin_manager_->IsAuthenticated()) { | |
| 171 // Signed-in: get OAuth token --> fetch snippets. | |
| 172 StartTokenRequest(); | |
| 173 } else if (use_authentication && signin_manager_->AuthInProgress()) { | |
| 174 // Currently signing in: wait for auth to finish (the refresh token) --> | |
| 175 // get OAuth token --> fetch snippets. | |
| 176 if (!waiting_for_refresh_token_) { | |
| 177 // Wait until we get a refresh token. | |
| 178 waiting_for_refresh_token_ = true; | |
| 179 token_service_->AddObserver(this); | |
| 180 } | |
| 181 } else { | |
| 182 // Not signed in: fetch snippets (without authentication). | |
| 183 FetchSnippetsNonAuthenticated(); | |
| 184 } | |
| 185 } | |
| 186 | |
| 187 void NTPSnippetsFetcher::FetchSnippetsImpl(const GURL& url, | |
| 188 const std::string& auth_header, | |
| 189 const std::string& request) { | |
| 190 url_fetcher_ = URLFetcher::Create(url, URLFetcher::POST, this); | |
| 191 | |
| 116 url_fetcher_->SetRequestContext(url_request_context_getter_.get()); | 192 url_fetcher_->SetRequestContext(url_request_context_getter_.get()); |
| 117 url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | | 193 url_fetcher_->SetLoadFlags(net::LOAD_DO_NOT_SEND_COOKIES | |
| 118 net::LOAD_DO_NOT_SAVE_COOKIES); | 194 net::LOAD_DO_NOT_SAVE_COOKIES); |
| 195 | |
| 119 data_use_measurement::DataUseUserData::AttachToFetcher( | 196 data_use_measurement::DataUseUserData::AttachToFetcher( |
| 120 url_fetcher_.get(), data_use_measurement::DataUseUserData::NTP_SNIPPETS); | 197 url_fetcher_.get(), data_use_measurement::DataUseUserData::NTP_SNIPPETS); |
| 198 | |
| 121 HttpRequestHeaders headers; | 199 HttpRequestHeaders headers; |
| 200 if (!auth_header.empty()) | |
| 201 headers.SetHeader("Authorization", auth_header); | |
| 122 headers.SetHeader("Content-Type", "application/json; charset=UTF-8"); | 202 headers.SetHeader("Content-Type", "application/json; charset=UTF-8"); |
| 123 url_fetcher_->SetExtraRequestHeaders(headers.ToString()); | 203 url_fetcher_->SetExtraRequestHeaders(headers.ToString()); |
| 124 url_fetcher_->SetUploadData("application/json", | 204 url_fetcher_->SetUploadData("application/json", request); |
| 125 base::StringPrintf(kRequestParameterFormat, | |
| 126 host_restricts.c_str(), | |
| 127 count)); | |
| 128 | |
| 129 // Fetchers are sometimes cancelled because a network change was detected. | 205 // Fetchers are sometimes cancelled because a network change was detected. |
| 130 url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); | 206 url_fetcher_->SetAutomaticallyRetryOnNetworkChanges(3); |
| 131 // Try to make fetching the files bit more robust even with poor connection. | 207 // Try to make fetching the files bit more robust even with poor connection. |
| 132 url_fetcher_->SetMaxRetriesOn5xx(3); | 208 url_fetcher_->SetMaxRetriesOn5xx(3); |
| 133 url_fetcher_->Start(); | 209 url_fetcher_->Start(); |
| 134 } | 210 } |
| 135 | 211 |
| 212 std::string NTPSnippetsFetcher::GetHostRestricts() const { | |
| 213 std::string host_restricts; | |
| 214 if (UseHostRestriction()) { | |
| 215 for (const std::string& host : hosts_) | |
| 216 host_restricts += base::StringPrintf(kHostRestrictFormat, host.c_str()); | |
| 217 } | |
| 218 return host_restricts; | |
| 219 } | |
| 220 | |
| 221 bool NTPSnippetsFetcher::UseHostRestriction() const { | |
| 222 return (variant_ == Variant::kRestricted || | |
| 223 variant_ == Variant::kRestrictedPersonalized) && | |
| 224 !base::CommandLine::ForCurrentProcess()->HasSwitch( | |
| 225 switches::kDontRestrict); | |
| 226 } | |
| 227 | |
| 228 bool NTPSnippetsFetcher::UseAuthentication() const { | |
| 229 return (variant_ == Variant::kPersonalized || | |
| 230 variant_ == Variant::kRestrictedPersonalized); | |
| 231 } | |
| 232 | |
| 233 void NTPSnippetsFetcher::FetchSnippetsNonAuthenticated() { | |
| 234 // When not providing OAuth token, we need to pass the Google API key. | |
| 235 const std::string& key = is_stable_channel_ | |
| 236 ? google_apis::GetAPIKey() | |
| 237 : google_apis::GetNonStableAPIKey(); | |
| 238 GURL url(base::StringPrintf(kSnippetsServerNonAuthorizedFormat, | |
| 239 kSnippetsServer, | |
| 240 key.c_str())); | |
| 241 | |
| 242 FetchSnippetsImpl(url, std::string(), | |
| 243 base::StringPrintf(kRequestParameterFormat, "", "", | |
| 244 GetHostRestricts().c_str(), | |
| 245 count_to_fetch_)); | |
| 246 } | |
| 247 | |
| 248 void NTPSnippetsFetcher::FetchSnippetsAuthenticated( | |
| 249 const std::string& account_id, | |
| 250 const std::string& oauth_access_token) { | |
| 251 std::string auth = base::StringPrintf(kGaiaIdFormat, account_id.c_str()); | |
| 252 std::string user_segment = | |
| 253 base::StringPrintf(kUserSegmentFormat, locale_.c_str()); | |
| 254 | |
| 255 FetchSnippetsImpl(GURL(kSnippetsServer), | |
| 256 base::StringPrintf(kAuthorizationRequestHeaderFormat, | |
| 257 oauth_access_token.c_str()), | |
| 258 base::StringPrintf(kRequestParameterFormat, | |
| 259 auth.c_str(), | |
| 260 user_segment.c_str(), | |
| 261 GetHostRestricts().c_str(), | |
| 262 count_to_fetch_)); | |
| 263 } | |
| 264 | |
| 265 void NTPSnippetsFetcher::StartTokenRequest() { | |
| 266 OAuth2TokenService::ScopeSet scopes; | |
| 267 scopes.insert(kApiScope); | |
| 268 oauth_request_ = token_service_->StartRequest( | |
| 269 signin_manager_->GetAuthenticatedAccountId(), scopes, this); | |
| 270 } | |
| 271 | |
| 272 //////////////////////////////////////////////////////////////////////////////// | |
| 273 // OAuth2TokenService::Consumer overrides | |
| 274 void NTPSnippetsFetcher::OnGetTokenSuccess( | |
| 275 const OAuth2TokenService::Request* request, | |
| 276 const std::string& access_token, | |
| 277 const base::Time& expiration_time) { | |
| 278 // delete after we leave this method | |
|
Marc Treib
2016/05/10 08:42:20
Full sentences in comments please ;P
jkrcal
2016/05/10 09:10:07
Done.
| |
| 279 std::unique_ptr<OAuth2TokenService::Request> oauth_request( | |
| 280 std::move(oauth_request_)); | |
| 281 DCHECK_EQ(oauth_request.get(), request) | |
| 282 << "Got tokens from some previous request"; | |
| 283 | |
| 284 FetchSnippetsAuthenticated(oauth_request->GetAccountId(), access_token); | |
| 285 } | |
| 286 | |
| 287 void NTPSnippetsFetcher::OnGetTokenFailure( | |
| 288 const OAuth2TokenService::Request* request, | |
| 289 const GoogleServiceAuthError& error) { | |
| 290 oauth_request_.reset(); | |
| 291 DLOG(ERROR) << "Unable to get token: " << error.ToString() | |
| 292 << " - fetching the snippets without authentication."; | |
| 293 | |
| 294 // Fallback to fetching non-authenticated tokens. | |
| 295 FetchSnippetsNonAuthenticated(); | |
| 296 } | |
| 297 | |
| 298 //////////////////////////////////////////////////////////////////////////////// | |
| 299 // OAuth2TokenService::Observer overrides | |
| 300 void NTPSnippetsFetcher::OnRefreshTokenAvailable( | |
| 301 const std::string& account_id) { | |
| 302 if (account_id == signin_manager_->GetAuthenticatedAccountId()) { | |
|
Marc Treib
2016/05/10 08:42:19
nitty nit: I prefer early-outing, i.e.
if (account
jkrcal
2016/05/10 09:10:07
Done.
| |
| 303 token_service_->RemoveObserver(this); | |
| 304 waiting_for_refresh_token_ = false; | |
| 305 StartTokenRequest(); | |
| 306 } | |
| 307 } | |
| 308 | |
| 136 //////////////////////////////////////////////////////////////////////////////// | 309 //////////////////////////////////////////////////////////////////////////////// |
| 137 // URLFetcherDelegate overrides | 310 // URLFetcherDelegate overrides |
| 138 void NTPSnippetsFetcher::OnURLFetchComplete(const URLFetcher* source) { | 311 void NTPSnippetsFetcher::OnURLFetchComplete(const URLFetcher* source) { |
| 139 DCHECK_EQ(url_fetcher_.get(), source); | 312 DCHECK_EQ(url_fetcher_.get(), source); |
| 140 | 313 |
| 141 std::string message; | 314 std::string message; |
| 142 const URLRequestStatus& status = source->GetStatus(); | 315 const URLRequestStatus& status = source->GetStatus(); |
| 143 | 316 |
| 144 UMA_HISTOGRAM_SPARSE_SLOWLY( | 317 UMA_HISTOGRAM_SPARSE_SLOWLY( |
| 145 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode", | 318 "NewTabPage.Snippets.FetchHttpResponseOrErrorCode", |
| 146 status.is_success() ? source->GetResponseCode() : status.error()); | 319 status.is_success() ? source->GetResponseCode() : status.error()); |
| 147 | 320 |
| 148 if (!status.is_success()) { | 321 if (!status.is_success()) { |
| 149 message = base::StringPrintf(kStatusMessageURLRequestErrorFormat, | 322 message = base::StringPrintf(kStatusMessageURLRequestErrorFormat, |
| 150 status.error()); | 323 status.error()); |
| 151 } else if (source->GetResponseCode() != net::HTTP_OK) { | 324 } else if (source->GetResponseCode() != net::HTTP_OK) { |
| 325 // TODO(jkrcal): https://crbug.com/609084 | |
| 326 // We need to deal with the edge case again where the auth | |
| 327 // token expires just before we send the request (in which case we need to | |
| 328 // fetch a new auth token). We should extract that into a common class | |
| 329 // instead of adding it to every single class that uses auth tokens. | |
| 152 message = base::StringPrintf(kStatusMessageHTTPErrorFormat, | 330 message = base::StringPrintf(kStatusMessageHTTPErrorFormat, |
| 153 source->GetResponseCode()); | 331 source->GetResponseCode()); |
| 154 } | 332 } |
| 155 | 333 |
| 156 if (!message.empty()) { | 334 if (!message.empty()) { |
| 335 std::string error_response; | |
| 336 source->GetResponseAsString(&error_response); | |
| 157 DLOG(WARNING) << message << " while trying to download " | 337 DLOG(WARNING) << message << " while trying to download " |
| 158 << source->GetURL().spec(); | 338 << source->GetURL().spec() << ": " << error_response; |
| 159 if (!snippets_available_callback_.is_null()) | 339 if (!snippets_available_callback_.is_null()) |
| 160 snippets_available_callback_.Run(NTPSnippet::PtrVector(), message); | 340 snippets_available_callback_.Run(NTPSnippet::PtrVector(), message); |
| 161 } else { | 341 } else { |
| 162 bool stores_result_to_string = source->GetResponseAsString( | 342 bool stores_result_to_string = source->GetResponseAsString( |
| 163 &last_fetch_json_); | 343 &last_fetch_json_); |
| 164 DCHECK(stores_result_to_string); | 344 DCHECK(stores_result_to_string); |
| 165 | 345 |
| 166 parse_json_callback_.Run( | 346 parse_json_callback_.Run( |
| 167 last_fetch_json_, | 347 last_fetch_json_, |
| 168 base::Bind(&NTPSnippetsFetcher::OnJsonParsed, | 348 base::Bind(&NTPSnippetsFetcher::OnJsonParsed, |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 194 LOG(WARNING) << "Received invalid JSON (" << error << "): " | 374 LOG(WARNING) << "Received invalid JSON (" << error << "): " |
| 195 << last_fetch_json_; | 375 << last_fetch_json_; |
| 196 if (!snippets_available_callback_.is_null()) { | 376 if (!snippets_available_callback_.is_null()) { |
| 197 snippets_available_callback_.Run( | 377 snippets_available_callback_.Run( |
| 198 NTPSnippet::PtrVector(), | 378 NTPSnippet::PtrVector(), |
| 199 base::StringPrintf(kStatusMessageJsonErrorFormat, error.c_str())); | 379 base::StringPrintf(kStatusMessageJsonErrorFormat, error.c_str())); |
| 200 } | 380 } |
| 201 } | 381 } |
| 202 | 382 |
| 203 } // namespace ntp_snippets | 383 } // namespace ntp_snippets |
| OLD | NEW |