22 *
33 * A wrapper for messaging on WebKit platforms. It supports modern WebKit messageHandlers
44 * along with encryption for older versions (like macOS Catalina)
5- *
6- * Note: If you wish to support Catalina then you'll need to implement the native
7- * part of the message handling, see {@link WebkitMessagingTransport} for details.
85 */
96// eslint-disable-next-line @typescript-eslint/no-unused-vars
107import { MessagingTransport , MissingHandler } from '../index.js' ;
@@ -21,39 +18,6 @@ import { isResponseFor, isSubscriptionEventFor } from '../schema.js';
2118 * const json = await window.webkit.messageHandlers.foo.postMessage({ bar: "baz" });
2219 * const response = JSON.parse(json)
2320 * ```
24- *
25- * @example
26- * On macOS 10 however, the process is a little more involved. A method will be appended to `window`
27- * that allows the response to be delivered there instead. It's not exactly this, but you can visualize the flow
28- * as being something along the lines of:
29- *
30- * ```js
31- * // add the window method
32- * window["_0123456"] = (response) => {
33- * // decrypt `response` and deliver the result to the caller here
34- * // then remove the temporary method
35- * delete window['_0123456']
36- * };
37- *
38- * // send the data + `messageHanding` values
39- * window.webkit.messageHandlers.foo.postMessage({
40- * bar: "baz",
41- * messagingHandling: {
42- * methodName: "_0123456",
43- * secret: "super-secret",
44- * key: [1, 2, 45, 2],
45- * iv: [34, 4, 43],
46- * }
47- * });
48- *
49- * // later in swift, the following JavaScript snippet will be executed
50- * (() => {
51- * window['_0123456']({
52- * ciphertext: [12, 13, 4],
53- * tag: [3, 5, 67, 56]
54- * })
55- * })()
56- * ```
5721 * @implements {MessagingTransport}
5822 */
5923export class WebkitMessagingTransport {
@@ -65,9 +29,7 @@ export class WebkitMessagingTransport {
6529 this . messagingContext = messagingContext ;
6630 this . config = config ;
6731 this . globals = captureGlobals ( ) ;
68- if ( ! this . config . hasModernWebkitAPI ) {
69- this . captureWebkitHandlers ( this . config . webkitMessageHandlerNames ) ;
70- }
32+ this . captureWebkitHandlers ( this . config . webkitMessageHandlerNames ) ;
7133 }
7234
7335 /**
@@ -77,24 +39,7 @@ export class WebkitMessagingTransport {
7739 * @internal
7840 */
7941 wkSend ( handler , data = { } ) {
80- if ( ! ( handler in this . globals . window . webkit . messageHandlers ) ) {
81- throw new MissingHandler ( `Missing webkit handler: '${ handler } '` , handler ) ;
82- }
83- if ( ! this . config . hasModernWebkitAPI ) {
84- const outgoing = {
85- ...data ,
86- messageHandling : {
87- ...data . messageHandling ,
88- secret : this . config . secret ,
89- } ,
90- } ;
91- if ( ! ( handler in this . globals . capturedWebkitHandlers ) ) {
92- throw new MissingHandler ( `cannot continue, method ${ handler } not captured on macos < 11` , handler ) ;
93- } else {
94- return this . globals . capturedWebkitHandlers [ handler ] ( outgoing ) ;
95- }
96- }
97- return this . globals . window . webkit . messageHandlers [ handler ] . postMessage ?. ( data ) ;
42+ return this . globals . capturedWebkitHandlers [ handler ] ?. ( data ) ;
9843 }
9944
10045 /**
@@ -105,49 +50,19 @@ export class WebkitMessagingTransport {
10550 * @internal
10651 */
10752 async wkSendAndWait ( handler , data ) {
108- if ( this . config . hasModernWebkitAPI ) {
109- const response = await this . wkSend ( handler , data ) ;
110- return this . globals . JSONparse ( response || '{}' ) ;
111- }
112-
113- try {
114- const randMethodName = this . createRandMethodName ( ) ;
115- const key = await this . createRandKey ( ) ;
116- const iv = this . createRandIv ( ) ;
117-
118- const { ciphertext, tag } = await new this . globals . Promise ( ( /** @type {any } */ resolve ) => {
119- this . generateRandomMethod ( randMethodName , resolve ) ;
120-
121- // @ts -expect-error - this is a carve-out for catalina that will be removed soon
122- data . messageHandling = new SecureMessagingParams ( {
123- methodName : randMethodName ,
124- secret : this . config . secret ,
125- key : this . globals . Arrayfrom ( key ) ,
126- iv : this . globals . Arrayfrom ( iv ) ,
127- } ) ;
128- this . wkSend ( handler , data ) ;
129- } ) ;
130-
131- const cipher = new this . globals . Uint8Array ( [ ...ciphertext , ...tag ] ) ;
132- const decrypted = await this . decrypt ( cipher , key , iv ) ;
133- return this . globals . JSONparse ( decrypted || '{}' ) ;
134- } catch ( e ) {
135- // re-throw when the error is just a 'MissingHandler'
136- if ( e instanceof MissingHandler ) {
137- throw e ;
138- } else {
139- console . error ( 'decryption failed' , e ) ;
140- console . error ( e ) ;
141- return { error : e } ;
142- }
143- }
53+ const response = await this . wkSend ( handler , data ) ;
54+ return this . globals . JSONparse ( response || '{}' ) ;
14455 }
14556
14657 /**
14758 * @param {import('../index.js').NotificationMessage } msg
14859 */
14960 notify ( msg ) {
150- this . wkSend ( msg . context , msg ) ;
61+ try {
62+ this . wkSend ( msg . context , msg ) ;
63+ } catch ( _e ) {
64+ // no-op
65+ }
15166 }
15267
15368 /**
@@ -170,93 +85,7 @@ export class WebkitMessagingTransport {
17085 }
17186
17287 /**
173- * Generate a random method name and adds it to the global scope
174- * The native layer will use this method to send the response
175- * @param {string | number } randomMethodName
176- * @param {Function } callback
177- * @internal
178- */
179- generateRandomMethod ( randomMethodName , callback ) {
180- this . globals . ObjectDefineProperty ( this . globals . window , randomMethodName , {
181- enumerable : false ,
182- // configurable, To allow for deletion later
183- configurable : true ,
184- writable : false ,
185- /**
186- * @param {any[] } args
187- */
188- value : ( ...args ) => {
189- callback ( ...args ) ;
190- delete this . globals . window [ randomMethodName ] ;
191- } ,
192- } ) ;
193- }
194-
195- /**
196- * @internal
197- * @return {string }
198- */
199- randomString ( ) {
200- return '' + this . globals . getRandomValues ( new this . globals . Uint32Array ( 1 ) ) [ 0 ] ;
201- }
202-
203- /**
204- * @internal
205- * @return {string }
206- */
207- createRandMethodName ( ) {
208- return '_' + this . randomString ( ) ;
209- }
210-
211- /**
212- * @type {{name: string, length: number} }
213- * @internal
214- */
215- algoObj = {
216- name : 'AES-GCM' ,
217- length : 256 ,
218- } ;
219-
220- /**
221- * @returns {Promise<Uint8Array> }
222- * @internal
223- */
224- async createRandKey ( ) {
225- const key = await this . globals . generateKey ( this . algoObj , true , [ 'encrypt' , 'decrypt' ] ) ;
226- const exportedKey = await this . globals . exportKey ( 'raw' , key ) ;
227- return new this . globals . Uint8Array ( exportedKey ) ;
228- }
229-
230- /**
231- * @returns {Uint8Array }
232- * @internal
233- */
234- createRandIv ( ) {
235- return this . globals . getRandomValues ( new this . globals . Uint8Array ( 12 ) ) ;
236- }
237-
238- /**
239- * @param {BufferSource } ciphertext
240- * @param {BufferSource } key
241- * @param {Uint8Array } iv
242- * @returns {Promise<string> }
243- * @internal
244- */
245- async decrypt ( ciphertext , key , iv ) {
246- const cryptoKey = await this . globals . importKey ( 'raw' , key , 'AES-GCM' , false , [ 'decrypt' ] ) ;
247- const algo = {
248- name : 'AES-GCM' ,
249- iv,
250- } ;
251-
252- const decrypted = await this . globals . decrypt ( algo , cryptoKey , ciphertext ) ;
253-
254- const dec = new this . globals . TextDecoder ( ) ;
255- return dec . decode ( decrypted ) ;
256- }
257-
258- /**
259- * When required (such as on macos 10.x), capture the `postMessage` method on
88+ * When required (such as on macOS 10.x), capture the `postMessage` method on
26089 * each webkit messageHandler
26190 *
26291 * @param {string[] } handlerNames
@@ -317,17 +146,10 @@ export class WebkitMessagingTransport {
317146export class WebkitMessagingConfig {
318147 /**
319148 * @param {object } params
320- * @param {boolean } params.hasModernWebkitAPI
321149 * @param {string[] } params.webkitMessageHandlerNames
322- * @param {string } params.secret
323150 * @internal
324151 */
325152 constructor ( params ) {
326- /**
327- * Whether or not the current WebKit Platform supports secure messaging
328- * by default (eg: macOS 11+)
329- */
330- this . hasModernWebkitAPI = params . hasModernWebkitAPI ;
331153 /**
332154 * A list of WebKit message handler names that a user script can send.
333155 *
@@ -344,11 +166,6 @@ export class WebkitMessagingConfig {
344166 * ```
345167 */
346168 this . webkitMessageHandlerNames = params . webkitMessageHandlerNames ;
347- /**
348- * A string provided by native platforms to be sent with future outgoing
349- * messages.
350- */
351- this . secret = params . secret ;
352169 }
353170}
354171
0 commit comments