| OLD | NEW |
| 1 // Copyright 2015 The Chromium Authors. All rights reserved. | 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 | 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/remote/remote_suggestion.h" | 5 #include "components/ntp_snippets/remote/remote_suggestion.h" |
| 6 | 6 |
| 7 #include "base/feature_list.h" | 7 #include "base/feature_list.h" |
| 8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/strings/string_number_conversions.h" | 9 #include "base/strings/string_number_conversions.h" |
| 10 #include "base/strings/stringprintf.h" | 10 #include "base/strings/stringprintf.h" |
| (...skipping 78 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 89 score_(0), | 89 score_(0), |
| 90 is_dismissed_(false), | 90 is_dismissed_(false), |
| 91 remote_category_id_(remote_category_id), | 91 remote_category_id_(remote_category_id), |
| 92 should_notify_(false) {} | 92 should_notify_(false) {} |
| 93 | 93 |
| 94 RemoteSuggestion::~RemoteSuggestion() = default; | 94 RemoteSuggestion::~RemoteSuggestion() = default; |
| 95 | 95 |
| 96 // static | 96 // static |
| 97 std::unique_ptr<RemoteSuggestion> | 97 std::unique_ptr<RemoteSuggestion> |
| 98 RemoteSuggestion::CreateFromChromeReaderDictionary( | 98 RemoteSuggestion::CreateFromChromeReaderDictionary( |
| 99 const base::DictionaryValue& dict) { | 99 const base::DictionaryValue& dict, |
| 100 const base::Time& fetch_date) { |
| 100 const base::DictionaryValue* content = nullptr; | 101 const base::DictionaryValue* content = nullptr; |
| 101 if (!dict.GetDictionary("contentInfo", &content)) { | 102 if (!dict.GetDictionary("contentInfo", &content)) { |
| 102 return nullptr; | 103 return nullptr; |
| 103 } | 104 } |
| 104 | 105 |
| 105 // Need at least a primary id. | 106 // Need at least a primary id. |
| 106 std::string primary_id; | 107 std::string primary_id; |
| 107 if (!content->GetString("url", &primary_id) || primary_id.empty()) { | 108 if (!content->GetString("url", &primary_id) || primary_id.empty()) { |
| 108 return nullptr; | 109 return nullptr; |
| 109 } | 110 } |
| (...skipping 50 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 160 // this for the primary ID). | 161 // this for the primary ID). |
| 161 ids.push_back(corpus_id_str); | 162 ids.push_back(corpus_id_str); |
| 162 } | 163 } |
| 163 if (sources.empty()) { | 164 if (sources.empty()) { |
| 164 DLOG(WARNING) << "No sources found for article " << primary_id; | 165 DLOG(WARNING) << "No sources found for article " << primary_id; |
| 165 return nullptr; | 166 return nullptr; |
| 166 } | 167 } |
| 167 | 168 |
| 168 std::unique_ptr<RemoteSuggestion> snippet( | 169 std::unique_ptr<RemoteSuggestion> snippet( |
| 169 new RemoteSuggestion(ids, kArticlesRemoteId)); | 170 new RemoteSuggestion(ids, kArticlesRemoteId)); |
| 171 snippet->fetch_date_ = fetch_date; |
| 170 | 172 |
| 171 std::string title; | 173 std::string title; |
| 172 if (content->GetString("title", &title)) { | 174 if (content->GetString("title", &title)) { |
| 173 snippet->title_ = title; | 175 snippet->title_ = title; |
| 174 } | 176 } |
| 175 std::string salient_image_url; | 177 std::string salient_image_url; |
| 176 if (content->GetString("thumbnailUrl", &salient_image_url)) { | 178 if (content->GetString("thumbnailUrl", &salient_image_url)) { |
| 177 snippet->salient_image_url_ = GURL(salient_image_url); | 179 snippet->salient_image_url_ = GURL(salient_image_url); |
| 178 } | 180 } |
| 179 std::string snippet_str; | 181 std::string snippet_str; |
| (...skipping 30 matching lines...) Expand all Loading... |
| 210 snippet->score_ = score; | 212 snippet->score_ = score; |
| 211 } | 213 } |
| 212 | 214 |
| 213 return snippet; | 215 return snippet; |
| 214 } | 216 } |
| 215 | 217 |
| 216 // static | 218 // static |
| 217 std::unique_ptr<RemoteSuggestion> | 219 std::unique_ptr<RemoteSuggestion> |
| 218 RemoteSuggestion::CreateFromContentSuggestionsDictionary( | 220 RemoteSuggestion::CreateFromContentSuggestionsDictionary( |
| 219 const base::DictionaryValue& dict, | 221 const base::DictionaryValue& dict, |
| 220 int remote_category_id) { | 222 int remote_category_id, |
| 223 const base::Time& fetch_date) { |
| 221 const base::ListValue* ids; | 224 const base::ListValue* ids; |
| 222 if (!dict.GetList("ids", &ids)) { | 225 if (!dict.GetList("ids", &ids)) { |
| 223 return nullptr; | 226 return nullptr; |
| 224 } | 227 } |
| 225 std::vector<std::string> parsed_ids; | 228 std::vector<std::string> parsed_ids; |
| 226 for (const auto& value : *ids) { | 229 for (const auto& value : *ids) { |
| 227 std::string id; | 230 std::string id; |
| 228 if (!value->GetAsString(&id)) { | 231 if (!value->GetAsString(&id)) { |
| 229 return nullptr; | 232 return nullptr; |
| 230 } | 233 } |
| 231 parsed_ids.push_back(id); | 234 parsed_ids.push_back(id); |
| 232 } | 235 } |
| 233 | 236 |
| 234 if (parsed_ids.empty()) { | 237 if (parsed_ids.empty()) { |
| 235 return nullptr; | 238 return nullptr; |
| 236 } | 239 } |
| 237 auto snippet = MakeUnique(parsed_ids, remote_category_id); | 240 auto snippet = MakeUnique(parsed_ids, remote_category_id); |
| 241 snippet->fetch_date_ = fetch_date; |
| 238 | 242 |
| 239 if (!(dict.GetString("title", &snippet->title_) && | 243 if (!(dict.GetString("title", &snippet->title_) && |
| 240 dict.GetString("snippet", &snippet->snippet_) && | 244 dict.GetString("snippet", &snippet->snippet_) && |
| 241 GetTimeValue(dict, "creationTime", &snippet->publish_date_) && | 245 GetTimeValue(dict, "creationTime", &snippet->publish_date_) && |
| 242 GetTimeValue(dict, "expirationTime", &snippet->expiry_date_) && | 246 GetTimeValue(dict, "expirationTime", &snippet->expiry_date_) && |
| 243 GetURLValue(dict, "imageUrl", &snippet->salient_image_url_) && | 247 GetURLValue(dict, "imageUrl", &snippet->salient_image_url_) && |
| 244 dict.GetString("attribution", &snippet->publisher_name_) && | 248 dict.GetString("attribution", &snippet->publisher_name_) && |
| 245 GetURLValue(dict, "fullPageUrl", &snippet->url_))) { | 249 GetURLValue(dict, "fullPageUrl", &snippet->url_))) { |
| 246 return nullptr; | 250 return nullptr; |
| 247 } | 251 } |
| (...skipping 26 matching lines...) Expand all Loading... |
| 274 // Need at least the id. | 278 // Need at least the id. |
| 275 if (proto.ids_size() == 0 || proto.ids(0).empty()) { | 279 if (proto.ids_size() == 0 || proto.ids(0).empty()) { |
| 276 return nullptr; | 280 return nullptr; |
| 277 } | 281 } |
| 278 | 282 |
| 279 int remote_category_id = proto.has_remote_category_id() | 283 int remote_category_id = proto.has_remote_category_id() |
| 280 ? proto.remote_category_id() | 284 ? proto.remote_category_id() |
| 281 : kArticlesRemoteId; | 285 : kArticlesRemoteId; |
| 282 | 286 |
| 283 std::vector<std::string> ids(proto.ids().begin(), proto.ids().end()); | 287 std::vector<std::string> ids(proto.ids().begin(), proto.ids().end()); |
| 288 |
| 284 auto snippet = MakeUnique(ids, remote_category_id); | 289 auto snippet = MakeUnique(ids, remote_category_id); |
| 285 | 290 |
| 286 snippet->title_ = proto.title(); | 291 snippet->title_ = proto.title(); |
| 287 snippet->snippet_ = proto.snippet(); | 292 snippet->snippet_ = proto.snippet(); |
| 288 snippet->salient_image_url_ = GURL(proto.salient_image_url()); | 293 snippet->salient_image_url_ = GURL(proto.salient_image_url()); |
| 289 snippet->publish_date_ = base::Time::FromInternalValue(proto.publish_date()); | 294 snippet->publish_date_ = base::Time::FromInternalValue(proto.publish_date()); |
| 290 snippet->expiry_date_ = base::Time::FromInternalValue(proto.expiry_date()); | 295 snippet->expiry_date_ = base::Time::FromInternalValue(proto.expiry_date()); |
| 291 snippet->score_ = proto.score(); | 296 snippet->score_ = proto.score(); |
| 292 snippet->is_dismissed_ = proto.dismissed(); | 297 snippet->is_dismissed_ = proto.dismissed(); |
| 293 | 298 |
| (...skipping 18 matching lines...) Expand all Loading... |
| 312 | 317 |
| 313 if (sources.empty()) { | 318 if (sources.empty()) { |
| 314 DLOG(WARNING) << "No sources found for article " << snippet->id(); | 319 DLOG(WARNING) << "No sources found for article " << snippet->id(); |
| 315 return nullptr; | 320 return nullptr; |
| 316 } | 321 } |
| 317 const SnippetSource& source = FindBestSource(sources); | 322 const SnippetSource& source = FindBestSource(sources); |
| 318 snippet->url_ = source.url; | 323 snippet->url_ = source.url; |
| 319 snippet->publisher_name_ = source.publisher_name; | 324 snippet->publisher_name_ = source.publisher_name; |
| 320 snippet->amp_url_ = source.amp_url; | 325 snippet->amp_url_ = source.amp_url; |
| 321 | 326 |
| 327 if (proto.has_fetch_date()) { |
| 328 snippet->fetch_date_ = base::Time::FromInternalValue(proto.fetch_date()); |
| 329 } |
| 330 |
| 322 return snippet; | 331 return snippet; |
| 323 } | 332 } |
| 324 | 333 |
| 325 // static | 334 // static |
| 326 std::unique_ptr<RemoteSuggestion> RemoteSuggestion::CreateForTesting( | 335 std::unique_ptr<RemoteSuggestion> RemoteSuggestion::CreateForTesting( |
| 327 const std::string& id, | 336 const std::string& id, |
| 328 int remote_category_id, | 337 int remote_category_id, |
| 329 const GURL& url, | 338 const GURL& url, |
| 330 const std::string& publisher_name, | 339 const std::string& publisher_name, |
| 331 const GURL& amp_url) { | 340 const GURL& amp_url) { |
| (...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 364 | 373 |
| 365 SnippetSourceProto* source_proto = result.add_sources(); | 374 SnippetSourceProto* source_proto = result.add_sources(); |
| 366 source_proto->set_url(url_.spec()); | 375 source_proto->set_url(url_.spec()); |
| 367 if (!publisher_name_.empty()) { | 376 if (!publisher_name_.empty()) { |
| 368 source_proto->set_publisher_name(publisher_name_); | 377 source_proto->set_publisher_name(publisher_name_); |
| 369 } | 378 } |
| 370 if (amp_url_.is_valid()) { | 379 if (amp_url_.is_valid()) { |
| 371 source_proto->set_amp_url(amp_url_.spec()); | 380 source_proto->set_amp_url(amp_url_.spec()); |
| 372 } | 381 } |
| 373 | 382 |
| 383 if (!fetch_date_.is_null()) { |
| 384 result.set_fetch_date(fetch_date_.ToInternalValue()); |
| 385 } |
| 374 return result; | 386 return result; |
| 375 } | 387 } |
| 376 | 388 |
| 377 ContentSuggestion RemoteSuggestion::ToContentSuggestion( | 389 ContentSuggestion RemoteSuggestion::ToContentSuggestion( |
| 378 Category category) const { | 390 Category category) const { |
| 379 GURL url = url_; | 391 GURL url = url_; |
| 380 if (base::FeatureList::IsEnabled(kPreferAmpUrlsFeature) && | 392 if (base::FeatureList::IsEnabled(kPreferAmpUrlsFeature) && |
| 381 !amp_url_.is_empty()) { | 393 !amp_url_.is_empty()) { |
| 382 url = amp_url_; | 394 url = amp_url_; |
| 383 } | 395 } |
| 384 ContentSuggestion suggestion(category, id(), url); | 396 ContentSuggestion suggestion(category, id(), url); |
| 385 suggestion.set_title(base::UTF8ToUTF16(title_)); | 397 suggestion.set_title(base::UTF8ToUTF16(title_)); |
| 386 suggestion.set_snippet_text(base::UTF8ToUTF16(snippet_)); | 398 suggestion.set_snippet_text(base::UTF8ToUTF16(snippet_)); |
| 387 suggestion.set_publish_date(publish_date_); | 399 suggestion.set_publish_date(publish_date_); |
| 388 suggestion.set_publisher_name(base::UTF8ToUTF16(publisher_name_)); | 400 suggestion.set_publisher_name(base::UTF8ToUTF16(publisher_name_)); |
| 389 suggestion.set_score(score_); | 401 suggestion.set_score(score_); |
| 390 if (should_notify_) { | 402 if (should_notify_) { |
| 391 NotificationExtra extra; | 403 NotificationExtra extra; |
| 392 extra.deadline = notification_deadline_; | 404 extra.deadline = notification_deadline_; |
| 393 suggestion.set_notification_extra( | 405 suggestion.set_notification_extra( |
| 394 base::MakeUnique<NotificationExtra>(extra)); | 406 base::MakeUnique<NotificationExtra>(extra)); |
| 395 } | 407 } |
| 408 suggestion.set_fetch_date(fetch_date_); |
| 396 return suggestion; | 409 return suggestion; |
| 397 } | 410 } |
| 398 | 411 |
| 399 // static | 412 // static |
| 400 base::Time RemoteSuggestion::TimeFromJsonString( | 413 base::Time RemoteSuggestion::TimeFromJsonString( |
| 401 const std::string& timestamp_str) { | 414 const std::string& timestamp_str) { |
| 402 int64_t timestamp; | 415 int64_t timestamp; |
| 403 if (!base::StringToInt64(timestamp_str, ×tamp)) { | 416 if (!base::StringToInt64(timestamp_str, ×tamp)) { |
| 404 // Even if there's an error in the conversion, some garbage data may still | 417 // Even if there's an error in the conversion, some garbage data may still |
| 405 // be written to the output var, so reset it. | 418 // be written to the output var, so reset it. |
| 406 DLOG(WARNING) << "Invalid json timestamp: " << timestamp_str; | 419 DLOG(WARNING) << "Invalid json timestamp: " << timestamp_str; |
| 407 timestamp = 0; | 420 timestamp = 0; |
| 408 } | 421 } |
| 409 return base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(timestamp); | 422 return base::Time::UnixEpoch() + base::TimeDelta::FromSeconds(timestamp); |
| 410 } | 423 } |
| 411 | 424 |
| 412 // static | 425 // static |
| 413 std::string RemoteSuggestion::TimeToJsonString(const base::Time& time) { | 426 std::string RemoteSuggestion::TimeToJsonString(const base::Time& time) { |
| 414 return base::Int64ToString((time - base::Time::UnixEpoch()).InSeconds()); | 427 return base::Int64ToString((time - base::Time::UnixEpoch()).InSeconds()); |
| 415 } | 428 } |
| 416 | 429 |
| 417 // static | 430 // static |
| 418 std::unique_ptr<RemoteSuggestion> RemoteSuggestion::MakeUnique( | 431 std::unique_ptr<RemoteSuggestion> RemoteSuggestion::MakeUnique( |
| 419 const std::vector<std::string>& ids, | 432 const std::vector<std::string>& ids, |
| 420 int remote_category_id) { | 433 int remote_category_id) { |
| 421 return base::WrapUnique(new RemoteSuggestion(ids, remote_category_id)); | 434 return base::WrapUnique(new RemoteSuggestion(ids, remote_category_id)); |
| 422 } | 435 } |
| 423 | 436 |
| 424 } // namespace ntp_snippets | 437 } // namespace ntp_snippets |
| OLD | NEW |