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 3 // found in the LICENSE file. 4 5 #include "components/ntp_snippets/remote/remote_suggestion_builder.h" 6 7 #include <limits> 8 #include <memory> 9 10 #include "base/strings/utf_string_conversions.h" 11 #include "base/time/time.h" 12 #include "components/ntp_snippets/remote/proto/ntp_snippets.pb.h" 13 #include "components/ntp_snippets/time_serialization.h" 14 #include "testing/gtest/include/gtest/gtest.h" 15 16 namespace ntp_snippets { 17 18 namespace test { 19 20 namespace { 21 GetDefaultSuggestionCreationTime()22base::Time GetDefaultSuggestionCreationTime() { 23 base::Time out_time; 24 EXPECT_TRUE(base::Time::FromUTCString("2000-01-01T00:00:01Z", &out_time)); 25 return out_time; 26 } 27 GetDefaultSuggestionExpirationTime()28base::Time GetDefaultSuggestionExpirationTime() { 29 base::Time out_time; 30 EXPECT_TRUE(base::Time::FromUTCString("2100-01-01T00:00:01Z", &out_time)); 31 return out_time; 32 } 33 34 } // namespace 35 36 RemoteSuggestionBuilder::RemoteSuggestionBuilder() = default; 37 RemoteSuggestionBuilder::RemoteSuggestionBuilder( 38 const RemoteSuggestionBuilder& other) = default; 39 RemoteSuggestionBuilder::~RemoteSuggestionBuilder() = default; 40 AddId(const std::string & id)41RemoteSuggestionBuilder& RemoteSuggestionBuilder::AddId(const std::string& id) { 42 if (!ids_) { 43 ids_ = std::vector<std::string>(); 44 } 45 ids_->push_back(id); 46 return *this; 47 } 48 SetTitle(const std::string & title)49RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetTitle( 50 const std::string& title) { 51 title_ = title; 52 return *this; 53 } 54 SetSnippet(const std::string & snippet)55RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetSnippet( 56 const std::string& snippet) { 57 snippet_ = snippet; 58 return *this; 59 } 60 SetImageUrl(const std::string & image_url)61RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetImageUrl( 62 const std::string& image_url) { 63 salient_image_url_ = image_url; 64 return *this; 65 } 66 SetPublishDate(const base::Time & publish_date)67RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetPublishDate( 68 const base::Time& publish_date) { 69 publish_date_ = publish_date; 70 return *this; 71 } 72 SetExpiryDate(const base::Time & expiry_date)73RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetExpiryDate( 74 const base::Time& expiry_date) { 75 expiry_date_ = expiry_date; 76 return *this; 77 } 78 SetScore(double score)79RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetScore(double score) { 80 score_ = score; 81 return *this; 82 } 83 SetIsDismissed(bool is_dismissed)84RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetIsDismissed( 85 bool is_dismissed) { 86 is_dismissed_ = is_dismissed; 87 return *this; 88 } 89 SetRemoteCategoryId(int remote_category_id)90RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetRemoteCategoryId( 91 int remote_category_id) { 92 remote_category_id_ = remote_category_id; 93 return *this; 94 } 95 SetUrl(const std::string & url)96RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetUrl( 97 const std::string& url) { 98 url_ = url; 99 return *this; 100 } 101 SetPublisher(const std::string & publisher)102RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetPublisher( 103 const std::string& publisher) { 104 publisher_name_ = publisher; 105 return *this; 106 } 107 SetAmpUrl(const std::string & amp_url)108RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetAmpUrl( 109 const std::string& amp_url) { 110 amp_url_ = amp_url; 111 return *this; 112 } 113 SetFetchDate(const base::Time & fetch_date)114RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetFetchDate( 115 const base::Time& fetch_date) { 116 fetch_date_ = fetch_date; 117 return *this; 118 } 119 SetRank(int rank)120RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetRank(int rank) { 121 rank_ = rank; 122 return *this; 123 } 124 SetShouldNotify(bool should_notify)125RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetShouldNotify( 126 bool should_notify) { 127 should_notify_ = should_notify; 128 return *this; 129 } 130 SetNotificationDeadline(const base::Time & notification_deadline)131RemoteSuggestionBuilder& RemoteSuggestionBuilder::SetNotificationDeadline( 132 const base::Time& notification_deadline) { 133 notification_deadline_ = notification_deadline; 134 return *this; 135 } 136 Build() const137std::unique_ptr<RemoteSuggestion> RemoteSuggestionBuilder::Build() const { 138 SnippetProto proto; 139 proto.set_title(title_.value_or("Title")); 140 proto.set_snippet(snippet_.value_or("Snippet")); 141 proto.set_salient_image_url( 142 salient_image_url_.value_or("http://image_url.com/")); 143 proto.set_publish_date(SerializeTime( 144 publish_date_.value_or(GetDefaultSuggestionCreationTime()))); 145 proto.set_expiry_date(SerializeTime( 146 expiry_date_.value_or(GetDefaultSuggestionExpirationTime()))); 147 proto.set_score(score_.value_or(1)); 148 proto.set_dismissed(is_dismissed_.value_or(false)); 149 proto.set_remote_category_id(remote_category_id_.value_or(1)); 150 auto* source = proto.mutable_source(); 151 source->set_url(url_.value_or("http://url.com/")); 152 source->set_publisher_name(publisher_name_.value_or("Publisher")); 153 source->set_amp_url(amp_url_.value_or("http://amp_url.com/")); 154 proto.set_fetch_date(SerializeTime(fetch_date_.value_or(base::Time::Now()))); 155 for (const auto& id : 156 ids_.value_or(std::vector<std::string>{source->url()})) { 157 proto.add_ids(id); 158 } 159 proto.set_rank(rank_.value_or(std::numeric_limits<int>::max())); 160 std::unique_ptr<RemoteSuggestion> suggestion = 161 RemoteSuggestion::CreateFromProto(proto); 162 suggestion->set_should_notify(should_notify_.value_or(false)); 163 suggestion->set_notification_deadline( 164 notification_deadline_.value_or(base::Time())); 165 return suggestion; 166 } 167 168 FetchedCategoryBuilder::FetchedCategoryBuilder() = default; 169 FetchedCategoryBuilder::FetchedCategoryBuilder( 170 const FetchedCategoryBuilder& other) = default; 171 FetchedCategoryBuilder::~FetchedCategoryBuilder() = default; 172 SetCategory(Category category)173FetchedCategoryBuilder& FetchedCategoryBuilder::SetCategory(Category category) { 174 category_ = category; 175 return *this; 176 } 177 SetTitle(const std::string & title)178FetchedCategoryBuilder& FetchedCategoryBuilder::SetTitle( 179 const std::string& title) { 180 title_ = base::UTF8ToUTF16(title); 181 return *this; 182 } 183 SetCardLayout(ContentSuggestionsCardLayout card_layout)184FetchedCategoryBuilder& FetchedCategoryBuilder::SetCardLayout( 185 ContentSuggestionsCardLayout card_layout) { 186 card_layout_ = card_layout; 187 return *this; 188 } 189 SetAdditionalAction(ContentSuggestionsAdditionalAction additional_action)190FetchedCategoryBuilder& FetchedCategoryBuilder::SetAdditionalAction( 191 ContentSuggestionsAdditionalAction additional_action) { 192 additional_action_ = additional_action; 193 return *this; 194 } 195 SetShowIfEmpty(bool show_if_empty)196FetchedCategoryBuilder& FetchedCategoryBuilder::SetShowIfEmpty( 197 bool show_if_empty) { 198 show_if_empty_ = show_if_empty; 199 return *this; 200 } 201 SetNoSuggestionsMessage(const std::string & no_suggestions_message)202FetchedCategoryBuilder& FetchedCategoryBuilder::SetNoSuggestionsMessage( 203 const std::string& no_suggestions_message) { 204 no_suggestions_message_ = base::UTF8ToUTF16(no_suggestions_message); 205 return *this; 206 } 207 AddSuggestionViaBuilder(const RemoteSuggestionBuilder & builder)208FetchedCategoryBuilder& FetchedCategoryBuilder::AddSuggestionViaBuilder( 209 const RemoteSuggestionBuilder& builder) { 210 if (!suggestion_builders_) { 211 suggestion_builders_ = std::vector<RemoteSuggestionBuilder>(); 212 } 213 suggestion_builders_->push_back(builder); 214 return *this; 215 } 216 Build() const217FetchedCategory FetchedCategoryBuilder::Build() const { 218 FetchedCategory result = FetchedCategory( 219 category_.value_or(Category::FromRemoteCategory(1)), 220 CategoryInfo( 221 title_.value_or(base::UTF8ToUTF16("Category title")), 222 card_layout_.value_or(ContentSuggestionsCardLayout::FULL_CARD), 223 additional_action_.value_or( 224 ContentSuggestionsAdditionalAction::FETCH), 225 show_if_empty_.value_or(false), 226 no_suggestions_message_.value_or( 227 base::UTF8ToUTF16("No suggestions message")))); 228 229 if (suggestion_builders_) { 230 for (const auto& suggestion_builder : *suggestion_builders_) 231 result.suggestions.push_back(suggestion_builder.Build()); 232 } 233 return result; 234 } 235 236 } // namespace test 237 238 } // namespace ntp_snippets 239