ASRouterPreferences.jsm 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181
  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. "use strict";
  5. const {Services} = ChromeUtils.import("resource://gre/modules/Services.jsm");
  6. const PROVIDER_PREF_BRANCH = "browser.newtabpage.activity-stream.asrouter.providers.";
  7. const DEVTOOLS_PREF = "browser.newtabpage.activity-stream.asrouter.devtoolsEnabled";
  8. const FXA_USERNAME_PREF = "services.sync.username";
  9. const DEFAULT_STATE = {
  10. _initialized: false,
  11. _providers: null,
  12. _providerPrefBranch: PROVIDER_PREF_BRANCH,
  13. _devtoolsEnabled: null,
  14. _devtoolsPref: DEVTOOLS_PREF,
  15. };
  16. const USER_PREFERENCES = {
  17. snippets: "browser.newtabpage.activity-stream.feeds.snippets",
  18. cfrAddons: "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.addons",
  19. cfrFeatures: "browser.newtabpage.activity-stream.asrouter.userprefs.cfr.features",
  20. };
  21. // Preferences that influence targeting attributes. When these change we need
  22. // to re-evaluate if the message targeting still matches
  23. const TARGETING_PREFERENCES = [FXA_USERNAME_PREF];
  24. const TEST_PROVIDERS = [{
  25. id: "snippets_local_testing",
  26. type: "local",
  27. localProvider: "SnippetsTestMessageProvider",
  28. enabled: true,
  29. }, {
  30. id: "panel_local_testing",
  31. type: "local",
  32. localProvider: "PanelTestProvider",
  33. enabled: true,
  34. }];
  35. class _ASRouterPreferences {
  36. constructor() {
  37. Object.assign(this, DEFAULT_STATE);
  38. this._callbacks = new Set();
  39. }
  40. _getProviderConfig() {
  41. const prefList = Services.prefs.getChildList(this._providerPrefBranch);
  42. return prefList.reduce((filtered, pref) => {
  43. let value;
  44. try {
  45. value = JSON.parse(Services.prefs.getStringPref(pref, ""));
  46. } catch (e) {
  47. Cu.reportError(`Could not parse ASRouter preference. Try resetting ${pref} in about:config.`);
  48. }
  49. if (value) {
  50. filtered.push(value);
  51. }
  52. return filtered;
  53. }, []);
  54. }
  55. get providers() {
  56. if (!this._initialized || this._providers === null) {
  57. const config = this._getProviderConfig();
  58. const providers = config.map(provider => Object.freeze(provider));
  59. if (this.devtoolsEnabled) {
  60. providers.unshift(...TEST_PROVIDERS);
  61. }
  62. this._providers = Object.freeze(providers);
  63. }
  64. return this._providers;
  65. }
  66. enableOrDisableProvider(id, value) {
  67. const providers = this._getProviderConfig();
  68. const config = providers.find(p => p.id === id);
  69. if (!config) {
  70. Cu.reportError(`Cannot set enabled state for '${id}' because the pref ${this._providerPrefBranch}${id} does not exist or is not correctly formatted.`);
  71. return;
  72. }
  73. Services.prefs.setStringPref(this._providerPrefBranch + id, JSON.stringify({...config, enabled: value}));
  74. }
  75. resetProviderPref() {
  76. for (const pref of Services.prefs.getChildList(this._providerPrefBranch)) {
  77. Services.prefs.clearUserPref(pref);
  78. }
  79. for (const id of Object.keys(USER_PREFERENCES)) {
  80. Services.prefs.clearUserPref(USER_PREFERENCES[id]);
  81. }
  82. }
  83. get devtoolsEnabled() {
  84. if (!this._initialized || this._devtoolsEnabled === null) {
  85. this._devtoolsEnabled = Services.prefs.getBoolPref(this._devtoolsPref, false);
  86. }
  87. return this._devtoolsEnabled;
  88. }
  89. observe(aSubject, aTopic, aPrefName) {
  90. if (aPrefName && aPrefName.startsWith(this._providerPrefBranch)) {
  91. this._providers = null;
  92. } else if (aPrefName === this._devtoolsPref) {
  93. this._providers = null;
  94. this._devtoolsEnabled = null;
  95. }
  96. this._callbacks.forEach(cb => cb(aPrefName));
  97. }
  98. getUserPreference(providerId) {
  99. if (!USER_PREFERENCES[providerId]) {
  100. return null;
  101. }
  102. return Services.prefs.getBoolPref(USER_PREFERENCES[providerId], true);
  103. }
  104. getAllUserPreferences() {
  105. const values = {};
  106. for (const id of Object.keys(USER_PREFERENCES)) {
  107. values[id] = this.getUserPreference(id);
  108. }
  109. return values;
  110. }
  111. setUserPreference(providerId, value) {
  112. if (!USER_PREFERENCES[providerId]) {
  113. return;
  114. }
  115. Services.prefs.setBoolPref(USER_PREFERENCES[providerId], value);
  116. }
  117. addListener(callback) {
  118. this._callbacks.add(callback);
  119. }
  120. removeListener(callback) {
  121. this._callbacks.delete(callback);
  122. }
  123. init() {
  124. if (this._initialized) {
  125. return;
  126. }
  127. Services.prefs.addObserver(this._providerPrefBranch, this);
  128. Services.prefs.addObserver(this._devtoolsPref, this);
  129. for (const id of Object.keys(USER_PREFERENCES)) {
  130. Services.prefs.addObserver(USER_PREFERENCES[id], this);
  131. }
  132. for (const targetingPref of TARGETING_PREFERENCES) {
  133. Services.prefs.addObserver(targetingPref, this);
  134. }
  135. this._initialized = true;
  136. }
  137. uninit() {
  138. if (this._initialized) {
  139. Services.prefs.removeObserver(this._providerPrefBranch, this);
  140. Services.prefs.removeObserver(this._devtoolsPref, this);
  141. for (const id of Object.keys(USER_PREFERENCES)) {
  142. Services.prefs.removeObserver(USER_PREFERENCES[id], this);
  143. }
  144. for (const targetingPref of TARGETING_PREFERENCES) {
  145. Services.prefs.removeObserver(targetingPref, this);
  146. }
  147. }
  148. Object.assign(this, DEFAULT_STATE);
  149. this._callbacks.clear();
  150. }
  151. }
  152. this._ASRouterPreferences = _ASRouterPreferences;
  153. this.ASRouterPreferences = new _ASRouterPreferences();
  154. this.TEST_PROVIDERS = TEST_PROVIDERS;
  155. this.TARGETING_PREFERENCES = TARGETING_PREFERENCES;
  156. const EXPORTED_SYMBOLS = ["_ASRouterPreferences", "ASRouterPreferences", "TEST_PROVIDERS", "TARGETING_PREFERENCES"];