Accessing an indexedDB from code inside a Blob
First I have to explain the scenario:
- Kiosk internet app with CHROMIUM showing LOCAL webs. That is, the web server is not installed. Chrome always shows "file: ///" pages.
- Reason: Sometimes the computer might be offline (network problems, wifi range ...).
- Requirement: We want to use Google Analytics. When the computer is ONLINE, the system sends an HTTP request to GA normally. When OFFLINE, we want to store the http request in indexedDB.
- Using a worker completing a task every X seconds, we check the internet connection. If successful, the worker receives http requests saved in indexedDB and sent to Google Analytics.
We have achieved all steps but one: accesing indexedDB of javascript code inside the Blob .
The reason for using js Worker inside Blob is because Chrome does not allow access to javascript files when the script is local (File: ///). This is a small example of a worker inside a Blob that receives an indexedDb every 3 seconds. For example, the example works fine in Firefox. But in Chrome this exception is thrown when code is executed, accessing indexedDb from BLOB code:
Unhandled rejection: OpenFailedError: SecurityError Failed to execute 'open' in 'IDBFactory': Access to the indexed database API in this context is denied.
<html>
<head>
<title>Example error blob and indexeddb</title>
</head>
<body>
<p>This example demostrate that javascript code inside a Blob can't access indexedDb in Chrome.</p>
<p>Click 'Start WebWorker' to create a Worker inside a Blob. This worker tries to insert some<br>
data into a database created in 'startWorker()' function.</p>
<button type="button" onclick="startWorker()" id="btnStart">
Start WebWorker
</button>
<button type="button" onclick="stopWorker()" id="btnStop">
Stop WebWorker
</button>
<!-- FOR LOGGING INFO PURPOSES -->
<p id="demo"></p>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<!-- TRICK !! Declare this block of type 'javascript/worker' or something non-standard.
Later we can create on the fly javascript executable code
using a Blob (see 'window.onload' function later on this file)
-->
<script id="worker" type="javascript/worker">
var started = false;
var timer;
onmessage = function (event)
{
var orden = event.data.toString();
switch (orden)
{
case 'start':
start();
break;
case 'stop':
stop();
break;
default:
notRecognized(orden);
break;
}
}
function start()
{
if( ! started)
{
timer = setInterval(function(){ job() }, 3000);
started = true;
}
}
function stop()
{
if(started)
{
clearInterval(timer);
started = false;
}
}
//Executed each 3 seconds (see start() )
function job()
{
// Open the database -> ERROR!! Uncaught SecurityError: Failed to execute 'open' on 'IDBFactory':
// access to the Indexed Database API is denied in this context.
var open = indexedDB.open("MyDatabase", 1);
open.onsuccess = function()
{
// Start a new transaction
var db = open.result;
var tx = db.transaction("MyObjectStore", "readwrite");
var store = tx.objectStore("MyObjectStore");
var index = store.index("NameIndex");
// Add some data
store.put({id: 12345, name: {first: "John", last: "Doe"}, age: 42});
store.put({id: 67890, name: {first: "Bob", last: "Smith"}, age: 35});
// Close the db when the transaction is done
tx.oncomplete = function()
{
db.close();
};
}
}//end job()
function notRecognized(orden)
{
var mensaje = 'Comando no reconocido';
selt.postMessage(mensaje + ': ' + orden);
}
</script>
<script type="text/javascript">
var myWorker;
var workerStarted = false;
//Al cargar la pagina, se llama al onload, que carga el WebWorker
window.onload = function () {
var blob = new Blob([ document.querySelector('#worker').textContent ], {type : 'text/javascript'});
myWorker = new Worker(window.URL.createObjectURL(blob));
myWorker.onmessage = function (event)
{
document.getElementById("demo").textContent = event.data; //cambiamos el texto del <p>
console.log("Got: " + event.data + "\n");
};
myWorker.onerror = function (error)
{
document.getElementById("demo").textContent = "Worker error: " + error.message;
console.log("Worker error: " + error.message + "\n");
throw error;
};
};//e onload
//click en botón iniciar, mandamos 'start' al worker
function startWorker()
{
if(workerStarted)
{
document.getElementById("demo").textContent = "Worker yet started !";
return;
}
//Create the DataBase
var indexedDB = window.indexedDB || window.mozIndexedDB || window.webkitIndexedDB || window.msIndexedDB || window.shimIndexedDB;
// Open (or create) the database
var open = indexedDB.open("MyDatabase", 1);
// Create the schema
open.onupgradeneeded = function() {
var db = open.result;
var store = db.createObjectStore("MyObjectStore", {keyPath: "id"});
var index = store.createIndex("NameIndex", ["name.last", "name.first"]);
};
workerStarted = true;
//Start Worker
myWorker.postMessage('start');
}
//click en botón parar, mandamos 'stop' al worker
function stopWorker() {
myWorker.postMessage('stop');
}
</script>
</body>
</html>
+3
source to share
No one has answered this question yet
See similar questions:
or similar: