Fix cloud storage errors not reported in user interface

Related feedback:
- https://www.reddit.com/r/uBlockOrigin/comments/i6e7lr/
This commit is contained in:
Raymond Hill 2020-08-10 08:30:52 -04:00
parent 3bcd970e07
commit b01cc6ca4f
No known key found for this signature in database
GPG Key ID: 25E1490B761470C2
4 changed files with 44 additions and 49 deletions

View File

@ -1599,28 +1599,14 @@ vAPI.cloud = (( ) => {
} }
bin[dataKey + chunkCount.toString()] = ''; // Sentinel bin[dataKey + chunkCount.toString()] = ''; // Sentinel
let result;
let errorStr;
try { try {
result = await webext.storage.sync.set(bin); await webext.storage.sync.set(bin);
} catch (reason) { } catch (reason) {
errorStr = reason; return String(reason);
}
// https://github.com/gorhill/uBlock/issues/3006#issuecomment-332597677
// - Delete all that was pushed in case of failure.
// - It's unknown whether such issue applies only to Firefox:
// until such cases are reported for other browsers, we will
// reset the (now corrupted) content of the cloud storage
// only on Firefox.
if ( errorStr !== undefined && vAPI.webextFlavor.soup.has('firefox') ) {
chunkCount = 0;
} }
// Remove potentially unused trailing chunks // Remove potentially unused trailing chunks
deleteChunks(dataKey, chunkCount); deleteChunks(dataKey, chunkCount);
return errorStr;
}; };
const pull = async function(dataKey) { const pull = async function(dataKey) {
@ -1638,7 +1624,7 @@ vAPI.cloud = (( ) => {
try { try {
bin = await webext.storage.sync.get(chunkKeys); bin = await webext.storage.sync.get(chunkKeys);
} catch (reason) { } catch (reason) {
return reason; return String(reason);
} }
// Assemble chunks into a single string. // Assemble chunks into a single string.

View File

@ -5,14 +5,16 @@
<title></title> <title></title>
</head> </head>
<body> <body>
<button id="cloudPush" type="button" data-i18n-title="cloudPush"><span class="fa-icon">cloud-upload</span></button> <div id="cloudToolbar">
<span id="cloudInfo" data-i18n="cloudNoData"></span> <button id="cloudPush" type="button" data-i18n-title="cloudPush"><span class="fa-icon">cloud-upload</span></button>
<button id="cloudPull" type="button" data-i18n-title="cloudPull" disabled><span class="fa-icon">cloud-download</span></button> <span id="cloudInfo" data-i18n="cloudNoData"></span>
<button id="cloudPullAndMerge" type="button" data-i18n-title="cloudPullAndMerge" disabled><span class="fa-icon">cloud-download</span><span class="fa-icon">plus</span></button> <button id="cloudPull" type="button" data-i18n-title="cloudPull" disabled><span class="fa-icon">cloud-download</span></button>
<span id="cloudError"></span> <button id="cloudPullAndMerge" type="button" data-i18n-title="cloudPullAndMerge" disabled><span class="fa-icon">cloud-download</span><span class="fa-icon">plus</span></button>
<span id="cloudCog" class="fa-icon">cog</span> <span id="cloudCog" class="fa-icon">cog</span>
<div id="cloudOptions"> <div id="cloudOptions">
<label data-i18n="cloudDeviceNamePrompt"></label> <input id="cloudDeviceName" type="text" value=""> <button id="cloudOptionsSubmit" class="vflex" type="button" data-i18n="genericSubmit"></button> <label data-i18n="cloudDeviceNamePrompt"></label> <input id="cloudDeviceName" type="text" value=""> <button id="cloudOptionsSubmit" class="vflex" type="button" data-i18n="genericSubmit"></button>
</div>
</div> </div>
<div id="cloudError"></div>
</body> </body>
</html> </html>

View File

@ -9,20 +9,19 @@
#cloudWidget.hide { #cloudWidget.hide {
display: none; display: none;
} }
#cloudWidget > button { #cloudToolbar > button {
font-size: 180%; font-size: 180%;
padding: 0 0.25em; padding: 0 0.25em;
position: relative; position: relative;
} }
#cloudWidget { #cloudToolbar {
align-items: center;
display: flex; display: flex;
flex-wrap: nowrap; flex-wrap: nowrap;
} }
#cloudWidget button[disabled] { #cloudToolbar button[disabled] {
visibility: hidden; visibility: hidden;
} }
#cloudWidget button.error { #cloudToolbar button.error {
color: var(--fg-icon-info-lvl-4); color: var(--fg-icon-info-lvl-4);
} }
#cloudPullAndMerge { #cloudPullAndMerge {
@ -47,21 +46,26 @@
color: var(--fg-icon-info-lvl-4); color: var(--fg-icon-info-lvl-4);
flex-grow: 1; flex-grow: 1;
flex-shrink: 2; flex-shrink: 2;
font-size: x-small; font-size: small;
margin: 0 1em; margin: 0.5em 0.5em 0 0;
} }
#cloudWidget #cloudCog { #cloudError:empty {
display: none;
}
#cloudToolbar #cloudCog {
color: var(--fg-0-50); color: var(--fg-0-50);
cursor: pointer; cursor: pointer;
fill: var(--fg-0-50); fill: var(--fg-0-50);
flex-grow: 1;
font-size: 110%; font-size: 110%;
justify-content: flex-end;
padding: 0.4em; padding: 0.4em;
} }
#cloudWidget #cloudCog:hover { #cloudToolbar #cloudCog:hover {
color: inherit; color: inherit;
fill: inherit; fill: inherit;
} }
#cloudWidget #cloudOptions { #cloudToolbar #cloudOptions {
background-color: var(--default-surface); background-color: var(--default-surface);
border: 1px solid var(--bg-1-border); border: 1px solid var(--bg-1-border);
bottom: 0; bottom: 0;
@ -74,6 +78,6 @@
top: 0; top: 0;
z-index: 10; z-index: 10;
} }
#cloudWidget #cloudOptions.show { #cloudToolbar #cloudOptions.show {
display: block; display: block;
} }

View File

@ -52,7 +52,7 @@ const fetchCloudData = async function() {
what: 'cloudPull', what: 'cloudPull',
datakey: self.cloud.datakey, datakey: self.cloud.datakey,
}); });
if ( entry instanceof Object === false ) { return; } if ( entry instanceof Object === false ) { return entry; }
self.cloud.data = entry.data; self.cloud.data = entry.data;
@ -92,20 +92,23 @@ const pushData = async function() {
.toggle('error', failed); .toggle('error', failed);
document.querySelector('#cloudError') document.querySelector('#cloudError')
.textContent = failed ? error : ''; .textContent = failed ? error : '';
if ( failed ) { return; }
fetchCloudData(); fetchCloudData();
}; };
/******************************************************************************/ /******************************************************************************/
var pullData = function() { const pullData = function() {
if ( typeof self.cloud.onPull === 'function' ) { if ( typeof self.cloud.onPull === 'function' ) {
self.cloud.onPull(self.cloud.data, false); self.cloud.onPull(self.cloud.data, false);
} }
document.getElementById('cloudPush').classList.remove('error');
document.querySelector('#cloudError').textContent = '';
}; };
/******************************************************************************/ /******************************************************************************/
var pullAndMergeData = function() { const pullAndMergeData = function() {
if ( typeof self.cloud.onPull === 'function' ) { if ( typeof self.cloud.onPull === 'function' ) {
self.cloud.onPull(self.cloud.data, true); self.cloud.onPull(self.cloud.data, true);
} }
@ -113,8 +116,8 @@ var pullAndMergeData = function() {
/******************************************************************************/ /******************************************************************************/
var openOptions = function() { const openOptions = function() {
var input = uDom.nodeFromId('cloudDeviceName'); const input = uDom.nodeFromId('cloudDeviceName');
input.value = self.cloud.options.deviceName; input.value = self.cloud.options.deviceName;
input.setAttribute('placeholder', self.cloud.options.defaultDeviceName); input.setAttribute('placeholder', self.cloud.options.defaultDeviceName);
uDom.nodeFromId('cloudOptions').classList.add('show'); uDom.nodeFromId('cloudOptions').classList.add('show');
@ -122,11 +125,9 @@ var openOptions = function() {
/******************************************************************************/ /******************************************************************************/
var closeOptions = function(ev) { const closeOptions = function(ev) {
var root = uDom.nodeFromId('cloudOptions'); const root = uDom.nodeFromId('cloudOptions');
if ( ev.target !== root ) { if ( ev.target !== root ) { return; }
return;
}
root.classList.remove('show'); root.classList.remove('show');
}; };
@ -180,9 +181,11 @@ const onInitialize = function(options) {
uDom('#cloudOptions').on('click', closeOptions); uDom('#cloudOptions').on('click', closeOptions);
uDom('#cloudOptionsSubmit').on('click', ( ) => { submitOptions(); }); uDom('#cloudOptionsSubmit').on('click', ( ) => { submitOptions(); });
// Patch 2018-01-05: Must not assume this XHR will always be faster fetchCloudData().then(result => {
// than messaging if ( typeof result !== 'string' ) { return; }
fetchCloudData(); document.getElementById('cloudPush').classList.add('error');
document.querySelector('#cloudError').textContent = result;
});
}; };
xhr.send(); xhr.send();
}; };