使用SQLite Chrome浏览器打包应用程序? [英] Chrome Packaged App with SQLite?
问题描述
我试图整合 sql.js
(基于JS的SQLite https://github.com/kripken/sql.js/ )到我的Chrome应用程序中,但当我启动我的应用程序时,控制台显示以下错误:
拒绝将字符串评估为JavaScript,因为'unsafe-eval'不是下列内容安全策略指令中允许的脚本源:default-src'self'chrome -extension资源。请注意,'script-src'没有明确设置,所以'default-src'被用作后备。
Uncaught EvalError:拒绝评估字符串为JavaScript,因为'unsafe-eval'不是下面内容安全策略指令允许的脚本源:default-src'self'chrome-extension-resource:。
我的清单文件如下所示:
{
manifest_version:2,
name:Chrome App,
description:这是测试程序! !,
版本:1,
图标:{
128:icon_128.png
},
权限 :[storage],
app:{
background:{
scripts:[background.js]
},
content_security_policy:script-src'self''unsafe-eval'; object-src'self'
},
minimum_chrome_version:28
}
@MarcRochkind我想为您的书添加一些知识, Chrome应用中的href =https://github.com/kripken/sql.js/ =nofollow> SQL.js 。
非常小的努力很可能(考虑到政策和规则的服从)。
为了集成任何使用 eval
的东西,您需要对该脚本的特定部分进行沙箱。对于SQL.js,它是整个库。
这可以通过iframe来完成,该iframe需要在 .html主文件中设置
需要创建(或主要)窗口的文档,例如 chrome.app.window.create('index-app.html',{..
主文档和iframe之间的通信将使用 postMessage 发送和接收邮件。
假设这个iframe的来源被称为 /iframes/sqljs-sandboxed.html
。
在 manifest.json
您需要指定 sqljs-sandboxed.html
作为沙箱。指定的沙箱可以运行 eval
和 eval
类似于新函数
的结构
{
manifest_version:1,
name:SQL.js测试,
..
sandbox:{
pages:[
iframes / sqljs-sandboxed.html,
]
}
sqljs-sandboxed.html
使用事件侦听器对 message
类型的事件作出反应。在这里,您可以简单地添加逻辑(为了简单起见,我使用了一个switch语句)来执行任何使用SQL.js构造的任何内容。 $ b
sqljs例如:
< script src =/ vendor / kripken / sql.js>< /脚本>
< script>
(function(window,undefined){
//一个测试数据库
var db = new SQL.Database();
//用一些测试值
sqlstr =CREATE TABLE hello(a int,b char);;
sqlstr + =INSERT INTO hello VALUES(0,'hello');;
sqlstr + =INSERT INTO hello VALUES(1,'world');;
//运行查询而不返回任何内容
db.run(sqlstr);
//我们事件侦听器
window.addEventListener('message',function(event){
var params = event.data.params,
data = event.data.data,
context = {};
try {
switch(params.cmd){
case'/ do / hello':
//处理任何东西使用sql.js
var result = db.exec(SELECT * FROM hello);
//设置响应上下文
context = {
message: /办/地狱o',
hash:params.hash,
response:result
};
//向源发送一个响应(父文档)
event.source.postMessage(context,event.origin);
//为简单起见,请重新发送一个响应,以查看
//'index-app.html'中的事件是否被第二次触发(即
// shouldn' t)
setTimeout(function(){
event.source.postMessage(context,event.origin);
},'1000');
break;
}
} catch(err){
console.log(err);
}
});
})(window);
< / script>
测试数据库仅创建一次,事件侦听器使用简单的开关镜像API。这意味着为了使用SQL.js,您需要针对API编写代码。这可能乍一看有点不舒服,但从本质上讲,这个想法在实施REST服务时是等同的,在我看来,这从长远来看非常舒适。
为了发送请求, index-app.html
是发起者。指出可以异步
对于快速演示,会创建一个对象,用于自动附加和分离消息
事件。最终, listen
函数最终应该筛选特定的字符串值,例如 sandbox ==='sql.js'
(在这个例子中没有实现)为了加速许多消息的过滤器选择
使用多个沙箱化iframe时可能发生的事件(例如,用于模板化的handlebars.js)。
var sqlRequest = function(request,data,callback){
//生成唯一的消息ID
var hash = Math.random()。toString(36).substr(2),
//你可以将iframe作为id来标识
content_window = document.getElementById('sqljs-sandbox')。contentWindow,
listen = function(event){
/ /将数据附加到稍后使用的回调
this.data = event.data;
//过滤正确的响应
if(hash === this.data.hash){
//移除监听器
window.removeEventListener('message',listen,false );
//执行回调
callback.call(this);
}
};
//添加监听器
window.addEventListener('message',listen,false);
//发送一个请求到sqljs iframe
content_window.postMessage({
params:{
cmd:request,$ b $ hash:hash
},
data:data
},'*');
};
//等待准备好捕获iframe元素
document.addEventListener('DOMContentLoaded',function(){
//伪装sqljs-sandboxed.html以准备好一个超时
setTimeout(function(){
new sqlRequest('/ do / hello',{
allthedata:'您需要传递'
},function(){
console.log('sql.js'的响应);
console.log(this.data);
});
},'1000');
});
为了简单起见,我使用超时来防止请求在iframe之前发送加载。根据我的经验,最好让iframe发布一条消息给iframe加载的父文档,从这里开始,您可以开始使用SQL.js。
最后,在 index-app.html
中指定iframe
< ; iframe src =/ iframes / sqljs-sandboxed.htmlid =sqljs-sandbox>< / iframe>
其中 index-app.html
可以是
<!DOCTYPE html>
< html>
< head>
< meta charset =utf-8>
< / head>
< body>
< iframe src =/ iframes / sqljs-sandboxed.htmlid =sqljs-sandbox>< / iframe>
< h1>您好,让我们使用SQL.js!< / h1>
< script src =/ assets / js / sqljs-request.js>< / script>
< / body>
< / html>
I was trying to integrate sql.js
(JS based SQLite https://github.com/kripken/sql.js/) into my chrome app but as I launch my app, console shows the following errors:
Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src 'self' chrome-extension-resource:". Note that 'script-src' was not explicitly set, so 'default-src' is used as a fallback.
Uncaught EvalError: Refused to evaluate a string as JavaScript because 'unsafe-eval' is not an allowed source of script in the following Content Security Policy directive: "default-src 'self' chrome-extension-resource:".
My manifest file looks like this:
{
"manifest_version": 2,
"name": "Chrome App",
"description": "This is the test app!!!",
"version": "1",
"icons": {
"128": "icon_128.png"
},
"permissions": ["storage"],
"app": {
"background": {
"scripts": ["background.js"]
},
"content_security_policy": "script-src 'self' 'unsafe-eval'; object-src 'self'"
},
"minimum_chrome_version": "28"
}
@MarcRochkind I would like to add some knowledge to your book for integrating SQL.js in Chrome Apps.
It is very well possible with very little effort (considered the obedience of policies and rules).
In order to integrate anything that uses eval
, you need to sandbox that particular part of the script. In case of SQL.js, it's the entire library.
This can be done with an iframe which needs to be set in the main .html
document that's called for creating a (or the main) window, e.g. chrome.app.window.create('index-app.html', { ..
The base of communication between the main document and the iframe will be by using postMessage for sending and receiving messages.
Let's say the source of this iframe is called /iframes/sqljs-sandboxed.html
.
In the manifest.json
you need to specify sqljs-sandboxed.html
as a sandbox. A designated sandbox makes it possible to run eval
and eval
-like constructs like new Function
.
{
"manifest_version": 1,
"name": "SQL.js Test",
..
"sandbox": {
"pages": [
"iframes/sqljs-sandboxed.html",
]
}
}
The sqljs-sandboxed.html
uses an event listener to react on an event of type message
. Here you can simply add logic (for simplicity sake I used a switch statement) to do anything structured with SQL.js.
The content of sqljs-sandboxed.html
as an example:
<script src="/vendor/kripken/sql.js"></script>
<script>
(function(window, undefined) {
// a test database
var db = new SQL.Database();
// create a table with some test values
sqlstr = "CREATE TABLE hello (a int, b char);";
sqlstr += "INSERT INTO hello VALUES (0, 'hello');";
sqlstr += "INSERT INTO hello VALUES (1, 'world');";
// run the query without returning anything
db.run(sqlstr);
// our event listener for message
window.addEventListener('message', function(event) {
var params = event.data.params,
data = event.data.data,
context = {};
try {
switch(params.cmd) {
case '/do/hello':
// process anything with sql.js
var result = db.exec("SELECT * FROM hello");
// set the response context
context = {
message: '/do/hello',
hash: params.hash,
response: result
};
// send a response to the source (parent document)
event.source.postMessage(context, event.origin);
// for simplicity, resend a response to see if event in
// 'index-app.html' gets triggered a second time (which it
// shouldn't)
setTimeout(function() {
event.source.postMessage(context, event.origin);
}, '1000');
break;
}
} catch(err) {
console.log(err);
}
});
})(window);
</script>
A test database is created only once and the event listener mirrors an API using a simple switch. This means in order to use SQL.js you need to write against an API. This might be at, first glance, a little uncomfortable but in plain sense the idea is equivalent when implementing a REST service, which is, in my opinion, very comfortable in the long run.
In order to send requests, the index-app.html
is the initiator. It's important to point out that multiple requests can be made to the iframe asynchronously. To prevent cross-fire, a state parameter is send with each request in the form of an unique-identifier (in my example unique-ish). At the same time a listener is attached on the message
event which filters out the desired response and triggers its designated callback, and if triggered, removes it from the event stack.
For a fast demo, an object is created which automates attachment and detachment of the message
event. Ultimately the listen
function should eventually filter on a specific string value, e.g. sandbox === 'sql.js'
(not implemented in this example) in order to speed up the filter selection for the many message
events that can take place when using multiple iframes that are sandboxed (e.g. handlebars.js for templating).
var sqlRequest = function(request, data, callback) {
// generate unique message id
var hash = Math.random().toString(36).substr(2),
// you can id the iframe as wished
content_window = document.getElementById('sqljs-sandbox').contentWindow,
listen = function(event) {
// attach data to the callback to be used later
this.data = event.data;
// filter the correct response
if(hash === this.data.hash) {
// remove listener
window.removeEventListener('message', listen, false);
// execute callback
callback.call(this);
}
};
// add listener
window.addEventListener('message', listen, false);
// post a request to the sqljs iframe
content_window.postMessage({
params: {
cmd: request,
hash: hash
},
data: data
}, '*');
};
// wait for readiness to catch the iframes element
document.addEventListener('DOMContentLoaded', function() {
// faking sqljs-sandboxed.html to be ready with a timeout
setTimeout(function() {
new sqlRequest('/do/hello', {
allthedata: 'you need to pass'
}, function() {
console.log('response from sql.js');
console.log(this.data);
});
}, '1000');
});
For simplicity, I'm using a timeout to prevent that the request is being send before the iframe was loaded. From my experience, it's best practice to let the iframe post a message to it's parent document that the iframe is loaded, from here on you can start using SQL.js.
Finally, in index-app.html
you specify the iframe
<iframe src="/iframes/sqljs-sandboxed.html" id="sqljs-sandbox"></iframe>
Where the content of index-app.html
could be
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
</head>
<body>
<iframe src="/iframes/sqljs-sandboxed.html" id="sqljs-sandbox"></iframe>
<h1>Hello, let's code with SQL.js!</h1>
<script src="/assets/js/sqljs-request.js"></script>
</body>
</html>
这篇关于使用SQLite Chrome浏览器打包应用程序?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!