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

相關問題