promisify DB access
This commit is contained in:
		
							parent
							
								
									02fd4f1abe
								
							
						
					
					
						commit
						acc4d83b9d
					
				|  | @ -1,4 +1,4 @@ | ||||||
| /* global getDatabase, getStyles, saveStyle */ | /* global dbExec, getStyles, saveStyle */ | ||||||
| 'use strict'; | 'use strict'; | ||||||
| 
 | 
 | ||||||
| // eslint-disable-next-line no-var
 | // eslint-disable-next-line no-var
 | ||||||
|  | @ -6,7 +6,7 @@ var browserCommands, contextMenus; | ||||||
| 
 | 
 | ||||||
| // *************************************************************************
 | // *************************************************************************
 | ||||||
| // preload the DB and report errors
 | // preload the DB and report errors
 | ||||||
| getDatabase(() => {}, (...args) => { | dbExec().catch((...args) => { | ||||||
|   args.forEach(arg => 'message' in arg && console.error(arg.message)); |   args.forEach(arg => 'message' in arg && console.error(arg.message)); | ||||||
| }); | }); | ||||||
| 
 | 
 | ||||||
|  | @ -183,7 +183,7 @@ prefs.subscribe((id, checked) => { | ||||||
| // *************************************************************************
 | // *************************************************************************
 | ||||||
| 
 | 
 | ||||||
| function webNavigationListener(method, {url, tabId, frameId}) { | function webNavigationListener(method, {url, tabId, frameId}) { | ||||||
|   getStyles({matchUrl: url, enabled: true, asHash: true}, styles => { |   getStyles({matchUrl: url, enabled: true, asHash: true}).then(styles => { | ||||||
|     if (method && !url.startsWith('chrome:') && tabId >= 0) { |     if (method && !url.startsWith('chrome:') && tabId >= 0) { | ||||||
|       chrome.tabs.sendMessage(tabId, { |       chrome.tabs.sendMessage(tabId, { | ||||||
|         method, |         method, | ||||||
|  | @ -209,9 +209,9 @@ function updateIcon(tab, styles) { | ||||||
|     stylesReceived(styles); |     stylesReceived(styles); | ||||||
|     return; |     return; | ||||||
|   } |   } | ||||||
|   getTabRealURL(tab).then(url => |   getTabRealURL(tab) | ||||||
|     getStyles({matchUrl: url, enabled: true, asHash: true}, |     .then(url => getStyles({matchUrl: url, enabled: true, asHash: true})) | ||||||
|       stylesReceived)); |     .then(stylesReceived); | ||||||
| 
 | 
 | ||||||
|   function stylesReceived(styles) { |   function stylesReceived(styles) { | ||||||
|     let numStyles = styles.length; |     let numStyles = styles.length; | ||||||
|  | @ -255,7 +255,7 @@ function onRuntimeMessage(request, sender, sendResponse) { | ||||||
|   switch (request.method) { |   switch (request.method) { | ||||||
| 
 | 
 | ||||||
|     case 'getStyles': |     case 'getStyles': | ||||||
|       getStyles(request, sendResponse); |       getStyles(request).then(sendResponse); | ||||||
|       return KEEP_CHANNEL_OPEN; |       return KEEP_CHANNEL_OPEN; | ||||||
| 
 | 
 | ||||||
|     case 'saveStyle': |     case 'saveStyle': | ||||||
|  | @ -263,9 +263,9 @@ function onRuntimeMessage(request, sender, sendResponse) { | ||||||
|       return KEEP_CHANNEL_OPEN; |       return KEEP_CHANNEL_OPEN; | ||||||
| 
 | 
 | ||||||
|     case 'healthCheck': |     case 'healthCheck': | ||||||
|       getDatabase( |       dbExec() | ||||||
|         () => sendResponse(true), |         .then(() => sendResponse(true)) | ||||||
|         () => sendResponse(false)); |         .catch(() => sendResponse(false)); | ||||||
|       return KEEP_CHANNEL_OPEN; |       return KEEP_CHANNEL_OPEN; | ||||||
| 
 | 
 | ||||||
|     case 'download': |     case 'download': | ||||||
|  |  | ||||||
							
								
								
									
										23
									
								
								messaging.js
									
									
									
									
									
								
							
							
						
						
									
										23
									
								
								messaging.js
									
									
									
									
									
								
							|  | @ -268,13 +268,13 @@ function sessionStorageHash(name) { | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| function onBackgroundReady() { | function onBackgroundReady(...dataPassthru) { | ||||||
|   return BG ? Promise.resolve() : new Promise(ping); |   return BG ? Promise.resolve(...dataPassthru) : new Promise(ping); | ||||||
|   function ping(resolve) { |   function ping(resolve) { | ||||||
|     chrome.runtime.sendMessage({method: 'healthCheck'}, health => { |     chrome.runtime.sendMessage({method: 'healthCheck'}, health => { | ||||||
|       if (health !== undefined) { |       if (health !== undefined) { | ||||||
|         BG = chrome.extension.getBackgroundPage(); |         BG = chrome.extension.getBackgroundPage(); | ||||||
|         resolve(); |         resolve(...dataPassthru); | ||||||
|       } else { |       } else { | ||||||
|         ping(resolve); |         ping(resolve); | ||||||
|       } |       } | ||||||
|  | @ -285,20 +285,13 @@ function onBackgroundReady() { | ||||||
| 
 | 
 | ||||||
| // in case Chrome haven't yet loaded the bg page and displays our page like edit/manage
 | // in case Chrome haven't yet loaded the bg page and displays our page like edit/manage
 | ||||||
| function getStylesSafe(options) { | function getStylesSafe(options) { | ||||||
|   return new Promise(resolve => { |   return onBackgroundReady(options).then(BG.getStyles); | ||||||
|     if (BG) { |  | ||||||
|       BG.getStyles(options, resolve); |  | ||||||
|     } else { |  | ||||||
|       onBackgroundReady().then(() => |  | ||||||
|         BG.getStyles(options, resolve)); |  | ||||||
|     } |  | ||||||
|   }); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| function saveStyleSafe(style) { | function saveStyleSafe(style) { | ||||||
|   return onBackgroundReady() |   return onBackgroundReady(BG.deepCopy(style)) | ||||||
|     .then(() => BG.saveStyle(BG.deepCopy(style))) |     .then(BG.saveStyle) | ||||||
|     .then(savedStyle => { |     .then(savedStyle => { | ||||||
|       if (style.notify === false) { |       if (style.notify === false) { | ||||||
|         handleUpdate(savedStyle, style); |         handleUpdate(savedStyle, style); | ||||||
|  | @ -309,8 +302,8 @@ function saveStyleSafe(style) { | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| function deleteStyleSafe({id, notify = true} = {}) { | function deleteStyleSafe({id, notify = true} = {}) { | ||||||
|   return onBackgroundReady() |   return onBackgroundReady({id, notify}) | ||||||
|     .then(() => BG.deleteStyle({id, notify})) |     .then(BG.deleteStyle) | ||||||
|     .then(() => { |     .then(() => { | ||||||
|       if (!notify) { |       if (!notify) { | ||||||
|         handleDelete(id); |         handleDelete(id); | ||||||
|  |  | ||||||
							
								
								
									
										236
									
								
								storage.js
									
									
									
									
									
								
							
							
						
						
									
										236
									
								
								storage.js
									
									
									
									
									
								
							|  | @ -43,58 +43,69 @@ var chromeLocal = { | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| function getDatabase(ready, error) { | function dbExec(method, data) { | ||||||
|   const dbOpenRequest = window.indexedDB.open('stylish', 2); |   return new Promise((resolve, reject) => { | ||||||
|   dbOpenRequest.onsuccess = event => { |     Object.assign(indexedDB.open('stylish', 2), { | ||||||
|     ready(event.target.result); |       onsuccess(event) { | ||||||
|   }; |         const database = event.target.result; | ||||||
|   dbOpenRequest.onerror = event => { |         if (!method) { | ||||||
|     console.warn(event.target.errorCode); |           resolve(database); | ||||||
|     if (error) { |         } else { | ||||||
|       error(event); |           const transaction = database.transaction(['styles'], 'readwrite'); | ||||||
|     } |           const store = transaction.objectStore('styles'); | ||||||
|   }; |           Object.assign(store[method](data), { | ||||||
|   dbOpenRequest.onupgradeneeded = event => { |             onsuccess: event => resolve(event, store, transaction, database), | ||||||
|     if (event.oldVersion == 0) { |             onerror: reject, | ||||||
|       event.target.result.createObjectStore('styles', { |           }); | ||||||
|         keyPath: 'id', |         } | ||||||
|         autoIncrement: true, |       }, | ||||||
|       }); |       onerror(event) { | ||||||
|     } |         console.warn(event.target.errorCode); | ||||||
|   }; |         reject(event); | ||||||
|  |       }, | ||||||
|  |       onupgradeneeded(event) { | ||||||
|  |         if (event.oldVersion == 0) { | ||||||
|  |           event.target.result.createObjectStore('styles', { | ||||||
|  |             keyPath: 'id', | ||||||
|  |             autoIncrement: true, | ||||||
|  |           }); | ||||||
|  |         } | ||||||
|  |       }, | ||||||
|  |     }); | ||||||
|  |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| function getStyles(options, callback) { | function getStyles(options) { | ||||||
|   if (cachedStyles.list) { |   if (cachedStyles.list) { | ||||||
|     callback(filterStyles(options)); |     return Promise.resolve(filterStyles(options)); | ||||||
|     return; |  | ||||||
|   } |   } | ||||||
|   if (cachedStyles.mutex.inProgress) { |   if (cachedStyles.mutex.inProgress) { | ||||||
|     cachedStyles.mutex.onDone.push({options, callback}); |     return new Promise(resolve => { | ||||||
|     return; |       cachedStyles.mutex.onDone.push({options, resolve}); | ||||||
|  |     }); | ||||||
|   } |   } | ||||||
|   cachedStyles.mutex.inProgress = true; |   cachedStyles.mutex.inProgress = true; | ||||||
| 
 | 
 | ||||||
|   getDatabase(db => { |   return dbExec('getAll').then(event => { | ||||||
|     const tx = db.transaction(['styles'], 'readonly'); |     cachedStyles.list = event.target.result || []; | ||||||
|     const os = tx.objectStore('styles'); |     cachedStyles.byId.clear(); | ||||||
|     os.getAll().onsuccess = event => { |     const t0 = performance.now(); | ||||||
|       cachedStyles.list = event.target.result || []; |     let hasTimeToCompile = true; | ||||||
|       cachedStyles.byId.clear(); |     for (const style of cachedStyles.list) { | ||||||
|       for (const style of cachedStyles.list) { |       cachedStyles.byId.set(style.id, style); | ||||||
|         cachedStyles.byId.set(style.id, style); |       if (hasTimeToCompile) { | ||||||
|         compileStyleRegExps({style}); |         hasTimeToCompile = !compileStyleRegExps({style}) || performance.now() - t0 > 100; | ||||||
|       } |       } | ||||||
|       callback(filterStyles(options)); |     } | ||||||
| 
 | 
 | ||||||
|       cachedStyles.mutex.inProgress = false; |     cachedStyles.mutex.inProgress = false; | ||||||
|       for (const {options, callback} of cachedStyles.mutex.onDone) { |     for (const {options, resolve} of cachedStyles.mutex.onDone) { | ||||||
|         callback(filterStyles(options)); |       resolve(filterStyles(options)); | ||||||
|       } |     } | ||||||
|       cachedStyles.mutex.onDone = []; |     cachedStyles.mutex.onDone = []; | ||||||
|     }; |     return filterStyles(options); | ||||||
|   }, null); |   }); | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -213,83 +224,81 @@ function filterStylesInternal({ | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| function saveStyle(style) { | function saveStyle(style) { | ||||||
|   return new Promise(resolve => { |   const id = Number(style.id) >= 0 ? Number(style.id) : null; | ||||||
|     getDatabase(db => { |   const reason = style.reason; | ||||||
|       const tx = db.transaction(['styles'], 'readwrite'); |   const notify = style.notify !== false; | ||||||
|       const os = tx.objectStore('styles'); |   delete style.method; | ||||||
| 
 |   delete style.reason; | ||||||
|       const id = style.id == '0' ? 0 : Number(style.id) || null; |   delete style.notify; | ||||||
|       const reason = style.reason; |   if (!style.name) { | ||||||
|       const notify = style.notify !== false; |     delete style.name; | ||||||
|       delete style.method; |   } | ||||||
|       delete style.reason; |   let existed, codeIsUpdated; | ||||||
|       delete style.notify; |   if (id !== null) { | ||||||
|       if (!style.name) { |     // Update or create
 | ||||||
|         delete style.name; |     style.id = id; | ||||||
|       } |     return dbExec('get', id).then((event, store) => { | ||||||
|       let existed, codeIsUpdated; |       const oldStyle = event.target.result; | ||||||
| 
 |       existed = Boolean(oldStyle); | ||||||
|       if (id !== null) { |       codeIsUpdated = !existed || style.sections && !styleSectionsEqual(style, oldStyle); | ||||||
|         // Update or create
 |       style = Object.assign({}, oldStyle, style); | ||||||
|         style.id = id; |       return write(style, store); | ||||||
|         os.get(id).onsuccess = eventGet => { |  | ||||||
|           const oldStyle = eventGet.target.result; |  | ||||||
|           existed = Boolean(oldStyle); |  | ||||||
|           codeIsUpdated = !existed || style.sections && !styleSectionsEqual(style, oldStyle); |  | ||||||
|           write(Object.assign({}, oldStyle, style)); |  | ||||||
|         }; |  | ||||||
|       } else { |  | ||||||
|         // Create
 |  | ||||||
|         delete style.id; |  | ||||||
|         write(Object.assign({ |  | ||||||
|           // Set optional things if they're undefined
 |  | ||||||
|           enabled: true, |  | ||||||
|           updateUrl: null, |  | ||||||
|           md5Url: null, |  | ||||||
|           url: null, |  | ||||||
|           originalMd5: null, |  | ||||||
|         }, style)); |  | ||||||
|       } |  | ||||||
| 
 |  | ||||||
|       function write(style) { |  | ||||||
|         style.sections = normalizeStyleSections(style); |  | ||||||
|         os.put(style).onsuccess = event => { |  | ||||||
|           style.id = style.id || event.target.result; |  | ||||||
|           invalidateCache(existed ? {updated: style} : {added: style}); |  | ||||||
|           compileStyleRegExps({style}); |  | ||||||
|           if (notify) { |  | ||||||
|             notifyAllTabs({ |  | ||||||
|               method: existed ? 'styleUpdated' : 'styleAdded', |  | ||||||
|               style, codeIsUpdated, reason, |  | ||||||
|             }); |  | ||||||
|           } |  | ||||||
|           if (reason == 'update') { |  | ||||||
|             updateStyleDigest(style); |  | ||||||
|           } else if (reason == 'import') { |  | ||||||
|             chrome.storage.local.remove(DIGEST_KEY_PREFIX + style.id, ignoreChromeError); |  | ||||||
|           } |  | ||||||
|           resolve(style); |  | ||||||
|         }; |  | ||||||
|       } |  | ||||||
|     }); |     }); | ||||||
|   }); |   } else { | ||||||
|  |     // Create
 | ||||||
|  |     delete style.id; | ||||||
|  |     style = Object.assign({ | ||||||
|  |       // Set optional things if they're undefined
 | ||||||
|  |       enabled: true, | ||||||
|  |       updateUrl: null, | ||||||
|  |       md5Url: null, | ||||||
|  |       url: null, | ||||||
|  |       originalMd5: null, | ||||||
|  |     }, style); | ||||||
|  |     return write(style); | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function write(style, store) { | ||||||
|  |     style.sections = normalizeStyleSections(style); | ||||||
|  |     if (store) { | ||||||
|  |       return new Promise(resolve => { | ||||||
|  |         store.put(style).onsuccess = event => resolve(done(event)); | ||||||
|  |       }); | ||||||
|  |     } else { | ||||||
|  |       return dbExec('put', style).then(done); | ||||||
|  |     } | ||||||
|  |   } | ||||||
|  | 
 | ||||||
|  |   function done(event) { | ||||||
|  |     style.id = style.id || event.target.result; | ||||||
|  |     invalidateCache(existed ? {updated: style} : {added: style}); | ||||||
|  |     compileStyleRegExps({style}); | ||||||
|  |     if (notify) { | ||||||
|  |       notifyAllTabs({ | ||||||
|  |         method: existed ? 'styleUpdated' : 'styleAdded', | ||||||
|  |         style, codeIsUpdated, reason, | ||||||
|  |       }); | ||||||
|  |     } | ||||||
|  |     if (reason == 'update') { | ||||||
|  |       updateStyleDigest(style); | ||||||
|  |     } else if (reason == 'import') { | ||||||
|  |       chrome.storage.local.remove(DIGEST_KEY_PREFIX + style.id, ignoreChromeError); | ||||||
|  |     } | ||||||
|  |     return style; | ||||||
|  |   } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| function deleteStyle({id, notify = true}) { | function deleteStyle({id, notify = true}) { | ||||||
|  |   id = Number(id); | ||||||
|   chrome.storage.local.remove(DIGEST_KEY_PREFIX + id, ignoreChromeError); |   chrome.storage.local.remove(DIGEST_KEY_PREFIX + id, ignoreChromeError); | ||||||
|   return new Promise(resolve => |   return dbExec('delete', id).then(() => { | ||||||
|     getDatabase(db => { |     invalidateCache({deletedId: id}); | ||||||
|       const tx = db.transaction(['styles'], 'readwrite'); |     if (notify) { | ||||||
|       const os = tx.objectStore('styles'); |       notifyAllTabs({method: 'styleDeleted', id}); | ||||||
|       os.delete(Number(id)).onsuccess = () => { |     } | ||||||
|         invalidateCache({deletedId: id}); |     return id; | ||||||
|         if (notify) { |   }); | ||||||
|           notifyAllTabs({method: 'styleDeleted', id}); |  | ||||||
|         } |  | ||||||
|         resolve(id); |  | ||||||
|       }; |  | ||||||
|     })); |  | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | @ -448,11 +457,12 @@ function compileStyleRegExps({style, compileAll}) { | ||||||
|         const rx = tryRegExp(anchored); |         const rx = tryRegExp(anchored); | ||||||
|         cachedStyles.regexps.set(cacheKey, rx || false); |         cachedStyles.regexps.set(cacheKey, rx || false); | ||||||
|         if (!compileAll && performance.now() - t0 > 100) { |         if (!compileAll && performance.now() - t0 > 100) { | ||||||
|           return; |           return false; | ||||||
|         } |         } | ||||||
|       } |       } | ||||||
|     } |     } | ||||||
|   } |   } | ||||||
|  |   return true; | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
							
								
								
									
										19
									
								
								update.js
									
									
									
									
									
								
							
							
						
						
									
										19
									
								
								update.js
									
									
									
									
									
								
							|  | @ -22,17 +22,14 @@ var updater = { | ||||||
| 
 | 
 | ||||||
|   checkAllStyles({observer = () => {}, save = true, ignoreDigest} = {}) { |   checkAllStyles({observer = () => {}, save = true, ignoreDigest} = {}) { | ||||||
|     updater.resetInterval(); |     updater.resetInterval(); | ||||||
|     return new Promise(resolve => { |     return getStyles({}).then(styles => { | ||||||
|       getStyles({}, styles => { |       styles = styles.filter(style => style.updateUrl); | ||||||
|         styles = styles.filter(style => style.updateUrl); |       observer(updater.COUNT, styles.length); | ||||||
|         observer(updater.COUNT, styles.length); |       return Promise.all( | ||||||
|         Promise.all(styles.map(style => |         styles.map(style => | ||||||
|           updater.checkStyle({style, observer, save, ignoreDigest}) |           updater.checkStyle({style, observer, save, ignoreDigest}))); | ||||||
|         )).then(() => { |     }).then(() => { | ||||||
|           observer(updater.DONE); |       observer(updater.DONE); | ||||||
|           resolve(); |  | ||||||
|         }); |  | ||||||
|       }); |  | ||||||
|     }); |     }); | ||||||
|   }, |   }, | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user