Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(51)

Side by Side Diff: chrome/android/java/src/org/chromium/chrome/browser/ntp/cards/SectionList.java

Issue 2618893003: 📰 Tweak the suggestion ranks for UMA to handle fetchMore (Closed)
Patch Set: Fix action item reported position Created 3 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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 package org.chromium.chrome.browser.ntp.cards; 5 package org.chromium.chrome.browser.ntp.cards;
6 6
7 import org.chromium.base.Log; 7 import org.chromium.base.Log;
8 import org.chromium.base.VisibleForTesting; 8 import org.chromium.base.VisibleForTesting;
9 import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager; 9 import org.chromium.chrome.browser.ntp.NewTabPageView.NewTabPageManager;
10 import org.chromium.chrome.browser.ntp.snippets.CategoryInt; 10 import org.chromium.chrome.browser.ntp.snippets.CategoryInt;
(...skipping 14 matching lines...) Expand all
25 * suggestions source and updates the corresponding sections. 25 * suggestions source and updates the corresponding sections.
26 */ 26 */
27 public class SectionList 27 public class SectionList
28 extends InnerNode implements SuggestionsSource.Observer, SuggestionsSect ion.Delegate { 28 extends InnerNode implements SuggestionsSource.Observer, SuggestionsSect ion.Delegate {
29 private static final String TAG = "Ntp"; 29 private static final String TAG = "Ntp";
30 30
31 /** Maps suggestion categories to sections, with stable iteration ordering. */ 31 /** Maps suggestion categories to sections, with stable iteration ordering. */
32 private final Map<Integer, SuggestionsSection> mSections = new LinkedHashMap <>(); 32 private final Map<Integer, SuggestionsSection> mSections = new LinkedHashMap <>();
33 private final NewTabPageManager mNewTabPageManager; 33 private final NewTabPageManager mNewTabPageManager;
34 private final OfflinePageBridge mOfflinePageBridge; 34 private final OfflinePageBridge mOfflinePageBridge;
35 private final SuggestionRanker mSuggestionRanker;
35 36
36 public SectionList(NewTabPageManager newTabPageManager, OfflinePageBridge of flinePageBridge) { 37 public SectionList(NewTabPageManager newTabPageManager, OfflinePageBridge of flinePageBridge) {
38 mSuggestionRanker = new SuggestionRanker();
37 mNewTabPageManager = newTabPageManager; 39 mNewTabPageManager = newTabPageManager;
38 mNewTabPageManager.getSuggestionsSource().setObserver(this); 40 mNewTabPageManager.getSuggestionsSource().setObserver(this);
39 mOfflinePageBridge = offlinePageBridge; 41 mOfflinePageBridge = offlinePageBridge;
40 resetSections(/* alwaysAllowEmptySections = */ false); 42 resetSections(/* alwaysAllowEmptySections = */ false);
41 } 43 }
42 44
43 /** 45 /**
44 * Resets the sections, reloading the whole new tab page content. 46 * Resets the sections, reloading the whole new tab page content.
45 * @param alwaysAllowEmptySections Whether sections are always allowed to be displayed when 47 * @param alwaysAllowEmptySections Whether sections are always allowed to be displayed when
46 * they are empty, even when they are normally not. 48 * they are empty, even when they are normally not.
47 */ 49 */
48 public void resetSections(boolean alwaysAllowEmptySections) { 50 public void resetSections(boolean alwaysAllowEmptySections) {
49 removeAllSections(); 51 removeAllSections();
50 52
51 SuggestionsSource suggestionsSource = mNewTabPageManager.getSuggestionsS ource(); 53 SuggestionsSource suggestionsSource = mNewTabPageManager.getSuggestionsS ource();
52 int[] categories = suggestionsSource.getCategories(); 54 int[] categories = suggestionsSource.getCategories();
53 int[] suggestionsPerCategory = new int[categories.length]; 55 int[] suggestionsPerCategory = new int[categories.length];
54 int i = 0; 56 int i = 0;
55 for (int category : categories) { 57 for (int category : categories) {
56 int categoryStatus = suggestionsSource.getCategoryStatus(category); 58 int categoryStatus = suggestionsSource.getCategoryStatus(category);
57 if (categoryStatus == CategoryStatus.LOADING_ERROR 59 if (categoryStatus == CategoryStatus.LOADING_ERROR
58 || categoryStatus == CategoryStatus.NOT_PROVIDED 60 || categoryStatus == CategoryStatus.NOT_PROVIDED
59 || categoryStatus == CategoryStatus.CATEGORY_EXPLICITLY_DISA BLED) 61 || categoryStatus == CategoryStatus.CATEGORY_EXPLICITLY_DISA BLED)
60 continue; 62 continue;
61 63
62 suggestionsPerCategory[i++] = 64 suggestionsPerCategory[i++] =
63 resetSection(category, categoryStatus, alwaysAllowEmptySecti ons); 65 resetSection(category, categoryStatus, alwaysAllowEmptySecti ons);
64 } 66 }
65 67
66 mNewTabPageManager.trackSnippetsPageImpression(categories, suggestionsPe rCategory); 68 mNewTabPageManager.getSuggestionsMetricsReporter().onPageShown(
69 categories, suggestionsPerCategory);
67 } 70 }
68 71
69 /** 72 /**
70 * Resets the section for {@code category}. Removes the section if there are no suggestions for 73 * Resets the section for {@code category}. Removes the section if there are no suggestions for
71 * it and it is not allowed to be empty. Otherwise, creates the section if i t is not present 74 * it and it is not allowed to be empty. Otherwise, creates the section if i t is not present
72 * yet. Sets the available suggestions on the section. 75 * yet. Sets the available suggestions on the section.
73 * @param category The category for which the section must be reset. 76 * @param category The category for which the section must be reset.
74 * @param categoryStatus The category status. 77 * @param categoryStatus The category status.
75 * @param alwaysAllowEmptySections Whether sections are always allowed to be displayed when 78 * @param alwaysAllowEmptySections Whether sections are always allowed to be displayed when
76 * they are empty, even when they are normally not. 79 * they are empty, even when they are normally not.
77 * @return The number of suggestions for the section. 80 * @return The number of suggestions for the section.
78 */ 81 */
79 private int resetSection(@CategoryInt int category, @CategoryStatusEnum int categoryStatus, 82 private int resetSection(@CategoryInt int category, @CategoryStatusEnum int categoryStatus,
80 boolean alwaysAllowEmptySections) { 83 boolean alwaysAllowEmptySections) {
81 SuggestionsSource suggestionsSource = mNewTabPageManager.getSuggestionsS ource(); 84 SuggestionsSource suggestionsSource = mNewTabPageManager.getSuggestionsS ource();
82 List<SnippetArticle> suggestions = suggestionsSource.getSuggestionsForCa tegory(category); 85 List<SnippetArticle> suggestions = suggestionsSource.getSuggestionsForCa tegory(category);
83 SuggestionsCategoryInfo info = suggestionsSource.getCategoryInfo(categor y); 86 SuggestionsCategoryInfo info = suggestionsSource.getCategoryInfo(categor y);
84 87
85 SuggestionsSection section = mSections.get(category); 88 SuggestionsSection section = mSections.get(category);
86 89
87 // Do not show an empty section if not allowed. 90 // Do not show an empty section if not allowed.
88 if (suggestions.isEmpty() && !info.showIfEmpty() && !alwaysAllowEmptySec tions) { 91 if (suggestions.isEmpty() && !info.showIfEmpty() && !alwaysAllowEmptySec tions) {
89 if (section != null) removeSection(section); 92 if (section != null) removeSection(section);
90 return 0; 93 return 0;
91 } 94 }
92 95
93 // Create the section if needed. 96 // Create the section if needed.
94 if (section == null) { 97 if (section == null) {
95 section = new SuggestionsSection(this, mNewTabPageManager, mOfflineP ageBridge, info); 98 section = new SuggestionsSection(
99 this, mNewTabPageManager, mSuggestionRanker, mOfflinePageBri dge, info);
96 mSections.put(category, section); 100 mSections.put(category, section);
101 mSuggestionRanker.registerCategory(category);
97 addChild(section); 102 addChild(section);
98 } 103 }
99 104
100 // Set the new suggestions. 105 // Set the new suggestions.
101 setSuggestions(category, suggestions, categoryStatus, /* replaceExisting = */ true); 106 setSuggestions(category, suggestions, categoryStatus, /* replaceExisting = */ true);
102 107
103 return suggestions.size(); 108 return suggestions.size();
104 } 109 }
105 110
106 @Override 111 @Override
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after
176 * may have no or only partial effect if changing the list of suggestions is not allowed (e.g. 181 * may have no or only partial effect if changing the list of suggestions is not allowed (e.g.
177 * because the user has already seen the suggestions). 182 * because the user has already seen the suggestions).
178 * @param category The category for which the suggestions should be set. 183 * @param category The category for which the suggestions should be set.
179 * @param suggestions The new list of suggestions for the given category. 184 * @param suggestions The new list of suggestions for the given category.
180 * @param status The new category status. 185 * @param status The new category status.
181 * @param replaceExisting If true, {@code suggestions} replace the current l ist of suggestions. 186 * @param replaceExisting If true, {@code suggestions} replace the current l ist of suggestions.
182 * If false, {@code suggestions} are appended to current list of suggestions . 187 * If false, {@code suggestions} are appended to current list of suggestions .
183 */ 188 */
184 private void setSuggestions(@CategoryInt int category, List<SnippetArticle> suggestions, 189 private void setSuggestions(@CategoryInt int category, List<SnippetArticle> suggestions,
185 @CategoryStatusEnum int status, boolean replaceExisting) { 190 @CategoryStatusEnum int status, boolean replaceExisting) {
186 // Count the number of suggestions before this category.
187 int globalPositionOffset = 0;
188 for (Map.Entry<Integer, SuggestionsSection> entry : mSections.entrySet() ) {
189 if (entry.getKey() == category) break;
190 globalPositionOffset += entry.getValue().getSuggestionsCount();
191 }
192 // Assign global indices to the new suggestions.
193 for (SnippetArticle suggestion : suggestions) {
194 suggestion.mGlobalPosition = globalPositionOffset + suggestion.mPosi tion;
195 }
196
197 mSections.get(category).setSuggestions(suggestions, status, replaceExist ing); 191 mSections.get(category).setSuggestions(suggestions, status, replaceExist ing);
198 } 192 }
199 193
200 private boolean canLoadSuggestions(@CategoryInt int category, @CategoryStatu sEnum int status) { 194 private boolean canLoadSuggestions(@CategoryInt int category, @CategoryStatu sEnum int status) {
201 // We never want to add suggestions from unknown categories. 195 // We never want to add suggestions from unknown categories.
202 if (!mSections.containsKey(category)) return false; 196 if (!mSections.containsKey(category)) return false;
203 197
204 // The status may have changed while the suggestions were loading, perha ps they should not 198 // The status may have changed while the suggestions were loading, perha ps they should not
205 // be displayed any more. 199 // be displayed any more.
206 if (!SnippetsBridge.isCategoryEnabled(status)) { 200 if (!SnippetsBridge.isCategoryEnabled(status)) {
(...skipping 40 matching lines...) Expand 10 before | Expand all | Expand 10 after
247 /** 241 /**
248 * @return Whether the list of sections is empty. 242 * @return Whether the list of sections is empty.
249 */ 243 */
250 public boolean isEmpty() { 244 public boolean isEmpty() {
251 return mSections.isEmpty(); 245 return mSections.isEmpty();
252 } 246 }
253 247
254 SuggestionsSection getSectionForTesting(@CategoryInt int categoryId) { 248 SuggestionsSection getSectionForTesting(@CategoryInt int categoryId) {
255 return mSections.get(categoryId); 249 return mSections.get(categoryId);
256 } 250 }
251
252 /**
253 * Attributes ranks to suggestions and related elements.
254 *
255 * Ranks here are 0-based scores attributed based on the position or loading order of the
256 * elements. See implementation for more details.
257 */
258 public static class SuggestionRanker {
Bernhard Bauer 2017/01/17 17:42:31 Can we move this to a separate class? There isn't
dgn 2017/01/17 18:46:24 Done.
259 private final Map<Integer, Integer> mSuggestionsAddedPerSection = new Li nkedHashMap<>();
260 private int mTotalAddedSuggestions;
261
262 /**
263 * Attributes a per section rank to the provided action item.
264 * @see ActionItem#getPerSectionRank()
265 */
266 public void rankItem(ActionItem actionItem, SuggestionsSection section) {
Bernhard Bauer 2017/01/17 17:42:31 Can we rename these methods to rankActionItem() an
dgn 2017/01/17 18:46:24 Done.
267 if (actionItem.getPerSectionRank() != -1) return; // Item was alread y ranked.
268 actionItem.setRank(section.getSuggestionsCount());
269 }
270
271 /**
272 * Attributes global and per section rank to the provided suggestion.
273 * @see SnippetArticle#getPerSectionRank()
274 * @see SnippetArticle#getGlobalRank()
275 */
276 public void rankItem(SnippetArticle suggestion) {
277 int globalRank = mTotalAddedSuggestions++;
278 int perSectionRank = mSuggestionsAddedPerSection.get(suggestion.mCat egory);
279 mSuggestionsAddedPerSection.put(suggestion.mCategory, perSectionRank + 1);
280
281 suggestion.setRank(perSectionRank, globalRank);
282 }
283
284 public void registerCategory(@CategoryInt int category) {
285 mSuggestionsAddedPerSection.put(category, 0);
286 }
287 }
257 } 288 }
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698