Chromeの拡張機能(およびアプリケーション)の所有者は、マニフェストの2番目のバージョンをサポートすることを検討します。
誰かが知らない場合、ブラウザ拡張機能の開発における新しい変更と革新が発表されたのはそれほど前ではありません。
次は、
2 ページの選択的な翻訳と、サンドボックス内からテンプレートエンジンを使用する方法です。
最初に、古い拡張機能をサポートするGoogleの計画について少し説明します
*次に、マニフェストのバージョン1で古い拡張機能拡張機能とアプリケーションを呼び出します(またはバージョンをまったく使用しません)。- Chrome 21以降、マニフェストの最初のバージョンでの新しい拡張機能の作成はブロックされますが、マニフェストの古いバージョンへの既存の拡張機能の更新は許可されています。
- Chrome 23のリリース(11月初旬)で、 Webストアは古いバージョンのマニフェストを使用した拡張機能への更新がブロックされます。 Chromeは、開発用に古い拡張機能のパックとアンパックされたもののロードを停止します。
- 2013年の第1四半期 -古い拡張機能は、Webストアではなくなります。 開発者にはメールで通知されます。
- 2013年の第2四半期 -古い拡張機能はすべてWebストアから削除され、開発者に別の通知が届きます。 ただし、Chromeはマニフェストバージョン1でインストールされている拡張機能をダウンロードして実行します。
- 2013年第3四半期 -Chromeは古い拡張機能をダウンロードして実行しなくなります。
マニフェストバージョン1と2の違い
- コンテンツセキュリティポリシーは 、デフォルトで
`script-src 'self'; object-src 'self'に設定されています`script-src 'self'; object-src 'self' `script-src 'self'; object-src 'self' 。 これは本質的に最も重要なアップデートです。 彼については少し後で。 - すべての拡張リソースは、URL
chrome-extension://[PACKAGE ID]/[PATH]で使用できなくなりましたchrome-extension://[PACKAGE ID]/[PATH] 。 つまり 拡張機能自体を除き、他のページから拡張機能のスクリプトまたは画像を接続することはできません。 しかし、この欠点を回避するために、 web_accessible_resourcesプロパティweb_accessible_resourcesしました。このプロパティでweb_accessible_resources 、必要なリソースへのパスを含む配列を指定できます。 background_pageプロパティ(文字列)の代わりに、 scriptsまたはpageプロパティを持つオブジェクトを含むbackground書き込むbackgroundになりました。- ブラウザーアクションの変更:
browser_actionsフィールドはbrowser_actionに置き換えられ、 chrome.browserActions APIはchrome.browserAction chrome.browserActions chrome.browserAction 。browser_actionからiconsプロパティをbrowser_action 。 代わりに、 default_iconまたはchrome.browserAction.setIcon使用してchrome.browserAction.setIcon 。browser_actionからnameプロパティをbrowser_action 。 代わりに、 default_titleまたはchrome.browserAction.setTitle使用してchrome.browserAction.setTitle 。browser_actionからpopupプロパティをbrowser_action 。 代わりに、 default_popupまたはchrome.browserAction.setPopup使用してchrome.browserAction.setPopup 。browser_actionのdefault_popupプロパティはオブジェクトではなく文字列でなければなりません
- ページアクションの変更:
page_actionsフィールドはpage_actionに置き換えられ、 chrome.pageActions APIはchrome.pageAction chrome.pageActions chrome.pageAction 。page_actionからiconsプロパティをpage_action 。 代わりに、 default_iconまたはchrome.pageAction.setIcon使用してchrome.pageAction.setIcon 。page_actionからnameプロパティをpage_action 。 代わりに、 default_titleまたはchrome.pageAction.setTitle使用してchrome.pageAction.setTitle 。page_actionからpopupプロパティをpage_action 。 代わりに、 default_popupまたはchrome.pageAction.setPopup使用してchrome.pageAction.setPopup 。page_actionのdefault_popupプロパティは、オブジェクトではなく文字列である必要があります。- APIから
chrome.selfを削除しchrome.self 。現在はchrome.extensionを使用する必要があります。
chrome.extension.getTabContentsesとchrome.extension.getExtensionTabsもうchrome.extension.getTabContentsesありません。 代わりに、 chrome.extension.getViews({ "type": "tab" })ます。
Port.tab代わりにPort.tab使用しPort.sender 。
拡張機能がXSS脆弱性の影響を受けにくくするために、CSPの一般原則が実装されています。 一般に、CSPは、拡張機能によってロードおよび実行されるリソースのホワイトリストおよびブラックリストメカニズムです。 CSPを使用すると、拡張機能に必要な権限のみを設定して、セキュリティを強化できます。
このポリシーは、
ホストのアクセス許可に対する追加の保護層です。
manifest.json文字列パラメーター
content_security_policyでセキュリティポリシーを設定できます。
マニフェストバージョン(
manifest_version )がインストールされていない場合、デフォルトではコンテンツセキュリティポリシーはありません。 ただし、マニフェストの2番目のバージョンでは、デフォルトで
script-src 'self'; object-src 'self'値でインストールされます
script-src 'self'; object-src 'self' script-src 'self'; object-src 'self' 。 したがって、いくつかの制限があります。 たとえば、
eval関数は実行されません。 また、インライン
(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }は実行されません
(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } } (). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }
(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } } (). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }
(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }
(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }
(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } } (). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }
(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } } (). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }
(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } } (). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }
(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } } (). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }
(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }(). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } } (). - setTimeout setInterval , .
, ( CDN, ), .
. (, https). content_security_policy , :
{ ..., "content_security_policy": "script-src 'self' https://example.com; object-src 'self'", ... }
“ eval?” “ ?”
- eval? (, new Function() ). ( sandbox ).
, (, eval) ( CSP ).
postMessage() .
underscore
sandboxed/template-renderer.html
template-renderer.html <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>Sandboxed Template Renderer</title> <script src="/js/libs/underscore/underscore-min.js"></script> </head> <body> <script> var templates = {}; window.addEventListener('message', function (event) { var template; if (typeof templates[event.data.templateName] == 'undefined') { template = _.template(event.data.template); templates[event.data.templateName] = template; } else { template = templates[event.data.templateName]; } event.source.postMessage({ id: event.data.id, result: template(event.data.context) }, event.origin); }); </script> </html>
html
{ ..., "sandbox": { "pages": ["sandboxed/template-renderer.html"] }, ... }
function getTemplate var getTemplate = (function(){ var iframe = document.createElement('iframe'), callbacks = []; iframe.src = 'sandboxed/template-renderer.html'; iframe.style.display = 'none'; document.body.appendChild(iframe); window.addEventListener('message', function (event) { callbacks.forEach(function (item, idx) { if (item && item.id == event.data.id) { item.callback(event.data.result); delete callbacks[idx]; } }); }); return function (templateName, template) { return function (context, callback) { var id = Math.random(); callbacks.push({ id: id, callback: callback }); iframe.contentWindow.postMessage({ id: id, templateName: templateName, template: template, context: context }, '*'); }; }; }());
// , var template = getTemplate('templateId', templateContent); // - template({text: 'Hello world'}, function (html) { // html // $('body').html , // $('body').html(html); });
- . (). .
, manifest.json :
manifest.json { "name": "Twittext", "description": "A lightweight Google Chrome extension for Twitter", "background": { "page": "background.html" }, "manifest_version": 2, "browser_action": { "default_icon": "img/icon_19.png", "default_title": "Twittext", "default_popup": "popup.html" }, "icons": { "128": "img/icon_128.png", "19": "img/icon_19.png", "48": "img/icon_48.png" }, "options_page": "options.html", "version": "1.6.1", "permissions": [ "tabs", "background", "https://api.twitter.com/", "https://userstream.twitter.com/" ], "sandbox": { "pages": ["sandboxed/template-renderer.html"] } }