pdf.sandbox.external.js 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. /* Copyright 2020 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. // In mozilla-central, this file is loaded as non-module script,
  16. // so it mustn't have any dependencies.
  17. class SandboxSupportBase {
  18. /**
  19. * @param {DOMWindow} - win
  20. */
  21. constructor(win) {
  22. this.win = win;
  23. this.timeoutIds = new Map();
  24. // Will be assigned after the sandbox is initialized
  25. this.commFun = null;
  26. }
  27. destroy() {
  28. this.commFun = null;
  29. for (const id of this.timeoutIds.values()) {
  30. this.win.clearTimeout(id);
  31. }
  32. this.timeoutIds = null;
  33. }
  34. /**
  35. * @param {Object} val - Export a value in the sandbox.
  36. */
  37. exportValueToSandbox(val) {
  38. throw new Error("Not implemented");
  39. }
  40. /**
  41. * @param {Object} val - Import a value from the sandbox.
  42. */
  43. importValueFromSandbox(val) {
  44. throw new Error("Not implemented");
  45. }
  46. /**
  47. * @param {String} errorMessage - Create an error in the sandbox.
  48. */
  49. createErrorForSandbox(errorMessage) {
  50. throw new Error("Not implemented");
  51. }
  52. /**
  53. * @param {String} name - Name of the function to call in the sandbox
  54. * @param {Array<Object>} args - Arguments of the function.
  55. */
  56. callSandboxFunction(name, args) {
  57. try {
  58. args = this.exportValueToSandbox(args);
  59. this.commFun(name, args);
  60. } catch (e) {
  61. this.win.console.error(e);
  62. }
  63. }
  64. createSandboxExternals() {
  65. // All the functions in externals object are called
  66. // from the sandbox.
  67. const externals = {
  68. setTimeout: (callbackId, nMilliseconds) => {
  69. if (
  70. typeof callbackId !== "number" ||
  71. typeof nMilliseconds !== "number"
  72. ) {
  73. return;
  74. }
  75. if (callbackId === 0) {
  76. // This callbackId corresponds to the one used for userActivation.
  77. // So here, we cancel the last userActivation.
  78. this.win.clearTimeout(this.timeoutIds.get(callbackId));
  79. }
  80. const id = this.win.setTimeout(() => {
  81. this.timeoutIds.delete(callbackId);
  82. this.callSandboxFunction("timeoutCb", {
  83. callbackId,
  84. interval: false,
  85. });
  86. }, nMilliseconds);
  87. this.timeoutIds.set(callbackId, id);
  88. },
  89. clearTimeout: callbackId => {
  90. this.win.clearTimeout(this.timeoutIds.get(callbackId));
  91. this.timeoutIds.delete(callbackId);
  92. },
  93. setInterval: (callbackId, nMilliseconds) => {
  94. if (
  95. typeof callbackId !== "number" ||
  96. typeof nMilliseconds !== "number"
  97. ) {
  98. return;
  99. }
  100. const id = this.win.setInterval(() => {
  101. this.callSandboxFunction("timeoutCb", {
  102. callbackId,
  103. interval: true,
  104. });
  105. }, nMilliseconds);
  106. this.timeoutIds.set(callbackId, id);
  107. },
  108. clearInterval: callbackId => {
  109. this.win.clearInterval(this.timeoutIds.get(callbackId));
  110. this.timeoutIds.delete(callbackId);
  111. },
  112. alert: cMsg => {
  113. if (typeof cMsg !== "string") {
  114. return;
  115. }
  116. this.win.alert(cMsg);
  117. },
  118. confirm: cMsg => {
  119. if (typeof cMsg !== "string") {
  120. return false;
  121. }
  122. return this.win.confirm(cMsg);
  123. },
  124. prompt: (cQuestion, cDefault) => {
  125. if (typeof cQuestion !== "string" || typeof cDefault !== "string") {
  126. return null;
  127. }
  128. return this.win.prompt(cQuestion, cDefault);
  129. },
  130. parseURL: cUrl => {
  131. const url = new this.win.URL(cUrl);
  132. const props = [
  133. "hash",
  134. "host",
  135. "hostname",
  136. "href",
  137. "origin",
  138. "password",
  139. "pathname",
  140. "port",
  141. "protocol",
  142. "search",
  143. "searchParams",
  144. "username",
  145. ];
  146. return Object.fromEntries(
  147. props.map(name => [name, url[name].toString()])
  148. );
  149. },
  150. send: data => {
  151. if (!data) {
  152. return;
  153. }
  154. const event = new this.win.CustomEvent("updatefromsandbox", {
  155. detail: this.importValueFromSandbox(data),
  156. });
  157. this.win.dispatchEvent(event);
  158. },
  159. };
  160. Object.setPrototypeOf(externals, null);
  161. return (name, args) => {
  162. try {
  163. const result = externals[name](...args);
  164. return this.exportValueToSandbox(result);
  165. } catch (error) {
  166. throw this.createErrorForSandbox(error?.toString() ?? "");
  167. }
  168. };
  169. }
  170. }
  171. if (typeof PDFJSDev === "undefined" || !PDFJSDev.test("MOZCENTRAL")) {
  172. exports.SandboxSupportBase = SandboxSupportBase;
  173. } else {
  174. /* eslint-disable-next-line no-unused-vars, no-var */
  175. var EXPORTED_SYMBOLS = ["SandboxSupportBase"];
  176. }