Refactor DisplayFloat=>Frontend message passing (#652)
* Change getOrCreatePopup arguments to be an object * Add ownerFrameId to popup and DisplayFloat * Refactor DisplayFloat host action invocation * Use CrossFrameAPI instead of window.postMessage * Update popup closing functionality on the search page
This commit is contained in:
parent
128588bb92
commit
295ffa6e54
@ -255,7 +255,7 @@ class DisplaySearch extends Display {
|
|||||||
this.clearContent();
|
this.clearContent();
|
||||||
}
|
}
|
||||||
this._setTitleText(query);
|
this._setTitleText(query);
|
||||||
window.parent.postMessage('popupClose', '*');
|
yomichan.trigger('closePopups');
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
this.onError(e);
|
this.onError(e);
|
||||||
}
|
}
|
||||||
|
@ -30,6 +30,7 @@ class DisplayFloat extends Display {
|
|||||||
this._secret = yomichan.generateId(16);
|
this._secret = yomichan.generateId(16);
|
||||||
this._token = null;
|
this._token = null;
|
||||||
this._nestedPopupsPrepared = false;
|
this._nestedPopupsPrepared = false;
|
||||||
|
this._ownerFrameId = null;
|
||||||
this._windowMessageHandlers = new Map([
|
this._windowMessageHandlers = new Map([
|
||||||
['initialize', {handler: this._onMessageInitialize.bind(this), authenticate: false}],
|
['initialize', {handler: this._onMessageInitialize.bind(this), authenticate: false}],
|
||||||
['configure', {handler: this._onMessageConfigure.bind(this)}],
|
['configure', {handler: this._onMessageConfigure.bind(this)}],
|
||||||
@ -60,7 +61,7 @@ class DisplayFloat extends Display {
|
|||||||
}
|
}
|
||||||
|
|
||||||
onEscape() {
|
onEscape() {
|
||||||
window.parent.postMessage('popupClose', '*');
|
this._invoke('closePopup');
|
||||||
}
|
}
|
||||||
|
|
||||||
async setOptionsContext(optionsContext) {
|
async setOptionsContext(optionsContext) {
|
||||||
@ -134,7 +135,8 @@ class DisplayFloat extends Display {
|
|||||||
this._initialize(params);
|
this._initialize(params);
|
||||||
}
|
}
|
||||||
|
|
||||||
async _onMessageConfigure({messageId, frameId, popupId, optionsContext, childrenSupported, scale}) {
|
async _onMessageConfigure({messageId, frameId, ownerFrameId, popupId, optionsContext, childrenSupported, scale}) {
|
||||||
|
this._ownerFrameId = ownerFrameId;
|
||||||
this.setOptionsContext(optionsContext);
|
this.setOptionsContext(optionsContext);
|
||||||
|
|
||||||
await this.updateOptions();
|
await this.updateOptions();
|
||||||
@ -173,7 +175,7 @@ class DisplayFloat extends Display {
|
|||||||
// Private
|
// Private
|
||||||
|
|
||||||
_copySelection() {
|
_copySelection() {
|
||||||
window.parent.postMessage('selectionCopy', '*');
|
this._invoke('copySelection');
|
||||||
}
|
}
|
||||||
|
|
||||||
_clearAutoPlayTimer() {
|
_clearAutoPlayTimer() {
|
||||||
@ -266,4 +268,8 @@ class DisplayFloat extends Display {
|
|||||||
);
|
);
|
||||||
await frontend.prepare();
|
await frontend.prepare();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_invoke(action, params={}) {
|
||||||
|
return api.crossFrame.invoke(this._ownerFrameId, action, params);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,7 +33,6 @@ class Frontend {
|
|||||||
this._pageZoomFactor = 1.0;
|
this._pageZoomFactor = 1.0;
|
||||||
this._contentScale = 1.0;
|
this._contentScale = 1.0;
|
||||||
this._lastShowPromise = Promise.resolve();
|
this._lastShowPromise = Promise.resolve();
|
||||||
this._enabledEventListeners = new EventListenerCollection();
|
|
||||||
this._activeModifiers = new Set();
|
this._activeModifiers = new Set();
|
||||||
this._optionsUpdatePending = false;
|
this._optionsUpdatePending = false;
|
||||||
this._textScanner = new TextScanner({
|
this._textScanner = new TextScanner({
|
||||||
@ -63,11 +62,6 @@ class Frontend {
|
|||||||
this._popupCache = new Map();
|
this._popupCache = new Map();
|
||||||
this._updatePopupToken = null;
|
this._updatePopupToken = null;
|
||||||
|
|
||||||
this._windowMessageHandlers = new Map([
|
|
||||||
['popupClose', this._onMessagePopupClose.bind(this)],
|
|
||||||
['selectionCopy', this._onMessageSelectionCopy.bind()]
|
|
||||||
]);
|
|
||||||
|
|
||||||
this._runtimeMessageHandlers = new Map([
|
this._runtimeMessageHandlers = new Map([
|
||||||
['popupSetVisibleOverride', this._onMessagePopupSetVisibleOverride.bind(this)],
|
['popupSetVisibleOverride', this._onMessagePopupSetVisibleOverride.bind(this)],
|
||||||
['rootPopupRequestInformationBroadcast', this._onMessageRootPopupRequestInformationBroadcast.bind(this)],
|
['rootPopupRequestInformationBroadcast', this._onMessageRootPopupRequestInformationBroadcast.bind(this)],
|
||||||
@ -111,13 +105,16 @@ class Frontend {
|
|||||||
|
|
||||||
yomichan.on('optionsUpdated', this.updateOptions.bind(this));
|
yomichan.on('optionsUpdated', this.updateOptions.bind(this));
|
||||||
yomichan.on('zoomChanged', this._onZoomChanged.bind(this));
|
yomichan.on('zoomChanged', this._onZoomChanged.bind(this));
|
||||||
|
yomichan.on('closePopups', this._onApiClosePopup.bind(this));
|
||||||
chrome.runtime.onMessage.addListener(this._onRuntimeMessage.bind(this));
|
chrome.runtime.onMessage.addListener(this._onRuntimeMessage.bind(this));
|
||||||
|
|
||||||
this._textScanner.on('clearSelection', this._onClearSelection.bind(this));
|
this._textScanner.on('clearSelection', this._onClearSelection.bind(this));
|
||||||
this._textScanner.on('activeModifiersChanged', this._onActiveModifiersChanged.bind(this));
|
this._textScanner.on('activeModifiersChanged', this._onActiveModifiersChanged.bind(this));
|
||||||
|
|
||||||
api.crossFrame.registerHandlers([
|
api.crossFrame.registerHandlers([
|
||||||
['getUrl', {async: false, handler: this._onApiGetUrl.bind(this)}]
|
['getUrl', {async: false, handler: this._onApiGetUrl.bind(this)}],
|
||||||
|
['closePopup', {async: false, handler: this._onApiClosePopup.bind(this)}],
|
||||||
|
['copySelection', {async: false, handler: this._onApiCopySelection.bind(this)}]
|
||||||
]);
|
]);
|
||||||
|
|
||||||
this._updateContentScale();
|
this._updateContentScale();
|
||||||
@ -179,14 +176,6 @@ class Frontend {
|
|||||||
|
|
||||||
// Message handlers
|
// Message handlers
|
||||||
|
|
||||||
_onMessagePopupClose() {
|
|
||||||
this._textScanner.clearSelection(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
_onMessageSelectionCopy() {
|
|
||||||
document.execCommand('copy');
|
|
||||||
}
|
|
||||||
|
|
||||||
_onMessagePopupSetVisibleOverride({visible}) {
|
_onMessagePopupSetVisibleOverride({visible}) {
|
||||||
this._popup.setVisibleOverride(visible);
|
this._popup.setVisibleOverride(visible);
|
||||||
}
|
}
|
||||||
@ -205,20 +194,20 @@ class Frontend {
|
|||||||
return window.location.href;
|
return window.location.href;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
_onApiClosePopup() {
|
||||||
|
this._textScanner.clearSelection(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
_onApiCopySelection() {
|
||||||
|
document.execCommand('copy');
|
||||||
|
}
|
||||||
|
|
||||||
// Private
|
// Private
|
||||||
|
|
||||||
_onResize() {
|
_onResize() {
|
||||||
this._updatePopupPosition();
|
this._updatePopupPosition();
|
||||||
}
|
}
|
||||||
|
|
||||||
_onWindowMessage(e) {
|
|
||||||
const action = e.data;
|
|
||||||
const handler = this._windowMessageHandlers.get(action);
|
|
||||||
if (typeof handler !== 'function') { return false; }
|
|
||||||
|
|
||||||
handler();
|
|
||||||
}
|
|
||||||
|
|
||||||
_onRuntimeMessage({action, params}, sender, callback) {
|
_onRuntimeMessage({action, params}, sender, callback) {
|
||||||
const handler = this._runtimeMessageHandlers.get(action);
|
const handler = this._runtimeMessageHandlers.get(action);
|
||||||
if (typeof handler !== 'function') { return false; }
|
if (typeof handler !== 'function') { return false; }
|
||||||
@ -307,11 +296,11 @@ class Frontend {
|
|||||||
}
|
}
|
||||||
|
|
||||||
async _getDefaultPopup() {
|
async _getDefaultPopup() {
|
||||||
return this._popupFactory.getOrCreatePopup(null, null, this._depth);
|
return this._popupFactory.getOrCreatePopup({depth: this._depth, ownerFrameId: this._frameId});
|
||||||
}
|
}
|
||||||
|
|
||||||
async _getProxyPopup() {
|
async _getProxyPopup() {
|
||||||
const popup = new PopupProxy(null, this._depth + 1, this._proxyPopupId, this._parentFrameId);
|
const popup = new PopupProxy(null, this._depth + 1, this._proxyPopupId, this._parentFrameId, this._frameId);
|
||||||
await popup.prepare();
|
await popup.prepare();
|
||||||
return popup;
|
return popup;
|
||||||
}
|
}
|
||||||
@ -328,7 +317,7 @@ class Frontend {
|
|||||||
api.broadcastTab('rootPopupRequestInformationBroadcast');
|
api.broadcastTab('rootPopupRequestInformationBroadcast');
|
||||||
const {popupId, frameId: parentFrameId} = await rootPopupInformationPromise;
|
const {popupId, frameId: parentFrameId} = await rootPopupInformationPromise;
|
||||||
|
|
||||||
const popup = new PopupProxy(popupId, 0, null, parentFrameId, this._frameOffsetForwarder);
|
const popup = new PopupProxy(popupId, 0, null, parentFrameId, this._frameId, this._frameOffsetForwarder);
|
||||||
popup.on('offsetNotFound', () => {
|
popup.on('offsetNotFound', () => {
|
||||||
this._allowRootFramePopupProxy = false;
|
this._allowRootFramePopupProxy = false;
|
||||||
this._updatePopup();
|
this._updatePopup();
|
||||||
@ -444,11 +433,7 @@ class Frontend {
|
|||||||
this._depth <= this._options.scanning.popupNestingMaxDepth &&
|
this._depth <= this._options.scanning.popupNestingMaxDepth &&
|
||||||
!this._disabledOverride
|
!this._disabledOverride
|
||||||
);
|
);
|
||||||
this._enabledEventListeners.removeAllEventListeners();
|
|
||||||
this._textScanner.setEnabled(enabled);
|
this._textScanner.setEnabled(enabled);
|
||||||
if (enabled) {
|
|
||||||
this._enabledEventListeners.addEventListener(window, 'message', this._onWindowMessage.bind(this));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
_updateContentScale() {
|
_updateContentScale() {
|
||||||
|
@ -43,7 +43,7 @@ class PopupFactory {
|
|||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
getOrCreatePopup(id=null, parentId=null, depth=null) {
|
getOrCreatePopup({id=null, parentId=null, ownerFrameId=null, depth=null}) {
|
||||||
// Find by existing id
|
// Find by existing id
|
||||||
if (id !== null) {
|
if (id !== null) {
|
||||||
const popup = this._popups.get(id);
|
const popup = this._popups.get(id);
|
||||||
@ -80,7 +80,7 @@ class PopupFactory {
|
|||||||
} else if (depth === null) {
|
} else if (depth === null) {
|
||||||
depth = 0;
|
depth = 0;
|
||||||
}
|
}
|
||||||
const popup = new Popup(id, depth, this._frameId);
|
const popup = new Popup(id, depth, this._frameId, ownerFrameId);
|
||||||
if (parent !== null) {
|
if (parent !== null) {
|
||||||
popup.setParent(parent);
|
popup.setParent(parent);
|
||||||
}
|
}
|
||||||
@ -91,8 +91,8 @@ class PopupFactory {
|
|||||||
|
|
||||||
// API message handlers
|
// API message handlers
|
||||||
|
|
||||||
_onApiGetOrCreatePopup({id, parentId}) {
|
_onApiGetOrCreatePopup({id, parentId, ownerFrameId}) {
|
||||||
const popup = this.getOrCreatePopup(id, parentId);
|
const popup = this.getOrCreatePopup({id, parentId, ownerFrameId});
|
||||||
return {
|
return {
|
||||||
id: popup.id
|
id: popup.id
|
||||||
};
|
};
|
||||||
|
@ -20,12 +20,13 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class PopupProxy extends EventDispatcher {
|
class PopupProxy extends EventDispatcher {
|
||||||
constructor(id, depth, parentPopupId, parentFrameId, frameOffsetForwarder=null) {
|
constructor(id, depth, parentPopupId, parentFrameId, ownerFrameId, frameOffsetForwarder=null) {
|
||||||
super();
|
super();
|
||||||
this._id = id;
|
this._id = id;
|
||||||
this._depth = depth;
|
this._depth = depth;
|
||||||
this._parentPopupId = parentPopupId;
|
this._parentPopupId = parentPopupId;
|
||||||
this._parentFrameId = parentFrameId;
|
this._parentFrameId = parentFrameId;
|
||||||
|
this._ownerFrameId = ownerFrameId;
|
||||||
this._frameOffsetForwarder = frameOffsetForwarder;
|
this._frameOffsetForwarder = frameOffsetForwarder;
|
||||||
|
|
||||||
this._frameOffset = null;
|
this._frameOffset = null;
|
||||||
@ -51,7 +52,7 @@ class PopupProxy extends EventDispatcher {
|
|||||||
// Public functions
|
// Public functions
|
||||||
|
|
||||||
async prepare() {
|
async prepare() {
|
||||||
const {id} = await this._invoke('getOrCreatePopup', {id: this._id, parentId: this._parentPopupId});
|
const {id} = await this._invoke('getOrCreatePopup', {id: this._id, parentId: this._parentPopupId, ownerFrameId: this._ownerFrameId});
|
||||||
this._id = id;
|
this._id = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -22,10 +22,11 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
class Popup {
|
class Popup {
|
||||||
constructor(id, depth, frameId) {
|
constructor(id, depth, frameId, ownerFrameId) {
|
||||||
this._id = id;
|
this._id = id;
|
||||||
this._depth = depth;
|
this._depth = depth;
|
||||||
this._frameId = frameId;
|
this._frameId = frameId;
|
||||||
|
this._ownerFrameId = ownerFrameId;
|
||||||
this._parent = null;
|
this._parent = null;
|
||||||
this._child = null;
|
this._child = null;
|
||||||
this._childrenSupported = true;
|
this._childrenSupported = true;
|
||||||
@ -382,6 +383,7 @@ class Popup {
|
|||||||
this._invokeApi('configure', {
|
this._invokeApi('configure', {
|
||||||
messageId,
|
messageId,
|
||||||
frameId: this._frameId,
|
frameId: this._frameId,
|
||||||
|
ownerFrameId: this._ownerFrameId,
|
||||||
popupId: this._id,
|
popupId: this._id,
|
||||||
optionsContext: this._optionsContext,
|
optionsContext: this._optionsContext,
|
||||||
childrenSupported: this._childrenSupported,
|
childrenSupported: this._childrenSupported,
|
||||||
|
Loading…
Reference in New Issue
Block a user