Merge pull request #31 from titaniumnetwork-dev/29-indexeddb-and-caches-not-isolated-between-proxied-websites
add idb api
This commit is contained in:
commit
945e04730c
4 changed files with 124 additions and 1 deletions
|
|
@ -1,11 +1,35 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @template Data
|
||||||
|
* @template Target
|
||||||
|
* @template That
|
||||||
|
* @property {Data} data
|
||||||
|
* @property {Target} target
|
||||||
|
* @property {That} that
|
||||||
|
*/
|
||||||
class HookEvent {
|
class HookEvent {
|
||||||
#intercepted;
|
#intercepted;
|
||||||
#returnValue;
|
#returnValue;
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Data} data
|
||||||
|
* @param {Target} target
|
||||||
|
* @param {That} that
|
||||||
|
*/
|
||||||
constructor(data = {}, target = null, that = null) {
|
constructor(data = {}, target = null, that = null) {
|
||||||
this.#intercepted = false;
|
this.#intercepted = false;
|
||||||
this.#returnValue = null;
|
this.#returnValue = null;
|
||||||
|
/**
|
||||||
|
* @type {Data}
|
||||||
|
*/
|
||||||
this.data = data;
|
this.data = data;
|
||||||
|
/**
|
||||||
|
* @type {Target}
|
||||||
|
*/
|
||||||
this.target = target;
|
this.target = target;
|
||||||
|
/**
|
||||||
|
* @type {That}
|
||||||
|
*/
|
||||||
this.that = that;
|
this.that = that;
|
||||||
}
|
}
|
||||||
get intercepted() {
|
get intercepted() {
|
||||||
|
|
|
||||||
62
src/client/idb.js
Normal file
62
src/client/idb.js
Normal file
|
|
@ -0,0 +1,62 @@
|
||||||
|
import EventEmitter from 'events';
|
||||||
|
import HookEvent from './hook.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @typedef {import('./index').default} Ultraviolet
|
||||||
|
*/
|
||||||
|
|
||||||
|
class IDBApi extends EventEmitter {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {Ultraviolet} ctx
|
||||||
|
*/
|
||||||
|
constructor(ctx) {
|
||||||
|
super();
|
||||||
|
this.ctx = ctx;
|
||||||
|
this.window = this.ctx.window;
|
||||||
|
this.IDBDatabase = this.window.IDBDatabase || {};
|
||||||
|
this.idbDatabaseProto = this.IDBDatabase.prototype || {};
|
||||||
|
this.IDBFactory = this.window.IDBFactory || {};
|
||||||
|
this.idbFactoryProto = this.IDBFactory.prototype || {};
|
||||||
|
this.open = this.idbFactoryProto.open;
|
||||||
|
}
|
||||||
|
overrideOpen() {
|
||||||
|
this.ctx.override(
|
||||||
|
this.IDBFactory.prototype,
|
||||||
|
'open',
|
||||||
|
(target, that, args) => {
|
||||||
|
if (!args.length) return target.apply(that, args);
|
||||||
|
|
||||||
|
if (!args.length) return target.apply(that, args);
|
||||||
|
const [name, version] = args;
|
||||||
|
|
||||||
|
const event = new HookEvent({ name, version }, target, that);
|
||||||
|
this.emit('idbFactoryOpen', event);
|
||||||
|
|
||||||
|
if (event.intercepted) return event.returnValue;
|
||||||
|
return event.target.call(
|
||||||
|
event.that,
|
||||||
|
event.data.name,
|
||||||
|
event.data.version
|
||||||
|
);
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
overrideName() {
|
||||||
|
this.ctx.overrideDescriptor(this.idbDatabaseProto, 'name', {
|
||||||
|
get: (target, that) => {
|
||||||
|
const event = new HookEvent(
|
||||||
|
{ value: target.call(that) },
|
||||||
|
target,
|
||||||
|
that
|
||||||
|
);
|
||||||
|
this.emit('idbFactoryName', event);
|
||||||
|
|
||||||
|
if (event.intercepted) return event.returnValue;
|
||||||
|
return event.data.value;
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default IDBApi;
|
||||||
|
|
@ -16,6 +16,7 @@ import URLApi from './url.js';
|
||||||
import EventEmitter from 'events';
|
import EventEmitter from 'events';
|
||||||
import StorageApi from './storage.js';
|
import StorageApi from './storage.js';
|
||||||
import StyleApi from './dom/style.js';
|
import StyleApi from './dom/style.js';
|
||||||
|
import IDBApi from './idb.js';
|
||||||
|
|
||||||
class UVClient extends EventEmitter {
|
class UVClient extends EventEmitter {
|
||||||
constructor(window = self, worker = !window.window) {
|
constructor(window = self, worker = !window.window) {
|
||||||
|
|
@ -43,6 +44,7 @@ class UVClient extends EventEmitter {
|
||||||
this.worker = worker;
|
this.worker = worker;
|
||||||
this.fetch = new Fetch(this);
|
this.fetch = new Fetch(this);
|
||||||
this.xhr = new Xhr(this);
|
this.xhr = new Xhr(this);
|
||||||
|
this.idb = new IDBApi(this);
|
||||||
this.history = new History(this);
|
this.history = new History(this);
|
||||||
this.element = new ElementApi(this);
|
this.element = new ElementApi(this);
|
||||||
this.node = new NodeApi(this);
|
this.node = new NodeApi(this);
|
||||||
|
|
@ -67,10 +69,19 @@ class UVClient extends EventEmitter {
|
||||||
this.worker
|
this.worker
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param {*} obj
|
||||||
|
* @param {*} prop
|
||||||
|
* @param {WrapFun} wrapper
|
||||||
|
* @param {*} construct
|
||||||
|
* @returns
|
||||||
|
*/
|
||||||
override(obj, prop, wrapper, construct) {
|
override(obj, prop, wrapper, construct) {
|
||||||
// if (!(prop in obj)) return false;
|
// if (!(prop in obj)) return false;
|
||||||
const wrapped = this.wrap(obj, prop, wrapper, construct);
|
const wrapped = this.wrap(obj, prop, wrapper, construct);
|
||||||
return (obj[prop] = wrapped);
|
obj[prop] = wrapped;
|
||||||
|
return wrapped;
|
||||||
}
|
}
|
||||||
overrideDescriptor(obj, prop, wrapObj = {}) {
|
overrideDescriptor(obj, prop, wrapObj = {}) {
|
||||||
const wrapped = this.wrapDescriptor(obj, prop, wrapObj);
|
const wrapped = this.wrapDescriptor(obj, prop, wrapObj);
|
||||||
|
|
@ -78,6 +89,19 @@ class UVClient extends EventEmitter {
|
||||||
this.nativeMethods.defineProperty(obj, prop, wrapped);
|
this.nativeMethods.defineProperty(obj, prop, wrapped);
|
||||||
return wrapped;
|
return wrapped;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
* @template {Function} [T=Function]
|
||||||
|
* @typedef {(fn: T, that: any, args: any[]) => {}} WrapFun
|
||||||
|
*/
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @template T
|
||||||
|
* @param {*} obj
|
||||||
|
* @param {*} prop
|
||||||
|
* @param {WrapFun<T>} wrap
|
||||||
|
* @param {boolean} construct
|
||||||
|
* @returns {T}
|
||||||
|
*/
|
||||||
wrap(obj, prop, wrap, construct) {
|
wrap(obj, prop, wrap, construct) {
|
||||||
const fn = obj[prop];
|
const fn = obj[prop];
|
||||||
if (!fn) return fn;
|
if (!fn) return fn;
|
||||||
|
|
|
||||||
|
|
@ -409,6 +409,17 @@ function __uvHook(window) {
|
||||||
event.data.url = __uv.rewriteUrl(event.data.url);
|
event.data.url = __uv.rewriteUrl(event.data.url);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
// IDB
|
||||||
|
client.idb.on('idbFactoryOpen', (event) => {
|
||||||
|
event.data.name = `${__uv.meta.url.origin}@${event.data.name}`;
|
||||||
|
});
|
||||||
|
|
||||||
|
client.idb.on('idbFactoryName', (event) => {
|
||||||
|
event.data.value = event.data.value.slice(
|
||||||
|
__uv.meta.url.origin.length + 1 /*the @*/
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
// History
|
// History
|
||||||
client.history.on('replaceState', (event) => {
|
client.history.on('replaceState', (event) => {
|
||||||
if (event.data.url)
|
if (event.data.url)
|
||||||
|
|
@ -1400,6 +1411,8 @@ function __uvHook(window) {
|
||||||
//client.document.overrideQuerySelector();
|
//client.document.overrideQuerySelector();
|
||||||
client.object.overrideGetPropertyNames();
|
client.object.overrideGetPropertyNames();
|
||||||
client.object.overrideGetOwnPropertyDescriptors();
|
client.object.overrideGetOwnPropertyDescriptors();
|
||||||
|
client.idb.overrideName();
|
||||||
|
client.idb.overrideOpen();
|
||||||
client.history.overridePushState();
|
client.history.overridePushState();
|
||||||
client.history.overrideReplaceState();
|
client.history.overrideReplaceState();
|
||||||
client.eventSource.overrideConstruct();
|
client.eventSource.overrideConstruct();
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue