Use cross frame API (#553)
* Use new CrossFrameAPI for popup proxy communication * Remove use of old cross-frame communication classes * Remove use of old cross-frame communication files * Make the crossFrame object a member of the api object
This commit is contained in:
parent
b614aca3dd
commit
9767b76553
@ -28,7 +28,6 @@
|
|||||||
<script src="/bg/js/backend.js"></script>
|
<script src="/bg/js/backend.js"></script>
|
||||||
<script src="/bg/js/mecab.js"></script>
|
<script src="/bg/js/mecab.js"></script>
|
||||||
<script src="/bg/js/audio-uri-builder.js"></script>
|
<script src="/bg/js/audio-uri-builder.js"></script>
|
||||||
<script src="/bg/js/backend-api-forwarder.js"></script>
|
|
||||||
<script src="/bg/js/clipboard-monitor.js"></script>
|
<script src="/bg/js/clipboard-monitor.js"></script>
|
||||||
<script src="/bg/js/conditions.js"></script>
|
<script src="/bg/js/conditions.js"></script>
|
||||||
<script src="/bg/js/database.js"></script>
|
<script src="/bg/js/database.js"></script>
|
||||||
|
@ -180,6 +180,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/mixed/js/core.js"></script>
|
<script src="/mixed/js/core.js"></script>
|
||||||
|
<script src="/mixed/js/comm.js"></script>
|
||||||
<script src="/mixed/js/dom.js"></script>
|
<script src="/mixed/js/dom.js"></script>
|
||||||
<script src="/mixed/js/api.js"></script>
|
<script src="/mixed/js/api.js"></script>
|
||||||
|
|
||||||
|
@ -1,44 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2019-2020 Yomichan Authors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
class BackendApiForwarder {
|
|
||||||
prepare() {
|
|
||||||
chrome.runtime.onConnect.addListener(this._onConnect.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
_onConnect(port) {
|
|
||||||
if (port.name !== 'backend-api-forwarder') { return; }
|
|
||||||
|
|
||||||
let tabId;
|
|
||||||
if (!(
|
|
||||||
port.sender &&
|
|
||||||
port.sender.tab &&
|
|
||||||
(typeof (tabId = port.sender.tab.id)) === 'number'
|
|
||||||
)) {
|
|
||||||
port.disconnect();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const forwardPort = chrome.tabs.connect(tabId, {name: 'frontend-api-receiver'});
|
|
||||||
|
|
||||||
port.onMessage.addListener((message) => forwardPort.postMessage(message));
|
|
||||||
forwardPort.onMessage.addListener((message) => port.postMessage(message));
|
|
||||||
port.onDisconnect.addListener(() => forwardPort.disconnect());
|
|
||||||
forwardPort.onDisconnect.addListener(() => port.disconnect());
|
|
||||||
}
|
|
||||||
}
|
|
@ -20,7 +20,6 @@
|
|||||||
* AnkiNoteBuilder
|
* AnkiNoteBuilder
|
||||||
* AudioSystem
|
* AudioSystem
|
||||||
* AudioUriBuilder
|
* AudioUriBuilder
|
||||||
* BackendApiForwarder
|
|
||||||
* ClipboardMonitor
|
* ClipboardMonitor
|
||||||
* Database
|
* Database
|
||||||
* DictionaryImporter
|
* DictionaryImporter
|
||||||
@ -76,9 +75,6 @@ class Backend {
|
|||||||
|
|
||||||
this.popupWindow = null;
|
this.popupWindow = null;
|
||||||
|
|
||||||
const apiForwarder = new BackendApiForwarder();
|
|
||||||
apiForwarder.prepare();
|
|
||||||
|
|
||||||
this._defaultBrowserActionTitle = null;
|
this._defaultBrowserActionTitle = null;
|
||||||
this._isPrepared = false;
|
this._isPrepared = false;
|
||||||
this._prepareError = false;
|
this._prepareError = false;
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
async function injectSearchFrontend() {
|
async function injectSearchFrontend() {
|
||||||
await dynamicLoader.loadScripts([
|
await dynamicLoader.loadScripts([
|
||||||
'/mixed/js/text-scanner.js',
|
'/mixed/js/text-scanner.js',
|
||||||
'/fg/js/frontend-api-receiver.js',
|
|
||||||
'/fg/js/frame-offset-forwarder.js',
|
'/fg/js/frame-offset-forwarder.js',
|
||||||
'/fg/js/popup.js',
|
'/fg/js/popup.js',
|
||||||
'/fg/js/popup-factory.js',
|
'/fg/js/popup-factory.js',
|
||||||
|
@ -71,6 +71,7 @@
|
|||||||
<script src="/mixed/lib/wanakana.min.js"></script>
|
<script src="/mixed/lib/wanakana.min.js"></script>
|
||||||
|
|
||||||
<script src="/mixed/js/core.js"></script>
|
<script src="/mixed/js/core.js"></script>
|
||||||
|
<script src="/mixed/js/comm.js"></script>
|
||||||
<script src="/mixed/js/dom.js"></script>
|
<script src="/mixed/js/dom.js"></script>
|
||||||
<script src="/mixed/js/api.js"></script>
|
<script src="/mixed/js/api.js"></script>
|
||||||
<script src="/mixed/js/japanese.js"></script>
|
<script src="/mixed/js/japanese.js"></script>
|
||||||
|
@ -119,13 +119,13 @@
|
|||||||
</div></div></div>
|
</div></div></div>
|
||||||
|
|
||||||
<script src="/mixed/js/core.js"></script>
|
<script src="/mixed/js/core.js"></script>
|
||||||
|
<script src="/mixed/js/comm.js"></script>
|
||||||
<script src="/mixed/js/dom.js"></script>
|
<script src="/mixed/js/dom.js"></script>
|
||||||
<script src="/mixed/js/api.js"></script>
|
<script src="/mixed/js/api.js"></script>
|
||||||
<script src="/mixed/js/dynamic-loader.js"></script>
|
<script src="/mixed/js/dynamic-loader.js"></script>
|
||||||
<script src="/mixed/js/text-scanner.js"></script>
|
<script src="/mixed/js/text-scanner.js"></script>
|
||||||
|
|
||||||
<script src="/fg/js/document.js"></script>
|
<script src="/fg/js/document.js"></script>
|
||||||
<script src="/fg/js/frontend-api-receiver.js"></script>
|
|
||||||
<script src="/fg/js/popup.js"></script>
|
<script src="/fg/js/popup.js"></script>
|
||||||
<script src="/fg/js/source.js"></script>
|
<script src="/fg/js/source.js"></script>
|
||||||
<script src="/fg/js/popup-factory.js"></script>
|
<script src="/fg/js/popup-factory.js"></script>
|
||||||
|
@ -1121,6 +1121,7 @@
|
|||||||
<script src="/mixed/lib/wanakana.min.js"></script>
|
<script src="/mixed/lib/wanakana.min.js"></script>
|
||||||
|
|
||||||
<script src="/mixed/js/core.js"></script>
|
<script src="/mixed/js/core.js"></script>
|
||||||
|
<script src="/mixed/js/comm.js"></script>
|
||||||
<script src="/mixed/js/dom.js"></script>
|
<script src="/mixed/js/dom.js"></script>
|
||||||
<script src="/mixed/js/environment.js"></script>
|
<script src="/mixed/js/environment.js"></script>
|
||||||
<script src="/mixed/js/api.js"></script>
|
<script src="/mixed/js/api.js"></script>
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
</div>
|
</div>
|
||||||
|
|
||||||
<script src="/mixed/js/core.js"></script>
|
<script src="/mixed/js/core.js"></script>
|
||||||
|
<script src="/mixed/js/comm.js"></script>
|
||||||
<script src="/mixed/js/dom.js"></script>
|
<script src="/mixed/js/dom.js"></script>
|
||||||
<script src="/mixed/js/api.js"></script>
|
<script src="/mixed/js/api.js"></script>
|
||||||
<script src="/mixed/js/japanese.js"></script>
|
<script src="/mixed/js/japanese.js"></script>
|
||||||
|
@ -24,7 +24,6 @@
|
|||||||
async function injectPopupNested() {
|
async function injectPopupNested() {
|
||||||
await dynamicLoader.loadScripts([
|
await dynamicLoader.loadScripts([
|
||||||
'/mixed/js/text-scanner.js',
|
'/mixed/js/text-scanner.js',
|
||||||
'/fg/js/frontend-api-sender.js',
|
|
||||||
'/fg/js/popup.js',
|
'/fg/js/popup.js',
|
||||||
'/fg/js/popup-proxy.js',
|
'/fg/js/popup-proxy.js',
|
||||||
'/fg/js/frontend.js',
|
'/fg/js/frontend.js',
|
||||||
|
@ -1,76 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2019-2020 Yomichan Authors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
class FrontendApiReceiver {
|
|
||||||
constructor(source, messageHandlers) {
|
|
||||||
this._source = source;
|
|
||||||
this._messageHandlers = messageHandlers;
|
|
||||||
}
|
|
||||||
|
|
||||||
prepare() {
|
|
||||||
chrome.runtime.onConnect.addListener(this._onConnect.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
_onConnect(port) {
|
|
||||||
if (port.name !== 'frontend-api-receiver') { return; }
|
|
||||||
|
|
||||||
port.onMessage.addListener(this._onMessage.bind(this, port));
|
|
||||||
}
|
|
||||||
|
|
||||||
_onMessage(port, {id, action, params, target, senderId}) {
|
|
||||||
if (target !== this._source) { return; }
|
|
||||||
|
|
||||||
const messageHandler = this._messageHandlers.get(action);
|
|
||||||
if (typeof messageHandler === 'undefined') { return; }
|
|
||||||
|
|
||||||
const {handler, async} = messageHandler;
|
|
||||||
|
|
||||||
this._sendAck(port, id, senderId);
|
|
||||||
if (async) {
|
|
||||||
this._invokeHandlerAsync(handler, params, port, id, senderId);
|
|
||||||
} else {
|
|
||||||
this._invokeHandler(handler, params, port, id, senderId);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_invokeHandler(handler, params, port, id, senderId) {
|
|
||||||
try {
|
|
||||||
const result = handler(params);
|
|
||||||
this._sendResult(port, id, senderId, {result});
|
|
||||||
} catch (error) {
|
|
||||||
this._sendResult(port, id, senderId, {error: errorToJson(error)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async _invokeHandlerAsync(handler, params, port, id, senderId) {
|
|
||||||
try {
|
|
||||||
const result = await handler(params);
|
|
||||||
this._sendResult(port, id, senderId, {result});
|
|
||||||
} catch (error) {
|
|
||||||
this._sendResult(port, id, senderId, {error: errorToJson(error)});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_sendAck(port, id, senderId) {
|
|
||||||
port.postMessage({type: 'ack', id, senderId});
|
|
||||||
}
|
|
||||||
|
|
||||||
_sendResult(port, id, senderId, data) {
|
|
||||||
port.postMessage({type: 'result', id, senderId, data});
|
|
||||||
}
|
|
||||||
}
|
|
@ -1,128 +0,0 @@
|
|||||||
/*
|
|
||||||
* Copyright (C) 2019-2020 Yomichan Authors
|
|
||||||
*
|
|
||||||
* This program is free software: you can redistribute it and/or modify
|
|
||||||
* it under the terms of the GNU General Public License as published by
|
|
||||||
* the Free Software Foundation, either version 3 of the License, or
|
|
||||||
* (at your option) any later version.
|
|
||||||
*
|
|
||||||
* This program is distributed in the hope that it will be useful,
|
|
||||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
||||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
||||||
* GNU General Public License for more details.
|
|
||||||
*
|
|
||||||
* You should have received a copy of the GNU General Public License
|
|
||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
|
|
||||||
class FrontendApiSender {
|
|
||||||
constructor(target) {
|
|
||||||
this._target = target;
|
|
||||||
this._senderId = yomichan.generateId(16);
|
|
||||||
this._ackTimeout = 3000; // 3 seconds
|
|
||||||
this._responseTimeout = 10000; // 10 seconds
|
|
||||||
this._callbacks = new Map();
|
|
||||||
this._disconnected = false;
|
|
||||||
this._nextId = 0;
|
|
||||||
this._port = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
invoke(action, params) {
|
|
||||||
if (this._disconnected) {
|
|
||||||
// attempt to reconnect the next time
|
|
||||||
this._disconnected = false;
|
|
||||||
return Promise.reject(new Error('Disconnected'));
|
|
||||||
}
|
|
||||||
|
|
||||||
if (this._port === null) {
|
|
||||||
this._createPort();
|
|
||||||
}
|
|
||||||
|
|
||||||
const id = `${this._nextId}`;
|
|
||||||
++this._nextId;
|
|
||||||
|
|
||||||
return new Promise((resolve, reject) => {
|
|
||||||
const info = {id, resolve, reject, ack: false, timer: null};
|
|
||||||
this._callbacks.set(id, info);
|
|
||||||
info.timer = setTimeout(() => this._onError(id, 'Timeout (ack)'), this._ackTimeout);
|
|
||||||
|
|
||||||
this._port.postMessage({id, action, params, target: this._target, senderId: this._senderId});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
_createPort() {
|
|
||||||
this._port = chrome.runtime.connect(null, {name: 'backend-api-forwarder'});
|
|
||||||
this._port.onDisconnect.addListener(this._onDisconnect.bind(this));
|
|
||||||
this._port.onMessage.addListener(this._onMessage.bind(this));
|
|
||||||
}
|
|
||||||
|
|
||||||
_onMessage({type, id, data, senderId}) {
|
|
||||||
if (senderId !== this._senderId) { return; }
|
|
||||||
switch (type) {
|
|
||||||
case 'ack':
|
|
||||||
this._onAck(id);
|
|
||||||
break;
|
|
||||||
case 'result':
|
|
||||||
this._onResult(id, data);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_onDisconnect() {
|
|
||||||
this._disconnected = true;
|
|
||||||
this._port = null;
|
|
||||||
|
|
||||||
for (const id of this._callbacks.keys()) {
|
|
||||||
this._onError(id, 'Disconnected');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_onAck(id) {
|
|
||||||
const info = this._callbacks.get(id);
|
|
||||||
if (typeof info === 'undefined') {
|
|
||||||
yomichan.logWarning(new Error(`ID ${id} not found for ack`));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (info.ack) {
|
|
||||||
yomichan.logWarning(new Error(`Request ${id} already ack'd`));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
info.ack = true;
|
|
||||||
clearTimeout(info.timer);
|
|
||||||
info.timer = setTimeout(() => this._onError(id, 'Timeout (response)'), this._responseTimeout);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onResult(id, data) {
|
|
||||||
const info = this._callbacks.get(id);
|
|
||||||
if (typeof info === 'undefined') {
|
|
||||||
yomichan.logWarning(new Error(`ID ${id} not found`));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!info.ack) {
|
|
||||||
yomichan.logWarning(new Error(`Request ${id} not ack'd`));
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
this._callbacks.delete(id);
|
|
||||||
clearTimeout(info.timer);
|
|
||||||
info.timer = null;
|
|
||||||
|
|
||||||
if (typeof data.error !== 'undefined') {
|
|
||||||
info.reject(jsonToError(data.error));
|
|
||||||
} else {
|
|
||||||
info.resolve(data.result);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
_onError(id, reason) {
|
|
||||||
const info = this._callbacks.get(id);
|
|
||||||
if (typeof info === 'undefined') { return; }
|
|
||||||
this._callbacks.delete(id);
|
|
||||||
info.timer = null;
|
|
||||||
info.reject(new Error(reason));
|
|
||||||
}
|
|
||||||
}
|
|
@ -16,8 +16,8 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* global
|
/* global
|
||||||
* FrontendApiReceiver
|
|
||||||
* Popup
|
* Popup
|
||||||
|
* api
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class PopupFactory {
|
class PopupFactory {
|
||||||
@ -29,7 +29,7 @@ class PopupFactory {
|
|||||||
// Public functions
|
// Public functions
|
||||||
|
|
||||||
async prepare() {
|
async prepare() {
|
||||||
const apiReceiver = new FrontendApiReceiver(`popup-factory#${this._frameId}`, new Map([
|
api.crossFrame.registerHandlers([
|
||||||
['getOrCreatePopup', {async: false, handler: this._onApiGetOrCreatePopup.bind(this)}],
|
['getOrCreatePopup', {async: false, handler: this._onApiGetOrCreatePopup.bind(this)}],
|
||||||
['setOptionsContext', {async: true, handler: this._onApiSetOptionsContext.bind(this)}],
|
['setOptionsContext', {async: true, handler: this._onApiSetOptionsContext.bind(this)}],
|
||||||
['hide', {async: false, handler: this._onApiHide.bind(this)}],
|
['hide', {async: false, handler: this._onApiHide.bind(this)}],
|
||||||
@ -41,8 +41,7 @@ class PopupFactory {
|
|||||||
['clearAutoPlayTimer', {async: false, handler: this._onApiClearAutoPlayTimer.bind(this)}],
|
['clearAutoPlayTimer', {async: false, handler: this._onApiClearAutoPlayTimer.bind(this)}],
|
||||||
['setContentScale', {async: false, handler: this._onApiSetContentScale.bind(this)}],
|
['setContentScale', {async: false, handler: this._onApiSetContentScale.bind(this)}],
|
||||||
['getUrl', {async: false, handler: this._onApiGetUrl.bind(this)}]
|
['getUrl', {async: false, handler: this._onApiGetUrl.bind(this)}]
|
||||||
]));
|
]);
|
||||||
apiReceiver.prepare();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getOrCreatePopup(id=null, parentId=null, depth=null) {
|
getOrCreatePopup(id=null, parentId=null, depth=null) {
|
||||||
|
@ -16,7 +16,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/* global
|
/* global
|
||||||
* FrontendApiSender
|
* api
|
||||||
*/
|
*/
|
||||||
|
|
||||||
class PopupProxy {
|
class PopupProxy {
|
||||||
@ -24,7 +24,7 @@ class PopupProxy {
|
|||||||
this._id = id;
|
this._id = id;
|
||||||
this._depth = depth;
|
this._depth = depth;
|
||||||
this._parentPopupId = parentPopupId;
|
this._parentPopupId = parentPopupId;
|
||||||
this._apiSender = new FrontendApiSender(`popup-factory#${parentFrameId}`);
|
this._parentFrameId = parentFrameId;
|
||||||
this._getFrameOffset = getFrameOffset;
|
this._getFrameOffset = getFrameOffset;
|
||||||
this._setDisabled = setDisabled;
|
this._setDisabled = setDisabled;
|
||||||
|
|
||||||
@ -111,7 +111,7 @@ class PopupProxy {
|
|||||||
// Private
|
// Private
|
||||||
|
|
||||||
_invoke(action, params={}) {
|
_invoke(action, params={}) {
|
||||||
return this._apiSender.invoke(action, params);
|
return api.crossFrame.invoke(this._parentFrameId, action, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _updateFrameOffset() {
|
async _updateFrameOffset() {
|
||||||
|
@ -36,13 +36,12 @@
|
|||||||
"matches": ["http://*/*", "https://*/*", "file://*/*"],
|
"matches": ["http://*/*", "https://*/*", "file://*/*"],
|
||||||
"js": [
|
"js": [
|
||||||
"mixed/js/core.js",
|
"mixed/js/core.js",
|
||||||
|
"mixed/js/comm.js",
|
||||||
"mixed/js/dom.js",
|
"mixed/js/dom.js",
|
||||||
"mixed/js/api.js",
|
"mixed/js/api.js",
|
||||||
"mixed/js/dynamic-loader.js",
|
"mixed/js/dynamic-loader.js",
|
||||||
"mixed/js/text-scanner.js",
|
"mixed/js/text-scanner.js",
|
||||||
"fg/js/document.js",
|
"fg/js/document.js",
|
||||||
"fg/js/frontend-api-sender.js",
|
|
||||||
"fg/js/frontend-api-receiver.js",
|
|
||||||
"fg/js/popup.js",
|
"fg/js/popup.js",
|
||||||
"fg/js/source.js",
|
"fg/js/source.js",
|
||||||
"fg/js/popup-factory.js",
|
"fg/js/popup-factory.js",
|
||||||
|
@ -15,10 +15,23 @@
|
|||||||
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
* along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/* global
|
||||||
|
* CrossFrameAPI
|
||||||
|
*/
|
||||||
|
|
||||||
const api = (() => {
|
const api = (() => {
|
||||||
class API {
|
class API {
|
||||||
constructor() {
|
constructor() {
|
||||||
this._forwardLogsToBackendEnabled = false;
|
this._forwardLogsToBackendEnabled = false;
|
||||||
|
this._crossFrame = new CrossFrameAPI();
|
||||||
|
}
|
||||||
|
|
||||||
|
get crossFrame() {
|
||||||
|
return this._crossFrame;
|
||||||
|
}
|
||||||
|
|
||||||
|
prepare() {
|
||||||
|
this._crossFrame.prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
forwardLogsToBackend() {
|
forwardLogsToBackend() {
|
||||||
@ -331,5 +344,8 @@ const api = (() => {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return new API();
|
// eslint-disable-next-line no-shadow
|
||||||
|
const api = new API();
|
||||||
|
api.prepare();
|
||||||
|
return api;
|
||||||
})();
|
})();
|
||||||
|
Loading…
Reference in New Issue
Block a user