web-view-element.ts 4.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125
  1. // When using context isolation, the WebViewElement and the custom element
  2. // methods have to be defined in the main world to be able to be registered.
  3. //
  4. // Note: The hidden values can only be read/set inside the same context, all
  5. // methods that access the "internal" hidden value must be put in this file.
  6. //
  7. // Note: This file could be loaded in the main world of contextIsolation page,
  8. // which runs in browserify environment instead of Node environment, all native
  9. // modules must be passed from outside, all included files must be plain JS.
  10. import type { SrcAttribute } from '@electron/internal/renderer/web-view/web-view-attributes';
  11. import { WEB_VIEW_ATTRIBUTES, WEB_VIEW_ERROR_MESSAGES } from '@electron/internal/renderer/web-view/web-view-constants';
  12. import { WebViewImpl, WebViewImplHooks, setupMethods } from '@electron/internal/renderer/web-view/web-view-impl';
  13. const internals = new WeakMap<HTMLElement, WebViewImpl>();
  14. // Return a WebViewElement class that is defined in this context.
  15. const defineWebViewElement = (hooks: WebViewImplHooks) => {
  16. return class WebViewElement extends HTMLElement {
  17. static get observedAttributes () {
  18. return [
  19. WEB_VIEW_ATTRIBUTES.PARTITION,
  20. WEB_VIEW_ATTRIBUTES.SRC,
  21. WEB_VIEW_ATTRIBUTES.HTTPREFERRER,
  22. WEB_VIEW_ATTRIBUTES.USERAGENT,
  23. WEB_VIEW_ATTRIBUTES.NODEINTEGRATION,
  24. WEB_VIEW_ATTRIBUTES.NODEINTEGRATIONINSUBFRAMES,
  25. WEB_VIEW_ATTRIBUTES.PLUGINS,
  26. WEB_VIEW_ATTRIBUTES.DISABLEWEBSECURITY,
  27. WEB_VIEW_ATTRIBUTES.ALLOWPOPUPS,
  28. WEB_VIEW_ATTRIBUTES.PRELOAD,
  29. WEB_VIEW_ATTRIBUTES.BLINKFEATURES,
  30. WEB_VIEW_ATTRIBUTES.DISABLEBLINKFEATURES,
  31. WEB_VIEW_ATTRIBUTES.WEBPREFERENCES
  32. ];
  33. }
  34. constructor () {
  35. super();
  36. internals.set(this, new WebViewImpl(this, hooks));
  37. }
  38. getWebContentsId () {
  39. const internal = internals.get(this);
  40. if (!internal || !internal.guestInstanceId) {
  41. throw new Error(WEB_VIEW_ERROR_MESSAGES.NOT_ATTACHED);
  42. }
  43. return internal.guestInstanceId;
  44. }
  45. connectedCallback () {
  46. const internal = internals.get(this);
  47. if (!internal) {
  48. return;
  49. }
  50. if (!internal.elementAttached) {
  51. hooks.guestViewInternal.registerEvents(internal.viewInstanceId, {
  52. dispatchEvent: internal.dispatchEvent.bind(internal)
  53. });
  54. internal.elementAttached = true;
  55. (internal.attributes.get(WEB_VIEW_ATTRIBUTES.SRC) as SrcAttribute).parse();
  56. }
  57. }
  58. attributeChangedCallback (name: string, oldValue: any, newValue: any) {
  59. const internal = internals.get(this);
  60. if (internal) {
  61. internal.handleWebviewAttributeMutation(name, oldValue, newValue);
  62. }
  63. }
  64. disconnectedCallback () {
  65. const internal = internals.get(this);
  66. if (!internal) {
  67. return;
  68. }
  69. hooks.guestViewInternal.deregisterEvents(internal.viewInstanceId);
  70. if (internal.guestInstanceId) {
  71. hooks.guestViewInternal.detachGuest(internal.guestInstanceId);
  72. }
  73. internal.elementAttached = false;
  74. internal.reset();
  75. }
  76. };
  77. };
  78. // Register <webview> custom element.
  79. const registerWebViewElement = (hooks: WebViewImplHooks) => {
  80. const WebViewElement = defineWebViewElement(hooks) as unknown as typeof ElectronInternal.WebViewElement;
  81. setupMethods(WebViewElement, hooks);
  82. // The customElements.define has to be called in a special scope.
  83. hooks.allowGuestViewElementDefinition(window, () => {
  84. window.customElements.define('webview', WebViewElement);
  85. window.WebView = WebViewElement;
  86. // Delete the callbacks so developers cannot call them and produce unexpected
  87. // behavior.
  88. delete WebViewElement.prototype.connectedCallback;
  89. delete WebViewElement.prototype.disconnectedCallback;
  90. delete WebViewElement.prototype.attributeChangedCallback;
  91. // Now that |observedAttributes| has been retrieved, we can hide it from
  92. // user code as well.
  93. // TypeScript is concerned that we're deleting a read-only attribute
  94. delete (WebViewElement as any).observedAttributes;
  95. });
  96. };
  97. // Prepare to register the <webview> element.
  98. export const setupWebView = (hooks: WebViewImplHooks) => {
  99. const useCapture = true;
  100. const listener = (event: Event) => {
  101. if (document.readyState === 'loading') {
  102. return;
  103. }
  104. registerWebViewElement(hooks);
  105. window.removeEventListener(event.type, listener, useCapture);
  106. };
  107. window.addEventListener('readystatechange', listener, useCapture);
  108. };