1/* vim: set ts=2 sw=2 sts=2 et tw=80: */ 2/* This Source Code Form is subject to the terms of the Mozilla Public 3 * License, v. 2.0. If a copy of the MPL was not distributed with this 4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 5"use strict"; 6 7const EXPORTED_SYMBOLS = ["ASRouterNewTabHook"]; 8 9class ASRouterNewTabHookInstance { 10 constructor() { 11 this._newTabMessageHandler = null; 12 this._parentProcessMessageHandler = null; 13 this._router = null; 14 this._clearChildMessages = (...params) => 15 this._newTabMessageHandler === null 16 ? Promise.resolve() 17 : this._newTabMessageHandler.clearChildMessages(...params); 18 this._clearChildProviders = (...params) => 19 this._newTabMessageHandler === null 20 ? Promise.resolve() 21 : this._newTabMessageHandler.clearChildProviders(...params); 22 this._updateAdminState = (...params) => 23 this._newTabMessageHandler === null 24 ? Promise.resolve() 25 : this._newTabMessageHandler.updateAdminState(...params); 26 } 27 28 /** 29 * Params: 30 * object - { 31 * messageHandler: message handler for parent process messages 32 * { 33 * handleCFRAction: Responds to CFR action and returns a Promise 34 * handleTelemetry: Logs telemetry events and returns nothing 35 * }, 36 * router: ASRouter instance 37 * createStorage: function to create DB storage for ASRouter 38 * } 39 */ 40 async initialize({ messageHandler, router, createStorage }) { 41 this._parentProcessMessageHandler = messageHandler; 42 this._router = router; 43 if (!this._router.initialized) { 44 const storage = await createStorage(); 45 await this._router.init({ 46 storage, 47 sendTelemetry: this._parentProcessMessageHandler.handleTelemetry, 48 dispatchCFRAction: this._parentProcessMessageHandler.handleCFRAction, 49 clearChildMessages: this._clearChildMessages, 50 clearChildProviders: this._clearChildProviders, 51 updateAdminState: this._updateAdminState, 52 }); 53 } 54 } 55 56 destroy() { 57 if (this._router?.initialized) { 58 this.disconnect(); 59 this._router.uninit(); 60 } 61 } 62 63 /** 64 * Connects new tab message handler to hook. 65 * Note: Should only ever be called on an initialized instance 66 * Params: 67 * newTabMessageHandler - { 68 * clearChildMessages: clears child messages and returns Promise 69 * clearChildProviders: clears child providers and returns Promise. 70 * updateAdminState: updates admin state and returns Promise 71 * } 72 * Returns: parentProcessMessageHandler 73 */ 74 connect(newTabMessageHandler) { 75 this._newTabMessageHandler = newTabMessageHandler; 76 return this._parentProcessMessageHandler; 77 } 78 79 /** 80 * Disconnects new tab message handler from hook. 81 */ 82 disconnect() { 83 this._newTabMessageHandler = null; 84 } 85} 86 87class AwaitSingleton { 88 constructor() { 89 this.instance = null; 90 const initialized = new Promise(resolve => { 91 this.setInstance = instance => { 92 this.setInstance = () => {}; 93 this.instance = instance; 94 resolve(instance); 95 }; 96 }); 97 this.getInstance = () => initialized; 98 } 99} 100 101const ASRouterNewTabHook = (() => { 102 const singleton = new AwaitSingleton(); 103 const instance = new ASRouterNewTabHookInstance(); 104 return { 105 getInstance: singleton.getInstance, 106 107 /** 108 * Param: 109 * params - see ASRouterNewTabHookInstance.init 110 */ 111 createInstance: async params => { 112 await instance.initialize(params); 113 singleton.setInstance(instance); 114 }, 115 116 destroy: () => { 117 instance.destroy(); 118 }, 119 }; 120})(); 121