blob: 7b4e9983e50098151bd2ba44bfa50b502ad63da9 [file] [log] [blame]
Akrone51eaa32020-11-10 09:35:53 +01001"use strict";
2
Akron22598cd2019-12-09 14:59:03 +01003define(function () {
Akronc3003642020-03-30 10:19:14 +02004
Akronce0d8822020-10-05 16:25:40 +02005 // Limit the supported sandbox permissions, especially
Marc Kupietz0d0dc6b2026-02-15 08:43:12 +01006 // to disallow 'same-origin' unless explicitly requested
7 // and the plugin is hosted on the same origin.
Akronce0d8822020-10-05 16:25:40 +02008 let allowed = {
9 "scripts" : 1,
10 "presentation" : 1,
11 "forms": 1,
12 "downloads-without-user-activation" : 1,
Akron8f1dbcf2022-12-21 12:09:39 +010013 "downloads" : 1,
Marc Kupietz0d0dc6b2026-02-15 08:43:12 +010014 "popups" : 1,
15 "same-origin" : 1
16 };
17
18 /**
19 * Check if a URL is on the same origin as the current page.
20 */
21 function _isSameOrigin (src) {
22 try {
23 const url = new URL(src, window.location.href);
24 return url.origin === window.location.origin;
25 } catch (e) {
26 return false;
27 }
Akronce0d8822020-10-05 16:25:40 +020028 };
29
Akron22598cd2019-12-09 14:59:03 +010030 return {
Akronbb891982020-10-05 16:07:18 +020031 create : function (data) {
32 return Object.create(this)._init(data);
Akron22598cd2019-12-09 14:59:03 +010033 },
34
35 // Initialize service
Akronbb891982020-10-05 16:07:18 +020036 _init : function (data) {
37 if (!data || !data["name"] || !data["src"] || !data["id"])
Akron22598cd2019-12-09 14:59:03 +010038 throw Error("Service not well defined");
Akronbb891982020-10-05 16:07:18 +020039
40 this.name = data["name"];
41 this.src = data["src"];
42 this.id = data["id"];
Akron3d013802020-10-07 15:03:38 +020043 this.desc = data["desc"];
Akronce0d8822020-10-05 16:25:40 +020044 let _perm = new Set();
Akronbb891982020-10-05 16:07:18 +020045 let perm = data["permissions"];
46 if (perm && Array.isArray(perm)) {
Akronce0d8822020-10-05 16:25:40 +020047 perm.forEach(function (p) {
48 if (p in allowed) {
49 _perm.add(p)
50 }
51 else {
52 KorAP.log(0, "Requested permission not allowed");
53 }
54 });
Akronbb891982020-10-05 16:07:18 +020055 };
Akronce0d8822020-10-05 16:25:40 +020056
57 this._perm = _perm;
Akronfb11a962020-10-05 12:12:55 +020058
Akron22598cd2019-12-09 14:59:03 +010059 // There is no close method defined yet
60 if (!this.close) {
61 this.close = function () {
62 this._closeIframe();
63 }
64 }
65
66 return this;
67 },
68
69 /**
70 * The element of the service as embedded in the panel
71 */
72 load : function () {
73 if (this._load)
74 return this._load;
Akron24f48ea2020-07-01 09:37:19 +020075
76 if (window.location.protocol == 'https:' &&
77 this.src.toLowerCase().indexOf('https:') != 0) {
78 KorAP.log(0, "Service endpoint is insecure");
79 return;
80 };
81
Akron22598cd2019-12-09 14:59:03 +010082 // Spawn new iframe
83 let e = document.createElement('iframe');
84 e.setAttribute('allowTransparency',"true");
85 e.setAttribute('frameborder', 0);
hebasta78913242020-03-30 13:39:20 +020086 // Allow forms in Plugins
Marc Kupietz1cd15692026-02-14 14:05:00 +010087 let permissions = Array.from(this._perm).sort().map(function(i){ return "allow-"+i });
Marc Kupietz0d0dc6b2026-02-15 08:43:12 +010088
89 // Only grant same-origin if plugin explicitly requested it
90 // AND is hosted on the same origin (security gate)
91 if (this._perm.has("same-origin") && !_isSameOrigin(this.src)) {
92 permissions = permissions.filter(function(p) { return p !== "allow-same-origin" });
93 KorAP.log(0, "Ignoring same-origin permission for cross-origin plugin");
94 };
95
Marc Kupietz1cd15692026-02-14 14:05:00 +010096 e.setAttribute('sandbox', permissions.join(" "));
Akron22598cd2019-12-09 14:59:03 +010097 e.style.height = '0px';
98 e.setAttribute('name', this.id);
99 e.setAttribute('src', this.src);
100
101 this._load = e;
102 return e;
103 },
104
Akronc3003642020-03-30 10:19:14 +0200105 /**
106 * Send a message to the embedded service.
107 */
108 sendMsg : function (d) {
109 let iframe = this.load();
Akronb0ae8412026-02-24 11:47:52 +0100110 if (iframe && iframe.contentWindow) {
111 iframe.contentWindow.postMessage(
112 d,
113 '*'
114 ); // TODO: Fix origin
115 };
Akronc3003642020-03-30 10:19:14 +0200116 },
117
Akron22598cd2019-12-09 14:59:03 +0100118 // onClose : function () {},
119
120 /**
121 * Close the service iframe.
122 */
123 _closeIframe : function () {
124 var e = this._load;
125 if (e && e.parentNode) {
126 e.parentNode.removeChild(e);
127 };
128 this._load = null;
129 }
130 };
131});