preferences.js 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. /* Copyright 2013 Mozilla Foundation
  2. *
  3. * Licensed under the Apache License, Version 2.0 (the "License");
  4. * you may not use this file except in compliance with the License.
  5. * You may obtain a copy of the License at
  6. *
  7. * http://www.apache.org/licenses/LICENSE-2.0
  8. *
  9. * Unless required by applicable law or agreed to in writing, software
  10. * distributed under the License is distributed on an "AS IS" BASIS,
  11. * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  12. * See the License for the specific language governing permissions and
  13. * limitations under the License.
  14. */
  15. import { AppOptions, OptionKind } from "./app_options.js";
  16. /**
  17. * BasePreferences - Abstract base class for storing persistent settings.
  18. * Used for settings that should be applied to all opened documents,
  19. * or every time the viewer is loaded.
  20. */
  21. class BasePreferences {
  22. #defaults = Object.freeze(
  23. typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")
  24. ? AppOptions.getAll(OptionKind.PREFERENCE)
  25. : PDFJSDev.eval("DEFAULT_PREFERENCES")
  26. );
  27. #prefs = Object.create(null);
  28. #initializedPromise = null;
  29. constructor() {
  30. if (this.constructor === BasePreferences) {
  31. throw new Error("Cannot initialize BasePreferences.");
  32. }
  33. if (typeof PDFJSDev !== "undefined" && PDFJSDev.test("CHROME")) {
  34. Object.defineProperty(this, "defaults", {
  35. get() {
  36. return this.#defaults;
  37. },
  38. });
  39. }
  40. this.#initializedPromise = this._readFromStorage(this.#defaults).then(
  41. prefs => {
  42. for (const name in this.#defaults) {
  43. const prefValue = prefs?.[name];
  44. // Ignore preferences whose types don't match the default values.
  45. if (typeof prefValue === typeof this.#defaults[name]) {
  46. this.#prefs[name] = prefValue;
  47. }
  48. }
  49. }
  50. );
  51. }
  52. /**
  53. * Stub function for writing preferences to storage.
  54. * @param {Object} prefObj The preferences that should be written to storage.
  55. * @returns {Promise} A promise that is resolved when the preference values
  56. * have been written.
  57. */
  58. async _writeToStorage(prefObj) {
  59. throw new Error("Not implemented: _writeToStorage");
  60. }
  61. /**
  62. * Stub function for reading preferences from storage.
  63. * @param {Object} prefObj The preferences that should be read from storage.
  64. * @returns {Promise} A promise that is resolved with an {Object} containing
  65. * the preferences that have been read.
  66. */
  67. async _readFromStorage(prefObj) {
  68. throw new Error("Not implemented: _readFromStorage");
  69. }
  70. /**
  71. * Reset the preferences to their default values and update storage.
  72. * @returns {Promise} A promise that is resolved when the preference values
  73. * have been reset.
  74. */
  75. async reset() {
  76. await this.#initializedPromise;
  77. const prefs = this.#prefs;
  78. this.#prefs = Object.create(null);
  79. return this._writeToStorage(this.#defaults).catch(reason => {
  80. // Revert all preference values, since writing to storage failed.
  81. this.#prefs = prefs;
  82. throw reason;
  83. });
  84. }
  85. /**
  86. * Set the value of a preference.
  87. * @param {string} name The name of the preference that should be changed.
  88. * @param {boolean|number|string} value The new value of the preference.
  89. * @returns {Promise} A promise that is resolved when the value has been set,
  90. * provided that the preference exists and the types match.
  91. */
  92. async set(name, value) {
  93. await this.#initializedPromise;
  94. const defaultValue = this.#defaults[name],
  95. prefs = this.#prefs;
  96. if (defaultValue === undefined) {
  97. throw new Error(`Set preference: "${name}" is undefined.`);
  98. } else if (value === undefined) {
  99. throw new Error("Set preference: no value is specified.");
  100. }
  101. const valueType = typeof value,
  102. defaultType = typeof defaultValue;
  103. if (valueType !== defaultType) {
  104. if (valueType === "number" && defaultType === "string") {
  105. value = value.toString();
  106. } else {
  107. throw new Error(
  108. `Set preference: "${value}" is a ${valueType}, expected a ${defaultType}.`
  109. );
  110. }
  111. } else {
  112. if (valueType === "number" && !Number.isInteger(value)) {
  113. throw new Error(`Set preference: "${value}" must be an integer.`);
  114. }
  115. }
  116. this.#prefs[name] = value;
  117. return this._writeToStorage(this.#prefs).catch(reason => {
  118. // Revert all preference values, since writing to storage failed.
  119. this.#prefs = prefs;
  120. throw reason;
  121. });
  122. }
  123. /**
  124. * Get the value of a preference.
  125. * @param {string} name The name of the preference whose value is requested.
  126. * @returns {Promise} A promise resolved with a {boolean|number|string}
  127. * containing the value of the preference.
  128. */
  129. async get(name) {
  130. await this.#initializedPromise;
  131. const defaultValue = this.#defaults[name];
  132. if (defaultValue === undefined) {
  133. throw new Error(`Get preference: "${name}" is undefined.`);
  134. }
  135. return this.#prefs[name] ?? defaultValue;
  136. }
  137. /**
  138. * Get the values of all preferences.
  139. * @returns {Promise} A promise that is resolved with an {Object} containing
  140. * the values of all preferences.
  141. */
  142. async getAll() {
  143. await this.#initializedPromise;
  144. const obj = Object.create(null);
  145. for (const name in this.#defaults) {
  146. obj[name] = this.#prefs[name] ?? this.#defaults[name];
  147. }
  148. return obj;
  149. }
  150. }
  151. export { BasePreferences };