Google Docs accessibility (#1875)

* Add accessibility option for forcing Google Docs HTML-based rendering

* Update settings

* Send a documentStart message at document start

* Add accessibility script for Google Docs

* Set up accessibility

* Update tests
This commit is contained in:
toasted-nutbread 2021-08-07 12:40:51 -04:00 committed by GitHub
parent ad31b70b67
commit 5d4141a429
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 177 additions and 6 deletions

View File

@ -120,6 +120,7 @@
"files": ["ext/**/*.js"], "files": ["ext/**/*.js"],
"excludedFiles": [ "excludedFiles": [
"ext/js/core.js", "ext/js/core.js",
"ext/js/document-start.js",
"ext/js/**/sandbox/**/*.js" "ext/js/**/sandbox/**/*.js"
], ],
"globals": { "globals": {
@ -146,6 +147,7 @@
"files": ["ext/**/*.js"], "files": ["ext/**/*.js"],
"excludedFiles": [ "excludedFiles": [
"ext/js/core.js", "ext/js/core.js",
"ext/js/document-start.js",
"ext/js/yomichan.js", "ext/js/yomichan.js",
"ext/js/**/sandbox/**/*.js" "ext/js/**/sandbox/**/*.js"
], ],

View File

@ -33,11 +33,14 @@
}, },
"content_scripts": [ "content_scripts": [
{ {
"run_at": "document_idle",
"matches": [ "matches": [
"http://*/*", "http://*/*",
"https://*/*", "https://*/*",
"file://*/*" "file://*/*"
], ],
"match_about_blank": true,
"all_frames": true,
"js": [ "js": [
"js/core.js", "js/core.js",
"js/yomichan.js", "js/yomichan.js",
@ -59,9 +62,20 @@
"js/language/text-scanner.js", "js/language/text-scanner.js",
"js/script/dynamic-loader.js", "js/script/dynamic-loader.js",
"js/app/content-script-main.js" "js/app/content-script-main.js"
]
},
{
"run_at": "document_start",
"matches": [
"http://*/*",
"https://*/*",
"file://*/*"
], ],
"match_about_blank": true, "match_about_blank": true,
"all_frames": true "all_frames": true,
"js": [
"js/document-start.js"
]
} }
], ],
"minimum_chrome_version": "57.0.0.0", "minimum_chrome_version": "57.0.0.0",

View File

@ -72,7 +72,8 @@
"anki", "anki",
"sentenceParsing", "sentenceParsing",
"inputs", "inputs",
"clipboard" "clipboard",
"accessibility"
], ],
"properties": { "properties": {
"general": { "general": {
@ -1109,6 +1110,18 @@
"minimum": 0 "minimum": 0
} }
} }
},
"accessibility": {
"type": "object",
"required": [
"forceGoogleDocsHtmlRendering"
],
"properties": {
"forceGoogleDocsHtmlRendering": {
"type": "boolean",
"default": false
}
}
} }
} }
} }

View File

@ -0,0 +1,27 @@
/*
* Copyright (C) 2021 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/>.
*/
(() => {
let parent = document.head;
if (parent === null) {
parent = document.documentElement;
if (parent === null) { return; }
}
const script = document.createElement('script');
script.textContent = 'window._docs_force_html_by_ext = true;';
parent.appendChild(script);
})();

View File

@ -124,7 +124,8 @@ class Backend {
['isTabSearchPopup', {async: true, contentScript: true, handler: this._onApiIsTabSearchPopup.bind(this)}], ['isTabSearchPopup', {async: true, contentScript: true, handler: this._onApiIsTabSearchPopup.bind(this)}],
['triggerDatabaseUpdated', {async: false, contentScript: true, handler: this._onApiTriggerDatabaseUpdated.bind(this)}], ['triggerDatabaseUpdated', {async: false, contentScript: true, handler: this._onApiTriggerDatabaseUpdated.bind(this)}],
['testMecab', {async: true, contentScript: true, handler: this._onApiTestMecab.bind(this)}], ['testMecab', {async: true, contentScript: true, handler: this._onApiTestMecab.bind(this)}],
['textHasJapaneseCharacters', {async: false, contentScript: true, handler: this._onApiTextHasJapaneseCharacters.bind(this)}] ['textHasJapaneseCharacters', {async: false, contentScript: true, handler: this._onApiTextHasJapaneseCharacters.bind(this)}],
['documentStart', {async: false, contentScript: true, handler: this._onDocumentStart.bind(this)}]
]); ]);
this._messageHandlersWithProgress = new Map([ this._messageHandlersWithProgress = new Map([
]); ]);
@ -745,6 +746,12 @@ class Backend {
return this._japaneseUtil.isStringPartiallyJapanese(text); return this._japaneseUtil.isStringPartiallyJapanese(text);
} }
_onDocumentStart(params, sender) {
const {tab, frameId, url} = sender;
if (typeof url !== 'string' || typeof tab !== 'object' || tab === null) { return; }
this._updateTabAccessibility(url, tab, frameId);
}
// Command handlers // Command handlers
async _onCommandOpenSearchPage(params) { async _onCommandOpenSearchPage(params) {
@ -2207,4 +2214,31 @@ class Backend {
// NOP // NOP
} }
} }
_updateTabAccessibility(url, tab, frameId) {
let file = null;
switch (new URL(url).hostname) {
case 'docs.google.com':
{
const optionsContext = {depth: 0, url};
const options = this._getProfileOptions(optionsContext);
if (!options.accessibility.forceGoogleDocsHtmlRendering) { return; }
file = 'js/accessibility/google-docs.js';
}
break;
}
if (file === null) { return; }
const details = {
allFrames: false,
frameId,
file,
matchAboutBlank: true,
runAt: 'document_start'
};
const callback = () => this._checkLastError(chrome.runtime.lastError);
chrome.tabs.executeScript(tab.id, details, callback);
}
} }

View File

@ -462,7 +462,8 @@ class OptionsUtil {
{async: true, update: this._updateVersion10.bind(this)}, {async: true, update: this._updateVersion10.bind(this)},
{async: false, update: this._updateVersion11.bind(this)}, {async: false, update: this._updateVersion11.bind(this)},
{async: true, update: this._updateVersion12.bind(this)}, {async: true, update: this._updateVersion12.bind(this)},
{async: true, update: this._updateVersion13.bind(this)} {async: true, update: this._updateVersion13.bind(this)},
{async: false, update: this._updateVersion14.bind(this)}
]; ];
if (typeof targetVersion === 'number' && targetVersion < result.length) { if (typeof targetVersion === 'number' && targetVersion < result.length) {
result.splice(targetVersion); result.splice(targetVersion);
@ -864,4 +865,15 @@ class OptionsUtil {
} }
return options; return options;
} }
_updateVersion14(options) {
// Version 14 changes:
// Added accessibility options.
for (const profile of options.profiles) {
profile.options.accessibility = {
forceGoogleDocsHtmlRendering: false
};
}
return options;
}
} }

18
ext/js/document-start.js Normal file
View File

@ -0,0 +1,18 @@
/*
* Copyright (C) 2021 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/>.
*/
chrome.runtime.sendMessage({action: 'documentStart'}, () => void chrome.runtime.lastError);

View File

@ -32,11 +32,14 @@
}, },
"content_scripts": [ "content_scripts": [
{ {
"run_at": "document_idle",
"matches": [ "matches": [
"http://*/*", "http://*/*",
"https://*/*", "https://*/*",
"file://*/*" "file://*/*"
], ],
"match_about_blank": true,
"all_frames": true,
"js": [ "js": [
"js/core.js", "js/core.js",
"js/yomichan.js", "js/yomichan.js",
@ -58,9 +61,20 @@
"js/language/text-scanner.js", "js/language/text-scanner.js",
"js/script/dynamic-loader.js", "js/script/dynamic-loader.js",
"js/app/content-script-main.js" "js/app/content-script-main.js"
]
},
{
"run_at": "document_start",
"matches": [
"http://*/*",
"https://*/*",
"file://*/*"
], ],
"match_about_blank": true, "match_about_blank": true,
"all_frames": true "all_frames": true,
"js": [
"js/document-start.js"
]
} }
], ],
"minimum_chrome_version": "57.0.0.0", "minimum_chrome_version": "57.0.0.0",

View File

@ -37,6 +37,7 @@
<a href="#!clipboard" class="button outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="clipboard"></span></span><span class="outline-item-label">Clipboard</span></a> <a href="#!clipboard" class="button outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="clipboard"></span></span><span class="outline-item-label">Clipboard</span></a>
<a href="#!shortcuts" class="button outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="keyboard"></span></span><span class="outline-item-label">Shortcuts</span></a> <a href="#!shortcuts" class="button outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="keyboard"></span></span><span class="outline-item-label">Shortcuts</span></a>
<a href="#!backup" class="button outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="backup"></span></span><span class="outline-item-label">Backup</span></a> <a href="#!backup" class="button outline-item"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="backup"></span></span><span class="outline-item-label">Backup</span></a>
<a href="#!accessibility" class="button outline-item advanced-only"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="accessibility"></span></span><span class="outline-item-label">Accessibility</span></a>
<a href="#!security" class="button outline-item advanced-only"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="lock"></span></span><span class="outline-item-label">Security</span></a> <a href="#!security" class="button outline-item advanced-only"><span class="outline-item-left"><span class="outline-item-icon icon" data-icon="lock"></span></span><span class="outline-item-label">Security</span></a>
</div> </div>
<div class="sidebar-bottom"> <div class="sidebar-bottom">
@ -1816,6 +1817,39 @@
</div></div> </div></div>
</div> </div>
<!-- Accessibility -->
<div class="heading-container advanced-only">
<div class="heading-container-icon"><span class="icon" data-icon="accessibility"></span></div>
<div class="heading-container-left"><h2 id="accessibility"><a href="#!accessibility">Accessibility</a></h2></div>
</div>
<div class="settings-group advanced-only">
<div class="settings-item">
<div class="settings-item-inner">
<div class="settings-item-left">
<div class="settings-item-label">
Force HTML-based rendering for Google Docs
<a class="more-toggle more-only" data-parent-distance="4">(?)</a>
</div>
</div>
<div class="settings-item-right">
<label class="toggle"><input type="checkbox" data-setting="accessibility.forceGoogleDocsHtmlRendering"><span class="toggle-body"><span class="toggle-track"></span><span class="toggle-knob"></span></span></label>
</div>
</div>
<div class="settings-item-children more" hidden>
<p>
Google Docs is moving from HTML-based rendering to
<a href="https://developer.mozilla.org/en-US/docs/Web/HTML/Element/canvas" target="_blank" rel="noopener noreferrer">canvas-based</a>
rendering to display content<sup><a href="https://workspaceupdates.googleblog.com/2021/05/Google-Docs-Canvas-Based-Rendering-Update.html" target="_blank" rel="noopener noreferrer">[2]</a></sup>,
which prevents Yomichan from being able to scan text.
Enabling this option will force HTML-based rendering to be used.
</p>
<p>
<a class="more-toggle" data-parent-distance="3">Less&hellip;</a>
</p>
</div>
</div>
</div>
<!-- Security --> <!-- Security -->
<div class="heading-container advanced-only"> <div class="heading-container advanced-only">
<div class="heading-container-icon"><span class="icon" data-icon="lock"></span></div> <div class="heading-container-icon"><span class="icon" data-icon="lock"></span></div>

View File

@ -503,6 +503,9 @@ function createProfileOptionsUpdatedTestData1() {
enableSearchPageMonitor: false, enableSearchPageMonitor: false,
autoSearchContent: true, autoSearchContent: true,
maximumSearchLength: 1000 maximumSearchLength: 1000
},
accessibility: {
forceGoogleDocsHtmlRendering: false
} }
}; };
} }
@ -590,7 +593,7 @@ function createOptionsUpdatedTestData1() {
} }
], ],
profileCurrent: 0, profileCurrent: 0,
version: 13, version: 14,
global: { global: {
database: { database: {
prefixWildcardsSupported: false prefixWildcardsSupported: false