(#5197) - detect WebSQL invalid on WKWebView
diff --git a/packages/pouchdb-adapter-websql/package.json b/packages/pouchdb-adapter-websql/package.json
index 34ffcf4..c0bb58d 100644
--- a/packages/pouchdb-adapter-websql/package.json
+++ b/packages/pouchdb-adapter-websql/package.json
@@ -14,6 +14,7 @@
],
"dependencies": {
"js-extend": "1.0.1",
- "pouchdb-adapter-websql-core": "5.4.0-prerelease"
+ "pouchdb-adapter-websql-core": "5.4.0-prerelease",
+ "pouchdb-utils": "5.4.0-prerelease"
}
}
diff --git a/packages/pouchdb-adapter-websql/src/index.js b/packages/pouchdb-adapter-websql/src/index.js
index 1f9c034..7081a9f 100644
--- a/packages/pouchdb-adapter-websql/src/index.js
+++ b/packages/pouchdb-adapter-websql/src/index.js
@@ -1,5 +1,6 @@
import WebSqlPouchCore from 'pouchdb-adapter-websql-core';
import { extend } from 'js-extend';
+import valid from './valid';
function websql(optsOrName, version, description, size) {
if (typeof sqlitePlugin !== 'undefined') {
@@ -22,13 +23,7 @@
WebSqlPouchCore.call(this, _opts, callback);
}
-WebSQLPouch.valid = function () {
- // SQLitePlugin leaks this global object, which we can use
- // to detect if it's installed or not. The benefit is that it's
- // declared immediately, before the 'deviceready' event has fired.
- return typeof openDatabase !== 'undefined' ||
- typeof SQLitePlugin !== 'undefined';
-};
+WebSQLPouch.valid = valid;
WebSQLPouch.use_prefix = true;
diff --git a/packages/pouchdb-adapter-websql/src/valid.js b/packages/pouchdb-adapter-websql/src/valid.js
new file mode 100644
index 0000000..41dbe42
--- /dev/null
+++ b/packages/pouchdb-adapter-websql/src/valid.js
@@ -0,0 +1,64 @@
+import { hasLocalStorage } from 'pouchdb-utils';
+
+function canOpenTestDB() {
+ try {
+ openDatabase('_pouch_validate_websql', 1, '', 1);
+ return true;
+ } catch (err) {
+ return false;
+ }
+}
+
+// WKWebView had a bug where WebSQL would throw a DOM Exception 18
+// (see https://bugs.webkit.org/show_bug.cgi?id=137760 and
+// https://github.com/pouchdb/pouchdb/issues/5079)
+// This has been fixed in latest WebKit, so we try to detect it here.
+function isValidWebSQL() {
+ // WKWebView UA:
+ // Mozilla/5.0 (iPhone; CPU iPhone OS 9_2 like Mac OS X)
+ // AppleWebKit/601.1.46 (KHTML, like Gecko) Mobile/13C75
+ // Chrome for iOS UA:
+ // Mozilla/5.0 (iPhone; U; CPU iPhone OS 5_1_1 like Mac OS X; en)
+ // AppleWebKit/534.46.0 (KHTML, like Gecko) CriOS/19.0.1084.60
+ // Mobile/9B206 Safari/7534.48.3
+ // Firefox for iOS UA:
+ // Mozilla/5.0 (iPhone; CPU iPhone OS 8_3 like Mac OS X) AppleWebKit/600.1.4
+ // (KHTML, like Gecko) FxiOS/1.0 Mobile/12F69 Safari/600.1.4
+
+ // typeof indexedDB is null on some UIWebViews and undefined in others
+ if (typeof indexedDB !== 'object' ||
+ !/iP(hone|od|ad)/.test(navigator.userAgent)) {
+ // definitely not WKWebView, avoid creating an unnecessary database
+ return true;
+ }
+ // Cache the result in LocalStorage. Reason we do this is because if we
+ // call openDatabase() too many times, Safari craps out in SauceLabs and
+ // starts throwing DOM Exception 14s.
+ var hasLS = hasLocalStorage();
+ // Include user agent in the hash, so that if Safari is upgraded, we don't
+ // continually think it's broken.
+ var localStorageKey = '_pouch__websqldb_valid_' + navigator.userAgent;
+ if (hasLS && localStorage[localStorageKey]) {
+ return localStorage[localStorageKey] === '1';
+ }
+ var openedTestDB = canOpenTestDB();
+ if (hasLS) {
+ localStorage[localStorageKey] = openedTestDB ? '1' : '0';
+ }
+ return openedTestDB;
+}
+
+function valid() {
+ // SQLitePlugin leaks this global object, which we can use
+ // to detect if it's installed or not. The benefit is that it's
+ // declared immediately, before the 'deviceready' event has fired.
+ if (typeof SQLitePlugin !== 'undefined') {
+ return true;
+ }
+ if (typeof openDatabase === 'undefined') {
+ return false;
+ }
+ return isValidWebSQL();
+}
+
+export default valid;
\ No newline at end of file