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 #ifndef COMPONENTS_NTP_SNIPPETS_CATEGORY_RANKERS_CLICK_BASED_CATEGORY_RANKER_H_ 6 #define COMPONENTS_NTP_SNIPPETS_CATEGORY_RANKERS_CLICK_BASED_CATEGORY_RANKER_H_ 7 8 #include <memory> 9 #include <vector> 10 11 #include "base/time/clock.h" 12 #include "base/time/time.h" 13 #include "components/ntp_snippets/category.h" 14 #include "components/ntp_snippets/category_rankers/category_ranker.h" 15 16 class PrefRegistrySimple; 17 class PrefService; 18 19 namespace ntp_snippets { 20 21 // An implementation of a CategoryRanker based on a number of clicks per 22 // category. Initial order is hardcoded, but sections with more clicks are moved 23 // to the top. The new remote categories must be registered using 24 // AppendCategoryIfNecessary. All other categories must be hardcoded in the 25 // initial order. The order and category usage data are persisted in prefs and 26 // reloaded on startup. 27 // TODO(crbug.com/675929): Remove unused categories from prefs. 28 class ClickBasedCategoryRanker : public CategoryRanker { 29 public: 30 explicit ClickBasedCategoryRanker(PrefService* pref_service, 31 base::Clock* clock); 32 ~ClickBasedCategoryRanker() override; 33 34 // CategoryRanker implementation. 35 bool Compare(Category left, Category right) const override; 36 void ClearHistory(base::Time begin, base::Time end) override; 37 void AppendCategoryIfNecessary(Category category) override; 38 void InsertCategoryBeforeIfNecessary(Category category_to_insert, 39 Category anchor) override; 40 void InsertCategoryAfterIfNecessary(Category category_to_insert, 41 Category anchor) override; 42 std::vector<CategoryRanker::DebugDataItem> GetDebugData() override; 43 void OnSuggestionOpened(Category category) override; 44 void OnCategoryDismissed(Category category) override; 45 46 // Returns time when last decay occured. For testing only. 47 base::Time GetLastDecayTime() const; 48 49 static void RegisterProfilePrefs(PrefRegistrySimple* registry); 50 51 // Returns passing margin, i.e. a number of extra clicks required to move a 52 // category upwards. For testing only. 53 static int GetPassingMargin(); 54 55 // Returns number of top categories with extra margin (i.e. with increased 56 // passing margin). For testing only. 57 static int GetNumTopCategoriesWithExtraMargin(); 58 59 // Returns number of positions by which a dismissed category is downgraded. 60 // For testing only. 61 static int GetDismissedCategoryPenalty(); 62 63 private: 64 struct RankedCategory { 65 Category category; 66 int clicks; 67 base::Time last_dismissed; 68 69 RankedCategory(Category category, 70 int clicks, 71 const base::Time& last_dismissed); 72 }; 73 74 int GetPositionPassingMargin( 75 std::vector<RankedCategory>::const_iterator category_position) const; 76 void RestoreDefaultOrder(); 77 void AppendKnownCategory(KnownCategories known_category); 78 bool ReadOrderFromPrefs(std::vector<RankedCategory>* result_categories) const; 79 void StoreOrderToPrefs(const std::vector<RankedCategory>& ordered_categories); 80 std::vector<RankedCategory>::iterator FindCategory(Category category); 81 bool ContainsCategory(Category category) const; 82 void InsertCategoryRelativeToIfNecessary(Category category_to_insert, 83 Category anchor, 84 bool after); 85 86 base::Time ReadLastDecayTimeFromPrefs() const; 87 void StoreLastDecayTimeToPrefs(base::Time last_decay_time); 88 bool IsEnoughClicksToDecay() const; 89 bool DecayClicksIfNeeded(); 90 91 std::vector<RankedCategory> ordered_categories_; 92 PrefService* pref_service_; 93 base::Clock* clock_; 94 95 DISALLOW_COPY_AND_ASSIGN(ClickBasedCategoryRanker); 96 }; 97 98 } // namespace ntp_snippets 99 100 #endif // COMPONENTS_NTP_SNIPPETS_CATEGORY_RANKERS_CLICK_BASED_CATEGORY_RANKER_H_ 101