Popup proxy host refactor (#516)

* Rename PopupProxyHost to PopupFactory

* Update FrontendApiReceiver to support non-async handlers

* Make some functions non-async

* Make setCustomCss non-async

* Make setContentScale non-async

* Remove static

* Rename variables

* Pass frameId into PopupFactory's constructor

* Change FrontendApiReceiver source from popup-proxy-host to popup-factor

* Rename _invokeHostApi to _invoke

* Rename PopupProxy.getHostUrl to getUrl
This commit is contained in:
toasted-nutbread 2020-05-08 19:04:53 -04:00 committed by GitHub
parent b972f8cbf6
commit b936c3e4b1
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
9 changed files with 94 additions and 73 deletions

View File

@ -31,7 +31,7 @@ async function injectSearchFrontend() {
'/fg/js/frontend-api-receiver.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-proxy-host.js', '/fg/js/popup-factory.js',
'/fg/js/frontend.js', '/fg/js/frontend.js',
'/fg/js/content-script-main.js' '/fg/js/content-script-main.js'
]); ]);

View File

@ -18,8 +18,9 @@
/* global /* global
* Frontend * Frontend
* Popup * Popup
* PopupProxyHost * PopupFactory
* TextSourceRange * TextSourceRange
* apiFrameInformationGet
* apiOptionsGet * apiOptionsGet
*/ */
@ -56,10 +57,12 @@ class SettingsPopupPreview {
window.apiOptionsGet = this.apiOptionsGet.bind(this); window.apiOptionsGet = this.apiOptionsGet.bind(this);
// Overwrite frontend // Overwrite frontend
const popupHost = new PopupProxyHost(); const {frameId} = await apiFrameInformationGet();
await popupHost.prepare();
this.popup = popupHost.getOrCreatePopup(); const popupFactory = new PopupFactory(frameId);
await popupFactory.prepare();
this.popup = popupFactory.getOrCreatePopup();
this.popup.setChildrenSupported(false); this.popup.setChildrenSupported(false);
this.popupSetCustomOuterCssOld = this.popup.setCustomOuterCss; this.popupSetCustomOuterCssOld = this.popup.setCustomOuterCss;

View File

@ -127,7 +127,7 @@
<script src="/fg/js/frontend-api-receiver.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-proxy-host.js"></script> <script src="/fg/js/popup-factory.js"></script>
<script src="/fg/js/frontend.js"></script> <script src="/fg/js/frontend.js"></script>
<script src="/bg/js/settings/popup-preview-frame.js"></script> <script src="/bg/js/settings/popup-preview-frame.js"></script>

View File

@ -19,10 +19,11 @@
* DOM * DOM
* FrameOffsetForwarder * FrameOffsetForwarder
* Frontend * Frontend
* PopupFactory
* PopupProxy * PopupProxy
* PopupProxyHost
* apiBroadcastTab * apiBroadcastTab
* apiForwardLogsToBackend * apiForwardLogsToBackend
* apiFrameInformationGet
* apiOptionsGet * apiOptionsGet
*/ */
@ -47,10 +48,17 @@ async function createIframePopupProxy(frameOffsetForwarder, setDisabled) {
} }
async function getOrCreatePopup(depth) { async function getOrCreatePopup(depth) {
const popupHost = new PopupProxyHost(); const {frameId} = await apiFrameInformationGet();
await popupHost.prepare(); if (typeof frameId !== 'number') {
const error = new Error('Failed to get frameId');
yomichan.logError(error);
throw error;
}
const popup = popupHost.getOrCreatePopup(null, null, depth); const popupFactory = new PopupFactory(frameId);
await popupFactory.prepare();
const popup = popupFactory.getOrCreatePopup(null, null, depth);
return popup; return popup;
} }
@ -89,20 +97,20 @@ async function createPopupProxy(depth, id, parentFrameId) {
}; };
let urlUpdatedAt = 0; let urlUpdatedAt = 0;
let proxyHostUrlCached = url; let popupProxyUrlCached = url;
const getProxyHostUrl = async () => { const getPopupProxyUrl = async () => {
const now = Date.now(); const now = Date.now();
if (popups.proxy !== null && now - urlUpdatedAt > 500) { if (popups.proxy !== null && now - urlUpdatedAt > 500) {
proxyHostUrlCached = await popups.proxy.getHostUrl(); popupProxyUrlCached = await popups.proxy.getUrl();
urlUpdatedAt = now; urlUpdatedAt = now;
} }
return proxyHostUrlCached; return popupProxyUrlCached;
}; };
const applyOptions = async () => { const applyOptions = async () => {
const optionsContext = { const optionsContext = {
depth: isSearchPage ? 0 : depth, depth: isSearchPage ? 0 : depth,
url: proxy ? await getProxyHostUrl() : window.location.href url: proxy ? await getPopupProxyUrl() : window.location.href
}; };
const options = await apiOptionsGet(optionsContext); const options = await apiOptionsGet(optionsContext);
@ -124,7 +132,7 @@ async function createPopupProxy(depth, id, parentFrameId) {
} }
if (frontend === null) { if (frontend === null) {
const getUrl = proxy ? getProxyHostUrl : null; const getUrl = proxy ? getPopupProxyUrl : null;
frontend = new Frontend(popup, getUrl); frontend = new Frontend(popup, getUrl);
frontendPreparePromise = frontend.prepare(); frontendPreparePromise = frontend.prepare();
await frontendPreparePromise; await frontendPreparePromise;

View File

@ -17,9 +17,9 @@
class FrontendApiReceiver { class FrontendApiReceiver {
constructor(source='', handlers=new Map()) { constructor(source, messageHandlers) {
this._source = source; this._source = source;
this._handlers = handlers; this._messageHandlers = messageHandlers;
} }
prepare() { prepare() {
@ -35,14 +35,29 @@ class FrontendApiReceiver {
_onMessage(port, {id, action, params, target, senderId}) { _onMessage(port, {id, action, params, target, senderId}) {
if (target !== this._source) { return; } if (target !== this._source) { return; }
const handler = this._handlers.get(action); const messageHandler = this._messageHandlers.get(action);
if (typeof handler !== 'function') { return; } if (typeof messageHandler === 'undefined') { return; }
const {handler, async} = messageHandler;
this._sendAck(port, id, senderId); this._sendAck(port, id, senderId);
this._invokeHandler(handler, params, port, id, senderId); if (async) {
this._invokeHandlerAsync(handler, params, port, id, senderId);
} else {
this._invokeHandler(handler, params, port, id, senderId);
}
} }
async _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 { try {
const result = await handler(params); const result = await handler(params);
this._sendResult(port, id, senderId, {result}); this._sendResult(port, id, senderId, {result});

View File

@ -18,34 +18,29 @@
/* global /* global
* FrontendApiReceiver * FrontendApiReceiver
* Popup * Popup
* apiFrameInformationGet
*/ */
class PopupProxyHost { class PopupFactory {
constructor() { constructor(frameId) {
this._popups = new Map(); this._popups = new Map();
this._frameId = null; this._frameId = frameId;
} }
// Public functions // Public functions
async prepare() { async prepare() {
const {frameId} = await apiFrameInformationGet(); const apiReceiver = new FrontendApiReceiver(`popup-factory#${this._frameId}`, new Map([
if (typeof frameId !== 'number') { return; } ['getOrCreatePopup', {async: false, handler: this._onApiGetOrCreatePopup.bind(this)}],
this._frameId = frameId; ['setOptionsContext', {async: true, handler: this._onApiSetOptionsContext.bind(this)}],
['hide', {async: false, handler: this._onApiHide.bind(this)}],
const apiReceiver = new FrontendApiReceiver(`popup-proxy-host#${this._frameId}`, new Map([ ['isVisible', {async: true, handler: this._onApiIsVisibleAsync.bind(this)}],
['getOrCreatePopup', this._onApiGetOrCreatePopup.bind(this)], ['setVisibleOverride', {async: true, handler: this._onApiSetVisibleOverride.bind(this)}],
['setOptionsContext', this._onApiSetOptionsContext.bind(this)], ['containsPoint', {async: true, handler: this._onApiContainsPoint.bind(this)}],
['hide', this._onApiHide.bind(this)], ['showContent', {async: true, handler: this._onApiShowContent.bind(this)}],
['isVisible', this._onApiIsVisibleAsync.bind(this)], ['setCustomCss', {async: false, handler: this._onApiSetCustomCss.bind(this)}],
['setVisibleOverride', this._onApiSetVisibleOverride.bind(this)], ['clearAutoPlayTimer', {async: false, handler: this._onApiClearAutoPlayTimer.bind(this)}],
['containsPoint', this._onApiContainsPoint.bind(this)], ['setContentScale', {async: false, handler: this._onApiSetContentScale.bind(this)}],
['showContent', this._onApiShowContent.bind(this)], ['getUrl', {async: false, handler: this._onApiGetUrl.bind(this)}]
['setCustomCss', this._onApiSetCustomCss.bind(this)],
['clearAutoPlayTimer', this._onApiClearAutoPlayTimer.bind(this)],
['setContentScale', this._onApiSetContentScale.bind(this)],
['getHostUrl', this._onApiGetHostUrl.bind(this)]
])); ]));
apiReceiver.prepare(); apiReceiver.prepare();
} }
@ -97,7 +92,7 @@ class PopupProxyHost {
// API message handlers // API message handlers
async _onApiGetOrCreatePopup({id, parentId}) { _onApiGetOrCreatePopup({id, parentId}) {
const popup = this.getOrCreatePopup(id, parentId); const popup = this.getOrCreatePopup(id, parentId);
return { return {
id: popup.id id: popup.id
@ -109,7 +104,7 @@ class PopupProxyHost {
return await popup.setOptionsContext(optionsContext, source); return await popup.setOptionsContext(optionsContext, source);
} }
async _onApiHide({id, changeFocus}) { _onApiHide({id, changeFocus}) {
const popup = this._getPopup(id); const popup = this._getPopup(id);
return popup.hide(changeFocus); return popup.hide(changeFocus);
} }
@ -126,33 +121,33 @@ class PopupProxyHost {
async _onApiContainsPoint({id, x, y}) { async _onApiContainsPoint({id, x, y}) {
const popup = this._getPopup(id); const popup = this._getPopup(id);
[x, y] = PopupProxyHost._convertPopupPointToRootPagePoint(popup, x, y); [x, y] = this._convertPopupPointToRootPagePoint(popup, x, y);
return await popup.containsPoint(x, y); return await popup.containsPoint(x, y);
} }
async _onApiShowContent({id, elementRect, writingMode, type, details, context}) { async _onApiShowContent({id, elementRect, writingMode, type, details, context}) {
const popup = this._getPopup(id); const popup = this._getPopup(id);
elementRect = PopupProxyHost._convertJsonRectToDOMRect(popup, elementRect); elementRect = this._convertJsonRectToDOMRect(popup, elementRect);
if (!PopupProxyHost._popupCanShow(popup)) { return; } if (!this._popupCanShow(popup)) { return; }
return await popup.showContent(elementRect, writingMode, type, details, context); return await popup.showContent(elementRect, writingMode, type, details, context);
} }
async _onApiSetCustomCss({id, css}) { _onApiSetCustomCss({id, css}) {
const popup = this._getPopup(id); const popup = this._getPopup(id);
return popup.setCustomCss(css); return popup.setCustomCss(css);
} }
async _onApiClearAutoPlayTimer({id}) { _onApiClearAutoPlayTimer({id}) {
const popup = this._getPopup(id); const popup = this._getPopup(id);
return popup.clearAutoPlayTimer(); return popup.clearAutoPlayTimer();
} }
async _onApiSetContentScale({id, scale}) { _onApiSetContentScale({id, scale}) {
const popup = this._getPopup(id); const popup = this._getPopup(id);
return popup.setContentScale(scale); return popup.setContentScale(scale);
} }
async _onApiGetHostUrl() { _onApiGetUrl() {
return window.location.href; return window.location.href;
} }
@ -166,12 +161,12 @@ class PopupProxyHost {
return popup; return popup;
} }
static _convertJsonRectToDOMRect(popup, jsonRect) { _convertJsonRectToDOMRect(popup, jsonRect) {
const [x, y] = PopupProxyHost._convertPopupPointToRootPagePoint(popup, jsonRect.x, jsonRect.y); const [x, y] = this._convertPopupPointToRootPagePoint(popup, jsonRect.x, jsonRect.y);
return new DOMRect(x, y, jsonRect.width, jsonRect.height); return new DOMRect(x, y, jsonRect.width, jsonRect.height);
} }
static _convertPopupPointToRootPagePoint(popup, x, y) { _convertPopupPointToRootPagePoint(popup, x, y) {
if (popup.parent !== null) { if (popup.parent !== null) {
const popupRect = popup.parent.getContainerRect(); const popupRect = popup.parent.getContainerRect();
x += popupRect.x; x += popupRect.x;
@ -180,7 +175,7 @@ class PopupProxyHost {
return [x, y]; return [x, y];
} }
static _popupCanShow(popup) { _popupCanShow(popup) {
return popup.parent === null || popup.parent.isVisibleSync(); return popup.parent === null || popup.parent.isVisibleSync();
} }
} }

View File

@ -51,7 +51,7 @@ class PopupProxy {
// Public functions // Public functions
async prepare() { async prepare() {
const {id} = await this._invokeHostApi('getOrCreatePopup', {id: this._id, parentId: this._parentId}); const {id} = await this._invoke('getOrCreatePopup', {id: this._id, parentId: this._parentId});
this._id = id; this._id = id;
} }
@ -60,19 +60,19 @@ class PopupProxy {
} }
async setOptionsContext(optionsContext, source) { async setOptionsContext(optionsContext, source) {
return await this._invokeHostApi('setOptionsContext', {id: this._id, optionsContext, source}); return await this._invoke('setOptionsContext', {id: this._id, optionsContext, source});
} }
hide(changeFocus) { hide(changeFocus) {
this._invokeHostApi('hide', {id: this._id, changeFocus}); this._invoke('hide', {id: this._id, changeFocus});
} }
async isVisible() { async isVisible() {
return await this._invokeHostApi('isVisible', {id: this._id}); return await this._invoke('isVisible', {id: this._id});
} }
setVisibleOverride(visible) { setVisibleOverride(visible) {
this._invokeHostApi('setVisibleOverride', {id: this._id, visible}); this._invoke('setVisibleOverride', {id: this._id, visible});
} }
async containsPoint(x, y) { async containsPoint(x, y) {
@ -80,7 +80,7 @@ class PopupProxy {
await this._updateFrameOffset(); await this._updateFrameOffset();
[x, y] = this._applyFrameOffset(x, y); [x, y] = this._applyFrameOffset(x, y);
} }
return await this._invokeHostApi('containsPoint', {id: this._id, x, y}); return await this._invoke('containsPoint', {id: this._id, x, y});
} }
async showContent(elementRect, writingMode, type, details, context) { async showContent(elementRect, writingMode, type, details, context) {
@ -90,32 +90,32 @@ class PopupProxy {
[x, y] = this._applyFrameOffset(x, y); [x, y] = this._applyFrameOffset(x, y);
} }
elementRect = {x, y, width, height}; elementRect = {x, y, width, height};
return await this._invokeHostApi('showContent', {id: this._id, elementRect, writingMode, type, details, context}); return await this._invoke('showContent', {id: this._id, elementRect, writingMode, type, details, context});
} }
async setCustomCss(css) { setCustomCss(css) {
return await this._invokeHostApi('setCustomCss', {id: this._id, css}); this._invoke('setCustomCss', {id: this._id, css});
} }
clearAutoPlayTimer() { clearAutoPlayTimer() {
this._invokeHostApi('clearAutoPlayTimer', {id: this._id}); this._invoke('clearAutoPlayTimer', {id: this._id});
} }
async setContentScale(scale) { setContentScale(scale) {
this._invokeHostApi('setContentScale', {id: this._id, scale}); this._invoke('setContentScale', {id: this._id, scale});
} }
async getHostUrl() { async getUrl() {
return await this._invokeHostApi('getHostUrl', {}); return await this._invoke('getUrl', {});
} }
// Private // Private
_invokeHostApi(action, params={}) { _invoke(action, params={}) {
if (typeof this._parentFrameId !== 'number') { if (typeof this._parentFrameId !== 'number') {
return Promise.reject(new Error('Invalid frame')); return Promise.reject(new Error('Invalid frame'));
} }
return this._apiSender.invoke(action, params, `popup-proxy-host#${this._parentFrameId}`); return this._apiSender.invoke(action, params, `popup-factory#${this._parentFrameId}`);
} }
async _updateFrameOffset() { async _updateFrameOffset() {

View File

@ -139,7 +139,7 @@ class Popup {
this._invokeApi('setContent', {type, details}); this._invokeApi('setContent', {type, details});
} }
async setCustomCss(css) { setCustomCss(css) {
this._invokeApi('setCustomCss', {css}); this._invokeApi('setCustomCss', {css});
} }

View File

@ -44,9 +44,9 @@
"fg/js/frontend-api-receiver.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/frame-offset-forwarder.js", "fg/js/frame-offset-forwarder.js",
"fg/js/popup-proxy.js", "fg/js/popup-proxy.js",
"fg/js/popup-proxy-host.js",
"fg/js/frontend.js", "fg/js/frontend.js",
"fg/js/content-script-main.js" "fg/js/content-script-main.js"
], ],