Extension unload detection (#647)

* Update how extension unload is detected

* Remove event handlers and use yomichan.isExtensionUnloaded instead

* Update terminology
This commit is contained in:
toasted-nutbread 2020-07-03 12:20:22 -04:00 committed by GitHub
parent ce634325ce
commit a07a8dfff6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 43 additions and 31 deletions

View File

@ -29,7 +29,7 @@
</div> </div>
</div> </div>
<div id="error-orphaned" hidden> <div id="error-extension-unloaded" hidden>
<div class="entry"> <div class="entry">
<h1>Yomichan Updated!</h1> <h1>Yomichan Updated!</h1>
<p> <p>

View File

@ -32,7 +32,6 @@ class Frontend {
this._options = null; this._options = null;
this._pageZoomFactor = 1.0; this._pageZoomFactor = 1.0;
this._contentScale = 1.0; this._contentScale = 1.0;
this._orphaned = false;
this._lastShowPromise = Promise.resolve(); this._lastShowPromise = Promise.resolve();
this._enabledEventListeners = new EventListenerCollection(); this._enabledEventListeners = new EventListenerCollection();
this._activeModifiers = new Set(); this._activeModifiers = new Set();
@ -110,7 +109,6 @@ class Frontend {
visualViewport.addEventListener('resize', this._onVisualViewportResize.bind(this)); visualViewport.addEventListener('resize', this._onVisualViewportResize.bind(this));
} }
yomichan.on('orphaned', this._onOrphaned.bind(this));
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));
chrome.runtime.onMessage.addListener(this._onRuntimeMessage.bind(this)); chrome.runtime.onMessage.addListener(this._onRuntimeMessage.bind(this));
@ -230,10 +228,6 @@ class Frontend {
return false; return false;
} }
_onOrphaned() {
this._orphaned = true;
}
_onZoomChanged({newZoomFactor}) { _onZoomChanged({newZoomFactor}) {
this._pageZoomFactor = newZoomFactor; this._pageZoomFactor = newZoomFactor;
this._updateContentScale(); this._updateContentScale();
@ -370,9 +364,9 @@ class Frontend {
} }
} }
} catch (e) { } catch (e) {
if (this._orphaned) { if (yomichan.isExtensionUnloaded) {
if (textSource !== null && this._options.scanning.modifier !== 'none') { if (textSource !== null && this._options.scanning.modifier !== 'none') {
this._showPopupContent(textSource, await this.getOptionsContext(), 'orphaned'); this._showPopupContent(textSource, await this.getOptionsContext(), 'extensionUnloaded');
} }
} else { } else {
yomichan.logError(e); yomichan.logError(e);

View File

@ -322,7 +322,7 @@ const api = (() => {
const data = {action, params}; const data = {action, params};
return new Promise((resolve, reject) => { return new Promise((resolve, reject) => {
try { try {
chrome.runtime.sendMessage(data, (response) => { yomichan.sendMessage(data, (response) => {
this._checkLastError(chrome.runtime.lastError); this._checkLastError(chrome.runtime.lastError);
if (response !== null && typeof response === 'object') { if (response !== null && typeof response === 'object') {
if (typeof response.error !== 'undefined') { if (typeof response.error !== 'undefined') {
@ -337,7 +337,6 @@ const api = (() => {
}); });
} catch (e) { } catch (e) {
reject(e); reject(e);
yomichan.triggerOrphaned(e);
} }
}); });
} }

View File

@ -268,7 +268,7 @@ class CrossFrameAPI {
} }
_createCommPort(otherFrameId) { _createCommPort(otherFrameId) {
const port = chrome.runtime.connect(null, {name: `background-cross-frame-communication-port-${otherFrameId}`}); const port = yomichan.connect(null, {name: `background-cross-frame-communication-port-${otherFrameId}`});
return this._setupCommPort(otherFrameId, port); return this._setupCommPort(otherFrameId, port);
} }

View File

@ -47,7 +47,6 @@ class Display {
useCache: true useCache: true
}); });
this._styleNode = null; this._styleNode = null;
this._orphaned = false;
this._eventListeners = new EventListenerCollection(); this._eventListeners = new EventListenerCollection();
this._persistentEventListeners = new EventListenerCollection(); this._persistentEventListeners = new EventListenerCollection();
@ -169,16 +168,11 @@ class Display {
this._setInteractive(true); this._setInteractive(true);
await yomichan.ready(); await yomichan.ready();
await this._displayGenerator.prepare(); await this._displayGenerator.prepare();
yomichan.on('orphaned', this._onOrphaned.bind(this));
}
_onOrphaned() {
this._orphaned = true;
} }
onError(error) { onError(error) {
if (this._orphaned) { if (yomichan.isExtensionUnloaded) {
this.setContent('orphaned'); this.setContent('extensionUnloaded');
} else { } else {
yomichan.logError(error); yomichan.logError(error);
} }
@ -494,8 +488,8 @@ class Display {
case 'kanji': case 'kanji':
await this._setContentKanji(details.definitions, details.context, token); await this._setContentKanji(details.definitions, details.context, token);
break; break;
case 'orphaned': case 'extensionUnloaded':
this._setContentOrphaned(); this._setContentExtensionUnloaded();
break; break;
} }
} catch (e) { } catch (e) {
@ -614,15 +608,15 @@ class Display {
this._updateAdderButtons(states); this._updateAdderButtons(states);
} }
_setContentOrphaned() { _setContentExtensionUnloaded() {
const errorOrphaned = document.querySelector('#error-orphaned'); const errorExtensionUnloaded = document.querySelector('#error-extension-unloaded');
if (this._container !== null) { if (this._container !== null) {
this._container.hidden = true; this._container.hidden = true;
} }
if (errorOrphaned !== null) { if (errorExtensionUnloaded !== null) {
errorOrphaned.hidden = false; errorExtensionUnloaded.hidden = false;
} }
this._updateNavigation(null, null); this._updateNavigation(null, null);

View File

@ -47,6 +47,8 @@ const yomichan = (() => {
// NOP // NOP
} }
this._isExtensionUnloaded = false;
const {promise, resolve} = deferPromise(); const {promise, resolve} = deferPromise();
this._isBackendPreparedPromise = promise; this._isBackendPreparedPromise = promise;
this._isBackendPreparedPromiseResolve = resolve; this._isBackendPreparedPromiseResolve = resolve;
@ -61,12 +63,16 @@ const yomichan = (() => {
// Public // Public
get isExtensionUnloaded() {
return this._isExtensionUnloaded;
}
prepare() { prepare() {
chrome.runtime.onMessage.addListener(this._onMessage.bind(this)); chrome.runtime.onMessage.addListener(this._onMessage.bind(this));
} }
ready() { ready() {
chrome.runtime.sendMessage({action: 'yomichanCoreReady'}); this.sendMessage({action: 'yomichanCoreReady'});
return this._isBackendPreparedPromise; return this._isBackendPreparedPromise;
} }
@ -80,10 +86,6 @@ const yomichan = (() => {
return id; return id;
} }
triggerOrphaned(error) {
this.trigger('orphaned', {error});
}
isExtensionUrl(url) { isExtensionUrl(url) {
try { try {
return url.startsWith(chrome.runtime.getURL('/')); return url.startsWith(chrome.runtime.getURL('/'));
@ -190,8 +192,31 @@ const yomichan = (() => {
this.trigger('log', {error, level, context}); this.trigger('log', {error, level, context});
} }
sendMessage(...args) {
try {
return chrome.runtime.sendMessage(...args);
} catch (e) {
this._onExtensionUnloaded(e);
throw e;
}
}
connect(...args) {
try {
return chrome.runtime.connect(...args);
} catch (e) {
this._onExtensionUnloaded(e);
throw e;
}
}
// Private // Private
_onExtensionUnloaded(error) {
this._isExtensionUnloaded = true;
this.trigger('extensionUnloaded', {error});
}
_getUrl() { _getUrl() {
return (typeof window === 'object' && window !== null ? window.location.href : ''); return (typeof window === 'object' && window !== null ? window.location.href : '');
} }