<commit_before>/* 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/. */
"use strict";

ChromeUtils.import("resource://gre/modules/EventEmitter.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
const {actionCreators: ac, actionTypes: at} = ChromeUtils.import("resource://activity-stream/common/Actions.jsm", {});

ChromeUtils.defineModuleGetter(this, "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm");

/*
 * Generators for built in sections, keyed by the pref name for their feed.
 * Built in sections may depend on options stored as serialised JSON in the pref
 * `${feed_pref_name}.options`.
 */
const BUILT_IN_SECTIONS = {
  "feeds.section.topstories": options => ({
    id: "topstories",
    pref: {
      titleString: {id: "header_recommended_by", values: {provider: options.provider_name}},
      descString: {id: options.provider_description || "pocket_description"},
      nestedPrefs: options.show_spocs ? [{
        name: "showSponsored",
        titleString: {id: "settings_pane_topstories_options_sponsored"},
        icon: "icon-info"
      }] : []
    },
    shouldHidePref: options.hidden,
    eventSource: "TOP_STORIES",
    icon: options.provider_icon,
    title: {id: "header_recommended_by", values: {provider: options.provider_name}},
    disclaimer: {
      text: {id: options.disclaimer_text || "section_disclaimer_topstories"},
      link: {
        // The href fallback is temporary so users in existing Shield studies get this configuration as well
        href: options.disclaimer_link || "https://getpocket.cdn.mozilla.net/firefox/new_tab_learn_more",
        id: options.disclaimer_linktext || "section_disclaimer_topstories_linktext"
      },
      button: {id: options.disclaimer_buttontext || "section_disclaimer_topstories_buttontext"}
    },
    privacyNoticeURL: options.privacy_notice_link || "https://www.mozilla.org/privacy/firefox/#suggest-relevant-content",
    maxRows: 1,
    availableLinkMenuOptions: ["CheckBookmarkOrArchive", "CheckSavedToPocket", "Separator", "OpenInNewWindow", "OpenInPrivateWindow", "Separator", "BlockUrl"],
    emptyState: {
      message: {id: "topstories_empty_state", values: {provider: options.provider_name}},
      icon: "check"
    },
    shouldSendImpressionStats: true,
    order: 0,
    dedupeFrom: ["highlights"]
  }),
  "feeds.section.highlights": options => ({
    id: "highlights",
    pref: {
      titleString: {id: "settings_pane_highlights_header"},
      descString: {id: "settings_pane_highlights_body2"}
    },
    shouldHidePref:  false,
    eventSource: "HIGHLIGHTS",
    icon: "highlights",
    title: {id: "header_highlights"},
    maxRows: 3,
    availableLinkMenuOptions: ["CheckBookmarkOrArchive", "CheckSavedToPocket", "Separator", "OpenInNewWindow", "OpenInPrivateWindow", "Separator", "BlockUrl", "CheckDeleteHistoryOrEmpty"],
    emptyState: {
      message: {id: "highlights_empty_state"},
      icon: "highlights"
    },
    shouldSendImpressionStats: false,
    order: 1
  })
};

const SectionsManager = {
  ACTIONS_TO_PROXY: ["WEBEXT_CLICK", "WEBEXT_DISMISS"],
  CONTEXT_MENU_PREFS: {"SaveToPocket": "extensions.pocket.enabled"},
  initialized: false,
  sections: new Map(),
  init(prefs = {}) {
    for (const feedPrefName of Object.keys(BUILT_IN_SECTIONS)) {
      const optionsPrefName = `${feedPrefName}.options`;
      this.addBuiltInSection(feedPrefName, prefs[optionsPrefName]);

      this._dedupeConfiguration = [];
      this.sections.forEach(section => {
        if (section.dedupeFrom) {
          this._dedupeConfiguration.push({
            id: section.id,
            dedupeFrom: section.dedupeFrom
          });
        }
      });
    }

    Object.keys(this.CONTEXT_MENU_PREFS).forEach(k =>
      Services.prefs.addObserver(this.CONTEXT_MENU_PREFS[k], this));

    this.initialized = true;
    this.emit(this.INIT);
  },
  observe(subject, topic, data) {
    switch (topic) {
      case "nsPref:changed":
        for (const pref of Object.keys(this.CONTEXT_MENU_PREFS)) {
          if (data === this.CONTEXT_MENU_PREFS[pref]) {
            this.updateSections();
          }
        }
        break;
    }
  },
  addBuiltInSection(feedPrefName, optionsPrefValue = "{}") {
    let options;
    try {
      options = JSON.parse(optionsPrefValue);
    } catch (e) {
      options = {};
      Cu.reportError("Problem parsing options pref", e);
    }
    const section = BUILT_IN_SECTIONS[feedPrefName](options);
    section.pref.feed = feedPrefName;
    this.addSection(section.id, Object.assign(section, {options}));
  },
  addSection(id, options) {
    this.updateLinkMenuOptions(options);
    this.sections.set(id, options);
    this.emit(this.ADD_SECTION, id, options);
  },
  removeSection(id) {
    this.emit(this.REMOVE_SECTION, id);
    this.sections.delete(id);
  },
  enableSection(id) {
    this.updateSection(id, {enabled: true}, true);
    this.emit(this.ENABLE_SECTION, id);
  },
  disableSection(id) {<commit_msg>Fix Bug 1442992 - Remove second argument from Cu.reportError call.<commit_after>/* 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/. */
"use strict";

ChromeUtils.import("resource://gre/modules/EventEmitter.jsm");
ChromeUtils.import("resource://gre/modules/Services.jsm");
ChromeUtils.import("resource://gre/modules/XPCOMUtils.jsm");
const {actionCreators: ac, actionTypes: at} = ChromeUtils.import("resource://activity-stream/common/Actions.jsm", {});

ChromeUtils.defineModuleGetter(this, "PlacesUtils", "resource://gre/modules/PlacesUtils.jsm");

/*
 * Generators for built in sections, keyed by the pref name for their feed.
 * Built in sections may depend on options stored as serialised JSON in the pref
 * `${feed_pref_name}.options`.
 */
const BUILT_IN_SECTIONS = {
  "feeds.section.topstories": options => ({
    id: "topstories",
    pref: {
      titleString: {id: "header_recommended_by", values: {provider: options.provider_name}},
      descString: {id: options.provider_description || "pocket_description"},
      nestedPrefs: options.show_spocs ? [{
        name: "showSponsored",
        titleString: {id: "settings_pane_topstories_options_sponsored"},
        icon: "icon-info"
      }] : []
    },
    shouldHidePref: options.hidden,
    eventSource: "TOP_STORIES",
    icon: options.provider_icon,
    title: {id: "header_recommended_by", values: {provider: options.provider_name}},
    disclaimer: {
      text: {id: options.disclaimer_text || "section_disclaimer_topstories"},
      link: {
        // The href fallback is temporary so users in existing Shield studies get this configuration as well
        href: options.disclaimer_link || "https://getpocket.cdn.mozilla.net/firefox/new_tab_learn_more",
        id: options.disclaimer_linktext || "section_disclaimer_topstories_linktext"
      },
      button: {id: options.disclaimer_buttontext || "section_disclaimer_topstories_buttontext"}
    },
    privacyNoticeURL: options.privacy_notice_link || "https://www.mozilla.org/privacy/firefox/#suggest-relevant-content",
    maxRows: 1,
    availableLinkMenuOptions: ["CheckBookmarkOrArchive", "CheckSavedToPocket", "Separator", "OpenInNewWindow", "OpenInPrivateWindow", "Separator", "BlockUrl"],
    emptyState: {
      message: {id: "topstories_empty_state", values: {provider: options.provider_name}},
      icon: "check"
    },
    shouldSendImpressionStats: true,
    order: 0,
    dedupeFrom: ["highlights"]
  }),
  "feeds.section.highlights": options => ({
    id: "highlights",
    pref: {
      titleString: {id: "settings_pane_highlights_header"},
      descString: {id: "settings_pane_highlights_body2"}
    },
    shouldHidePref:  false,
    eventSource: "HIGHLIGHTS",
    icon: "highlights",
    title: {id: "header_highlights"},
    maxRows: 3,
    availableLinkMenuOptions: ["CheckBookmarkOrArchive", "CheckSavedToPocket", "Separator", "OpenInNewWindow", "OpenInPrivateWindow", "Separator", "BlockUrl", "CheckDeleteHistoryOrEmpty"],
    emptyState: {
      message: {id: "highlights_empty_state"},
      icon: "highlights"
    },
    shouldSendImpressionStats: false,
    order: 1
  })
};

const SectionsManager = {
  ACTIONS_TO_PROXY: ["WEBEXT_CLICK", "WEBEXT_DISMISS"],
  CONTEXT_MENU_PREFS: {"SaveToPocket": "extensions.pocket.enabled"},
  initialized: false,
  sections: new Map(),
  init(prefs = {}) {
    for (const feedPrefName of Object.keys(BUILT_IN_SECTIONS)) {
      const optionsPrefName = `${feedPrefName}.options`;
      this.addBuiltInSection(feedPrefName, prefs[optionsPrefName]);

      this._dedupeConfiguration = [];
      this.sections.forEach(section => {
        if (section.dedupeFrom) {
          this._dedupeConfiguration.push({
            id: section.id,
            dedupeFrom: section.dedupeFrom
          });
        }
      });
    }

    Object.keys(this.CONTEXT_MENU_PREFS).forEach(k =>
      Services.prefs.addObserver(this.CONTEXT_MENU_PREFS[k], this));

    this.initialized = true;
    this.emit(this.INIT);
  },
  observe(subject, topic, data) {
    switch (topic) {
      case "nsPref:changed":
        for (const pref of Object.keys(this.CONTEXT_MENU_PREFS)) {
          if (data === this.CONTEXT_MENU_PREFS[pref]) {
            this.updateSections();
          }
        }
        break;
    }
  },
  addBuiltInSection(feedPrefName, optionsPrefValue = "{}") {
    let options;
    try {
      options = JSON.parse(optionsPrefValue);
    } catch (e) {
      options = {};
      Cu.reportError(`Problem parsing options pref for ${feedPrefName}`);
    }
    const section = BUILT_IN_SECTIONS[feedPrefName](options);
    section.pref.feed = feedPrefName;
    this.addSection(section.id, Object.assign(section, {options}));
  },
  addSection(id, options) {
    this.updateLinkMenuOptions(options);
    this.sections.set(id, options);
    this.emit(this.ADD_SECTION, id, options);
  },
  removeSection(id) {
    this.emit(this.REMOVE_SECTION, id);
    this.sections.delete(id);
  },
  enableSection(id) {
    this.updateSection(id, {enabled: true}, true);
    this.emit(this.ENABLE_SECTION, id);
  },
  disableSection(id) {
{'fraction_non_alphanumeric': 0.1348109767798887, 'fraction_numerical': 0.002398771828823642, 'mean_word_length': 3.699278629395852, 'pattern_counts': {'":': 8, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 4, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4024710', 'n_tokens_mistral': 3348, 'n_tokens_neox': 3295, 'n_words': 639}