OLD | NEW |
---|---|
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; |
11 import org.chromium.chrome.browser.ntp.snippets.CategoryStatus; | 11 import org.chromium.chrome.browser.ntp.snippets.CategoryStatus; |
12 import org.chromium.chrome.browser.ntp.snippets.CategoryStatus.CategoryStatusEnu m; | 12 import org.chromium.chrome.browser.ntp.snippets.CategoryStatus.CategoryStatusEnu m; |
13 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; | 13 import org.chromium.chrome.browser.ntp.snippets.SnippetArticle; |
14 import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge; | 14 import org.chromium.chrome.browser.ntp.snippets.SnippetsBridge; |
15 import org.chromium.chrome.browser.ntp.snippets.SnippetsConfig; | 15 import org.chromium.chrome.browser.ntp.snippets.SnippetsConfig; |
16 import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource; | 16 import org.chromium.chrome.browser.ntp.snippets.SuggestionsSource; |
17 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; | 17 import org.chromium.chrome.browser.offlinepages.OfflinePageBridge; |
18 import org.chromium.chrome.browser.suggestions.SuggestionsRanker; | |
18 | 19 |
19 import java.util.LinkedHashMap; | 20 import java.util.LinkedHashMap; |
20 import java.util.List; | 21 import java.util.List; |
21 import java.util.Map; | 22 import java.util.Map; |
22 | 23 |
23 /** | 24 /** |
24 * A node in the tree containing a list of all suggestions sections. It listens to changes in the | 25 * A node in the tree containing a list of all suggestions sections. It listens to changes in the |
25 * suggestions source and updates the corresponding sections. | 26 * suggestions source and updates the corresponding sections. |
26 */ | 27 */ |
27 public class SectionList | 28 public class SectionList |
28 extends InnerNode implements SuggestionsSource.Observer, SuggestionsSect ion.Delegate { | 29 extends InnerNode implements SuggestionsSource.Observer, SuggestionsSect ion.Delegate { |
29 private static final String TAG = "Ntp"; | 30 private static final String TAG = "Ntp"; |
30 | 31 |
31 /** Maps suggestion categories to sections, with stable iteration ordering. */ | 32 /** Maps suggestion categories to sections, with stable iteration ordering. */ |
32 private final Map<Integer, SuggestionsSection> mSections = new LinkedHashMap <>(); | 33 private final Map<Integer, SuggestionsSection> mSections = new LinkedHashMap <>(); |
33 private final NewTabPageManager mNewTabPageManager; | 34 private final NewTabPageManager mNewTabPageManager; |
34 private final OfflinePageBridge mOfflinePageBridge; | 35 private final OfflinePageBridge mOfflinePageBridge; |
36 private final SuggestionsRanker mSuggestionsRanker; | |
35 | 37 |
36 public SectionList(NewTabPageManager newTabPageManager, OfflinePageBridge of flinePageBridge) { | 38 public SectionList(NewTabPageManager newTabPageManager, OfflinePageBridge of flinePageBridge) { |
39 mSuggestionsRanker = new SuggestionsRanker(); | |
37 mNewTabPageManager = newTabPageManager; | 40 mNewTabPageManager = newTabPageManager; |
38 mNewTabPageManager.getSuggestionsSource().setObserver(this); | 41 mNewTabPageManager.getSuggestionsSource().setObserver(this); |
42 mNewTabPageManager.getSuggestionsMetricsReporter().setRanker(mSuggestion sRanker); | |
39 mOfflinePageBridge = offlinePageBridge; | 43 mOfflinePageBridge = offlinePageBridge; |
40 resetSections(/* alwaysAllowEmptySections = */ false); | 44 resetSections(/* alwaysAllowEmptySections = */ false); |
41 } | 45 } |
42 | 46 |
43 /** | 47 /** |
44 * Resets the sections, reloading the whole new tab page content. | 48 * Resets the sections, reloading the whole new tab page content. |
45 * @param alwaysAllowEmptySections Whether sections are always allowed to be displayed when | 49 * @param alwaysAllowEmptySections Whether sections are always allowed to be displayed when |
46 * they are empty, even when they are normally not. | 50 * they are empty, even when they are normally not. |
47 */ | 51 */ |
48 public void resetSections(boolean alwaysAllowEmptySections) { | 52 public void resetSections(boolean alwaysAllowEmptySections) { |
49 removeAllSections(); | 53 removeAllSections(); |
50 | 54 |
51 SuggestionsSource suggestionsSource = mNewTabPageManager.getSuggestionsS ource(); | 55 SuggestionsSource suggestionsSource = mNewTabPageManager.getSuggestionsS ource(); |
52 int[] categories = suggestionsSource.getCategories(); | 56 int[] categories = suggestionsSource.getCategories(); |
53 int[] suggestionsPerCategory = new int[categories.length]; | 57 int[] suggestionsPerCategory = new int[categories.length]; |
54 int categoryIndex = 0; | 58 int categoryIndex = 0; |
55 for (int category : categories) { | 59 for (int category : categories) { |
56 int categoryStatus = suggestionsSource.getCategoryStatus(category); | 60 int categoryStatus = suggestionsSource.getCategoryStatus(category); |
57 if (categoryStatus == CategoryStatus.LOADING_ERROR | 61 if (categoryStatus == CategoryStatus.LOADING_ERROR |
58 || categoryStatus == CategoryStatus.NOT_PROVIDED | 62 || categoryStatus == CategoryStatus.NOT_PROVIDED |
59 || categoryStatus == CategoryStatus.CATEGORY_EXPLICITLY_DISA BLED) | 63 || categoryStatus == CategoryStatus.CATEGORY_EXPLICITLY_DISA BLED) |
60 continue; | 64 continue; |
61 | 65 |
62 suggestionsPerCategory[categoryIndex] = | 66 suggestionsPerCategory[categoryIndex] = |
63 resetSection(category, categoryStatus, alwaysAllowEmptySecti ons); | 67 resetSection(category, categoryStatus, alwaysAllowEmptySecti ons); |
64 SuggestionsSection section = mSections.get(category); | |
65 if (section != null) section.setCategoryIndex(categoryIndex); | |
66 ++categoryIndex; | 68 ++categoryIndex; |
67 } | 69 } |
68 | 70 |
69 mNewTabPageManager.trackSnippetsPageImpression(categories, suggestionsPe rCategory); | 71 mNewTabPageManager.getSuggestionsMetricsReporter().onPageShown( |
72 categories, suggestionsPerCategory); | |
70 } | 73 } |
71 | 74 |
72 /** | 75 /** |
73 * Resets the section for {@code category}. Removes the section if there are no suggestions for | 76 * Resets the section for {@code category}. Removes the section if there are no suggestions for |
74 * it and it is not allowed to be empty. Otherwise, creates the section if i t is not present | 77 * it and it is not allowed to be empty. Otherwise, creates the section if i t is not present |
75 * yet. Sets the available suggestions on the section. | 78 * yet. Sets the available suggestions on the section. |
76 * @param category The category for which the section must be reset. | 79 * @param category The category for which the section must be reset. |
77 * @param categoryStatus The category status. | 80 * @param categoryStatus The category status. |
78 * @param alwaysAllowEmptySections Whether sections are always allowed to be displayed when | 81 * @param alwaysAllowEmptySections Whether sections are always allowed to be displayed when |
79 * they are empty, even when they are normally not. | 82 * they are empty, even when they are normally not. |
80 * @return The number of suggestions for the section. | 83 * @return The number of suggestions for the section. |
81 */ | 84 */ |
82 private int resetSection(@CategoryInt int category, @CategoryStatusEnum int categoryStatus, | 85 private int resetSection(@CategoryInt int category, @CategoryStatusEnum int categoryStatus, |
83 boolean alwaysAllowEmptySections) { | 86 boolean alwaysAllowEmptySections) { |
84 SuggestionsSource suggestionsSource = mNewTabPageManager.getSuggestionsS ource(); | 87 SuggestionsSource suggestionsSource = mNewTabPageManager.getSuggestionsS ource(); |
85 List<SnippetArticle> suggestions = suggestionsSource.getSuggestionsForCa tegory(category); | 88 List<SnippetArticle> suggestions = suggestionsSource.getSuggestionsForCa tegory(category); |
86 SuggestionsCategoryInfo info = suggestionsSource.getCategoryInfo(categor y); | 89 SuggestionsCategoryInfo info = suggestionsSource.getCategoryInfo(categor y); |
87 | 90 |
88 SuggestionsSection section = mSections.get(category); | 91 SuggestionsSection section = mSections.get(category); |
89 | 92 |
90 // Do not show an empty section if not allowed. | 93 // Do not show an empty section if not allowed. |
91 if (suggestions.isEmpty() && !info.showIfEmpty() && !alwaysAllowEmptySec tions) { | 94 if (suggestions.isEmpty() && !info.showIfEmpty() && !alwaysAllowEmptySec tions) { |
92 if (section != null) removeSection(section); | 95 if (section != null) removeSection(section); |
93 return 0; | 96 return 0; |
94 } | 97 } |
95 | 98 |
96 // Create the section if needed. | 99 // Create the section if needed. |
97 if (section == null) { | 100 if (section == null) { |
98 section = new SuggestionsSection(this, mNewTabPageManager, mOfflineP ageBridge, info); | 101 section = new SuggestionsSection( |
102 this, mNewTabPageManager, mSuggestionsRanker, mOfflinePageBr idge, info); | |
99 mSections.put(category, section); | 103 mSections.put(category, section); |
104 mSuggestionsRanker.registerCategory(category); | |
vitaliii
2017/01/18 08:46:27
I discussed ignoring not shown empty sections with
| |
100 addChild(section); | 105 addChild(section); |
101 } | 106 } |
102 | 107 |
103 // Set the new suggestions. | 108 // Set the new suggestions. |
104 setSuggestions(category, suggestions, categoryStatus, /* replaceExisting = */ true); | 109 setSuggestions(category, suggestions, categoryStatus, /* replaceExisting = */ true); |
105 | 110 |
106 return suggestions.size(); | 111 return suggestions.size(); |
107 } | 112 } |
108 | 113 |
109 @Override | 114 @Override |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
179 * may have no or only partial effect if changing the list of suggestions is not allowed (e.g. | 184 * may have no or only partial effect if changing the list of suggestions is not allowed (e.g. |
180 * because the user has already seen the suggestions). | 185 * because the user has already seen the suggestions). |
181 * @param category The category for which the suggestions should be set. | 186 * @param category The category for which the suggestions should be set. |
182 * @param suggestions The new list of suggestions for the given category. | 187 * @param suggestions The new list of suggestions for the given category. |
183 * @param status The new category status. | 188 * @param status The new category status. |
184 * @param replaceExisting If true, {@code suggestions} replace the current l ist of suggestions. | 189 * @param replaceExisting If true, {@code suggestions} replace the current l ist of suggestions. |
185 * If false, {@code suggestions} are appended to current list of suggestions . | 190 * If false, {@code suggestions} are appended to current list of suggestions . |
186 */ | 191 */ |
187 private void setSuggestions(@CategoryInt int category, List<SnippetArticle> suggestions, | 192 private void setSuggestions(@CategoryInt int category, List<SnippetArticle> suggestions, |
188 @CategoryStatusEnum int status, boolean replaceExisting) { | 193 @CategoryStatusEnum int status, boolean replaceExisting) { |
189 // Count the number of suggestions before this category. | |
190 int globalPositionOffset = 0; | |
191 for (Map.Entry<Integer, SuggestionsSection> entry : mSections.entrySet() ) { | |
192 if (entry.getKey() == category) break; | |
193 globalPositionOffset += entry.getValue().getSuggestionsCount(); | |
194 } | |
195 // Assign global indices to the new suggestions. | |
196 for (SnippetArticle suggestion : suggestions) { | |
197 suggestion.mGlobalPosition = globalPositionOffset + suggestion.mPosi tion; | |
198 } | |
199 | |
200 mSections.get(category).setSuggestions(suggestions, status, replaceExist ing); | 194 mSections.get(category).setSuggestions(suggestions, status, replaceExist ing); |
201 } | 195 } |
202 | 196 |
203 private boolean canLoadSuggestions(@CategoryInt int category, @CategoryStatu sEnum int status) { | 197 private boolean canLoadSuggestions(@CategoryInt int category, @CategoryStatu sEnum int status) { |
204 // We never want to add suggestions from unknown categories. | 198 // We never want to add suggestions from unknown categories. |
205 if (!mSections.containsKey(category)) return false; | 199 if (!mSections.containsKey(category)) return false; |
206 | 200 |
207 // The status may have changed while the suggestions were loading, perha ps they should not | 201 // The status may have changed while the suggestions were loading, perha ps they should not |
208 // be displayed any more. | 202 // be displayed any more. |
209 if (!SnippetsBridge.isCategoryEnabled(status)) { | 203 if (!SnippetsBridge.isCategoryEnabled(status)) { |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
251 * @return Whether the list of sections is empty. | 245 * @return Whether the list of sections is empty. |
252 */ | 246 */ |
253 public boolean isEmpty() { | 247 public boolean isEmpty() { |
254 return mSections.isEmpty(); | 248 return mSections.isEmpty(); |
255 } | 249 } |
256 | 250 |
257 SuggestionsSection getSectionForTesting(@CategoryInt int categoryId) { | 251 SuggestionsSection getSectionForTesting(@CategoryInt int categoryId) { |
258 return mSections.get(categoryId); | 252 return mSections.get(categoryId); |
259 } | 253 } |
260 } | 254 } |
OLD | NEW |