tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

Store.sys.mjs (5447B)


      1 /* This Source Code Form is subject to the terms of the Mozilla Public
      2 * License, v. 2.0. If a copy of the MPL was not distributed with this
      3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
      4 
      5 import { ActivityStreamMessageChannel } from "resource://newtab/lib/ActivityStreamMessageChannel.sys.mjs";
      6 import { Prefs } from "resource://newtab/lib/ActivityStreamPrefs.sys.mjs";
      7 import { reducers } from "resource://newtab/common/Reducers.sys.mjs";
      8 import { redux } from "chrome://global/content/vendor/Redux.sys.mjs";
      9 
     10 /**
     11 * Store - This has a similar structure to a redux store, but includes some extra
     12 *         functionality to allow for routing of actions between the Main processes
     13 *         and child processes via a ActivityStreamMessageChannel.
     14 *         It also accepts an array of "Feeds" on inititalization, which
     15 *         can listen for any action that is dispatched through the store.
     16 */
     17 export class Store {
     18  /**
     19   * constructor - The redux store and message manager are created here,
     20   *               but no listeners are added until "init" is called.
     21   */
     22  constructor() {
     23    this._middleware = this._middleware.bind(this);
     24    // Bind each redux method so we can call it directly from the Store. E.g.,
     25    // store.dispatch() will call store._store.dispatch();
     26    for (const method of ["dispatch", "getState", "subscribe"]) {
     27      this[method] = (...args) => this._store[method](...args);
     28    }
     29    this.feeds = new Map();
     30    this._prefs = new Prefs();
     31    this._messageChannel = new ActivityStreamMessageChannel({
     32      dispatch: this.dispatch,
     33    });
     34    this._store = redux.createStore(
     35      redux.combineReducers(reducers),
     36      redux.applyMiddleware(this._middleware, this._messageChannel.middleware)
     37    );
     38  }
     39 
     40  /**
     41   * _middleware - This is redux middleware consumed by redux.createStore.
     42   *               it calls each feed's .onAction method, if one
     43   *               is defined.
     44   */
     45  _middleware() {
     46    return next => action => {
     47      next(action);
     48      for (const store of this.feeds.values()) {
     49        if (store.onAction) {
     50          store.onAction(action);
     51        }
     52      }
     53    };
     54  }
     55 
     56  /**
     57   * initFeed - Initializes a feed by calling its constructor function
     58   *
     59   * @param  {string} feedName The name of a feed, as defined in the object
     60   *                           passed to Store.init
     61   * @param {Action} initAction An optional action to initialize the feed
     62   */
     63  initFeed(feedName, initAction) {
     64    const feed = this._feedFactories.get(feedName)();
     65    feed.store = this;
     66    this.feeds.set(feedName, feed);
     67    if (initAction && feed.onAction) {
     68      feed.onAction(initAction);
     69    }
     70  }
     71 
     72  /**
     73   * uninitFeed - Removes a feed and calls its uninit function if defined
     74   *
     75   * @param  {string} feedName The name of a feed, as defined in the object
     76   *                           passed to Store.init
     77   * @param {Action} uninitAction An optional action to uninitialize the feed
     78   */
     79  uninitFeed(feedName, uninitAction) {
     80    const feed = this.feeds.get(feedName);
     81    if (!feed) {
     82      return;
     83    }
     84    if (uninitAction && feed.onAction) {
     85      feed.onAction(uninitAction);
     86    }
     87    this.feeds.delete(feedName);
     88  }
     89 
     90  /**
     91   * onPrefChanged - Listener for handling feed changes.
     92   */
     93  onPrefChanged(name, value) {
     94    if (this._feedFactories.has(name)) {
     95      if (value) {
     96        this.initFeed(name, this._initAction);
     97      } else {
     98        this.uninitFeed(name, this._uninitAction);
     99      }
    100    }
    101  }
    102 
    103  /**
    104   * init - Initializes the ActivityStreamMessageChannel channel, and adds feeds.
    105   *
    106   * Note that it intentionally initializes the TelemetryFeed first so that the
    107   * addon is able to report the init errors from other feeds.
    108   *
    109   * @param  {Map} feedFactories A Map of feeds with the name of the pref for
    110   *                                the feed as the key and a function that
    111   *                                constructs an instance of the feed.
    112   * @param {Action} initAction An optional action that will be dispatched
    113   *                            to feeds when they're created.
    114   * @param {Action} uninitAction An optional action for when feeds uninit.
    115   */
    116  init(feedFactories, initAction, uninitAction) {
    117    this._feedFactories = feedFactories;
    118    this._initAction = initAction;
    119    this._uninitAction = uninitAction;
    120 
    121    const telemetryKey = "feeds.telemetry";
    122    if (feedFactories.has(telemetryKey) && this._prefs.get(telemetryKey)) {
    123      this.initFeed(telemetryKey);
    124    }
    125 
    126    for (const pref of feedFactories.keys()) {
    127      if (pref !== telemetryKey && this._prefs.get(pref)) {
    128        this.initFeed(pref);
    129      }
    130    }
    131 
    132    this._prefs.observeBranch(this);
    133 
    134    // Dispatch an initial action after all enabled feeds are ready
    135    if (initAction) {
    136      this.dispatch(initAction);
    137    }
    138 
    139    // Dispatch NEW_TAB_INIT/NEW_TAB_LOAD events after INIT event.
    140    this._messageChannel.simulateMessagesForExistingTabs();
    141  }
    142 
    143  /**
    144   * uninit -  Uninitalizes each feed, clears them, and destroys the message
    145   *           manager channel.
    146   */
    147  uninit() {
    148    if (this._uninitAction) {
    149      this.dispatch(this._uninitAction);
    150    }
    151    this._prefs.ignoreBranch(this);
    152    this.feeds.clear();
    153    this._feedFactories = null;
    154  }
    155 
    156  /**
    157   * getMessageChannel - Used by the AboutNewTabParent actor to get the message channel.
    158   */
    159  getMessageChannel() {
    160    return this._messageChannel;
    161  }
    162 }