[rs-commit] r28 - in /redwax-signtext/trunk/src/macos/experimental: ./ firefox/ firefox/_locales/ firefox/_locales/en/ firefox/images/

rs-commit at redwax.eu rs-commit at redwax.eu
Sun Feb 27 20:50:46 CET 2022


Author: minfrin at redwax.eu
Date: Sun Feb 27 20:50:45 2022
New Revision: 28

Log:
Add an experiment where we try return ReadableStreams wrapped in
Promises on Firefox.

Cannot get past this error:

Error: Permission denied to access property "then"

Bug raised with Firefox here:

https://bugzilla.mozilla.org/show_bug.cgi?id=1757066


Added:
    redwax-signtext/trunk/src/macos/experimental/
    redwax-signtext/trunk/src/macos/experimental/firefox/   (with props)
    redwax-signtext/trunk/src/macos/experimental/firefox/Makefile
    redwax-signtext/trunk/src/macos/experimental/firefox/README.md
    redwax-signtext/trunk/src/macos/experimental/firefox/_locales/
    redwax-signtext/trunk/src/macos/experimental/firefox/_locales/en/
    redwax-signtext/trunk/src/macos/experimental/firefox/_locales/en/messages.json   (with props)
    redwax-signtext/trunk/src/macos/experimental/firefox/background.js
    redwax-signtext/trunk/src/macos/experimental/firefox/content.js
    redwax-signtext/trunk/src/macos/experimental/firefox/images/
    redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-128.png   (with props)
    redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-256.png   (with props)
    redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-48.png   (with props)
    redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-512.png   (with props)
    redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-64.png   (with props)
    redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-96.png   (with props)
    redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-16.png   (with props)
    redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-19.png   (with props)
    redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-32.png   (with props)
    redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-38.png   (with props)
    redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-48.png   (with props)
    redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-72.png   (with props)
    redwax-signtext/trunk/src/macos/experimental/firefox/manifest.json   (with props)

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/
------------------------------------------------------------------------------
--- svn:ignore	(added)
+++ svn:ignore	Sun Feb 27 20:50:45 2022
@@ -0,0 +1 @@
+web-ext-artifacts

Added: redwax-signtext/trunk/src/macos/experimental/firefox/Makefile
==============================================================================
--- redwax-signtext/trunk/src/macos/experimental/firefox/Makefile	(added)
+++ redwax-signtext/trunk/src/macos/experimental/firefox/Makefile	Sun Feb 27 20:50:45 2022
@@ -0,0 +1,12 @@
+
+all: ./$(TARGET_TEMP_DIR)/redwax_signtext_extension-*.zip
+
+./$(TARGET_TEMP_DIR)/redwax_signtext_extension-*.zip: manifest.json *.js _locales/*/messages.json images/*
+	web-ext build --overwrite-dest --artifacts-dir "./$(TARGET_TEMP_DIR)"
+
+lint:
+	web-ext lint
+
+clean:
+	rm -rf "./$(TARGET_TEMP_DIR)/redwax_signtext_extension-*.zip"
+

Added: redwax-signtext/trunk/src/macos/experimental/firefox/README.md
==============================================================================
--- redwax-signtext/trunk/src/macos/experimental/firefox/README.md	(added)
+++ redwax-signtext/trunk/src/macos/experimental/firefox/README.md	Sun Feb 27 20:50:45 2022
@@ -0,0 +1,12 @@
+# experimental
+
+This contains an attempt to use signText returning a ReadableStream that returns
+Promises.
+
+The Promise so returned does not have the correct permissions to be run from the
+page scope, and all attempts fail as follows:
+
+    Error: Permission denied to access property "then"
+
+Giving up for now.
+

Added: redwax-signtext/trunk/src/macos/experimental/firefox/_locales/en/messages.json
==============================================================================
Binary file - no diff available.

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/_locales/en/messages.json
------------------------------------------------------------------------------
    svn:mime-type = application/json

Added: redwax-signtext/trunk/src/macos/experimental/firefox/background.js
==============================================================================
--- redwax-signtext/trunk/src/macos/experimental/firefox/background.js	(added)
+++ redwax-signtext/trunk/src/macos/experimental/firefox/background.js	Sun Feb 27 20:50:45 2022
@@ -0,0 +1,117 @@
+
+console.log('Redwax SignText: background started');
+
+var csPorts = [];
+//var nativePort = undefined;
+
+function nativeMessaged(m) {
+
+    console.log('Redwax SignText: background: message received from native: ', m);
+
+    /*
+     * Native message response is handled here. Send the message
+     * to the correctly numbered content script.
+     */
+    window.csPorts.forEach(p => {
+        if (p.sender.tab.id == m.id) {
+
+           console.log('Redwax SignText: background: message passed from native to content: ', m);
+
+            p.postMessage({ uuid: m.uuid, response: m.response, contentType: m.contentType });
+        }
+    });
+}
+
+function nativeDisconnected(p) {
+
+            window.nativePort.onMessage.removeListener(nativeMessaged);
+            window.nativePort.onDisconnect.removeListener(nativeDisconnected);
+
+//    window.nativePort.disconnect();
+    window.nativePort = undefined;
+
+    window.csPorts.forEach(cp => {
+        cp.postMessage({ error: 'error:nativeDisconnected', exception: p.error.message });
+    });
+    console.log('Redwax SignText: native port disconnected.');
+}
+
+function connected(p) {
+    window.csPorts[p.sender.tab.id] = p;
+    console.log('Redwax SignText: background: connection received from content: ', p);
+    messageHandler = function(m) {
+
+        console.log('Redwax SignText: background: message received from content: ', m);
+
+        if (typeof window.nativePort === 'undefined') {
+
+            console.log('Redwax SignText: background: open native port (attempt one)');
+
+            window.nativePort = browser.runtime.connectNative('eu.redwax.Redwax.SignText');
+            window.nativePort.onMessage.addListener(nativeMessaged);
+            window.nativePort.onDisconnect.addListener(nativeDisconnected);
+        }
+
+        let title = p.sender.tab.title ? p.sender.tab.title : "No title";
+        let url = p.sender.tab.url ? p.sender.tab.url : "No URL";
+
+        console.log('Redwax SignText: background: nativeport created');
+
+        try {
+            /*
+             * Let's try send the message on the assumption the port is
+             * open and works. On failure, try to open the port and retry.
+             */
+
+            console.log('Redwax SignText: background: send message (attempt one)');
+
+            window.nativePort.postMessage({ title: title, url: url, id: p.sender.tab.id, uuid: m.uuid, request: m.request, contentType: m.contentType });
+        }
+        catch (exception) {
+
+            console.log('Redwax SignText: background: open native port (attempt two)');
+
+            /*
+             * Not able to send the message. (Re)open the port and try
+             * once more.
+             */
+            window.nativePort = browser.runtime.connectNative('eu.redwax.Redwax.SignText');
+            window.nativePort.onMessage.addListener(nativeMessaged);
+            window.nativePort.onDisconnect.addListener(nativeDisconnected);
+            
+            /*
+             * One more try to send the message.
+             */
+            try {
+                console.log('Redwax SignText: background: send message (attempt two)');
+                window.nativePort.postMessage({ title: title, url: url, id: p.sender.tab.id, uuid: m.uuid, request: m.request, contentType: m.contentType });
+            }
+            catch (exception) {
+
+                window.nativePort = undefined;
+
+                /*
+                 * No luck, send a message back to the content script with
+                 * the bad news.
+                 */
+                console.log('Redwax SignText: postNativeMessageFailed: ', exception);
+                p.postMessage({ uuid: m.uuid, error: 'error:postNativeMessageFailed', exception: exception.message });
+                
+            }
+            
+        }
+        
+    };
+
+    p.onMessage.addListener(messageHandler);
+
+    p.onDisconnect.addListener(function(p) {
+        p.onMessage.removeListener(messageHandler);
+        console.log('Redwax SignText: tab ' + p.sender.tab.id + ' disconnected.');
+        delete csPorts[p.sender.tab.id];
+    });
+}
+
+browser.runtime.onConnect.addListener(connected);
+
+console.log('Redwax SignText: background ended');

Added: redwax-signtext/trunk/src/macos/experimental/firefox/content.js
==============================================================================
--- redwax-signtext/trunk/src/macos/experimental/firefox/content.js	(added)
+++ redwax-signtext/trunk/src/macos/experimental/firefox/content.js	Sun Feb 27 20:50:45 2022
@@ -0,0 +1,387 @@
+/*
+ * Handle all background script events, passing them as
+ * appropriate to the webpage.
+ */
+const port = browser.runtime.connect('rst at redwax.eu', {
+	name: window.location.href
+});
+
+/*
+ * Firefox
+ * =======
+ *
+ * We cannot document.dispatchEvent on Firefox. Instead, declare a crypto.signText function
+ * using exportFunction to pass the messages.
+ */
+if (typeof exportFunction == 'function') {
+
+	function stringReader(str) {
+		var offset = 0;
+		const chunkSize = 1024;
+		return new ReadableStream({
+			pull(controller) {
+				var nextOffset = offset + chunkSize;
+				if (nextOffset >= str.length) {
+					nextOffset = str.length;
+					controller.enqueue(str.substring(offset, nextOffset));
+					controller.close();
+				} else {
+					controller.enqueue(str.substring(offset, nextOffset));
+				}
+				offset = nextOffset;
+			}
+		});
+	}
+
+	function uuidv4() {
+		return ([1e7] + -1e3 + -4e3 + -8e3 + -1e11).replace(/[018]/g, c =>
+			(c ^ crypto.getRandomValues(new Uint8Array(1))[0] & 15 >> c / 4).toString(16)
+		);
+	}
+
+	function signTextReader(requestStream, options, ...CAs) {
+		const uuid = uuidv4();
+		const reader = requestStream.getReader();
+		return new ReadableStream({
+			start(controller) {
+
+				function push() {
+					reader.read().then(({
+						done,
+						value
+					}) => {
+
+						try {
+							if (!done) {
+								port.postMessage({
+									protocol: location.protocol,
+									hostname: location.hostname,
+									contentType: 'text/plain',
+									uuid: uuid,
+									request: value
+								});
+							} else {
+								port.postMessage({
+									protocol: location.protocol,
+									hostname: location.hostname,
+									contentType: 'text/plain',
+									uuid: uuid,
+									request: {
+										signText: options,
+										CAs: CAs
+									}
+								});
+							}
+
+						} catch (exception) {
+
+							const response = new window.wrappedJSObject.Error('error:postMessageFailed');
+
+							return new window.wrappedJSObject.Promise(
+								exportFunction(
+									function(resolve, reject) {
+										reject(response);
+									}, window.wrappedJSObject
+								)
+							);
+						}
+					});
+				}
+
+				const signTextHandler = function(e) {
+					/* message not for us */
+					if (!(e.uuid === undefined) && !(e.uuid === uuid)) {
+						/* do nothing */
+					}
+					/* an error was received, cancel the stream */
+					else if (e.error) {
+						const error = new window.wrappedJSObject.Error(e.error);
+						controller.enqueue(error);
+						controller.close();
+						port.onMessage.removeListener(signTextHandler);
+					}
+					/* an ack was received, send the next chunk */
+					else if (e.response === true) {
+						push();
+					}
+					/* an eos was received, we're done */
+					else if (e.response === false) {
+						controller.close();
+						port.onMessage.removeListener(signTextHandler);
+					}
+					/* a response was received, enqueue the response */
+					else {
+						controller.enqueue(e.response);
+					}
+				};
+
+				/* add our listener */
+				port.onMessage.addListener(signTextHandler);
+
+				port.onDisconnect.addListener((p) => {
+					if (p.error) {
+						console.log(`Redwax SignText: disconnected due to an error: ${p.error.message}`);
+					} else {
+						console.log(`Redwax SignText: disconnected`);
+					}
+				});
+
+				/* fire off initial request */
+				push();
+
+			}
+		});
+	}
+
+	function readerStreamToString(stream) {
+		const reader = stream.getReader();
+		let result = '';
+
+		let processText = exportFunction(function processText({
+			done,
+			value
+		}) {
+
+			return new window.wrappedJSObject.Promise(
+				exportFunction(
+					function(resolve, reject) {
+
+						if (Object.prototype.toString.call(value) === "[object Error]") {
+							reject(value);
+						} else if (done) {
+							console.log("Stream complete:" + result);
+							resolve(result);
+						} else {
+							result += value;
+							resolve(reader.read().then(processText));
+						}
+					}, window.wrappedJSObject
+				)
+			);
+
+		}, window.wrappedJSObject);
+
+		return new window.wrappedJSObject.Promise(
+			exportFunction(
+				function(resolve, reject) {
+					resolve( reader.read().then(processText) );
+				}, window.wrappedJSObject
+			)
+		);
+	}
+
+	signText = function SignText(source, options, ...CAs) {
+
+		var requestStream;
+
+		if (typeof source === 'undefined') {
+
+			/*
+			 * We've been asked for info about the signtext extension.
+			 *
+			 * This can be used to detect support for the extension
+			 * before trying to use it.
+			 */
+
+			const manifest = browser.runtime.getManifest();
+			const response = cloneInto({
+				name: manifest.name,
+				version: manifest.version
+			}, window.wrappedJSObject);
+
+			return new window.wrappedJSObject.Promise(
+				exportFunction(
+					function(resolve, reject) {
+						resolve(response);
+					}, window.wrappedJSObject
+				)
+			);
+
+		}
+
+
+		/* pass a string, we return a string */
+		if (typeof source === 'string') {
+			var requestStream = stringReader(source);
+		}
+
+		/* consume a ReadableStream */
+		else if (source instanceof ReadableStream) {
+			var requestStream = source;
+		} else {
+
+			const response = new window.wrappedJSObject.Error('error:unknownType');
+
+			return new window.wrappedJSObject.Promise(
+				exportFunction(
+					function(resolve, reject) {
+						reject(response);
+					}, window.wrappedJSObject
+				)
+			);
+		}
+
+		const responseStream = signTextReader(requestStream, options, CAs);
+
+		/* pass a string, we return a string */
+		if (typeof source === 'string') {
+
+			return new window.wrappedJSObject.Promise(
+				exportFunction(
+					function(resolve, reject) {
+						resolve(readerStreamToString(responseStream));
+					}, window.wrappedJSObject
+				)
+			);
+
+			//      return readerStreamToString(responseStream);
+		}
+
+		/* return a ReadableStream */
+		else {
+			return responseStream;
+		}
+
+	};
+
+	exportFunction(signText, window.crypto, {
+		defineAs: "signText"
+	});
+
+}
+
+/*
+ * Chrome / Safari
+ * ===============
+ *
+ * We cannot exportFunction on Chrome or Safari. Instead, pass messages using document.dispatchEvent
+ * to get data back and forth.
+ */
+else {
+
+	port.onMessage.addListener((message) => {
+		document.dispatchEvent(new CustomEvent('eu.redwax.signTextResponse', {
+			bubbles: true,
+			detail: message
+		}));
+	});
+
+	port.onDisconnect.addListener((p) => {
+		if (p.error) {
+			console.log(`Redwax SignText: disconnected due to an error: ${p.error.message}`);
+		} else {
+			console.log(`Redwax SignText: disconnected`);
+		}
+	});
+
+
+	/*
+	 * Handle all webpage signtext info events, return our version
+	 * information.
+	 */
+	document.addEventListener('eu.redwax.signTextRequestInfo', function(e) {
+		/*
+		 * We've been asked for info about the signtext extension.
+		 *
+		 * This can be used to detect support for the extension
+		 * before trying to use it.
+		 */
+		const manifest = browser.runtime.getManifest();
+		e.target.dispatchEvent(new CustomEvent('eu.redwax.signTextResponseInfo', {
+			bubbles: true,
+			detail: {
+				name: manifest.name,
+				version: manifest.version
+			}
+		}));
+
+	});
+
+	/*
+	 * Handle all webpage signtext events, passing them as approriate
+	 * to the background script.
+	 */
+	document.addEventListener('eu.redwax.signTextRequest', function(e) {
+		/*
+		 * We've been asked to sign a specific request. Check the
+		 * request, and pass the request to the background if the
+		 * check passes.
+		 */
+		if (e.detail.request) {
+
+			/*
+			 * UUID valid? If not, complain.
+			 */
+			if (typeof e.detail.uuid !== 'string') {
+				/* error - uuid is missing or invalid */
+				e.target.dispatchEvent(new CustomEvent('eu.redwax.signTextResponse', {
+					bubbles: true,
+					detail: {
+						uuid: e.detail.uuid,
+						error: 'error:uuidInvalid'
+					}
+				}));
+			}
+
+			/*
+			 * Hostname valid? If not, complain.
+			 */
+			if (typeof e.detail.hostname !== 'string') {
+				/* error - hostname is missing or invalid */
+				e.target.dispatchEvent(new CustomEvent('eu.redwax.signTextResponse', {
+					bubbles: true,
+					detail: {
+						uuid: e.detail.uuid,
+						error: 'error:hostnameInvalid'
+					}
+				}));
+			}
+
+			/*
+			 * Content Type valid? If not, complain.
+			 */
+			switch (e.detail.contentType) {
+				case undefined:
+				case 'text/plain':
+				case 'application/pkcs7-mime': {
+
+					/*
+					 * Checks have passed, send message to background script.
+					 */
+					try {
+						port.postMessage({
+							uuid: e.detail.uuid,
+							hostname: e.hostname,
+							protocol: e.protocol,
+							request: e.detail.request,
+							contentType: e.detail.contentType
+						});
+					} catch (exception) {
+						e.target.dispatchEvent(new CustomEvent('eu.redwax.signTextResponse', {
+							bubbles: true,
+							detail: {
+								uuid: e.detail.uuid,
+								error: 'error:postMessageFailed',
+								exception: exception
+							}
+						}));
+					}
+
+					break;
+				}
+				default: {
+					/* error - mime type unrecognised */
+					e.target.dispatchEvent(new CustomEvent('eu.redwax.signTextResponse', {
+						bubbles: true,
+						detail: {
+							uuid: e.detail.uuid,
+							error: 'error:contentTypeUnrecognised'
+						}
+					}));
+				}
+			}
+
+		}
+	});
+
+}

Added: redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-128.png
==============================================================================
Binary file - no diff available.

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-128.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-256.png
==============================================================================
Binary file - no diff available.

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-256.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-48.png
==============================================================================
Binary file - no diff available.

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-48.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-512.png
==============================================================================
Binary file - no diff available.

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-512.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-64.png
==============================================================================
Binary file - no diff available.

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-64.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-96.png
==============================================================================
Binary file - no diff available.

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/images/icon-96.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-16.png
==============================================================================
Binary file - no diff available.

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-16.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-19.png
==============================================================================
Binary file - no diff available.

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-19.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-32.png
==============================================================================
Binary file - no diff available.

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-32.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-38.png
==============================================================================
Binary file - no diff available.

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-38.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-48.png
==============================================================================
Binary file - no diff available.

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-48.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-72.png
==============================================================================
Binary file - no diff available.

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/images/toolbar-icon-72.png
------------------------------------------------------------------------------
    svn:mime-type = image/png

Added: redwax-signtext/trunk/src/macos/experimental/firefox/manifest.json
==============================================================================
Binary file - no diff available.

Propchange: redwax-signtext/trunk/src/macos/experimental/firefox/manifest.json
------------------------------------------------------------------------------
    svn:mime-type = application/json



More information about the rs-commit mailing list