Bug 1682379 - Remove SPOCS Fill event in Activity Stream r=thecount

Differential Revision: https://phabricator.services.mozilla.com/D99805
This commit is contained in:
Nan Jiang 2020-12-17 18:15:25 +00:00
Родитель 2493b6432d
Коммит cd43564e6e
12 изменённых файлов: 79 добавлений и 668 удалений

Просмотреть файл

@ -67,7 +67,6 @@ for (const type of [
"DISCOVERY_STREAM_RETRY_FEED",
"DISCOVERY_STREAM_SPOCS_CAPS",
"DISCOVERY_STREAM_SPOCS_ENDPOINT",
"DISCOVERY_STREAM_SPOCS_FILL",
"DISCOVERY_STREAM_SPOCS_PLACEMENTS",
"DISCOVERY_STREAM_SPOCS_UPDATE",
"DISCOVERY_STREAM_SPOC_BLOCKED",
@ -303,21 +302,6 @@ function ASRouterUserEvent(data) {
});
}
/**
* DiscoveryStreamSpocsFill - A telemetry ping indicating a SPOCS Fill event.
*
* @param {object} data Fields to include in the ping (spoc_fills, etc.)
* @param {int} importContext (For testing) Override the import context for testing.
* @return {object} An AlsoToMain action
*/
function DiscoveryStreamSpocsFill(data, importContext = globalImportContext) {
const action = {
type: actionTypes.DISCOVERY_STREAM_SPOCS_FILL,
data,
};
return importContext === UI_CODE ? AlsoToMain(action) : action;
}
/**
* UndesiredEvent - A telemetry ping indicating an undesired state.
*
@ -416,7 +400,6 @@ this.actionCreators = {
WebExtEvent,
DiscoveryStreamImpressionStats,
DiscoveryStreamLoadedContent,
DiscoveryStreamSpocsFill,
};
// These are helpers to test for certain kinds of actions

Просмотреть файл

@ -2,7 +2,6 @@
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
import { actionCreators as ac } from "common/Actions.jsm";
import { CardGrid } from "content-src/components/DiscoveryStreamComponents/CardGrid/CardGrid";
import { CollectionCardGrid } from "content-src/components/DiscoveryStreamComponents/CollectionCardGrid/CollectionCardGrid";
import { CollapsibleSection } from "content-src/components/CollapsibleSection/CollapsibleSection";
@ -260,27 +259,13 @@ export class _DiscoveryStreamBase extends React.PureComponent {
render() {
// Select layout render data by adding spocs and position to recommendations
const { layoutRender, spocsFill } = selectLayoutRender({
const { layoutRender } = selectLayoutRender({
state: this.props.DiscoveryStream,
prefs: this.props.Prefs.values,
rollCache,
locale: this.props.locale,
});
const { config, spocs, feeds } = this.props.DiscoveryStream;
// Send SPOCS Fill if any. Note that it should not send it again if the same
// page gets re-rendered by state changes.
if (
spocs.loaded &&
feeds.loaded &&
spocsFill.length &&
!this._spocsFillSent
) {
this.props.dispatch(
ac.DiscoveryStreamSpocsFill({ spoc_fills: spocsFill })
);
this._spocsFillSent = true;
}
const { config } = this.props.DiscoveryStream;
// Allow rendering without extracting special components
if (!config.collapsible) {

Просмотреть файл

@ -11,9 +11,6 @@ export const selectLayoutRender = ({
const { layout, feeds, spocs } = state;
let spocIndexMap = {};
let bufferRollCache = [];
// Records the chosen and unchosen spocs by the probability selection.
let chosenSpocs = new Set();
let unchosenSpocs = new Set();
function rollForSpocs(data, spocsConfig, spocsData, placementName) {
if (!spocIndexMap[placementName] && spocIndexMap[placementName] !== 0) {
@ -40,10 +37,7 @@ export const selectLayoutRender = ({
spocIndexMap[placementName]++;
if (!spocs.blocked.includes(spoc.url)) {
results.splice(position.index, 0, spoc);
chosenSpocs.add(spoc);
}
} else {
unchosenSpocs.add(spoc);
}
}
@ -263,47 +257,5 @@ export const selectLayoutRender = ({
rollCache.push(...bufferRollCache);
}
// Generate the payload for the SPOCS Fill ping. Note that a SPOC could be rejected
// by the `probability_selection` first, then gets chosen for the next position. For
// all other SPOCS that never went through the probabilistic selection, its reason will
// be "out_of_position".
let spocsFill = [];
if (
spocs.loaded &&
feeds.loaded &&
spocs.data.spocs &&
spocs.data.spocs.items
) {
const chosenSpocsFill = [...chosenSpocs].map(spoc => ({
id: spoc.id,
reason: "n/a",
displayed: 1,
full_recalc: 0,
}));
const unchosenSpocsFill = [...unchosenSpocs]
.filter(spoc => !chosenSpocs.has(spoc))
.map(spoc => ({
id: spoc.id,
reason: "probability_selection",
displayed: 0,
full_recalc: 0,
}));
const outOfPositionSpocsFill = spocs.data.spocs.items
.slice(spocIndexMap.spocs)
.filter(spoc => !unchosenSpocs.has(spoc))
.map(spoc => ({
id: spoc.id,
reason: "out_of_position",
displayed: 0,
full_recalc: 0,
}));
spocsFill = [
...chosenSpocsFill,
...unchosenSpocsFill,
...outOfPositionSpocsFill,
];
}
return { spocsFill, layoutRender };
return { layoutRender };
};

Просмотреть файл

@ -205,7 +205,7 @@ const globalImportContext = typeof Window === "undefined" ? BACKGROUND_PROCESS :
// }
const actionTypes = {};
for (const type of ["ABOUT_SPONSORED_TOP_SITES", "ADDONS_INFO_REQUEST", "ADDONS_INFO_RESPONSE", "ARCHIVE_FROM_POCKET", "AS_ROUTER_INITIALIZED", "AS_ROUTER_PREF_CHANGED", "AS_ROUTER_TARGETING_UPDATE", "AS_ROUTER_TELEMETRY_USER_EVENT", "BLOCK_URL", "BOOKMARK_URL", "CLEAR_PREF", "COPY_DOWNLOAD_LINK", "DELETE_BOOKMARK_BY_ID", "DELETE_FROM_POCKET", "DELETE_HISTORY_URL", "DIALOG_CANCEL", "DIALOG_OPEN", "DISCOVERY_STREAM_COLLECTION_DISMISSIBLE_TOGGLE", "DISCOVERY_STREAM_CONFIG_CHANGE", "DISCOVERY_STREAM_CONFIG_RESET", "DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS", "DISCOVERY_STREAM_CONFIG_SETUP", "DISCOVERY_STREAM_CONFIG_SET_VALUE", "DISCOVERY_STREAM_DEV_EXPIRE_CACHE", "DISCOVERY_STREAM_DEV_IDLE_DAILY", "DISCOVERY_STREAM_DEV_SYNC_RS", "DISCOVERY_STREAM_DEV_SYSTEM_TICK", "DISCOVERY_STREAM_FEEDS_UPDATE", "DISCOVERY_STREAM_FEED_UPDATE", "DISCOVERY_STREAM_IMPRESSION_STATS", "DISCOVERY_STREAM_LAYOUT_RESET", "DISCOVERY_STREAM_LAYOUT_UPDATE", "DISCOVERY_STREAM_LINK_BLOCKED", "DISCOVERY_STREAM_LOADED_CONTENT", "DISCOVERY_STREAM_PERSONALIZATION_INIT", "DISCOVERY_STREAM_PERSONALIZATION_LAST_UPDATED", "DISCOVERY_STREAM_PERSONALIZATION_VERSION", "DISCOVERY_STREAM_PERSONALIZATION_VERSION_TOGGLE", "DISCOVERY_STREAM_RETRY_FEED", "DISCOVERY_STREAM_SPOCS_CAPS", "DISCOVERY_STREAM_SPOCS_ENDPOINT", "DISCOVERY_STREAM_SPOCS_FILL", "DISCOVERY_STREAM_SPOCS_PLACEMENTS", "DISCOVERY_STREAM_SPOCS_UPDATE", "DISCOVERY_STREAM_SPOC_BLOCKED", "DISCOVERY_STREAM_SPOC_IMPRESSION", "DOWNLOAD_CHANGED", "FAKE_FOCUS_SEARCH", "FILL_SEARCH_TERM", "HANDOFF_SEARCH_TO_AWESOMEBAR", "HIDE_PRIVACY_INFO", "HIDE_SEARCH", "INIT", "NEW_TAB_INIT", "NEW_TAB_INITIAL_STATE", "NEW_TAB_LOAD", "NEW_TAB_REHYDRATED", "NEW_TAB_STATE_REQUEST", "NEW_TAB_UNLOAD", "OPEN_DOWNLOAD_FILE", "OPEN_LINK", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "OPEN_WEBEXT_SETTINGS", "PARTNER_LINK_ATTRIBUTION", "PLACES_BOOKMARK_ADDED", "PLACES_BOOKMARK_REMOVED", "PLACES_HISTORY_CLEARED", "PLACES_LINKS_CHANGED", "PLACES_LINK_BLOCKED", "PLACES_LINK_DELETED", "PLACES_SAVED_TO_POCKET", "POCKET_CTA", "POCKET_LINK_DELETED_OR_ARCHIVED", "POCKET_LOGGED_IN", "POCKET_WAITING_FOR_SPOC", "PREFS_INITIAL_VALUES", "PREF_CHANGED", "PREVIEW_REQUEST", "PREVIEW_REQUEST_CANCEL", "PREVIEW_RESPONSE", "REMOVE_DOWNLOAD_FILE", "RICH_ICON_MISSING", "SAVE_SESSION_PERF_DATA", "SAVE_TO_POCKET", "SCREENSHOT_UPDATED", "SECTION_DEREGISTER", "SECTION_DISABLE", "SECTION_ENABLE", "SECTION_MOVE", "SECTION_OPTIONS_CHANGED", "SECTION_REGISTER", "SECTION_UPDATE", "SECTION_UPDATE_CARD", "SETTINGS_CLOSE", "SETTINGS_OPEN", "SET_PREF", "SHOW_DOWNLOAD_FILE", "SHOW_FIREFOX_ACCOUNTS", "SHOW_PRIVACY_INFO", "SHOW_SEARCH", "SKIPPED_SIGNIN", "SNIPPETS_BLOCKLIST_CLEARED", "SNIPPETS_BLOCKLIST_UPDATED", "SNIPPETS_DATA", "SNIPPETS_PREVIEW_MODE", "SNIPPETS_RESET", "SNIPPET_BLOCKED", "SUBMIT_EMAIL", "SUBMIT_SIGNIN", "SYSTEM_TICK", "TELEMETRY_IMPRESSION_STATS", "TELEMETRY_UNDESIRED_EVENT", "TELEMETRY_USER_EVENT", "TOP_SITES_CANCEL_EDIT", "TOP_SITES_CLOSE_SEARCH_SHORTCUTS_MODAL", "TOP_SITES_EDIT", "TOP_SITES_INSERT", "TOP_SITES_OPEN_SEARCH_SHORTCUTS_MODAL", "TOP_SITES_PIN", "TOP_SITES_PREFS_UPDATED", "TOP_SITES_UNPIN", "TOP_SITES_UPDATED", "TOTAL_BOOKMARKS_REQUEST", "TOTAL_BOOKMARKS_RESPONSE", "UNINIT", "UPDATE_PINNED_SEARCH_SHORTCUTS", "UPDATE_SEARCH_SHORTCUTS", "UPDATE_SECTION_PREFS", "WEBEXT_CLICK", "WEBEXT_DISMISS"]) {
for (const type of ["ABOUT_SPONSORED_TOP_SITES", "ADDONS_INFO_REQUEST", "ADDONS_INFO_RESPONSE", "ARCHIVE_FROM_POCKET", "AS_ROUTER_INITIALIZED", "AS_ROUTER_PREF_CHANGED", "AS_ROUTER_TARGETING_UPDATE", "AS_ROUTER_TELEMETRY_USER_EVENT", "BLOCK_URL", "BOOKMARK_URL", "CLEAR_PREF", "COPY_DOWNLOAD_LINK", "DELETE_BOOKMARK_BY_ID", "DELETE_FROM_POCKET", "DELETE_HISTORY_URL", "DIALOG_CANCEL", "DIALOG_OPEN", "DISCOVERY_STREAM_COLLECTION_DISMISSIBLE_TOGGLE", "DISCOVERY_STREAM_CONFIG_CHANGE", "DISCOVERY_STREAM_CONFIG_RESET", "DISCOVERY_STREAM_CONFIG_RESET_DEFAULTS", "DISCOVERY_STREAM_CONFIG_SETUP", "DISCOVERY_STREAM_CONFIG_SET_VALUE", "DISCOVERY_STREAM_DEV_EXPIRE_CACHE", "DISCOVERY_STREAM_DEV_IDLE_DAILY", "DISCOVERY_STREAM_DEV_SYNC_RS", "DISCOVERY_STREAM_DEV_SYSTEM_TICK", "DISCOVERY_STREAM_FEEDS_UPDATE", "DISCOVERY_STREAM_FEED_UPDATE", "DISCOVERY_STREAM_IMPRESSION_STATS", "DISCOVERY_STREAM_LAYOUT_RESET", "DISCOVERY_STREAM_LAYOUT_UPDATE", "DISCOVERY_STREAM_LINK_BLOCKED", "DISCOVERY_STREAM_LOADED_CONTENT", "DISCOVERY_STREAM_PERSONALIZATION_INIT", "DISCOVERY_STREAM_PERSONALIZATION_LAST_UPDATED", "DISCOVERY_STREAM_PERSONALIZATION_VERSION", "DISCOVERY_STREAM_PERSONALIZATION_VERSION_TOGGLE", "DISCOVERY_STREAM_RETRY_FEED", "DISCOVERY_STREAM_SPOCS_CAPS", "DISCOVERY_STREAM_SPOCS_ENDPOINT", "DISCOVERY_STREAM_SPOCS_PLACEMENTS", "DISCOVERY_STREAM_SPOCS_UPDATE", "DISCOVERY_STREAM_SPOC_BLOCKED", "DISCOVERY_STREAM_SPOC_IMPRESSION", "DOWNLOAD_CHANGED", "FAKE_FOCUS_SEARCH", "FILL_SEARCH_TERM", "HANDOFF_SEARCH_TO_AWESOMEBAR", "HIDE_PRIVACY_INFO", "HIDE_SEARCH", "INIT", "NEW_TAB_INIT", "NEW_TAB_INITIAL_STATE", "NEW_TAB_LOAD", "NEW_TAB_REHYDRATED", "NEW_TAB_STATE_REQUEST", "NEW_TAB_UNLOAD", "OPEN_DOWNLOAD_FILE", "OPEN_LINK", "OPEN_NEW_WINDOW", "OPEN_PRIVATE_WINDOW", "OPEN_WEBEXT_SETTINGS", "PARTNER_LINK_ATTRIBUTION", "PLACES_BOOKMARK_ADDED", "PLACES_BOOKMARK_REMOVED", "PLACES_HISTORY_CLEARED", "PLACES_LINKS_CHANGED", "PLACES_LINK_BLOCKED", "PLACES_LINK_DELETED", "PLACES_SAVED_TO_POCKET", "POCKET_CTA", "POCKET_LINK_DELETED_OR_ARCHIVED", "POCKET_LOGGED_IN", "POCKET_WAITING_FOR_SPOC", "PREFS_INITIAL_VALUES", "PREF_CHANGED", "PREVIEW_REQUEST", "PREVIEW_REQUEST_CANCEL", "PREVIEW_RESPONSE", "REMOVE_DOWNLOAD_FILE", "RICH_ICON_MISSING", "SAVE_SESSION_PERF_DATA", "SAVE_TO_POCKET", "SCREENSHOT_UPDATED", "SECTION_DEREGISTER", "SECTION_DISABLE", "SECTION_ENABLE", "SECTION_MOVE", "SECTION_OPTIONS_CHANGED", "SECTION_REGISTER", "SECTION_UPDATE", "SECTION_UPDATE_CARD", "SETTINGS_CLOSE", "SETTINGS_OPEN", "SET_PREF", "SHOW_DOWNLOAD_FILE", "SHOW_FIREFOX_ACCOUNTS", "SHOW_PRIVACY_INFO", "SHOW_SEARCH", "SKIPPED_SIGNIN", "SNIPPETS_BLOCKLIST_CLEARED", "SNIPPETS_BLOCKLIST_UPDATED", "SNIPPETS_DATA", "SNIPPETS_PREVIEW_MODE", "SNIPPETS_RESET", "SNIPPET_BLOCKED", "SUBMIT_EMAIL", "SUBMIT_SIGNIN", "SYSTEM_TICK", "TELEMETRY_IMPRESSION_STATS", "TELEMETRY_UNDESIRED_EVENT", "TELEMETRY_USER_EVENT", "TOP_SITES_CANCEL_EDIT", "TOP_SITES_CLOSE_SEARCH_SHORTCUTS_MODAL", "TOP_SITES_EDIT", "TOP_SITES_INSERT", "TOP_SITES_OPEN_SEARCH_SHORTCUTS_MODAL", "TOP_SITES_PIN", "TOP_SITES_PREFS_UPDATED", "TOP_SITES_UNPIN", "TOP_SITES_UPDATED", "TOTAL_BOOKMARKS_REQUEST", "TOTAL_BOOKMARKS_RESPONSE", "UNINIT", "UPDATE_PINNED_SEARCH_SHORTCUTS", "UPDATE_SEARCH_SHORTCUTS", "UPDATE_SECTION_PREFS", "WEBEXT_CLICK", "WEBEXT_DISMISS"]) {
actionTypes[type] = type;
} // Helper function for creating routed actions between content and main
// Not intended to be used by consumers
@ -358,22 +358,6 @@ function ASRouterUserEvent(data) {
data
});
}
/**
* DiscoveryStreamSpocsFill - A telemetry ping indicating a SPOCS Fill event.
*
* @param {object} data Fields to include in the ping (spoc_fills, etc.)
* @param {int} importContext (For testing) Override the import context for testing.
* @return {object} An AlsoToMain action
*/
function DiscoveryStreamSpocsFill(data, importContext = globalImportContext) {
const action = {
type: actionTypes.DISCOVERY_STREAM_SPOCS_FILL,
data
};
return importContext === UI_CODE ? AlsoToMain(action) : action;
}
/**
* UndesiredEvent - A telemetry ping indicating an undesired state.
*
@ -476,8 +460,7 @@ var actionCreators = {
SetPref,
WebExtEvent,
DiscoveryStreamImpressionStats,
DiscoveryStreamLoadedContent,
DiscoveryStreamSpocsFill
DiscoveryStreamLoadedContent
}; // These are helpers to test for certain kinds of actions
var actionUtils = {
@ -3113,26 +3096,25 @@ __webpack_require__.r(__webpack_exports__);
/* WEBPACK VAR INJECTION */(function(global) {/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "isAllowedCSS", function() { return isAllowedCSS; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "_DiscoveryStreamBase", function() { return _DiscoveryStreamBase; });
/* harmony export (binding) */ __webpack_require__.d(__webpack_exports__, "DiscoveryStreamBase", function() { return DiscoveryStreamBase; });
/* harmony import */ var common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(1);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_CardGrid_CardGrid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(17);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_CollectionCardGrid_CollectionCardGrid__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(32);
/* harmony import */ var content_src_components_CollapsibleSection_CollapsibleSection__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(34);
/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(7);
/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_4___default = /*#__PURE__*/__webpack_require__.n(react_redux__WEBPACK_IMPORTED_MODULE_4__);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSMessage_DSMessage__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(39);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSPrivacyModal_DSPrivacyModal__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(40);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSSignup_DSSignup__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(42);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSTextPromo_DSTextPromo__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(43);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_Hero_Hero__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(44);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_Highlights_Highlights__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(46);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_HorizontalRule_HorizontalRule__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(59);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_List_List__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(45);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_Navigation_Navigation__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(60);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(8);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_14___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_14__);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_SectionTitle_SectionTitle__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(61);
/* harmony import */ var content_src_lib_selectLayoutRender__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(62);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_TopSites_TopSites__WEBPACK_IMPORTED_MODULE_17__ = __webpack_require__(63);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_CardGrid_CardGrid__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(17);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_CollectionCardGrid_CollectionCardGrid__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(32);
/* harmony import */ var content_src_components_CollapsibleSection_CollapsibleSection__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(34);
/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(7);
/* harmony import */ var react_redux__WEBPACK_IMPORTED_MODULE_3___default = /*#__PURE__*/__webpack_require__.n(react_redux__WEBPACK_IMPORTED_MODULE_3__);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSMessage_DSMessage__WEBPACK_IMPORTED_MODULE_4__ = __webpack_require__(39);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSPrivacyModal_DSPrivacyModal__WEBPACK_IMPORTED_MODULE_5__ = __webpack_require__(40);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSSignup_DSSignup__WEBPACK_IMPORTED_MODULE_6__ = __webpack_require__(42);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_DSTextPromo_DSTextPromo__WEBPACK_IMPORTED_MODULE_7__ = __webpack_require__(43);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_Hero_Hero__WEBPACK_IMPORTED_MODULE_8__ = __webpack_require__(44);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_Highlights_Highlights__WEBPACK_IMPORTED_MODULE_9__ = __webpack_require__(46);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_HorizontalRule_HorizontalRule__WEBPACK_IMPORTED_MODULE_10__ = __webpack_require__(59);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_List_List__WEBPACK_IMPORTED_MODULE_11__ = __webpack_require__(45);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_Navigation_Navigation__WEBPACK_IMPORTED_MODULE_12__ = __webpack_require__(60);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_13__ = __webpack_require__(8);
/* harmony import */ var react__WEBPACK_IMPORTED_MODULE_13___default = /*#__PURE__*/__webpack_require__.n(react__WEBPACK_IMPORTED_MODULE_13__);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_SectionTitle_SectionTitle__WEBPACK_IMPORTED_MODULE_14__ = __webpack_require__(61);
/* harmony import */ var content_src_lib_selectLayoutRender__WEBPACK_IMPORTED_MODULE_15__ = __webpack_require__(62);
/* harmony import */ var content_src_components_DiscoveryStreamComponents_TopSites_TopSites__WEBPACK_IMPORTED_MODULE_16__ = __webpack_require__(63);
/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this file,
* You can obtain one at http://mozilla.org/MPL/2.0/. */
@ -3153,7 +3135,6 @@ __webpack_require__.r(__webpack_exports__);
const ALLOWED_CSS_URL_PREFIXES = ["chrome://", "resource://", "https://img-getpocket.cdn.mozilla.net/"];
const DUMMY_CSS_SELECTOR = "DUMMY#CSS.SELECTOR";
let rollCache = []; // Cache of random probability values for a spoc position
@ -3174,7 +3155,7 @@ function isAllowedCSS(property, value) {
const urls = value.match(/url\("[^"]+"\)/g);
return !urls || urls.every(url => ALLOWED_CSS_URL_PREFIXES.some(prefix => url.slice(5).startsWith(prefix)));
}
class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a.PureComponent {
class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_13___default.a.PureComponent {
constructor(props) {
super(props);
this.onStyleMount = this.onStyleMount.bind(this);
@ -3233,7 +3214,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
switch (component.type) {
case "Highlights":
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_Highlights_Highlights__WEBPACK_IMPORTED_MODULE_10__["Highlights"], null);
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_Highlights_Highlights__WEBPACK_IMPORTED_MODULE_9__["Highlights"], null);
case "TopSites":
let promoAlignment;
@ -3242,28 +3223,28 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
promoAlignment = component.spocs.positions[0].index === 0 ? "left" : "right";
}
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_TopSites_TopSites__WEBPACK_IMPORTED_MODULE_17__["TopSites"], {
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_TopSites_TopSites__WEBPACK_IMPORTED_MODULE_16__["TopSites"], {
header: component.header,
data: component.data,
promoAlignment: promoAlignment
});
case "TextPromo":
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSTextPromo_DSTextPromo__WEBPACK_IMPORTED_MODULE_8__["DSTextPromo"], {
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSTextPromo_DSTextPromo__WEBPACK_IMPORTED_MODULE_7__["DSTextPromo"], {
dispatch: this.props.dispatch,
type: component.type,
data: component.data
});
case "Signup":
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSSignup_DSSignup__WEBPACK_IMPORTED_MODULE_7__["DSSignup"], {
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSSignup_DSSignup__WEBPACK_IMPORTED_MODULE_6__["DSSignup"], {
dispatch: this.props.dispatch,
type: component.type,
data: component.data
});
case "Message":
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSMessage_DSMessage__WEBPACK_IMPORTED_MODULE_5__["DSMessage"], {
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSMessage_DSMessage__WEBPACK_IMPORTED_MODULE_4__["DSMessage"], {
title: component.header && component.header.title,
subtitle: component.header && component.header.subtitle,
link_text: component.header && component.header.link_text,
@ -3272,12 +3253,12 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
});
case "SectionTitle":
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_SectionTitle_SectionTitle__WEBPACK_IMPORTED_MODULE_15__["SectionTitle"], {
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_SectionTitle_SectionTitle__WEBPACK_IMPORTED_MODULE_14__["SectionTitle"], {
header: component.header
});
case "Navigation":
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_Navigation_Navigation__WEBPACK_IMPORTED_MODULE_13__["Navigation"], {
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_Navigation_Navigation__WEBPACK_IMPORTED_MODULE_12__["Navigation"], {
dispatch: this.props.dispatch,
links: component.properties.links,
alignment: component.properties.alignment,
@ -3290,7 +3271,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
const {
DiscoveryStream
} = this.props;
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_CollectionCardGrid_CollectionCardGrid__WEBPACK_IMPORTED_MODULE_2__["CollectionCardGrid"], {
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_CollectionCardGrid_CollectionCardGrid__WEBPACK_IMPORTED_MODULE_1__["CollectionCardGrid"], {
data: component.data,
feed: component.feed,
spocs: DiscoveryStream.spocs,
@ -3305,7 +3286,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
});
case "CardGrid":
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_CardGrid_CardGrid__WEBPACK_IMPORTED_MODULE_1__["CardGrid"], {
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_CardGrid_CardGrid__WEBPACK_IMPORTED_MODULE_0__["CardGrid"], {
enable_video_playheads: !!component.properties.enable_video_playheads,
title: component.header && component.header.title,
display_variant: component.properties.display_variant,
@ -3320,7 +3301,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
});
case "Hero":
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_Hero_Hero__WEBPACK_IMPORTED_MODULE_9__["Hero"], {
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_Hero_Hero__WEBPACK_IMPORTED_MODULE_8__["Hero"], {
subComponentType: embedWidth >= 9 ? `cards` : `list`,
feed: component.feed,
title: component.header && component.header.title,
@ -3332,10 +3313,10 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
});
case "HorizontalRule":
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_HorizontalRule_HorizontalRule__WEBPACK_IMPORTED_MODULE_11__["HorizontalRule"], null);
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_HorizontalRule_HorizontalRule__WEBPACK_IMPORTED_MODULE_10__["HorizontalRule"], null);
case "List":
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_List_List__WEBPACK_IMPORTED_MODULE_12__["List"], {
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_List_List__WEBPACK_IMPORTED_MODULE_11__["List"], {
data: component.data,
feed: component.feed,
fullWidth: component.properties.full_width,
@ -3348,7 +3329,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
});
default:
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div", null, component.type);
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement("div", null, component.type);
}
}
@ -3356,7 +3337,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
// Use json string as both the key and styles to render so React knows when
// to unmount and mount a new instance for new styles.
const json = JSON.stringify(styles);
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("style", {
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement("style", {
key: json,
"data-styles": json,
ref: this.onStyleMount
@ -3372,28 +3353,16 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
render() {
// Select layout render data by adding spocs and position to recommendations
const {
layoutRender,
spocsFill
} = Object(content_src_lib_selectLayoutRender__WEBPACK_IMPORTED_MODULE_16__["selectLayoutRender"])({
layoutRender
} = Object(content_src_lib_selectLayoutRender__WEBPACK_IMPORTED_MODULE_15__["selectLayoutRender"])({
state: this.props.DiscoveryStream,
prefs: this.props.Prefs.values,
rollCache,
locale: this.props.locale
});
const {
config,
spocs,
feeds
} = this.props.DiscoveryStream; // Send SPOCS Fill if any. Note that it should not send it again if the same
// page gets re-rendered by state changes.
if (spocs.loaded && feeds.loaded && spocsFill.length && !this._spocsFillSent) {
this.props.dispatch(common_Actions_jsm__WEBPACK_IMPORTED_MODULE_0__["actionCreators"].DiscoveryStreamSpocsFill({
spoc_fills: spocsFill
}));
this._spocsFillSent = true;
} // Allow rendering without extracting special components
config
} = this.props.DiscoveryStream; // Allow rendering without extracting special components
if (!config.collapsible) {
return this.renderLayout(layoutRender);
@ -3437,7 +3406,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
}
}; // Render a DS-style TopSites then the rest if any in a collapsible section
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(react__WEBPACK_IMPORTED_MODULE_14___default.a.Fragment, null, this.props.DiscoveryStream.isPrivacyInfoModalVisible && react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSPrivacyModal_DSPrivacyModal__WEBPACK_IMPORTED_MODULE_6__["DSPrivacyModal"], {
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(react__WEBPACK_IMPORTED_MODULE_13___default.a.Fragment, null, this.props.DiscoveryStream.isPrivacyInfoModalVisible && react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_DiscoveryStreamComponents_DSPrivacyModal_DSPrivacyModal__WEBPACK_IMPORTED_MODULE_5__["DSPrivacyModal"], {
dispatch: this.props.dispatch
}), topSites && this.renderLayout([{
width: 12,
@ -3445,7 +3414,7 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
}]), sponsoredCollection && this.renderLayout([{
width: 12,
components: [sponsoredCollection]
}]), !!layoutRender.length && react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement(content_src_components_CollapsibleSection_CollapsibleSection__WEBPACK_IMPORTED_MODULE_3__["CollapsibleSection"], {
}]), !!layoutRender.length && react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement(content_src_components_CollapsibleSection_CollapsibleSection__WEBPACK_IMPORTED_MODULE_2__["CollapsibleSection"], {
className: "ds-layout",
collapsed: topStories.pref.collapsed,
dispatch: this.props.dispatch,
@ -3472,12 +3441,12 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
renderLayout(layoutRender) {
const styles = [];
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div", {
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement("div", {
className: "discovery-stream ds-layout"
}, layoutRender.map((row, rowIndex) => react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div", {
}, layoutRender.map((row, rowIndex) => react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement("div", {
key: `row-${rowIndex}`,
className: `ds-column ds-column-${row.width}`
}, react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div", {
}, react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement("div", {
className: "ds-column-grid"
}, row.components.map((component, componentIndex) => {
if (!component) {
@ -3485,14 +3454,14 @@ class _DiscoveryStreamBase extends react__WEBPACK_IMPORTED_MODULE_14___default.a
}
styles[rowIndex] = [...(styles[rowIndex] || []), component.styles];
return react__WEBPACK_IMPORTED_MODULE_14___default.a.createElement("div", {
return react__WEBPACK_IMPORTED_MODULE_13___default.a.createElement("div", {
key: `component-${componentIndex}`
}, this.renderComponent(component, row.width));
})))), this.renderStyles(styles));
}
}
const DiscoveryStreamBase = Object(react_redux__WEBPACK_IMPORTED_MODULE_4__["connect"])(state => ({
const DiscoveryStreamBase = Object(react_redux__WEBPACK_IMPORTED_MODULE_3__["connect"])(state => ({
DiscoveryStream: state.DiscoveryStream,
Prefs: state.Prefs,
Sections: state.Sections,
@ -9751,10 +9720,7 @@ const selectLayoutRender = ({
spocs
} = state;
let spocIndexMap = {};
let bufferRollCache = []; // Records the chosen and unchosen spocs by the probability selection.
let chosenSpocs = new Set();
let unchosenSpocs = new Set();
let bufferRollCache = [];
function rollForSpocs(data, spocsConfig, spocsData, placementName) {
if (!spocIndexMap[placementName] && spocIndexMap[placementName] !== 0) {
@ -9786,10 +9752,7 @@ const selectLayoutRender = ({
if (!spocs.blocked.includes(spoc.url)) {
results.splice(position.index, 0, spoc);
chosenSpocs.add(spoc);
}
} else {
unchosenSpocs.add(spoc);
}
}
@ -9964,38 +9927,9 @@ const selectLayoutRender = ({
if (!rollCache.length) {
rollCache.push(...bufferRollCache);
} // Generate the payload for the SPOCS Fill ping. Note that a SPOC could be rejected
// by the `probability_selection` first, then gets chosen for the next position. For
// all other SPOCS that never went through the probabilistic selection, its reason will
// be "out_of_position".
let spocsFill = [];
if (spocs.loaded && feeds.loaded && spocs.data.spocs && spocs.data.spocs.items) {
const chosenSpocsFill = [...chosenSpocs].map(spoc => ({
id: spoc.id,
reason: "n/a",
displayed: 1,
full_recalc: 0
}));
const unchosenSpocsFill = [...unchosenSpocs].filter(spoc => !chosenSpocs.has(spoc)).map(spoc => ({
id: spoc.id,
reason: "probability_selection",
displayed: 0,
full_recalc: 0
}));
const outOfPositionSpocsFill = spocs.data.spocs.items.slice(spocIndexMap.spocs).filter(spoc => !unchosenSpocs.has(spoc)).map(spoc => ({
id: spoc.id,
reason: "out_of_position",
displayed: 0,
full_recalc: 0
}));
spocsFill = [...chosenSpocsFill, ...unchosenSpocsFill, ...outOfPositionSpocsFill];
}
return {
spocsFill,
layoutRender
};
};

Просмотреть файл

@ -136,30 +136,6 @@ Schema definitions/validations that can be used for tests can be found in `syste
}
```
## Example Discovery Stream `SPOCS Fill` log
```js
{
// both "client_id" and "session_id" are set to "n/a" in this ping.
"client_id": "n/a",
"session_id": "n/a",
"impression_id": "{005deed0-e3e4-4c02-a041-17405fd703f6}",
"addon_version": "20180710100040",
"locale": "en-US",
"version": "68",
"release_channel": "release",
"spoc_fills": [
{"id": 10000, displayed: 0, reason: "frequency_cap", full_recalc: 1},
{"id": 10001, displayed: 0, reason: "blocked_by_user", full_recalc: 1},
{"id": 10002, displayed: 0, reason: "below_min_score", full_recalc: 1},
{"id": 10003, displayed: 0, reason: "flight_duplicate", full_recalc: 1},
{"id": 10004, displayed: 0, reason: "probability_selection", full_recalc: 0},
{"id": 10004, displayed: 0, reason: "out_of_position", full_recalc: 0},
{"id": 10005, displayed: 1, reason: "n/a", full_recalc: 0}
]
}
```
## Example Activity Stream `Router` Pings
```js

Просмотреть файл

@ -689,36 +689,6 @@ These pings record user interaction with the save to Pocket button.
}
```
## Discovery Stream SPOCS Fill ping
This reports the internal status of Pocket SPOCS (Sponsored Contents).
```js
{
// both "client_id" and "session_id" are set to "n/a" in this ping.
"client_id": "n/a",
"session_id": "n/a",
"impression_id": "{005deed0-e3e4-4c02-a041-17405fd703f6}",
"addon_version": "20180710100040",
"locale": "en-US",
"version": "68",
"release_channel": "release",
"experiments": {
"experiment_1": {"branch": "control"},
"experiment_2": {"branch": "treatment"}
},
"spoc_fills": [
{"id": 10000, displayed: 0, reason: "frequency_cap", full_recalc: 1},
{"id": 10001, displayed: 0, reason: "blocked_by_user", full_recalc: 1},
{"id": 10002, displayed: 0, reason: "below_min_score", full_recalc: 1},
{"id": 10003, displayed: 0, reason: "campaign_duplicate", full_recalc: 1},
{"id": 10004, displayed: 0, reason: "probability_selection", full_recalc: 0},
{"id": 10004, displayed: 0, reason: "out_of_position", full_recalc: 0},
{"id": 10005, displayed: 1, reason: "n/a", full_recalc: 0}
]
}
```
## Undesired event pings
These pings record the undesired events happen in the addon for further investigation.

Просмотреть файл

@ -97,35 +97,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
return impressionId;
}
/**
* Send SPOCS Fill telemetry.
* @param {object} filteredItems An object keyed on filter reasons, and the value
* is a list of SPOCS.
* reasons: blocked_by_user, frequency_cap, below_min_score, flight_duplicate
* @param {boolean} fullRecalc A boolean indicating if it's a full recalculation.
* Calling `loadSpocs` will be treated as a full recalculation.
* Whereas responding the action "DISCOVERY_STREAM_SPOC_IMPRESSION"
* is not a full recalculation.
*/
_sendSpocsFill(filteredItems, fullRecalc) {
const full_recalc = fullRecalc ? 1 : 0;
const spocsFill = [];
for (const [reason, items] of Object.entries(filteredItems)) {
items.forEach(item => {
// Only send SPOCS (i.e. it has a flight_id)
if (item.flight_id) {
spocsFill.push({ reason, full_recalc, id: item.id, displayed: 0 });
}
});
}
if (spocsFill.length) {
this.store.dispatch(
ac.DiscoveryStreamSpocsFill({ spoc_fills: spocsFill })
);
}
}
finalLayoutEndpoint(url, apiKey) {
if (url.includes("$apiKey") && !apiKey) {
throw new Error(
@ -692,10 +663,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
const cachedData = (await this.cache.get()) || {};
let spocsState;
let frequencyCapped = [];
let blockedItems = [];
let belowMinScore = [];
const { placements } = this.store.getState().DiscoveryStream.spocs;
if (this.showSpocs) {
@ -775,24 +742,14 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
normalizedSpocsItems
);
const {
data: capResult,
filtered: caps,
} = this.frequencyCapSpocs(migratedSpocs);
frequencyCapped = [...frequencyCapped, ...caps];
const { data: capResult } = this.frequencyCapSpocs(migratedSpocs);
const {
data: blockedResults,
filtered: blocks,
} = this.filterBlocked(capResult);
blockedItems = [...blockedItems, ...blocks];
const { data: blockedResults } = this.filterBlocked(capResult);
const {
data: scoredResults,
filtered: minScoreFilter,
} = await this.scoreItems(blockedResults, "spocs");
belowMinScore = [...belowMinScore, ...minScoreFilter];
const { data: scoredResults } = await this.scoreItems(
blockedResults,
"spocs"
);
spocsState.spocs = {
...spocsState.spocs,
@ -813,14 +770,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
lastUpdated: spocsState.lastUpdated,
spocs: spocsState.spocs,
});
this._sendSpocsFill(
{
frequency_cap: frequencyCapped,
blocked_by_user: blockedItems,
below_min_score: belowMinScore,
},
true
);
} else {
Cu.reportError("No response for spocs_endpoint prop");
}
@ -987,7 +936,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
}
async scoreItems(items, type) {
const filtered = [];
const spocsPersonalized = this.store.getState().Prefs.values[
PREF_SPOCS_PERSONALIZED
];
@ -1007,13 +955,12 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
if (s.score >= s.min_score) {
return true;
}
filtered.push(s);
return false;
})
// Sort by highest scores.
.sort(this.sortItem);
return { data, filtered };
return { data };
}
async scoreItem(item, personalizedByType) {
@ -1029,24 +976,17 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
}
filterBlocked(data) {
const filtered = [];
if (data && data.length) {
let flights = this.readDataPref(PREF_FLIGHT_BLOCKS);
const filteredItems = data.filter(item => {
const blocked =
NewTabUtils.blockedLinks.isBlocked({ url: item.url }) ||
flights[item.flight_id];
if (blocked) {
filtered.push(item);
}
return !blocked;
});
return {
data: filteredItems,
filtered,
};
return { data: filteredItems };
}
return { data, filtered };
return { data };
}
// For backwards compatibility, older spoc endpoint don't have flight_id,
@ -1320,7 +1260,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
}
async scoreSpocs(spocsState) {
let belowMinScore = [];
const spocsResultPromises = this.getPlacements().map(async placement => {
const nextSpocs = spocsState.data[placement.name] || {};
const { items } = nextSpocs;
@ -1329,12 +1268,7 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
return;
}
const {
data: scoreResult,
filtered: minScoreFilter,
} = await this.scoreItems(items, "spocs");
belowMinScore = [...belowMinScore, ...minScoreFilter];
const { data: scoreResult } = await this.scoreItems(items, "spocs");
spocsState.data = {
...spocsState.data,
@ -1361,14 +1295,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
},
})
);
if (belowMinScore.length) {
this._sendSpocsFill(
{
below_min_score: belowMinScore,
},
false
);
}
}
async refreshContent(options = {}) {
@ -1735,7 +1661,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
},
})
);
this._sendSpocsFill({ frequency_cap: frequencyCapped }, false);
}
}
break;
@ -1778,7 +1703,6 @@ this.DiscoveryStreamFeed = class DiscoveryStreamFeed {
spocs: spocsState.data,
});
this._sendSpocsFill({ blocked_by_user: blockedItems }, false);
// If we're blocking a spoc, we want open tabs to have
// a slightly different treatment from future tabs.
// AlsoToPreloaded updates the source data and preloaded tabs with a new spoc.

Просмотреть файл

@ -556,13 +556,6 @@ this.TelemetryFeed = class TelemetryFeed {
});
}
createSpocsFillPing(data) {
return Object.assign(this.createPing(null), data, {
impression_id: this._impressionId,
session_id: "n/a",
});
}
createUserEvent(action) {
return Object.assign(
this.createPing(au.getPortIdOfSender(action)),
@ -941,9 +934,6 @@ this.TelemetryFeed = class TelemetryFeed {
action.data
);
break;
case at.DISCOVERY_STREAM_SPOCS_FILL:
this.handleDiscoveryStreamSpocsFill(action.data);
break;
case at.TELEMETRY_UNDESIRED_EVENT:
this.handleUndesiredEvent(action);
break;
@ -1031,38 +1021,6 @@ this.TelemetryFeed = class TelemetryFeed {
session.loadedContentSets = loadedContentSets;
}
/**
* Handl SPOCS Fill actions from Discovery Stream.
*
* @param {Object} data
* The SPOCS Fill event structured as:
* {
* spoc_fills: [
* {
* id: 123,
* displayed: 0,
* reason: "frequency_cap",
* full_recalc: 1
* },
* {
* id: 124,
* displayed: 1,
* reason: "n/a",
* full_recalc: 1
* }
* ]
* }
*/
handleDiscoveryStreamSpocsFill(data) {
const payload = this.createSpocsFillPing(data);
this.sendStructuredIngestionEvent(
payload,
STRUCTURED_INGESTION_NAMESPACE_AS,
"spoc-fills",
"1"
);
}
/**
* Take all enumerable members of the data object and merge them into
* the session.perf object for the given port, so that it is sent to the

Просмотреть файл

@ -189,29 +189,6 @@ export const ImpressionStatsPing = Joi.object().keys(
})
);
export const SpocsFillEntrySchema = Joi.object().keys({
id: Joi.number()
.integer()
.required(),
displayed: Joi.number()
.integer()
.required(),
reason: Joi.string().required(),
full_recalc: Joi.number()
.integer()
.required(),
});
export const SpocsFillPing = Joi.object().keys(
Object.assign({}, baseKeys, {
impression_id: Joi.string().required(),
session_id: Joi.valid("n/a").required(),
spoc_fills: Joi.array()
.items(SpocsFillEntrySchema)
.required(),
})
);
export const SessionPing = Joi.object().keys(
Object.assign({}, baseKeys, {
session_id: baseKeys.session_id.required(),

Просмотреть файл

@ -37,13 +37,6 @@ describe("selectLayoutRender", () => {
assert.deepEqual(layoutRender, []);
});
it("should return an empty SPOCS fill array given initial state", () => {
const { spocsFill } = selectLayoutRender({
state: store.getState().DiscoveryStream,
});
assert.deepEqual(spocsFill, []);
});
it("should add .data property from feeds to each compontent in .layout", () => {
store.dispatch({
type: at.DISCOVERY_STREAM_LAYOUT_UPDATE,
@ -217,7 +210,7 @@ describe("selectLayoutRender", () => {
});
});
it("should return spoc result and spocs fill for rolls below the probability", () => {
it("should return spoc result for rolls below the probability", () => {
const fakeSpocConfig = {
positions: [{ index: 0 }, { index: 1 }],
probability: 0.5,
@ -250,7 +243,7 @@ describe("selectLayoutRender", () => {
});
const randomStub = globals.sandbox.stub(global.Math, "random").returns(0.1);
const { spocsFill, layoutRender } = selectLayoutRender({
const { layoutRender } = selectLayoutRender({
state: store.getState().DiscoveryStream,
});
@ -270,14 +263,9 @@ describe("selectLayoutRender", () => {
assert.deepEqual(layoutRender[0].components[0].data.recommendations[3], {
id: "bar",
});
assert.deepEqual(spocsFill, [
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
]);
});
it("should return spoc result and spocs fill when there are more positions than spocs", () => {
it("should return spoc result when there are more positions than spocs", () => {
const fakeSpocConfig = {
positions: [{ index: 0 }, { index: 1 }, { index: 2 }],
probability: 0.5,
@ -310,7 +298,7 @@ describe("selectLayoutRender", () => {
});
const randomStub = globals.sandbox.stub(global.Math, "random").returns(0.1);
const { spocsFill, layoutRender } = selectLayoutRender({
const { layoutRender } = selectLayoutRender({
state: store.getState().DiscoveryStream,
});
@ -330,11 +318,6 @@ describe("selectLayoutRender", () => {
assert.deepEqual(layoutRender[0].components[0].data.recommendations[3], {
id: "bar",
});
assert.deepEqual(spocsFill, [
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
]);
});
it("should report non-displayed spocs with reason as probability_selection and out_of_position", () => {
@ -370,7 +353,7 @@ describe("selectLayoutRender", () => {
});
const randomStub = globals.sandbox.stub(global.Math, "random");
const { spocsFill, layoutRender } = selectLayoutRender({
const { layoutRender } = selectLayoutRender({
state: store.getState().DiscoveryStream,
rollCache: [0.7, 0.3, 0.8],
});
@ -387,22 +370,6 @@ describe("selectLayoutRender", () => {
assert.deepEqual(layoutRender[0].components[0].data.recommendations[2], {
id: "bar",
});
assert.deepEqual(spocsFill, [
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
{
id: undefined,
reason: "probability_selection",
displayed: 0,
full_recalc: 0,
},
{
id: undefined,
reason: "out_of_position",
displayed: 0,
full_recalc: 0,
},
]);
});
it("should not return spoc result for rolls above the probability", () => {
@ -438,7 +405,7 @@ describe("selectLayoutRender", () => {
});
const randomStub = globals.sandbox.stub(global.Math, "random").returns(0.6);
const { spocsFill, layoutRender } = selectLayoutRender({
const { layoutRender } = selectLayoutRender({
state: store.getState().DiscoveryStream,
});
@ -450,21 +417,6 @@ describe("selectLayoutRender", () => {
assert.deepEqual(layoutRender[0].components[0].data.recommendations[1], {
id: "bar",
});
assert.deepEqual(spocsFill, [
{
id: undefined,
reason: "probability_selection",
displayed: 0,
full_recalc: 0,
},
{
id: undefined,
reason: "out_of_position",
displayed: 0,
full_recalc: 0,
},
]);
});
it("Subsequent render should return spoc result for cached rolls below the probability", () => {
@ -500,7 +452,7 @@ describe("selectLayoutRender", () => {
});
const randomStub = globals.sandbox.stub(global.Math, "random");
const { spocsFill, layoutRender } = selectLayoutRender({
const { layoutRender } = selectLayoutRender({
state: store.getState().DiscoveryStream,
rollCache: [0.4, 0.3],
});
@ -521,11 +473,6 @@ describe("selectLayoutRender", () => {
assert.deepEqual(layoutRender[0].components[0].data.recommendations[3], {
id: "bar",
});
assert.deepEqual(spocsFill, [
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
]);
});
it("Subsequent render should not return spoc result for cached rolls above the probability", () => {
@ -561,7 +508,7 @@ describe("selectLayoutRender", () => {
});
const randomStub = globals.sandbox.stub(global.Math, "random");
const { spocsFill, layoutRender } = selectLayoutRender({
const { layoutRender } = selectLayoutRender({
state: store.getState().DiscoveryStream,
rollCache: [0.6, 0.7],
});
@ -574,21 +521,6 @@ describe("selectLayoutRender", () => {
assert.deepEqual(layoutRender[0].components[0].data.recommendations[1], {
id: "bar",
});
assert.deepEqual(spocsFill, [
{
id: undefined,
reason: "probability_selection",
displayed: 0,
full_recalc: 0,
},
{
id: undefined,
reason: "out_of_position",
displayed: 0,
full_recalc: 0,
},
]);
});
it("Subsequent render should return spoc result by cached rolls probability", () => {
@ -624,7 +556,7 @@ describe("selectLayoutRender", () => {
});
const randomStub = globals.sandbox.stub(global.Math, "random");
const { spocsFill, layoutRender } = selectLayoutRender({
const { layoutRender } = selectLayoutRender({
state: store.getState().DiscoveryStream,
rollCache: [0.7, 0.2],
});
@ -641,16 +573,6 @@ describe("selectLayoutRender", () => {
assert.deepEqual(layoutRender[0].components[0].data.recommendations[2], {
id: "bar",
});
assert.deepEqual(spocsFill, [
{ id: undefined, reason: "n/a", displayed: 1, full_recalc: 0 },
{
id: undefined,
reason: "out_of_position",
displayed: 0,
full_recalc: 0,
},
]);
});
it("should return a layout with feeds of items length with positions", () => {
@ -681,7 +603,7 @@ describe("selectLayoutRender", () => {
});
store.dispatch({ type: at.DISCOVERY_STREAM_FEEDS_UPDATE });
const { spocsFill, layoutRender } = selectLayoutRender({
const { layoutRender } = selectLayoutRender({
state: store.getState().DiscoveryStream,
});
@ -691,8 +613,6 @@ describe("selectLayoutRender", () => {
assert.equal(recommendations[1].pos, 1);
assert.equal(recommendations[2].pos, 2);
assert.equal(recommendations[3].pos, undefined);
assert.lengthOf(spocsFill, 0);
});
it("should stop rendering feeds if we hit one that's not ready", () => {
const fakeLayout = [

Просмотреть файл

@ -1234,7 +1234,7 @@ describe("DiscoveryStreamFeed", () => {
});
it("should remove items with scores lower than min_score", async () => {
const { data: result, filtered } = await feed.scoreItems([
const { data: result } = await feed.scoreItems([
{ id: 2, flight_id: 2, item_score: 0.8, min_score: 0.9 },
{ id: 3, flight_id: 3, item_score: 0.7, min_score: 0.7 },
{ id: 1, flight_id: 1, item_score: 0.9, min_score: 0.8 },
@ -1244,10 +1244,6 @@ describe("DiscoveryStreamFeed", () => {
{ id: 1, flight_id: 1, item_score: 0.9, score: 0.9, min_score: 0.8 },
{ id: 3, flight_id: 3, item_score: 0.7, score: 0.7, min_score: 0.7 },
]);
assert.deepEqual(filtered, [
{ id: 2, flight_id: 2, item_score: 0.8, min_score: 0.9, score: 0.8 },
]);
});
it("should add a score prop to spocs", async () => {
@ -1258,7 +1254,7 @@ describe("DiscoveryStreamFeed", () => {
assert.equal(result[0].score, 0.9);
});
it("should score items using item_score and min_score", async () => {
const { data: result, filtered } = await feed.scoreItems([
const { data: result } = await feed.scoreItems([
{ item_score: 0.8, min_score: 0.1 },
{ item_score: 0.5, min_score: 0.6 },
{ item_score: 0.7, min_score: 0.1 },
@ -1269,9 +1265,6 @@ describe("DiscoveryStreamFeed", () => {
{ item_score: 0.8, score: 0.8, min_score: 0.1 },
{ item_score: 0.7, score: 0.7, min_score: 0.1 },
]);
assert.deepEqual(filtered, [
{ item_score: 0.5, min_score: 0.6, score: 0.5 },
]);
});
});
@ -1288,21 +1281,6 @@ describe("DiscoveryStreamFeed", () => {
]);
assert.equal(result.length, 2);
});
it("should return filtered out based on blockedlist", () => {
fakeNewTabUtils.blockedLinks.links = [{ url: "https://foo.com" }];
fakeNewTabUtils.blockedLinks.isBlocked = site =>
fakeNewTabUtils.blockedLinks.links[0].url === site.url;
const { data: result, filtered } = feed.filterBlocked([
{ id: 1, url: "https://foo.com" },
{ id: 2, url: "test.com" },
]);
assert.lengthOf(result, 1);
assert.equal(result[0].url, "test.com");
assert.notInclude(result, fakeNewTabUtils.blockedLinks.links[0]);
assert.deepEqual(filtered, [{ id: 1, url: "https://foo.com" }]);
});
it("should return initial recommendations data if links are not blocked", () => {
const { data: result } = feed.filterBlocked([
{ url: "https://foo.com" },
@ -1767,15 +1745,6 @@ describe("DiscoveryStreamFeed", () => {
],
},
};
const spocFillResult = [
{
id: 1,
reason: "frequency_cap",
displayed: 0,
full_recalc: 0,
},
];
sandbox.stub(feed, "recordFlightImpression").returns();
sandbox.stub(feed, "readDataPref").returns(fakeImpressions);
sandbox.spy(feed.store, "dispatch");
@ -1789,10 +1758,6 @@ describe("DiscoveryStreamFeed", () => {
feed.store.dispatch.secondCall.args[0].data.spocs,
result
);
assert.deepEqual(
feed.store.dispatch.thirdCall.args[0].data.spoc_fills,
spocFillResult
);
});
it("should not call dispatch to ac.AlsoToPreloaded if spocs were not changed by frequency capping", async () => {
Object.defineProperty(feed, "showSpocs", { get: () => true });
@ -1881,16 +1846,8 @@ describe("DiscoveryStreamFeed", () => {
});
});
it("should call dispatch with the SPOCS Fill if found a blocked spoc", async () => {
it("should call dispatch if found a blocked spoc", async () => {
Object.defineProperty(feed, "showSpocs", { get: () => true });
const spocFillResult = [
{
id: 1,
reason: "blocked_by_user",
displayed: 0,
full_recalc: 0,
},
];
sandbox.spy(feed.store, "dispatch");
@ -1900,15 +1857,11 @@ describe("DiscoveryStreamFeed", () => {
});
assert.deepEqual(
feed.store.dispatch.firstCall.args[0].data.spoc_fills,
spocFillResult
);
assert.deepEqual(
feed.store.dispatch.secondCall.args[0].data.url,
feed.store.dispatch.firstCall.args[0].data.url,
"foo.com"
);
});
it("should not call dispatch with the SPOCS Fill if the blocked is not a SPOC", async () => {
it("should dispatch once if the blocked is not a SPOC", async () => {
Object.defineProperty(feed, "showSpocs", { get: () => true });
sandbox.spy(feed.store, "dispatch");
@ -1933,7 +1886,7 @@ describe("DiscoveryStreamFeed", () => {
});
assert.equal(
feed.store.dispatch.thirdCall.args[0].type,
feed.store.dispatch.secondCall.args[0].type,
"DISCOVERY_STREAM_SPOC_BLOCKED"
);
});
@ -2677,10 +2630,9 @@ describe("DiscoveryStreamFeed", () => {
});
describe("#scoreSpocs", () => {
it("should score spocs and set cache, dispatch, and spocsFill", async () => {
it("should score spocs and set cache, dispatch", async () => {
sandbox.stub(feed.cache, "set").resolves();
sandbox.spy(feed.store, "dispatch");
sandbox.stub(feed, "_sendSpocsFill").returns();
const fakeDiscoveryStream = {
Prefs: {
values: {
@ -2779,13 +2731,6 @@ describe("DiscoveryStreamFeed", () => {
feed.store.dispatch.firstCall.args[0].data,
spocsTestResult
);
assert.calledWith(
feed._sendSpocsFill,
{
below_min_score: [{ item_score: 0.4, min_score: 0.5, score: 0.4 }],
},
false
);
});
});
@ -2892,7 +2837,7 @@ describe("DiscoveryStreamFeed", () => {
});
describe("#scoreItems", () => {
it("should score items using item_score and min_score", async () => {
const { data: result, filtered } = await feed.scoreItems([
const { data: result } = await feed.scoreItems([
{ item_score: 0.8, min_score: 0.1 },
{ item_score: 0.5, min_score: 0.6 },
{ item_score: 0.7, min_score: 0.1 },
@ -2903,9 +2848,6 @@ describe("DiscoveryStreamFeed", () => {
{ item_score: 0.8, score: 0.8, min_score: 0.1 },
{ item_score: 0.7, score: 0.7, min_score: 0.1 },
]);
assert.deepEqual(filtered, [
{ item_score: 0.5, min_score: 0.6, score: 0.5 },
]);
});
});
describe("#scoreItem", () => {
@ -2945,84 +2887,4 @@ describe("DiscoveryStreamFeed", () => {
assert.equal(result.min_score, 0);
});
});
describe("#_sendSpocsFill", () => {
it("should send out all the SPOCS Fill pings", () => {
sandbox.spy(feed.store, "dispatch");
const expected = [
{ id: 1, reason: "frequency_cap", displayed: 0, full_recalc: 1 },
{ id: 2, reason: "frequency_cap", displayed: 0, full_recalc: 1 },
{ id: 3, reason: "blocked_by_user", displayed: 0, full_recalc: 1 },
{ id: 4, reason: "blocked_by_user", displayed: 0, full_recalc: 1 },
{ id: 5, reason: "flight_duplicate", displayed: 0, full_recalc: 1 },
{ id: 6, reason: "flight_duplicate", displayed: 0, full_recalc: 1 },
{ id: 7, reason: "below_min_score", displayed: 0, full_recalc: 1 },
{ id: 8, reason: "below_min_score", displayed: 0, full_recalc: 1 },
];
const filtered = {
frequency_cap: [
{ id: 1, flight_id: 1 },
{ id: 2, flight_id: 2 },
],
blocked_by_user: [
{ id: 3, flight_id: 3 },
{ id: 4, flight_id: 4 },
],
flight_duplicate: [
{ id: 5, flight_id: 5 },
{ id: 6, flight_id: 6 },
],
below_min_score: [
{ id: 7, flight_id: 7 },
{ id: 8, flight_id: 8 },
],
};
feed._sendSpocsFill(filtered, true);
assert.deepEqual(
feed.store.dispatch.firstCall.args[0].data.spoc_fills,
expected
);
});
it("should send SPOCS Fill ping with the correct full_recalc", () => {
sandbox.spy(feed.store, "dispatch");
const expected = [
{ id: 1, reason: "frequency_cap", displayed: 0, full_recalc: 0 },
{ id: 2, reason: "frequency_cap", displayed: 0, full_recalc: 0 },
];
const filtered = {
frequency_cap: [
{ id: 1, flight_id: 1 },
{ id: 2, flight_id: 2 },
],
};
feed._sendSpocsFill(filtered, false);
assert.deepEqual(
feed.store.dispatch.firstCall.args[0].data.spoc_fills,
expected
);
});
it("should not send non-SPOCS Fill pings", () => {
sandbox.spy(feed.store, "dispatch");
const expected = [
{ id: 1, reason: "frequency_cap", displayed: 0, full_recalc: 1 },
{ id: 3, reason: "blocked_by_user", displayed: 0, full_recalc: 1 },
{ id: 5, reason: "flight_duplicate", displayed: 0, full_recalc: 1 },
{ id: 7, reason: "below_min_score", displayed: 0, full_recalc: 1 },
];
const filtered = {
frequency_cap: [{ id: 1, flight_id: 1 }, { id: 2 }],
blocked_by_user: [{ id: 3, flight_id: 3 }, { id: 4 }],
flight_duplicate: [{ id: 5, flight_id: 5 }, { id: 6 }],
below_min_score: [{ id: 7, flight_id: 7 }, { id: 8 }],
};
feed._sendSpocsFill(filtered, true);
assert.deepEqual(
feed.store.dispatch.firstCall.args[0].data.spoc_fills,
expected
);
});
});
});

Просмотреть файл

@ -9,7 +9,6 @@ import {
BasePing,
ImpressionStatsPing,
SessionPing,
SpocsFillPing,
UndesiredPing,
UserEventPing,
} from "test/schemas/pings";
@ -731,20 +730,6 @@ describe("TelemetryFeed", () => {
assert.propertyVal(ping.tiles[0], "shim", tiles[0].shim);
});
});
describe("#createSpocsFillPing", () => {
it("should create a valid SPOCS Fill ping", async () => {
const spocFills = [
{ id: 10001, displayed: 0, reason: "frequency_cap", full_recalc: 1 },
{ id: 10002, displayed: 0, reason: "blocked_by_user", full_recalc: 1 },
{ id: 10003, displayed: 1, reason: "n/a", full_recalc: 1 },
];
const action = ac.DiscoveryStreamSpocsFill({ spoc_fills: spocFills });
const ping = await instance.createSpocsFillPing(action.data);
assert.validate(ping, SpocsFillPing);
assert.propertyVal(ping, "spoc_fills", spocFills);
});
});
describe("#applyCFRPolicy", () => {
it("should use client_id and message_id in prerelease", async () => {
globals.set("UpdateUtils", {
@ -1520,21 +1505,6 @@ describe("TelemetryFeed", () => {
data
);
});
it("should send an event on a DISCOVERY_STREAM_SPOCS_FILL action", () => {
const sendEvent = sandbox.stub(instance, "sendStructuredIngestionEvent");
const eventCreator = sandbox.stub(instance, "createSpocsFillPing");
const spocFills = [
{ id: 10001, displayed: 0, reason: "frequency_cap", full_recalc: 1 },
{ id: 10002, displayed: 0, reason: "blocked_by_user", full_recalc: 1 },
{ id: 10003, displayed: 1, reason: "n/a", full_recalc: 1 },
];
const action = ac.DiscoveryStreamSpocsFill({ spoc_fills: spocFills });
instance.onAction(action);
assert.calledWith(eventCreator, action.data);
assert.calledWith(sendEvent, eventCreator.returnValue);
});
});
describe("#handleNewTabInit", () => {
it("should set the session as preloaded if the browser is preloaded", () => {