Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 #import "ios/chrome/browser/content_suggestions/content_suggestions_mediator.h" | 5 #import "ios/chrome/browser/content_suggestions/content_suggestions_mediator.h" |
| 6 | 6 |
| 7 #include "base/mac/bind_objc_block.h" | 7 #include "base/mac/bind_objc_block.h" |
| 8 #include "base/memory/ptr_util.h" | 8 #include "base/memory/ptr_util.h" |
| 9 #include "base/optional.h" | 9 #include "base/optional.h" |
| 10 #include "base/strings/sys_string_conversions.h" | 10 #include "base/strings/sys_string_conversions.h" |
| 11 #include "components/ntp_snippets/category.h" | 11 #include "components/ntp_snippets/category.h" |
| 12 #include "components/ntp_snippets/content_suggestion.h" | 12 #include "components/ntp_snippets/content_suggestion.h" |
| 13 #import "ios/chrome/browser/content_suggestions/content_suggestions_category_wra pper.h" | 13 #import "ios/chrome/browser/content_suggestions/content_suggestions_category_wra pper.h" |
| 14 #import "ios/chrome/browser/content_suggestions/content_suggestions_service_brid ge_observer.h" | 14 #import "ios/chrome/browser/content_suggestions/content_suggestions_service_brid ge_observer.h" |
| 15 #import "ios/chrome/browser/ui/content_suggestions/content_suggestion.h" | 15 #import "ios/chrome/browser/ui/content_suggestions/content_suggestion.h" |
| 16 #import "ios/chrome/browser/ui/content_suggestions/content_suggestion_identifier .h" | 16 #import "ios/chrome/browser/ui/content_suggestions/content_suggestion_identifier .h" |
| 17 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_data_sink .h" | 17 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_data_sink .h" |
| 18 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_image_fet cher.h" | 18 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_image_fet cher.h" |
| 19 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_section_i nformation.h" | 19 #import "ios/chrome/browser/ui/content_suggestions/content_suggestions_section_i nformation.h" |
| 20 #include "ui/gfx/image/image.h" | 20 #include "ui/gfx/image/image.h" |
| 21 | 21 |
| 22 #if !defined(__has_feature) || !__has_feature(objc_arc) | 22 #if !defined(__has_feature) || !__has_feature(objc_arc) |
| 23 #error "This file requires ARC support." | 23 #error "This file requires ARC support." |
| 24 #endif | 24 #endif |
| 25 | 25 |
| 26 namespace { | 26 namespace { |
| 27 | 27 |
| 28 // TODO(crbug.com/701275):Once base::BindBlock supports the move semantics, | |
|
lpromero
2017/03/14 16:33:08
Add a space after the colon.
gambard
2017/03/15 09:53:36
Done.
| |
| 29 // remove this wrapper. | |
| 30 // Wraps a callback taking a const ref to a callback taking an object. | |
| 31 void BindWrapper( | |
| 32 base::Callback<void(ntp_snippets::Status status_code, | |
| 33 const std::vector<ntp_snippets::ContentSuggestion>& | |
| 34 suggestions)> callback, | |
| 35 ntp_snippets::Status status_code, | |
| 36 std::vector<ntp_snippets::ContentSuggestion> suggestions) { | |
| 37 if (callback) { | |
| 38 callback.Run(status_code, suggestions); | |
| 39 } | |
| 40 } | |
| 41 | |
| 28 // Returns the Type for this |category|. | 42 // Returns the Type for this |category|. |
| 29 ContentSuggestionType TypeForCategory(ntp_snippets::Category category) { | 43 ContentSuggestionType TypeForCategory(ntp_snippets::Category category) { |
| 30 // For now, only Article is a relevant type. | 44 // For now, only Article is a relevant type. |
| 31 return ContentSuggestionTypeArticle; | 45 return ContentSuggestionTypeArticle; |
| 32 } | 46 } |
| 33 | 47 |
| 34 // Returns the section ID for this |category|. | 48 // Returns the section ID for this |category|. |
| 35 ContentSuggestionsSectionID SectionIDForCategory( | 49 ContentSuggestionsSectionID SectionIDForCategory( |
| 36 ntp_snippets::Category category) { | 50 ntp_snippets::Category category) { |
| 37 if (category.IsKnownCategory(ntp_snippets::KnownCategories::BOOKMARKS)) | 51 if (category.IsKnownCategory(ntp_snippets::KnownCategories::BOOKMARKS)) |
| (...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 105 std::unique_ptr<ContentSuggestionsServiceBridge> _suggestionBridge; | 119 std::unique_ptr<ContentSuggestionsServiceBridge> _suggestionBridge; |
| 106 } | 120 } |
| 107 | 121 |
| 108 @property(nonatomic, assign) | 122 @property(nonatomic, assign) |
| 109 ntp_snippets::ContentSuggestionsService* contentService; | 123 ntp_snippets::ContentSuggestionsService* contentService; |
| 110 @property(nonatomic, strong, nonnull) | 124 @property(nonatomic, strong, nonnull) |
| 111 NSMutableDictionary<ContentSuggestionsCategoryWrapper*, | 125 NSMutableDictionary<ContentSuggestionsCategoryWrapper*, |
| 112 ContentSuggestionsSectionInformation*>* | 126 ContentSuggestionsSectionInformation*>* |
| 113 sectionInformationByCategory; | 127 sectionInformationByCategory; |
| 114 | 128 |
| 115 // Converts the data in |category| to ContentSuggestion and adds them to the | 129 // Converts the |suggestions| from |category| to ContentSuggestion and adds them |
| 116 // |contentArray|. | 130 // to the |contentArray|. |
| 117 - (void)addContentInCategory:(ntp_snippets::Category&)category | 131 - (void)addSuggestions: |
| 118 toArray:(NSMutableArray<ContentSuggestion*>*)contentArray; | 132 (const std::vector<ntp_snippets::ContentSuggestion>&)suggestions |
| 133 fromCategory:(ntp_snippets::Category&)category | |
| 134 toArray:(NSMutableArray<ContentSuggestion*>*)contentArray; | |
| 119 | 135 |
| 120 // Adds the section information for |category| in | 136 // Adds the section information for |category| in |
| 121 // self.sectionInformationByCategory. | 137 // self.sectionInformationByCategory. |
| 122 - (void)addSectionInformationForCategory:(ntp_snippets::Category)category; | 138 - (void)addSectionInformationForCategory:(ntp_snippets::Category)category; |
| 123 | 139 |
| 124 // Returns a CategoryWrapper acting as a key for this section info. | 140 // Returns a CategoryWrapper acting as a key for this section info. |
| 125 - (ContentSuggestionsCategoryWrapper*)categoryWrapperForSectionInfo: | 141 - (ContentSuggestionsCategoryWrapper*)categoryWrapperForSectionInfo: |
| 126 (ContentSuggestionsSectionInformation*)sectionInfo; | 142 (ContentSuggestionsSectionInformation*)sectionInfo; |
| 127 | 143 |
| 128 @end | 144 @end |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 165 NSMutableArray<ContentSuggestion*>* dataHolders = [NSMutableArray array]; | 181 NSMutableArray<ContentSuggestion*>* dataHolders = [NSMutableArray array]; |
| 166 for (auto& category : categories) { | 182 for (auto& category : categories) { |
| 167 if (self.contentService->GetCategoryStatus(category) != | 183 if (self.contentService->GetCategoryStatus(category) != |
| 168 ntp_snippets::CategoryStatus::AVAILABLE) { | 184 ntp_snippets::CategoryStatus::AVAILABLE) { |
| 169 continue; | 185 continue; |
| 170 } | 186 } |
| 171 if (!self.sectionInformationByCategory[ | 187 if (!self.sectionInformationByCategory[ |
| 172 [ContentSuggestionsCategoryWrapper wrapperWithCategory:category]]) { | 188 [ContentSuggestionsCategoryWrapper wrapperWithCategory:category]]) { |
| 173 [self addSectionInformationForCategory:category]; | 189 [self addSectionInformationForCategory:category]; |
| 174 } | 190 } |
| 175 [self addContentInCategory:category toArray:dataHolders]; | 191 const std::vector<ntp_snippets::ContentSuggestion>& suggestions = |
| 192 self.contentService->GetSuggestionsForCategory(category); | |
| 193 [self addSuggestions:suggestions fromCategory:category toArray:dataHolders]; | |
| 176 } | 194 } |
| 177 return dataHolders; | 195 return dataHolders; |
| 178 } | 196 } |
| 179 | 197 |
| 180 - (id<ContentSuggestionsImageFetcher>)imageFetcher { | 198 - (id<ContentSuggestionsImageFetcher>)imageFetcher { |
| 181 return self; | 199 return self; |
| 182 } | 200 } |
| 183 | 201 |
| 202 - (void)fetchMoreSuggestionsKnowing: | |
| 203 (NSArray<ContentSuggestionIdentifier*>*)knownSuggestions | |
| 204 fromSectionInfo: | |
| 205 (ContentSuggestionsSectionInformation*)sectionInfo | |
| 206 callback:(MoreSuggestionsFetched)callback { | |
| 207 std::set<std::string> known_suggestion_ids; | |
| 208 for (ContentSuggestionIdentifier* identifier in knownSuggestions) { | |
| 209 if (identifier.sectionInfo != sectionInfo) | |
| 210 continue; | |
| 211 known_suggestion_ids.insert(identifier.IDInSection); | |
| 212 } | |
| 213 | |
| 214 ContentSuggestionsCategoryWrapper* wrapper = | |
| 215 [self categoryWrapperForSectionInfo:sectionInfo]; | |
| 216 | |
| 217 __weak ContentSuggestionsMediator* weakSelf = self; | |
| 218 ntp_snippets::FetchDoneCallback serviceCallback = base::Bind( | |
| 219 &BindWrapper, | |
| 220 base::BindBlockArc(^void( | |
| 221 ntp_snippets::Status status, | |
| 222 const std::vector<ntp_snippets::ContentSuggestion>& suggestions) { | |
| 223 [weakSelf didFetchMoreSuggestions:suggestions | |
| 224 withStatusCode:status | |
| 225 callback:callback]; | |
| 226 })); | |
| 227 | |
| 228 self.contentService->Fetch([wrapper category], known_suggestion_ids, | |
| 229 serviceCallback); | |
| 230 } | |
| 231 | |
| 184 #pragma mark - ContentSuggestionsServiceObserver | 232 #pragma mark - ContentSuggestionsServiceObserver |
| 185 | 233 |
| 186 - (void)contentSuggestionsService: | 234 - (void)contentSuggestionsService: |
| 187 (ntp_snippets::ContentSuggestionsService*)suggestionsService | 235 (ntp_snippets::ContentSuggestionsService*)suggestionsService |
| 188 newSuggestionsInCategory:(ntp_snippets::Category)category { | 236 newSuggestionsInCategory:(ntp_snippets::Category)category { |
| 189 [self.dataSink dataAvailable]; | 237 [self.dataSink dataAvailable]; |
| 190 } | 238 } |
| 191 | 239 |
| 192 - (void)contentSuggestionsService: | 240 - (void)contentSuggestionsService: |
| 193 (ntp_snippets::ContentSuggestionsService*)suggestionsService | 241 (ntp_snippets::ContentSuggestionsService*)suggestionsService |
| (...skipping 34 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 228 callback:(void (^)(const gfx::Image&))callback { | 276 callback:(void (^)(const gfx::Image&))callback { |
| 229 self.contentService->FetchSuggestionImage( | 277 self.contentService->FetchSuggestionImage( |
| 230 SuggestionIDForSectionID( | 278 SuggestionIDForSectionID( |
| 231 [self categoryWrapperForSectionInfo:suggestionIdentifier.sectionInfo], | 279 [self categoryWrapperForSectionInfo:suggestionIdentifier.sectionInfo], |
| 232 suggestionIdentifier.IDInSection), | 280 suggestionIdentifier.IDInSection), |
| 233 base::BindBlockArc(callback)); | 281 base::BindBlockArc(callback)); |
| 234 } | 282 } |
| 235 | 283 |
| 236 #pragma mark - Private | 284 #pragma mark - Private |
| 237 | 285 |
| 238 - (void)addContentInCategory:(ntp_snippets::Category&)category | 286 - (void)addSuggestions: |
| 239 toArray:(NSMutableArray<ContentSuggestion*>*)contentArray { | 287 (const std::vector<ntp_snippets::ContentSuggestion>&)suggestions |
| 240 const std::vector<ntp_snippets::ContentSuggestion>& suggestions = | 288 fromCategory:(ntp_snippets::Category&)category |
| 241 self.contentService->GetSuggestionsForCategory(category); | 289 toArray:(NSMutableArray<ContentSuggestion*>*)contentArray { |
| 242 ContentSuggestionsCategoryWrapper* categoryWrapper = | 290 ContentSuggestionsCategoryWrapper* categoryWrapper = |
| 243 [[ContentSuggestionsCategoryWrapper alloc] initWithCategory:category]; | 291 [[ContentSuggestionsCategoryWrapper alloc] initWithCategory:category]; |
| 244 for (auto& contentSuggestion : suggestions) { | 292 for (auto& contentSuggestion : suggestions) { |
| 245 ContentSuggestion* suggestion = ConvertContentSuggestion(contentSuggestion); | 293 ContentSuggestion* suggestion = ConvertContentSuggestion(contentSuggestion); |
| 246 suggestion.type = TypeForCategory(category); | 294 suggestion.type = TypeForCategory(category); |
| 295 | |
| 247 suggestion.suggestionIdentifier.sectionInfo = | 296 suggestion.suggestionIdentifier.sectionInfo = |
| 248 self.sectionInformationByCategory[categoryWrapper]; | 297 self.sectionInformationByCategory[categoryWrapper]; |
| 249 | 298 |
| 250 [contentArray addObject:suggestion]; | 299 [contentArray addObject:suggestion]; |
| 251 } | 300 } |
| 252 } | 301 } |
| 253 | 302 |
| 254 - (void)addSectionInformationForCategory:(ntp_snippets::Category)category { | 303 - (void)addSectionInformationForCategory:(ntp_snippets::Category)category { |
| 255 base::Optional<ntp_snippets::CategoryInfo> categoryInfo = | 304 base::Optional<ntp_snippets::CategoryInfo> categoryInfo = |
| 256 self.contentService->GetCategoryInfo(category); | 305 self.contentService->GetCategoryInfo(category); |
| 257 | 306 |
| 258 ContentSuggestionsSectionInformation* sectionInfo = | 307 ContentSuggestionsSectionInformation* sectionInfo = |
| 259 SectionInformationFromCategoryInfo(categoryInfo, category); | 308 SectionInformationFromCategoryInfo(categoryInfo, category); |
| 260 | 309 |
| 261 self.sectionInformationByCategory[[ContentSuggestionsCategoryWrapper | 310 self.sectionInformationByCategory[[ContentSuggestionsCategoryWrapper |
| 262 wrapperWithCategory:category]] = sectionInfo; | 311 wrapperWithCategory:category]] = sectionInfo; |
| 263 } | 312 } |
| 264 | 313 |
| 265 - (ContentSuggestionsCategoryWrapper*)categoryWrapperForSectionInfo: | 314 - (ContentSuggestionsCategoryWrapper*)categoryWrapperForSectionInfo: |
| 266 (ContentSuggestionsSectionInformation*)sectionInfo { | 315 (ContentSuggestionsSectionInformation*)sectionInfo { |
| 267 return [[self.sectionInformationByCategory allKeysForObject:sectionInfo] | 316 return [[self.sectionInformationByCategory allKeysForObject:sectionInfo] |
| 268 firstObject]; | 317 firstObject]; |
| 269 } | 318 } |
| 270 | 319 |
| 320 // If the |statusCode| is a success and |suggestions| is not empty, runs the | |
| 321 // |callback| with the |suggestions| converted to Objective-C. | |
| 322 - (void)didFetchMoreSuggestions: | |
| 323 (const std::vector<ntp_snippets::ContentSuggestion>&)suggestions | |
| 324 withStatusCode:(ntp_snippets::Status)statusCode | |
| 325 callback:(MoreSuggestionsFetched)callback { | |
| 326 if (statusCode.IsSuccess() && !suggestions.empty() && callback) { | |
| 327 NSMutableArray<ContentSuggestion*>* contentSuggestions = | |
| 328 [NSMutableArray array]; | |
| 329 ntp_snippets::Category category = suggestions[0].id().category(); | |
| 330 [self addSuggestions:suggestions | |
| 331 fromCategory:category | |
| 332 toArray:contentSuggestions]; | |
| 333 callback(contentSuggestions); | |
| 334 } | |
| 335 } | |
| 336 | |
| 271 @end | 337 @end |
| OLD | NEW |