Advertisement
Advertisement

More Related Content

Advertisement

Recently uploaded(20)

Advertisement

Chrome Extensionsの基本とデザインパターン

  1. Chrome Extensionsの基本 とデザインパターン Chrome+HTML5 Developers Live Japan #1
  2. Chrome Extension 使ってますか?
  3. Chrome Extensionで 何ができるの?
  4. Browser Actions
  5. Page Actions
  6. Context Menus
  7. Desktop Notifications
  8. Options Pages
  9. Options Pages
  10. APIs alarms, bookmarks, browserAction, browsingData, commands, contentSettings, contextMenus, cookies, debugger, declarativeWebRequest, devtools.network, devtools.inspectedWindow, devtools.panels, downloads, events, extension, fileBrowserHandler, fontSettings, history, i18n, idle, input.ime, management, omnibox, pageAction, pageCapture, permissions, privacy, proxy, pushMessaging, runtime, scriptBadge, storage, tabs, topSites, tts, ttsEngine, types, webNavigation, webRequest, webstore, windows
  11. APIs
  12. Chrome Extensionは 何でできてるの?
  13. Technologies Web pages + JavaScript API
  14. Structure マニフェストファイル(manifest.json) 1つ以上のHTMLファイル (Optional) 1つ以上のJavaScriptファイル (Optional) 必要となる他のファイル - 画像ファイルなど これらをzipファイルにまとめてChromeウェブ ストアにアップロードする
  15. Minimum Extension manifest.json { "manifest_version": 2, "name": "Minimum Extension", "version": "0.0.1", "browser_action": { "default_popup": "popup.html" } }
  16. Minimum Extension popup.html <!DOCTYPE html> <html> <head></head> <body> <div>Hello, Chrome extension!</div> </body> </html>
  17. Minimum Extension
  18. Minimum Extension
  19. Minimum Extension
  20. Minimum Extension
  21. Minimum Extension
  22. オレ流 Chrome Extension デザインパターン
  23. Structure manifest.json analytics.json background.js options.html options.js popup.html popup.js
  24. My design pattern for Chrome Extension manifest.json
  25. { ... "version": "バージョン番号(XX.XX.XX形式)", "browser_action": { "default_icon": "./icon_**.png (**はサイズ)", "default_popup": "./popup.html", ... }, "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'", "background": { "scripts": [ "./jquery-min.js", "./background.js" ], "persistent": false, ... }, "options_page": "./options.html", "default_locale": "en", ... }
  26. { ... "version": "バージョン番号(XX.XX.XX形式)", "browser_action": { "default_icon": "./icon_**.png (**はサイズ)", "default_popup": "./popup.html", ... }, "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'", "background": { "scripts": [ "./jquery-min.js", "./background.js" ], "persist": false, ... }, "options_page": "./options.html", "default_locale": "en", ... } Browser/Page actionのコンテ ンツは「popup.html」という ファイル名にする
  27. { ... "version": "バージョン番号(XX.XX.XX形式)", "browser_action": { "default_icon": "./icon_**.png (**はサイズ)", "default_popup": "./popup.html", ... }, "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'", "background": { "scripts": ["./jquery-min.js","./background.js" ], "persistent": false, ... }, "options_page": "./options.html", "default_locale": "en", ... } Background Pageは必ず作成 し「background.js」というフ ァイル名とする 軽いExtensionとするために Event pageとする
  28. { ... "version": "バージョン番号(XX.XX.XX形式)", "browser_action": { "default_icon": "./icon_**.png (**はサイズ)", "default_popup": "./popup.html", ... }, "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'", "background": { "scripts": [ "./jquery-min.js", "./background.js" ], "persistent": false, ... }, "options_page": "./options.html", "default_locale": "en", ... } 設定ページが必要な場合は 「options.html」というファ イル名で作成する
  29. { ... "version": "バージョン番号(XX.XX.XX形式)", "browser_action": { "default_icon": "./icon_**.png (**はサイズ)", "default_popup": "./popup.html", ... }, "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'", "background": { "scripts": [ "./jquery-min.js", "./background.js" ], "persistent": false, ... }, "options_page": "./options.html", "default_locale": "en", ... } どんなに小さなExtensionで も国際化しておく 最低限enとjaをサポートする
  30. { ... "version": "バージョン番号(XX.XX.XX形式)", "browser_action": { "default_icon": "./icon_**.png (**はサイズ)", "default_popup": "./popup.html", ... }, "content_security_policy": "script-src 'self' https://ssl.google-analytics.com; object-src 'self'", "background": { "scripts": [ "./jquery-min.js", "./background.js" ], "persistent": false, ... }, "options_page": "./options.html", "default_locale": "en", ... } 利用状況を把握するために Google Analyticsを仕込んでおく Google Analyticsサーバと通信す るためにCSPに記載しておく
  31. Google Analytics ポリシー: 「Google Analyticsを使っていることを開示し、 トラッキングデータの収集のためにCookieが使 われていることも明記する」 ChromeウェブストアのページやExtension内に てちゃんとユーザに説明しましょう。
  32. My design pattern for Chrome Extension background.js
  33. popup.html popup.js options.html options.js background.js Backend server UI処理に専念 UI処理に専念 Ajaxでの通信 設定値出し入れ イベント処理
  34. var Background = function() { this.assignEventHandlers(); }; Background.prototype = { assignEventHandlers: function() {...}, load***: function(callbacks) {...}, get***Config: function() {...}, set***Config: function() {...} ... }; var bg = new Background();
  35. var Background = function() { this.assignEventHandlers(); }; Background.prototype = { assignEventHandlers: function() {...}, load***: function(callbacks) {...}, get***Config: function() {...}, set***Config: function() {...} ... }; var bg = new Background(); 各種イベントハンドラを登録する 処理を「assignEventHandlers()」 関数にまとめる
  36. var Background = function() { this.assignEventHandlers(); }; Background.prototype = { assignEventHandlers: function() {...}, load***: function(callbacks) {...}, get***Config: function() {...}, set***Config: function() {...} ... }; var bg = new Background(); assignEventHandlers: function() { // タブの変更監視 chrome.tab.onActivated.addListener( function(activeInfo) { ... } ); // Chromeの起動監視 chrome.runtime.onStartup.addListener( function() { // Google Analyticsに記録など _gaq.push(["_trackEvent", "..", ".."]); } ); ... },
  37. var Background = function() { this.assignEventHandlers(); }; Background.prototype = { assignEventHandlers: function() {...}, load***: function(callbacks) {...}, get***Config: function() {...}, set***Config: function() {...} ... }; var bg = new Background(); Ajax処理は「load***()」という関 数名にする Ajax処理をbackground.jsに集めて おく(Debugしやすくなるため)
  38. var Background = function() { this.assignEventHandlers(); }; Background.prototype = { assignEventHandlers: function() {...}, load***: function(callbacks) {...}, get***Config: function() {...}, set***Config: function() {...} ... }; var bg = new Background(); load***: function(callbacks) { $.ajax({ url: this.getServerUrl + "ajax/get_***" }) .done(function(data) { callbacks.onSuccess(data); }); }, getServerUrl: function() { return "http://backend.server.name/"; },
  39. var Background = function() { this.assignEventHandlers(); }; Background.prototype = { assignEventHandlers: function() {...}, load***: function(callbacks) {...}, get***Config: function() {...}, set***Config: function() {...} ... }; var bg = new Background();設定ページで設定されるような動 的な設定値の格納と取得処理も background.jsにまとめておく
  40. var Background = function() { this.assignEventHandlers(); }; Background.prototype = { assignEventHandlers: function() {...}, load***: function(callbacks) {...}, get***Config: function() {...}, set***Config: function() {...} ... }; var bg = new Background(); get***Config: function() { var value = localStorage["***"]; if (value) { return value; } else { return "初期値"; } }, set***Config: function() { localStorage["***"] = value; },
  41. popup.html popup.js options.html options.js background.js Backend server chrome.runtime.getBackgroundPage() でアクセス可能 Chrome DevTools
  42. My design pattern for Chrome Extension options.html
  43. Options Pages
  44. <!DOCTYPE html> <html> <head> <script type="text/javascript" src="./jquery-min.js"> <script type="text/javascript" src="./options.js"> </head> <body> <script type="text/javascript" src="./analytics.js"> ... <div><span id="opt***"></span></div> <table> <tr> <td> <input type="checkbox" id="***" /> </td> <td> <span id="opt***"></span> </td> </tr> ... </table> ...
  45. <!DOCTYPE html> <html> <head> <script type="text/javascript" src="./jquery-min.js"> <script type="text/javascript" src="./options.js"> </head> <body> <script type="text/javascript" src="./analytics.js"> ... <div><span id="opt***"></span></div> <table> <tr> <td> <input type="checkbox" id="***" /> </td> <td> <span id="opt***"></span> </td> </tr> ... </table> ... Google Analyticsで設定ページへの アクセスを計測できるようにする
  46. var _gaq = _gaq || []; _gaq.push(['_setAccount', 'UA-xxxxxx-xx']); _gaq.push(['_trackPageview']); (function() { var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true; ga.src = 'https://ssl.google-analytics.com/ga.js'; var s = document.getElementByTagName('script')[0]; s.parentNode.insertBefore(ga, s); })();
  47. <!DOCTYPE html> <html> <head> <script type="text/javascript" src="./jquery-min.js"> <script type="text/javascript" src="./options.js"> </head> <body> <script type="text/javascript" src="./analytics.js"> ... <div><span id="opt***"></span></div> <table> <tr> <td> <input type="checkbox" id="***" /> </td> <td> <span id="opt***"></span> </td> </tr> ... </table> ... 表示文字列はhtmlに 一切記載しない id属性はしっかり 書いておく
  48. My design pattern for Chrome Extension options.js
  49. (function() { var Options = function() { this.assignMessages(); this.assignEventHandlers(); this.restoreConfigurations(); }; Options.prototype = { assignMessages: function() { ... }, assignEventHandlers: function() { ... }, restoreConfigurations: function() { ... }, }; window.addEventListener( "load", function(evt) { new Options(); }); })();
  50. (function() { var Options = function() { this.assignMessages(); this.assignEventHandlers(); this.restoreConfigurations(); }; Options.prototype = { assignMessages: function() { ... }, assignEventHandlers: function() { ... }, restoreConfigurations: function() { ... }, }; window.addEventListener( "load", function(evt) { new Options(); }); })(); onloadイベント発生に応じて初期 化処理が動くようにしておく
  51. (function() { var Options = function() { this.assignMessages(); this.assignEventHandlers(); this.restoreConfigurations(); }; Options.prototype = { assignMessages: function() { ... }, assignEventHandlers: function() { ... }, restoreConfigurations: function() { ... }, }; window.addEventListener( "load", function(evt) { new Options(); }); })(); 各種初期化処理を呼び出す 他のjsと関数名を揃えておく
  52. (function() { var Options = function() { this.assignMessages(); this.assignEventHandlers(); this.restoreConfigurations(); }); }; Options.prototype = { assignMessages: function() { ... }, assignEventHandlers: function() { ... }, restoreConfigurations: function() { ... }, }; window.addEventListener( "load", function(evt) { new Options(); }); })(); assignMessages: function() { var hash = { "opt***" : "opt***", ... }; for (var key in hash) { $("#" + key).text( chrome.i18n.getMessage(hash[key])); } }, HTMLの各プレースホルダ(id属性を振っ た要素)に対して、メッセージリソース から得た国際化文字列をセットする
  53. (function() { var Options = function() { this.assignMessages(); this.assignEventHandlers(); this.restoreConfigurations(); }); }; Options.prototype = { assignMessages: function() { ... }, assignEventHandlers: function() { ... }, restoreConfigurations: function() { ... }, }; window.addEventListener( "load", function(evt) { new Options(); }); })(); restoreConfigurations: function() { chrome.runtime.getBackgroundPage( function(bg) { $("#***").val(bg.get***Config()); ... } ); }; Background pageの設定値取得 関数を使って、せっせとUIに値 をセットしていく
  54. (function() { var Options = function() { this.assignMessages(); this.assignEventHandlers(); this.restoreConfigurations(); }); }; Options.prototype = { assignMessages: function() { ... }, assignEventHandlers: function() { ... }, restoreConfigurations: function() { ... }, }; window.addEventListener( "load", function(evt) { new Options(); }); })(); assignEventHandlers: function() { $("#***").on("click", $.proxy( function(evt) { this.onClick***(evt); }, this )); }, onClick***: function(evt) { chrome.runtime.getBackgroundPage( function(bg) { var value = $("#***").val(); bg.set***Config(value); } ); }, Background pageの設定値格納 関数を使って設定値を保存する
  55. (function() { var Options = function() { this.assignMessages(); this.assignEventHandlers(); this.restoreConfigurations(); }); }; Options.prototype = { assignMessages: function() { ... }, assignEventHandlers: function() { ... }, restoreConfigurations: function() { ... }, }; window.addEventListener( "load", function(evt) { new Options(); }); })(); assignEventHandlers: function() { $("#***").on("click", $.proxy( function(evt) { this.onClick***(evt); }, this )); }, onClick***: function(evt) { chrome.runtime.getBackgroundPage( function(bg) { var value = $("#***").val(); bg.set***Config(value); } ); }, イベントハンドラの名前は 「on+イベント種別+UI項目名」 とする
  56. My design pattern for Chrome Extension popup.html
  57. <!DOCTYPE html> <html> <head> <script type="text/javascript" src="./jquery-min.js"> <script type="text/javascript" src="./popup.js"> </head> <body> <script type="text/javascript" src="./analytics.js"> <span id="***"></span> ... options.jsとほぼ一緒
  58. My design pattern for Chrome Extension popup.js
  59. (function() { var Popup = function() { this.assignMessages(); this.assignEventHandlers(); }; Popup.prototype = { assignMessages: function() { ... }, assignEventHandlers: function() { ... }, ... }; window.addEventListener( "load", function(evt) { new Popup(); }); })(); options.jsとほぼ一緒
  60. (function() { var Popup = function() { this.assignMessages(); this.assignEventHandlers(); }; Popup.prototype = { assignMessages: function() { ... }, assignEventHandlers: function() { ... }, ... }; window.addEventListener( "load", function(evt) { new Popup(); }); })(); assignEventHandlers: function() { $("#***").on("click", $.proxy(function(evt) { this.onClick***(evt); }, this)); }, onClick***: function(evt) { chrome.runtime.getBackgroundPage( function(bg) { // 設定値を取得 var config =bg.get***Config(); // Ajax通信 bg.load***({ onSuccess: function(data) { ... } }); } ); }, Background pageが提 供する関数を利用
  61. My design pattern ロジックを整理&集中させる - Background pageをうまく使うこと 統一感を作り出す - assign***() , onClick***() , set/get***Config() 国際化を徹底させる - id属性, assignMessages()
  62. 利用者が増えるのを 楽しむには?
  63. http://developer.chrome.com/extensions/
Advertisement