2

我试图整合sql.js(基于JS的SQLite https://github.com/kripken/sql.js/)到我的Chrome应用程序,但因为我启动我的应用程序,控制台显示以下错误:使用SQLite Chrome打包应用程序?

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:". 

我的清单文件看起来是这样的:

{ 
    "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" 
} 

回答

3

@MarcRochkind我想一些知识添加到您的书在Chrome应用集成SQL.js

这很可能只需很少的努力(考虑到政策和规则的服从)。

为了任何使用eval整合,需要沙箱脚本的特定部分。在SQL.js的情况下,它是整个库。

这可以通过在主要.html文档中需要设置的iframe来完成,该文档被称为创建(或主)窗口,例如, chrome.app.window.create('index-app.html', { ..

主文档和iframe之间的通信基地将使用postMessage发送和接收消息。

比方说,这个iframe的来源被称为/iframes/sqljs-sandboxed.html。 在manifest.json中,您需要指定sqljs-sandboxed.html作为沙箱。指定的沙箱可以运行evaleval样构建,如new Function

{ 
    "manifest_version": 1, 
    "name": "SQL.js Test", 
    .. 
    "sandbox": { 
    "pages": [ 
     "iframes/sqljs-sandboxed.html", 
    ] 
    } 
} 

sqljs-sandboxed.html使用一个事件监听器上message类型的事件作出反应。在这里,您可以简单地添加逻辑(为了简单起见,我使用了switch语句)来执行任何使用SQL.js构造的任何内容。

sqljs-sandboxed.html内容为例:

<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> 

测试数据库中创建只有一次,事件侦听器镜使用一个简单的开关的API。这意味着为了使用SQL.js,您需要针对API编写代码。这可能乍一看有点不舒服,但从本质上讲,这个想法在实施REST服务时是等同的,在我看来,这从长远来看非常舒适。

为了发送请求,index-app.html是发起者。需要指出的是,可以异步地向iframe 发出多个请求。为了防止交叉,每个请求都以唯一标识符的形式发送一个状态参数(在我的例子中是unique-ish)。同时在message事件中附加了一个监听器,该事件筛选出所需的响应并触发其指定的回调,如果触发,则将其从事件堆栈中移除。

对于快速演示,会创建一个对象,用于自动附加和拆除message事件。最终,listen函数最终应该过滤特定的字符串值,例如, sandbox === 'sql.js'(在此示例中未实现),以便加速使用多个沙箱化iframe(例如,用于模板化的handlebars.js)时可能发生的多个message事件的筛选器选择。

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'); 

}); 

为了简单起见,我使用超时来防止在加载iframe之前发送请求。根据我的经验,最好让iframe发送一条消息给iframe加载的父文档,从这里开始,您可以开始使用SQL.js.

最后,在index-app.html您指定的iframe

<iframe src="/iframes/sqljs-sandboxed.html" id="sqljs-sandbox"></iframe> 

index-app.html的内容可以是

<!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> 
+0

虽然现在我已经切换到node-webkit,因为它扩大了使用节点模块的更多选项的访问权限,但仍然提供的信息看起来非常合理,并且肯定会尝试上述解决方案! – Ric 2015-05-12 09:47:18

1
  1. “content_security_policy”不是Chrome应用的文件清单属性。

  2. 据我所知,sql.js是无法与Chrome兼容应用程序,因为你的错误消息指示。

  3. SQLite的,网络SQL的一个变体,是专门记录为不与Chrome应用工作。

  4. IndexedDB可以与Chrome应用程序一起使用,但是(a)不是基于SQL的;(b)它的实用程序有限,因为它是沙箱化的,其他应用程序无法看到数据,甚至没有其他Chrome应用程序可见。

  5. 你提到的“Chrome封装应用程序”可能意味着你的想法遗产“打包应用程序”,这在较新的Chrome应用不同的规则进行操作的。但是,打包的应用程序不再受Google支持,不应开发。也许您正在查看包应用程序的文档或示例,而不是Chrome应用程序。

+0

参照你的答案,我刚刚看了一下包装应用和Chrome应用程序,其实我使用官方文档编写Chrome应用程序。我的情景是,我需要创建一个桌面应用程序,我需要持久数据源,可以脱机访问并支持大多数SQL功能,如连接,聚合等。那么最好的选择是什么? – Ric 2014-11-25 15:42:48

+0

在编写我的书的过程中,我已经深入研究了这个问题,并且没有像Chrome应用程序那样的数据库解决方案。鉴于您的数据库要求,您必须寻找其他技术,例如Java或编写本地应用程序,可以使用像wxWidgets这样的可移植工具包。 – 2014-11-25 16:20:05

相关问题