app_options.js 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  1. /* Copyright 2018 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. const compatibilityParams = Object.create(null);
  16. if (typeof PDFJSDev === "undefined" || PDFJSDev.test("GENERIC")) {
  17. if (
  18. typeof PDFJSDev !== "undefined" &&
  19. PDFJSDev.test("LIB") &&
  20. typeof navigator === "undefined"
  21. ) {
  22. globalThis.navigator = Object.create(null);
  23. }
  24. const userAgent = navigator.userAgent || "";
  25. const platform = navigator.platform || "";
  26. const maxTouchPoints = navigator.maxTouchPoints || 1;
  27. const isAndroid = /Android/.test(userAgent);
  28. const isIOS =
  29. /\b(iPad|iPhone|iPod)(?=;)/.test(userAgent) ||
  30. (platform === "MacIntel" && maxTouchPoints > 1);
  31. // Limit canvas size to 5 mega-pixels on mobile.
  32. // Support: Android, iOS
  33. (function checkCanvasSizeLimitation() {
  34. if (isIOS || isAndroid) {
  35. compatibilityParams.maxCanvasPixels = 5242880;
  36. }
  37. })();
  38. }
  39. const OptionKind = {
  40. VIEWER: 0x02,
  41. API: 0x04,
  42. WORKER: 0x08,
  43. PREFERENCE: 0x80,
  44. };
  45. /**
  46. * NOTE: These options are used to generate the `default_preferences.json` file,
  47. * see `OptionKind.PREFERENCE`, hence the values below must use only
  48. * primitive types and cannot rely on any imported types.
  49. */
  50. const defaultOptions = {
  51. annotationEditorMode: {
  52. /** @type {number} */
  53. value: 0,
  54. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  55. },
  56. annotationMode: {
  57. /** @type {number} */
  58. value: 2,
  59. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  60. },
  61. cursorToolOnLoad: {
  62. /** @type {number} */
  63. value: 0,
  64. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  65. },
  66. defaultZoomDelay: {
  67. /** @type {number} */
  68. value:
  69. typeof PDFJSDev === "undefined" || !PDFJSDev.test("GENERIC") ? 400 : -1,
  70. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  71. },
  72. defaultZoomValue: {
  73. /** @type {string} */
  74. value: "",
  75. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  76. },
  77. disableHistory: {
  78. /** @type {boolean} */
  79. value: false,
  80. kind: OptionKind.VIEWER,
  81. },
  82. disablePageLabels: {
  83. /** @type {boolean} */
  84. value: false,
  85. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  86. },
  87. enablePermissions: {
  88. /** @type {boolean} */
  89. value: false,
  90. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  91. },
  92. enablePrintAutoRotate: {
  93. /** @type {boolean} */
  94. value: true,
  95. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  96. },
  97. enableScripting: {
  98. /** @type {boolean} */
  99. value: typeof PDFJSDev === "undefined" || !PDFJSDev.test("CHROME"),
  100. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  101. },
  102. externalLinkRel: {
  103. /** @type {string} */
  104. value: "noopener noreferrer nofollow",
  105. kind: OptionKind.VIEWER,
  106. },
  107. externalLinkTarget: {
  108. /** @type {number} */
  109. value: 0,
  110. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  111. },
  112. historyUpdateUrl: {
  113. /** @type {boolean} */
  114. value: false,
  115. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  116. },
  117. ignoreDestinationZoom: {
  118. /** @type {boolean} */
  119. value: false,
  120. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  121. },
  122. imageResourcesPath: {
  123. /** @type {string} */
  124. value: "./images/",
  125. kind: OptionKind.VIEWER,
  126. },
  127. maxCanvasPixels: {
  128. /** @type {number} */
  129. value: 16777216,
  130. kind: OptionKind.VIEWER,
  131. },
  132. forcePageColors: {
  133. /** @type {boolean} */
  134. value: false,
  135. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  136. },
  137. pageColorsBackground: {
  138. /** @type {string} */
  139. value: "Canvas",
  140. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  141. },
  142. pageColorsForeground: {
  143. /** @type {string} */
  144. value: "CanvasText",
  145. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  146. },
  147. pdfBugEnabled: {
  148. /** @type {boolean} */
  149. value: typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION"),
  150. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  151. },
  152. printResolution: {
  153. /** @type {number} */
  154. value: 150,
  155. kind: OptionKind.VIEWER,
  156. },
  157. sidebarViewOnLoad: {
  158. /** @type {number} */
  159. value: -1,
  160. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  161. },
  162. scrollModeOnLoad: {
  163. /** @type {number} */
  164. value: -1,
  165. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  166. },
  167. spreadModeOnLoad: {
  168. /** @type {number} */
  169. value: -1,
  170. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  171. },
  172. textLayerMode: {
  173. /** @type {number} */
  174. value: 1,
  175. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  176. },
  177. useOnlyCssZoom: {
  178. /** @type {boolean} */
  179. value: false,
  180. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  181. },
  182. viewerCssTheme: {
  183. /** @type {number} */
  184. value: typeof PDFJSDev !== "undefined" && PDFJSDev.test("CHROME") ? 2 : 0,
  185. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  186. },
  187. viewOnLoad: {
  188. /** @type {boolean} */
  189. value: 0,
  190. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  191. },
  192. cMapPacked: {
  193. /** @type {boolean} */
  194. value: true,
  195. kind: OptionKind.API,
  196. },
  197. cMapUrl: {
  198. /** @type {string} */
  199. value:
  200. typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")
  201. ? "../external/bcmaps/"
  202. : "../web/cmaps/",
  203. kind: OptionKind.API,
  204. },
  205. disableAutoFetch: {
  206. /** @type {boolean} */
  207. value: false,
  208. kind: OptionKind.API + OptionKind.PREFERENCE,
  209. },
  210. disableFontFace: {
  211. /** @type {boolean} */
  212. value: false,
  213. kind: OptionKind.API + OptionKind.PREFERENCE,
  214. },
  215. disableRange: {
  216. /** @type {boolean} */
  217. value: false,
  218. kind: OptionKind.API + OptionKind.PREFERENCE,
  219. },
  220. disableStream: {
  221. /** @type {boolean} */
  222. value: false,
  223. kind: OptionKind.API + OptionKind.PREFERENCE,
  224. },
  225. docBaseUrl: {
  226. /** @type {string} */
  227. value: "",
  228. kind: OptionKind.API,
  229. },
  230. enableXfa: {
  231. /** @type {boolean} */
  232. value: true,
  233. kind: OptionKind.API + OptionKind.PREFERENCE,
  234. },
  235. fontExtraProperties: {
  236. /** @type {boolean} */
  237. value: false,
  238. kind: OptionKind.API,
  239. },
  240. isEvalSupported: {
  241. /** @type {boolean} */
  242. value: true,
  243. kind: OptionKind.API,
  244. },
  245. isOffscreenCanvasSupported: {
  246. /** @type {boolean} */
  247. value: true,
  248. kind: OptionKind.API,
  249. },
  250. maxImageSize: {
  251. /** @type {number} */
  252. value: -1,
  253. kind: OptionKind.API,
  254. },
  255. pdfBug: {
  256. /** @type {boolean} */
  257. value: false,
  258. kind: OptionKind.API,
  259. },
  260. standardFontDataUrl: {
  261. /** @type {string} */
  262. value:
  263. typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")
  264. ? "../external/standard_fonts/"
  265. : "../web/standard_fonts/",
  266. kind: OptionKind.API,
  267. },
  268. verbosity: {
  269. /** @type {number} */
  270. value: 1,
  271. kind: OptionKind.API,
  272. },
  273. workerPort: {
  274. /** @type {Object} */
  275. value: null,
  276. kind: OptionKind.WORKER,
  277. },
  278. workerSrc: {
  279. /** @type {string} */
  280. value:
  281. typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")
  282. ? "../src/worker_loader.js"
  283. : "../build/pdf.worker.js",
  284. kind: OptionKind.WORKER,
  285. },
  286. };
  287. if (
  288. typeof PDFJSDev === "undefined" ||
  289. PDFJSDev.test("!PRODUCTION || GENERIC")
  290. ) {
  291. defaultOptions.defaultUrl = {
  292. /** @type {string} */
  293. value: "compressed.tracemonkey-pldi-09.pdf",
  294. kind: OptionKind.VIEWER,
  295. };
  296. defaultOptions.disablePreferences = {
  297. /** @type {boolean} */
  298. value: typeof PDFJSDev !== "undefined" && PDFJSDev.test("TESTING"),
  299. kind: OptionKind.VIEWER,
  300. };
  301. defaultOptions.locale = {
  302. /** @type {string} */
  303. value: navigator.language || "en-US",
  304. kind: OptionKind.VIEWER,
  305. };
  306. defaultOptions.renderer = {
  307. /** @type {string} */
  308. value: "canvas",
  309. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  310. };
  311. defaultOptions.sandboxBundleSrc = {
  312. /** @type {string} */
  313. value:
  314. typeof PDFJSDev === "undefined" || !PDFJSDev.test("PRODUCTION")
  315. ? "../build/dev-sandbox/pdf.sandbox.js"
  316. : "../build/pdf.sandbox.js",
  317. kind: OptionKind.VIEWER,
  318. };
  319. } else if (PDFJSDev.test("CHROME")) {
  320. defaultOptions.defaultUrl = {
  321. /** @type {string} */
  322. value: "",
  323. kind: OptionKind.VIEWER,
  324. };
  325. defaultOptions.disableTelemetry = {
  326. /** @type {boolean} */
  327. value: false,
  328. kind: OptionKind.VIEWER + OptionKind.PREFERENCE,
  329. };
  330. defaultOptions.sandboxBundleSrc = {
  331. /** @type {string} */
  332. value: "../build/pdf.sandbox.js",
  333. kind: OptionKind.VIEWER,
  334. };
  335. }
  336. const userOptions = Object.create(null);
  337. class AppOptions {
  338. constructor() {
  339. throw new Error("Cannot initialize AppOptions.");
  340. }
  341. static get(name) {
  342. const userOption = userOptions[name];
  343. if (userOption !== undefined) {
  344. return userOption;
  345. }
  346. const defaultOption = defaultOptions[name];
  347. if (defaultOption !== undefined) {
  348. return compatibilityParams[name] ?? defaultOption.value;
  349. }
  350. return undefined;
  351. }
  352. static getAll(kind = null) {
  353. const options = Object.create(null);
  354. for (const name in defaultOptions) {
  355. const defaultOption = defaultOptions[name];
  356. if (kind) {
  357. if ((kind & defaultOption.kind) === 0) {
  358. continue;
  359. }
  360. if (kind === OptionKind.PREFERENCE) {
  361. const value = defaultOption.value,
  362. valueType = typeof value;
  363. if (
  364. valueType === "boolean" ||
  365. valueType === "string" ||
  366. (valueType === "number" && Number.isInteger(value))
  367. ) {
  368. options[name] = value;
  369. continue;
  370. }
  371. throw new Error(`Invalid type for preference: ${name}`);
  372. }
  373. }
  374. const userOption = userOptions[name];
  375. options[name] =
  376. userOption !== undefined
  377. ? userOption
  378. : compatibilityParams[name] ?? defaultOption.value;
  379. }
  380. return options;
  381. }
  382. static set(name, value) {
  383. userOptions[name] = value;
  384. }
  385. static setAll(options) {
  386. for (const name in options) {
  387. userOptions[name] = options[name];
  388. }
  389. }
  390. static remove(name) {
  391. delete userOptions[name];
  392. }
  393. /**
  394. * @ignore
  395. */
  396. static _hasUserOptions() {
  397. return Object.keys(userOptions).length > 0;
  398. }
  399. }
  400. export { AppOptions, compatibilityParams, OptionKind };