Merge branch 'soon' into staging
commit
48ad82c4fb
|
@ -1,3 +1,10 @@
|
|||
# WIP
|
||||
|
||||
* Sheet export
|
||||
* most exports broken by Chrome 92, mostly fixed
|
||||
* we discovered that CSV export was not working in any major browser, though it's unclear why. We've disabled CSV export in the meantime
|
||||
* some new browser-specific checkup tests to make it easier to detect future regressions in the APIs needed for sheet export
|
||||
|
||||
# 4.9.0
|
||||
|
||||
## Goals and announcements
|
||||
|
|
|
@ -14,11 +14,15 @@ html, body {
|
|||
|
||||
.report {
|
||||
font-size: 30px;
|
||||
max-width: 50%;
|
||||
max-width: 26em;
|
||||
margin: auto;
|
||||
padding-top: 15px;
|
||||
}
|
||||
|
||||
.summary, .failure, .error, .success {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.pending {
|
||||
border: 1px solid @cryptpad_text_col;
|
||||
.fa {
|
||||
|
@ -42,10 +46,18 @@ html, body {
|
|||
padding: 15px;
|
||||
}
|
||||
|
||||
table {
|
||||
td {
|
||||
padding: 5px;
|
||||
border: 1px solid @cryptpad_text_col;
|
||||
.table-container {
|
||||
overflow-x: auto;
|
||||
width: 100%;
|
||||
table {
|
||||
td {
|
||||
padding: 5px;
|
||||
border: 1px solid @cryptpad_text_col;
|
||||
font-size: 60%;
|
||||
}
|
||||
td:nth-child(2) {
|
||||
word-break: break-word;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -72,7 +84,12 @@ html, body {
|
|||
color: @cryptpad_color_link;
|
||||
}
|
||||
}
|
||||
.cp-app-checkup-version {
|
||||
|
||||
.cp-notice-browser, .cp-notice-details, .cp-notice-other {
|
||||
font-size: 70%;
|
||||
}
|
||||
|
||||
.cp-app-checkup-version, .cp-app-checkup-browser {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
define([
|
||||
], function () {
|
||||
var Tools = {};
|
||||
Tools.supportsSharedArrayBuffers = function () {
|
||||
try {
|
||||
return Object.prototype.toString.call(new window.WebAssembly.Memory({
|
||||
shared: true,
|
||||
initial: 0,
|
||||
maximum: 0,
|
||||
}).buffer) === '[object SharedArrayBuffer]';
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
|
||||
Tools.isSafari = function () {
|
||||
return navigator.vendor.match(/apple/i);
|
||||
};
|
||||
|
||||
Tools.isChrome = function () {
|
||||
return navigator.vendor.match(/google/i);
|
||||
};
|
||||
|
||||
Tools.guessBrowser = function () {
|
||||
if (Tools.isChrome()) { return 'chrome/blink'; }
|
||||
if (Tools.isSafari()) { return 'safari/webkit'; }
|
||||
if (navigator.userAgent.match(/firefox\//i)) { return 'firefox/gecko'; }
|
||||
if (navigator.userAgent.match(/edge\//i)) { return 'edge/edgehtml'; }
|
||||
if (navigator.userAgent.match(/trident\//i)) { return 'ie/trident'; }
|
||||
return navigator.userAgent + "\n" + navigator.vendor;
|
||||
};
|
||||
|
||||
return Tools;
|
||||
});
|
|
@ -13,13 +13,14 @@ define([
|
|||
'/common/pinpad.js',
|
||||
'/common/outer/network-config.js',
|
||||
'/customize/pages.js',
|
||||
'/checkup/checkup-tools.js',
|
||||
|
||||
'/bower_components/tweetnacl/nacl-fast.min.js',
|
||||
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||
'less!/checkup/app-checkup.less',
|
||||
], function ($, ApiConfig, Assertions, h, Messages, DomReady,
|
||||
nThen, SFCommonO, Login, Hash, Util, Pinpad,
|
||||
NetConfig, Pages) {
|
||||
NetConfig, Pages, Tools) {
|
||||
var Assert = Assertions();
|
||||
var trimSlashes = function (s) {
|
||||
if (typeof(s) !== 'string') { return s; }
|
||||
|
@ -703,6 +704,69 @@ define([
|
|||
});
|
||||
});
|
||||
|
||||
var safariGripe = function () {
|
||||
return h('p.cp-notice-other', 'This is expected because Safari and platforms that use its engine lack commonly supported functionality.');
|
||||
};
|
||||
|
||||
var browserIssue = function () {
|
||||
return h('p.cp-notice-other', 'This test checks for the presence of features in your browser and is not necessarily caused by server misconfiguration.');
|
||||
};
|
||||
|
||||
assert(function (cb, msg) {
|
||||
cb = Util.once(cb);
|
||||
setWarningClass(msg);
|
||||
var notice = h('span', [
|
||||
h('p', 'It appears that some features required for Office file format conversion are not present.'),
|
||||
Tools.isSafari()? safariGripe(): undefined,
|
||||
browserIssue(),
|
||||
]);
|
||||
|
||||
msg.appendChild(notice);
|
||||
|
||||
var expected = [
|
||||
'Atomics',
|
||||
'SharedArrayBuffer',
|
||||
'WebAssembly',
|
||||
['WebAssembly', 'Memory'],
|
||||
['WebAssembly', 'instantiate'],
|
||||
['WebAssembly', 'instantiateStreaming'],
|
||||
['Buffer', 'from'],
|
||||
|
||||
'SharedWorker',
|
||||
'worker',
|
||||
'crossOriginIsolated',
|
||||
];
|
||||
|
||||
var responses = {};
|
||||
|
||||
nThen(function (w) {
|
||||
deferredPostMessage({
|
||||
command: 'CHECK_JS_APIS',
|
||||
content: {
|
||||
globals: expected,
|
||||
},
|
||||
}, w(function (response) {
|
||||
Util.extend(responses, response);
|
||||
}));
|
||||
|
||||
deferredPostMessage({
|
||||
command: 'FANCY_API_CHECKS',
|
||||
content: {
|
||||
},
|
||||
}, w(function (response) {
|
||||
Util.extend(responses, response);
|
||||
}));
|
||||
}).nThen(function () {
|
||||
if (!responses.Atomics || !responses.WebAssembly) {
|
||||
return void cb(responses);
|
||||
}
|
||||
if (responses.SharedArrayBuffer || responses.SharedArrayBufferFallback) {
|
||||
return cb(true);
|
||||
}
|
||||
return void cb(response);
|
||||
});
|
||||
});
|
||||
|
||||
var isHTTPS = function (host) {
|
||||
return /^https:\/\//.test(host);
|
||||
};
|
||||
|
@ -831,17 +895,19 @@ define([
|
|||
var failureReport = function (obj) {
|
||||
var printableValue = obj.output;
|
||||
try {
|
||||
printableValue = JSON.stringify(obj.output);
|
||||
printableValue = JSON.stringify(obj.output, null, ' ');
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
|
||||
return h('div.error', [
|
||||
h('h5', obj.message),
|
||||
h('table', [
|
||||
row(["Failed test number", obj.test + 1]),
|
||||
row(["Returned value", code(printableValue)]),
|
||||
]),
|
||||
h('div.table-container',
|
||||
h('table', [
|
||||
row(["Failed test number", obj.test + 1]),
|
||||
row(["Returned value", h('pre', code(printableValue))]),
|
||||
]),
|
||||
),
|
||||
]);
|
||||
};
|
||||
|
||||
|
@ -849,7 +915,7 @@ define([
|
|||
var $progress = $('#cp-progress');
|
||||
|
||||
var versionStatement = function () {
|
||||
return h('p', [
|
||||
return h('p.cp--notice-version', [
|
||||
"This instance is running ",
|
||||
h('span.cp-app-checkup-version',[
|
||||
"CryptPad",
|
||||
|
@ -860,6 +926,16 @@ define([
|
|||
]);
|
||||
};
|
||||
|
||||
var browserStatement = function () {
|
||||
var name = Tools.guessBrowser();
|
||||
if (!name) { return; }
|
||||
return h('p.cp-notice-browser', [
|
||||
"You appear to be using a ",
|
||||
h('span.cp-app-checkup-browser', name),
|
||||
' browser to view this page.',
|
||||
]);
|
||||
};
|
||||
|
||||
Assert.run(function (state) {
|
||||
var errors = state.errors;
|
||||
var failed = errors.length;
|
||||
|
@ -870,10 +946,11 @@ define([
|
|||
|
||||
var failedDetails = "Details found below";
|
||||
var successDetails = "This checkup only tests the most common configuration issues. You may still experience errors or incorrect behaviour.";
|
||||
var details = h('p', failed? failedDetails: successDetails);
|
||||
var details = h('p.cp-notice-details', failed? failedDetails: successDetails);
|
||||
|
||||
var summary = h('div.summary.' + statusClass, [
|
||||
versionStatement(),
|
||||
browserStatement(),
|
||||
h('p', Messages._getKey('assert_numberOfTestsPassed', [
|
||||
state.passed,
|
||||
state.total
|
||||
|
|
|
@ -1,10 +1,12 @@
|
|||
define([
|
||||
'jquery',
|
||||
'/common/common-util.js',
|
||||
'/checkup/checkup-tools.js',
|
||||
|
||||
'/bower_components/tweetnacl/nacl-fast.min.js',
|
||||
'css!/bower_components/components-font-awesome/css/font-awesome.min.css',
|
||||
'less!/checkup/app-checkup.less',
|
||||
], function ($) {
|
||||
], function ($, Util, Tools) {
|
||||
var postMessage = function (content) {
|
||||
window.parent.postMessage(JSON.stringify(content), '*');
|
||||
};
|
||||
|
@ -26,6 +28,26 @@ define([
|
|||
});
|
||||
};
|
||||
|
||||
COMMANDS.CHECK_JS_APIS = function (content, cb) {
|
||||
var globalAPIs = content['globals'] || [];
|
||||
var response = {};
|
||||
globalAPIs.forEach(function (key) {
|
||||
if (Array.isArray(key)) {
|
||||
response[key.join('.')] = Boolean(Util.find(window, key));
|
||||
return;
|
||||
}
|
||||
|
||||
response[key] = Boolean(window[key]);
|
||||
});
|
||||
cb(response);
|
||||
};
|
||||
|
||||
COMMANDS.FANCY_API_CHECKS = function (content, cb) {
|
||||
cb({
|
||||
SharedArrayBufferFallback: Tools.supportsSharedArrayBuffers(),
|
||||
});
|
||||
};
|
||||
|
||||
window.addEventListener("message", function (event) {
|
||||
var txid, command;
|
||||
if (event && event.data) {
|
||||
|
|
|
@ -72,8 +72,31 @@ define([
|
|||
return JSONSortify(obj);
|
||||
};
|
||||
|
||||
/* Chrome 92 dropped support for SharedArrayBuffer in cross-origin contexts
|
||||
where window.crossOriginIsolated is false.
|
||||
|
||||
Their blog (https://blog.chromium.org/2021/02/restriction-on-sharedarraybuffers.html)
|
||||
isn't clear about why they're doing this, but since it's related to site-isolation
|
||||
it seems they're trying to do vague security things.
|
||||
|
||||
In any case, there seems to be a workaround where you can still create them
|
||||
by using `new WebAssembly.Memory({shared: true, ...})` instead of `new SharedArrayBuffer`.
|
||||
|
||||
This seems unreliable, but it's better than not being able to export, since
|
||||
we actively rely on postMessage between iframes and therefore can't afford
|
||||
to opt for full isolation.
|
||||
*/
|
||||
var supportsSharedArrayBuffers = function () {
|
||||
try {
|
||||
return Object.prototype.toString.call(new window.WebAssembly.Memory({shared: true, initial: 0, maximum: 0}).buffer) === '[object SharedArrayBuffer]';
|
||||
} catch (err) {
|
||||
console.error(err);
|
||||
}
|
||||
return false;
|
||||
};
|
||||
|
||||
var supportsXLSX = function () {
|
||||
return !(typeof(Atomics) === "undefined" || typeof (SharedArrayBuffer) === "undefined" || typeof(WebAssembly) === 'undefined');
|
||||
return !(typeof(Atomics) === "undefined" || !supportsSharedArrayBuffers() /* || typeof (SharedArrayBuffer) === "undefined" */ || typeof(WebAssembly) === 'undefined');
|
||||
};
|
||||
|
||||
|
||||
|
@ -1915,7 +1938,9 @@ define([
|
|||
var exportXLSXFile = function() {
|
||||
var text = getContent();
|
||||
var suggestion = Title.suggestTitle(Title.defaultTitle);
|
||||
var ext = ['.xlsx', '.ods', '.bin', '.csv', '.pdf'];
|
||||
var ext = ['.xlsx', '.ods', '.bin',
|
||||
//'.csv', // XXX
|
||||
'.pdf'];
|
||||
var type = common.getMetadataMgr().getPrivateData().ooType;
|
||||
var warning = '';
|
||||
if (type==="presentation") {
|
||||
|
|
|
@ -1,3 +1,8 @@
|
|||
function SUPPORTS_SHARED_MEMORY() {
|
||||
return typeof(SharedArrayBuffer) !== 'undefined';
|
||||
}
|
||||
|
||||
|
||||
// Support for growable heap + pthreads, where the buffer may change, so JS views
|
||||
// must be updated.
|
||||
function GROWABLE_HEAP_STORE_I8(ptr, value) {
|
||||
|
@ -1030,7 +1035,7 @@ if (ENVIRONMENT_IS_PTHREAD) {
|
|||
"maximum": 1073741824 / WASM_PAGE_SIZE,
|
||||
"shared": true
|
||||
});
|
||||
if (!(wasmMemory.buffer instanceof SharedArrayBuffer)) {
|
||||
if (Object.prototype.toString.call(wasmMemory.buffer) !== '[object SharedArrayBuffer]') {
|
||||
err("requested a shared WebAssembly.Memory but the returned buffer is not a SharedArrayBuffer, indicating that while the browser has SharedArrayBuffer it does not have WebAssembly threads support - you may need to set a flag");
|
||||
if (ENVIRONMENT_HAS_NODE) {
|
||||
console.log("(on node you may need: --experimental-wasm-threads --experimental-wasm-bulk-memory and also use a recent version)");
|
||||
|
@ -2161,7 +2166,7 @@ var PThread = {
|
|||
}),
|
||||
receiveObjectTransfer: (function(data) {}),
|
||||
allocateUnusedWorkers: (function(numWorkers, onFinishedLoading) {
|
||||
if (typeof SharedArrayBuffer === "undefined") return;
|
||||
if (!SUPPORTS_SHARED_MEMORY()) return;
|
||||
var workers = [];
|
||||
var numWorkersToCreate = numWorkers;
|
||||
if (PThread.preallocatedWorkers.length > 0) {
|
||||
|
@ -2276,7 +2281,7 @@ var PThread = {
|
|||
}
|
||||
}),
|
||||
createNewWorkers: (function(numWorkers) {
|
||||
if (typeof SharedArrayBuffer === "undefined") return [];
|
||||
if (!SUPPORTS_SHARED_MEMORY()) return [];
|
||||
var pthreadMainJs = "x2t.worker.js";
|
||||
pthreadMainJs = locateFile(pthreadMainJs);
|
||||
var newWorkers = [];
|
||||
|
@ -5683,7 +5688,7 @@ function _emscripten_get_sbrk_ptr() {
|
|||
}
|
||||
Module["_emscripten_get_sbrk_ptr"] = _emscripten_get_sbrk_ptr;
|
||||
function _emscripten_has_threading_support() {
|
||||
return typeof SharedArrayBuffer !== "undefined";
|
||||
return SUPPORTS_SHARED_MEMORY();
|
||||
}
|
||||
Module["_emscripten_has_threading_support"] = _emscripten_has_threading_support;
|
||||
function _emscripten_is_main_browser_thread() {
|
||||
|
@ -6761,7 +6766,7 @@ function _pthread_self() {
|
|||
}
|
||||
Module["_pthread_self"] = _pthread_self;
|
||||
function _pthread_create(pthread_ptr, attr, start_routine, arg) {
|
||||
if (typeof SharedArrayBuffer === "undefined") {
|
||||
if (!SUPPORTS_SHARED_MEMORY()) {
|
||||
err("Current environment does not support SharedArrayBuffer, pthreads are not available!");
|
||||
return 6;
|
||||
}
|
||||
|
|
|
@ -560,7 +560,7 @@
|
|||
"form_form": "フォーム",
|
||||
"form_editor": "エディタ",
|
||||
"form_delete": "削除",
|
||||
"form_sent": "送信しました",
|
||||
"form_sent": "回答を送信しました",
|
||||
"form_reset": "リセット",
|
||||
"form_update": "更新",
|
||||
"form_submit": "送信",
|
||||
|
@ -1378,5 +1378,6 @@
|
|||
"notification_linkShared": "{0}があなたとリンクを共有しました: <b>{1}</b>",
|
||||
"fm_link_name_placeholder": "あなたのリンク",
|
||||
"fm_link_warning": "注意:URLが200字を超えています",
|
||||
"fm_link_invalid": "URLが無効です"
|
||||
"fm_link_invalid": "URLが無効です",
|
||||
"form_answerAs": "名前を記入してください"
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue