å°ãèããŠã Google Chromeæ¡åŒµæ©èœãªãã·ã§ã³ãæãä»ããŸããã
- Cromeã¯Blinkãšã³ãžã³ã䜿çšããŸãïŒWebKitã¯2013幎4æãŸã§äœ¿çšãããŠããŸããïŒãBlinkã¯WebKitã®åå²ã§ãïŒããã¯Safariã§ãïŒããŸããæ°ããOperaãå¿ããŸããïŒå€ãããã¯ããŒã¯ãããã¯ããŒã¯ã«äœ¿çšããŠããŸãïŒã ãããã£ãŠãChromeã®æ¡åŒµæ©èœãäœæããããšã«ãããæå°éã®å€æŽã§ïŒãŸãã¯è¿œå ããã«ïŒããã«2ã€ã®ãã©ãŠã¶ã«ç§»æ€ã§ããŸãã
- Google Chrome APIã®çµéšããªã
- Googleã¯ãŸã è¯ãäŒç€Ÿã§ã:)
ç§ã®èããå°ãèœã¡çãããšããç§ãæåã«ããããšã¯ãããŒãã®æ€çŽ¢ã§Google Chromeæ¡åŒµæ©èœãå ¥åããããšã§ããã ãã®ãããã¯ã«é¢ããåºç¯ãªèšäºãèŠãŠãç§ã¯å®å¿ããŠå®¶ã«åž°ããŸãããææ¥ã®æããããèªãã åŸãäžæ¥ã®çµããã«ã¯ã åžœåããã¶ã£ãŠãã ãïŒåœæã®èªåã®ééãïŒãšå®å šã«ç¢ºä¿¡ããŸããã ãããã®ããã€ããèªãã åŸãç§ã¯ãããã©ã®ããã«æ©èœãããã«ã€ããŠã®äžè¬çãªã¢ã€ãã¢ãæã£ãŠããŸããããããã¯ç§ã®ã¢ã€ãã¢ãå®çŸããã«ã¯ååã§ã¯ãããŸããã§ããã ãããå§ããŸããã...
Google Chromeãéãã chromeïŒ// extensionsãšå ¥åããéçºè ã¢ãŒãã®ãã§ãã¯ããã¯ã¹ããªã³ã«ãã[å±éãããæ¡åŒµæ©èœãèªã¿èŸŒã]ãã¿ã³ãã¯ãªãã¯ãããã©ã«ããŒãéžæããŠ[OK]ãã¯ãªãã¯ããŸãã

æåã¯ãããã§ã¹ã
manifest.json
{ "manifest_version": 2, "name": "My application", // "version": "0.9", "icons": { "16": "./16x16.png", "32": "./32x32.png", "48": "./48x48.png", "128": "./128x128.png" }, "permissions": [ "tabs", "http://*/*", "https://*/*" ], "background" : { "page": "background.html" }, "content_scripts":[{ "matches": [ "http://*/*", "https://*/*" ], "js": [ "script_in_content.js" ] }], "browser_action": { "default_title": "Application", "default_icon" : "./16x16.png" // "default_popup": "login.html" // html- , , JS html } }
manifest_version-çŸåš2ã®å€ãå¿ èŠã§ãã
version-æ¡åŒµæ©èœã®ããŒãžã§ã³ãæ°åãšãããã®ã¿ãå«ãŸããå ŽåããããŸãïŒã2.1.12ããã0.59ããªã©ïŒ
ã¢ã€ã³ã³ã¯ããã©ãŠã¶ã®ããŸããŸãªå Žæã«è¡šç€ºããããã¹ãŠã®ã¢ã€ã³ã³ã®ãªã¹ãã§ãïŒã¢ãã¬ã¹ããŒã«16ããã¹ãŠã®æ¡åŒµæ©èœã®ãªã¹ãã«48ãªã©ïŒã
èš±å¯ - èš±å¯ã®ããé åãããã«ãªã¹ããããŸããtabs.httpãšhttpsã ããå¿ èŠã§ããã¹ãŠã®ãµã€ããšã®ajax亀æã«å¿ èŠã§ãããŸããscript_in_content.jsãããã¯ã°ã©ãŠã³ãããŒãž-background.htmlãšããŒã¿ã亀æã§ããããã«ãªããŸãã
backgroundã¯ãèæ¯ããŒãžã®ååã§ãã ããã¯ã°ã©ãŠã³ãããŒãžã¯éèŠãªèŠçŽ ã§ãããäžéšã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯å¿ èŠãããŸããã å°ãåŸã§å¿ èŠã«ãªãã®ã¯ãªãã§ããã
content_scripts -script_in_content.jsãã¡ã€ã«ãã¿ãã§éãããããŒãžã«èªåçã«ããŒããããããšã瀺ããŸãã ãã®ããŒãžã¯ãhttpsã®ãµã€ãããéãå¿ èŠããããŸãïŒ// * / * httpãå«ããã¹ãŠã®ãµã€ãã®ããŒãžïŒhttpsã§ã¯ãªãïŒããã ããæå®ããããšãã§ããŸãã
browser_action-æ¡åŒµæ©èœã¢ã€ã³ã³ã衚瀺ããããã®2ã€ã®ãªãã·ã§ã³ããããŸãïŒ browser_actionãšpage_action
page_actionã¯ãæ¡åŒµåãã¿ãããšã«åå¥ã§ãããã€ãŸããã¢ã€ã³ã³ãã¢ãã¬ã¹ããŒã«è¡šç€ºãããããšã瀺ããŠããŸãã ãã®ã¢ã€ã³ã³ã¯ãå Žåã«ãã£ãŠã¯JSã䜿çšããŠé衚瀺/衚瀺ã§ããŸãã
äžæ¹ãbrowser_actionã¯åå¥ãšã¯èŠãªããããã¢ãã¬ã¹ããŒã«ã¯è¡šç€ºããããæ¡åŒµæ©èœã®ããã«ã«è¡šç€ºãããŸãã ãã®ã¢ã€ã³ã³ã¯JSã§é衚瀺ã«ããããšã¯ã§ããŸãããïŒãããã¯ããããšã¯ã§ããŸãïŒãåžžã«è¡šç€ºãããŸãã Browser_actionã«ã¯page_actionããã1ã€ã®å©ç¹ããããŸããbrowser_actionã¢ã€ã³ã³ã®äžã«ãçŸããæåãããã€ãæžãããšãã§ããŸãïŒ4ã€ãããããŸããïŒã

1ã€ã®ãµã€ãã§ã¯ãªããè€æ°ã®ãµã€ãã§äœæ¥ããå¿ èŠãããããã browser_actionãéžæããŸãã ã ãããŠãã¯ããã¢ã€ã³ã³ã«çŸãããã£ã©ã¯ã¿ãŒãé©çšããŸãã
Googleãããã«ã€ããŠèšã£ãŠããããšã¯æ¬¡ã®ãšããã§ãã
æ°ããŒãžã®ã¿ã«æå³ã®ããæ©èœã«ã¯ããŒãžã¢ã¯ã·ã§ã³ã䜿çšããŠãã ããã
ã»ãšãã©ã®ããŒãžã§æå³ã®ããæ©èœã«ã¯ããŒãžã¢ã¯ã·ã§ã³ã䜿çšããªãã§ãã ããã 代ããã«ãã©ãŠã¶ã¢ã¯ã·ã§ã³ã䜿çšããŠãã ããã
ãããŠãç§ãã¡ã®ã¢ããªã±ãŒã·ã§ã³ã¯äœãããã®ã§ããããã ããã«èšããŸããããã®ã¢ããªã±ãŒã·ã§ã³ã¯ãåŸã§èª¬æããŸãããã¯ã©ã€ã¢ã³ãã®ããã«è¡ããããã®ã®ã»ãã®äžéšã§ãã ãããŒãžã£ãŒããµã€ãhantim.ruã«ã¢ã¯ã»ã¹ããŠå¥çŽ/æ¬ å¡ã«é¢ããæ å ±ã衚瀺ãããšãã¢ããªã±ãŒã·ã§ã³ã¯ããŒãžã®htmlã³ãŒãã解æãããã®æ å ±ïŒæ¬ å¡ãéœåžãªã©ïŒãèŠã€ããŸãã æ¡åŒµæ©èœã¢ã€ã³ã³ãã¯ãªãã¯ãããšã管çè ãããŒã¿ãå ¥åãããã°ã€ã³ãã©ãŒã ã衚瀺ãããéžæãã空åž/å¥çŽãäŒç€Ÿã®Webãµã€ãã®ãããã¡ã€ã«ã«è¿œå ã§ããŸãã
次ã«ããã¹ãŠã®ä»çµã¿ã«ã€ããŠèª¬æããŸãã Googleã¯æ¬¡ã®ç»åãæäŸããŸãã

1ïŒæ€æ»ããããŠã£ã³ããŠã¯ã¿ãã§éãããã®ã§ããã³ã³ãã³ãã¹ã¯ãªããã¯script_in_content.jsã§ãããããŒãžã®DOMãžã®ãã«ã¢ã¯ã»ã¹ããããŸãã
2ïŒèæ¯ããŒãžã¯ã¢ããªã±ãŒã·ã§ã³ã®äžå¿ã§ããããã®å Žåã¯background.htmlã§ãã
3ïŒDevToolsããŒãž-ããã¯ãæ¡åŒµæ©èœã¢ã€ã³ã³ïŒãã®å Žåã¯ãlogin.htmlãŸãã¯find.htmlïŒãã¯ãªãã¯ãããšè¡šç€ºãããŸãã
ãã®å³ã§ç§ãæ©ãŸãå¯äžã®ããšã¯ã DevToolsããŒãžãšInspectedãŠã£ã³ããŠã®éã®æ¥ç¶ã§ãã ãããšãªã¢ããå¥ã®ãšãªã¢ã«ããŒã¿ã転éãã解決çãèŠã€ãããŸããã§ããã ãããã ããã¯ã°ã©ãŠã³ãããŒãžã仲ä»ãšããŠå ¬éãããã®ããŒã¿ãä»ããŠãã®ããŒã¿ã転éãããšããã¹ãŠãæ©èœããŸãã
ãããŠãã³ãŒãã®æãæ¥ãŸããã ç®ã«èŠããªãåŽããå§ããŸãããã
background.html
<!DOCTYPE html> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <script type="text/javascript" src="lib.js"></script> <script type="text/javascript" src="bg.js"></script> </head> <body></body> </html>
ããŸãããã°ãããã§åé¡ãçºçããªãã¯ãã§ãã 1ã€ã®ã³ã¡ã³ãïŒãbackground.html-ãã©ãŠã¶ãŒãåäœããŠããéã¯äžåºŠã ãèªã¿èŸŒãŸããŸãããèµ·åæã«äœ¿çšå¯èœã§ãããã ããã§ã2ã€ã®jsãã¡ã€ã«ãããŒãããŠããããšãããããŸãïŒlib.jsã¯é¢æ°ã®ã»ããã§ãããbg.jsã¯ã¢ããªã±ãŒã·ã§ã³ã®ãããããã§ãïŒã
bg.js
/** * OnLoad function * * @return void */ window.onload = function(){ // tmp storage window.bg = new bgObj(); // some variables !!! important window.bg.api_site_host = 'http://katran.by'; // get all graber hosts: !!!once!!! new Ajax({ url: window.bg.api_site_host+'/regexp.php', response: 'json', async: false, onComplete: function(data){ if(data && data.status && (data.status === 'ok')) window.bg.grabber_hosts = data.data; } }).send(); // set handler to tabs chrome.tabs.onActivated.addListener(function(info) { window.bg.onActivated(info); }); // set handler to tabs: need for seng objects chrome.extension.onConnect.addListener(function(port){ port.onMessage.addListener(factory); }); // set handler to extention on icon click chrome.browserAction.onClicked.addListener(function(tab) { window.bg.onClicked(tab); }); // set handler to tabs chrome.tabs.onUpdated.addListener(function(id, info, tab) { // if tab load if (info && info.status && (info.status.toLowerCase() === 'complete')){ // if user open empty tab or ftp protocol and etc. if(!id || !tab || !tab.url || (tab.url.indexOf('http:') == -1)) return 0; // save tab info if need window.bg.push(tab); // connect with new tab, and save object var port = chrome.tabs.connect(id); window.bg.tabs[id].port_info = port; // run function in popup.html chrome.tabs.executeScript(id, {code:"initialization()"}); // send id, hosts and others information into popup.js window.bg.tabs[id].port_info.postMessage({method:'setTabId', data:id}); window.bg.tabs[id].port_info.postMessage({method:'setHosts', data:window.bg.grabber_hosts}); window.bg.tabs[id].port_info.postMessage({method:'run'}); // if user is logged into application set find.html popup if(window.bg.user.id) chrome.browserAction.setPopup({popup: "find.html"}); }; }); window.bg.onAppReady(); }; /** * Functino will be called when popup.js send some data by port interface * * @return void */ function factory(obj){ if(obj && obj.method){ if(obj.data) window.bg[obj.method](obj.data); else window.bg[obj.method](); } } /** * Popup object * * @version 2013-10-11 * @return Object */ window.bgObj = function(){ }; /** * Pablic methods */ window.bgObj.prototype = { /** * some internal params */ tabs: {}, user: {}, popup_dom: {}, active_tab: {}, grabber_hosts: {}, done_urls: [], /** * init() function */ onAppReady: function() { // if user not logged into application set login.html popup chrome.browserAction.setPopup({popup: "login.html"}); }, /** * Function add tab into $tabs object, if need */ push: function(tab) { if(tab.id && (tab.id != 0)){ if(!this.tabs[tab.id]) this.tabs[tab.id] = {tab_obj:tab}; } }, /** * Function will be called from popup.js */ mustParsed: function(data) { if(this.tabs[data.tab_id]){ var id = data.tab_id; this.tabs[id].must_parsed = data.find; // run parser in popup.js, if need if(this.tabs[id].must_parsed && (this.tabs[id].must_parsed === true)) this.tabs[id].port_info.postMessage({method:'parsePage'}); } }, /** * Function will be called from popup.js */ matchesCount: function(data) { if(data.tab_id && this.tabs[data.tab_id]){ var id = data.tab_id; this.tabs[id].matches = data.matches; this.tabs[id].matches_count = this.tabs[id].matches.length+''; if(this.tabs[id].matches_count && this.tabs[id].matches_count != '0'){ chrome.browserAction.setBadgeText({text: this.tabs[id].matches_count}); return 0; } } // show default text chrome.browserAction.setBadgeText({text:''}); }, /** * Function will be called when user change active tab */ onActivated: function(info) { // set active tab this.active_tab = info; var data = {}; data.matches = []; if(info.tabId){ data.tab_id = info.tabId; if(!this.tabs[data.tab_id]) this.tabs[data.tab_id] = {}; if(!this.tabs[data.tab_id].matches) this.tabs[data.tab_id].matches = []; data.matches = this.tabs[data.tab_id].matches; } // set actual count of matches for current tab this.matchesCount(data); // if user is logged into application set find.html popup if(this.user.id) chrome.browserAction.setPopup({popup: "find.html"}); }, /** * Function will be called when user click on extension icon */ onClicked: function(tab) { alert(' . .'); return 0; }, /** * Function will be called from login.js */ loginUser: function(user_data) { var self = this; var json_data = false; // get all graber hosts: !!!once!!! new Ajax({ url: window.bg.api_site_host+'/login.php?user='+encodeURIComponent(JSON.stringify(user_data)), method: 'post', response: 'json', async: false, onComplete: function(data){ if(data && data.status){ // if login - ok if(data.status === 'ok') self.user = data.data; json_data = data; } } }).send(); // return value for login.js return json_data; }, /** * Function will be called from login.js and others places */ setPopup: function(popup_file) { chrome.browserAction.setPopup({tabId: this.active_tab.tabId, popup: popup_file}); }, /** * Function will be called from find.js and others places */ getMatches: function() { // init if need if(!this.tabs[this.active_tab.tabId]) this.tabs[this.active_tab.tabId] = {}; if(!this.tabs[this.active_tab.tabId].matches) this.tabs[this.active_tab.tabId].matches = []; // if user alredy send this url - remove for(var i = 0, cnt = this.tabs[this.active_tab.tabId].matches.length; i < cnt; i++){ for(var j = 0, len = this.done_urls.length; j < len; j++){ if(this.tabs[this.active_tab.tabId].matches[i].url === this.done_urls[j]){ this.tabs[this.active_tab.tabId].matches[i].url = ''; break; } } } return this.tabs[this.active_tab.tabId].matches; }, /** * Function will be called from find.js and others places */ addUrlToGrabber: function(url) { // if $url == '' - already used if(json_data.status && (json_data.status === 'ok')){ var matches = this.tabs[this.active_tab.tabId].matches; for(var i = 0, cnt = matches.length; i < cnt; i++){ if(matches[i].url && (matches[i].url === url)) matches[i].url = ''; this.done_urls.push(url); } } // return value for login.js return json_data; }, /** * Empty method */ empty: function() { } }
ãŸãã window.onloadãåŸ ã£ãŠããkatran.byã«ãªã¯ãšã¹ããéä¿¡ãïŒjsonããŒã¿ãååŸããã©ã®ãµã€ããããã©ã®RegExpã§å¿ èŠãªããŒã¿ãæäŸããŸãïŒããã©ãŠã¶ãŒã¿ãã§ãã³ãã©ãŒããã³ã°ãããŸãïŒããã¯ãããã§ã¹ãã§æå®ããŸããïŒæš©éãã¿ãïŒã
chrome.tabs.onActivated.addListener(function(info) { window.bg.onActivated(info); });
onActivated-ãŠãŒã¶ãŒãïŒã¯ãªãã¯ãŸãã¯Alt + Tabã§ïŒæ°ããã¿ãã«åãæ¿ãããšãã«çºçããŸãã
chrome.tabs.onUpdated.addListener(function(id, info, tab) { ..... });
onUpdated-ã¿ãã«ããŒãžãå®å šã«ããŒãããããšïŒDOMã ãã§ãªãããã¹ãŠã®ç»åãïŒããŒããããŸãã
chrome.browserAction.onClicked.addListener(function(tab) { window.bg.onClicked(tab); });
onClicked-ãŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ã¢ã€ã³ã³ãã¯ãªãã¯ãããšçºçããŸãã å°ããªã³ã¡ã³ããã¯ãªãã¯äžã«default_popupãèšå®ãããŠããå ŽåãonClickedãã³ãã©ãŒã¯èµ·åããŸããã default_popupã¯ãæ¡åŒµæ©èœã¢ã€ã³ã³ãã¯ãªãã¯ããåŸã«è¡šç€ºãããHTMLããŒãžã§ãã default_popupã¯ã chrome.browserAction.setPopupïŒ{popupïŒ "find.html"}ïŒ;ã䜿çšããŠãããã§ã¹ãã§èšå®ã§ããŸãã ãŸãã¯chrome.pageAction.setPopupïŒ{popupïŒ "find.html"}ïŒ;
chrome.extension.onConnect.addListener(function(port){ port.onMessage.addListener(factory); });
portã䜿çšããŠscript_in_content.jsããéä¿¡ãããããŒã¿ãåä¿¡ããã«ã¯ããã®
ããŒã¿åŠçã¯ãã¡ã¯ããªãŒã«ãã£ãŠè¡ãããŸãïŒobjïŒ
function factory(obj){ if(obj && obj.method){ if(obj.data) window.bg[obj.method](obj.data); else window.bg[obj.method](); } }
ãŠãŒã¶ãŒãã¿ããããŒããããšã次ã®ããšãèµ·ãããŸãã
- åŒã³åºããããã³ãã©ãŒ
onUpdated
-
if (info && info.status && (info.status.toLowerCase() === 'complete'))
ãã¹ãŠãããŒããããå Žå-ãããªãŒãã£ã³ã°ãç¶è¡ããŸãã -
if(!id || !tab || !tab.url || (tab.url.indexOf('http:') == -1))
ãŠãŒã¶ãŒãWebãµã€ããéããªãå ŽåïŒhttpsã確èªããã®ãå¿ããå ŽåïŒ :)ïŒãããã³ãããšãã°ãèšå®ã¿ããŸãã¯ftpãªã©ã«æ°ã¥ããå ŽåãäœãããŸãã -
window.bg.push(tab);
-çŸåšã®ã¿ãã«é¢ããæ å ±ãåéãã -
chrome.tabs.executeScript(id, {code:"initialization()"});
-ä»ã script_in_content.jsã泚æããŠåæåïŒïŒé¢æ°ãå®è¡ããŸã -
window.bg.tabs[id].port_info.postMessage({method:'setTabId', data:id})
- script_in_content.jsã«ããŒã¿ãéä¿¡ããŸã -
chrome.browserAction.setPopup({popup: "find.html"});
-ãŠãŒã¶ãŒã以åã«ãã°ã€ã³ããå Žåã«ãããã¢ããããŒãžãèšå®ãã
background.htmlããscript_in_content.jsã«ããŒã¿ã転éããã«ã¯2ã€ã®æ¹æ³ããããŸãã
- chrome.tabs.executeScriptïŒæŽæ°tabIdãInjectDetailsã®è©³çŽ°ãé¢æ°ã³ãŒã«ããã¯ïŒ-1ã€ã§ããããã®æ¹æ³ã§ã¯ããŒã¿ãæååãšããŠã®ã¿ïŒãªããžã§ã¯ãã§ã¯ãªãé åã§ã¯ãªãïŒè»¢éã§ããŸã
- hrome.tabs.sendMessageïŒinteger tabIdãä»»æã®ã¡ãã»ãŒãžãé¢æ°responseCallbackïŒ -ãã®æ¹æ³ã§ã¯äœã§ãæž¡ãããšãã§ããŸãããå®éã«ã¯è¿œå ã®èšå®ãå¿ èŠã«ãªããŸã
ãã®ãããããŒã¿ãscript_in_content.jsã«éä¿¡ããã®ã§ãã³ãŒããæ€èšããŸãã
script_in_content.js
// set handler to tabs: need for seng objects to backgroung.js chrome.extension.onConnect.addListener(function(port){ port.onMessage.addListener(factory); }); /** * Function remove spaces in begin and end of string * * @version 2012-11-05 * @param string str * @return string */ function trim(str) { return String(str).replace(/^\s+|\s+$/g, ''); } /** * Functino will be called from background.js * * @return void */ function initialization(){ window.popup = new popupObj(); } /** * Functino will be called when background.js send some data by port interface * * @return void */ function factory(obj){ if(obj && obj.method){ if(obj.data) window.popup[obj.method](obj.data); else window.popup[obj.method](); } } /** * Popup object * * @version 2013-10-11 * @return Object */ window.popupObj = function(){ }; /** * Pablic methods */ window.popupObj.prototype = { /** * some internal params */ available_hosts: [], total_host: null, matches: [], tab_id: null, port: null, cars: [], /** * Function will be called from bg.js */ setHosts: function(hosts) { this.available_hosts = hosts; }, /** * Function will be called from bg.js */ setTabId: function(id) { this.tab_id = id; }, /** * Function check total host */ run: function() { // get total host if(document.location.host && (document.location.host != '')) this.total_host = document.location.host; else if(document.location.hostname && (document.location.hostname != '')) this.total_host = document.location.hostname; if(!this.total_host || (this.total_host === '')) return 0; var find = false; // if total host in array $available_hosts - parse page for finde cars for (host in this.available_hosts) { if(this.total_host.indexOf(host) != -1){ this.total_host = host; find = true; break; } }; // create connection to backgroung.html and send request this.port = chrome.extension.connect(); this.port.postMessage({method:'mustParsed', data:{tab_id:this.tab_id, find:find}}); }, /** * Function will be called from bg.js * Parse page */ parsePage: function() { // reset variable before parse this.matches = []; if(!this.available_hosts[this.total_host]) return 0; var html = window.document.body.innerHTML; var reg_exp = this.available_hosts[this.total_host]; var matches = {}; var match = []; var find = false; for(var i = 0, len = reg_exp.length; i < len; i++) { var exp = new RegExp(reg_exp[i].reg_exp, reg_exp[i].flag); match = exp.exec(html); if(match && match.length && reg_exp[i].index){ matches[reg_exp[i].field] = trim(match[reg_exp[i].index]); find = true; } else if(match && match.length){ matches[reg_exp[i].field] = match; find = true; } } // this url will be send to site if(find === true){ matches.url = document.location.href; this.matches.push(matches); } // send count of matches this.port.postMessage({method:'matchesCount', data:{tab_id:this.tab_id, matches: this.matches}}); } }
æåã«ç®ãåŒãã®ã¯ãbg.jsãšåãã§ããããšããããããã«ãbackground.htmlããã®ããŒã¿ã®åä¿¡ã§ãã
chrome.extension.onConnect.addListener(function(port){ port.onMessage.addListener(factory); });
ãæ°ä»ãã®ããã«ã bg.jsã®åæ段éã§
initialization()
ã
setTabId()
ã
setHosts()
ããã³
run()
ã
run()
ã æãèå³æ·±ãã®ã¯window.popup.runïŒïŒã§ãã ããã§ãéããŠããããŒãžã®ãµãŒããŒã®ãã¡ã€ã³åããã§ãã¯ããããã®ååãé¢å¿ã®ãããµã€ãã®ãªã¹ããšäžèŽããå ŽåïŒããŒã¿ãäŒæ¥ãªãœãŒã¹ã«è»¢éããå¿ èŠãããïŒ
find = true;
ãããŠããªã¯ãšã¹ã
window.bg.mustParsed(obj)
ãbg.jsã«éä¿¡ããŸãã
/** * Function will be called from script_in_content.js */ mustParsed: function(data) { if(this.tabs[data.tab_id]){ var id = data.tab_id; this.tabs[id].must_parsed = data.find; // run parser in popup.js, if need if(this.tabs[id].must_parsed && (this.tabs[id].must_parsed === true)) this.tabs[id].port_info.postMessage({method:'parsePage'}); } }
ãã¡ã€ã³ã®äžèŽãèŠã€ãã£ãå Žåã
parsePage()
ããŒãžã®ããŒãµãŒãå®è¡ããŸã ã
/** * Function will be called from bg.js * Parse page */ parsePage: function() { // reset variable before parse this.matches = []; if(!this.available_hosts[this.total_host]) return 0; var html = window.document.body.innerHTML; var reg_exp = this.available_hosts[this.total_host]; var matches = {}; var match = []; var find = false; for(var i = 0, len = reg_exp.length; i < len; i++) { var exp = new RegExp(reg_exp[i].reg_exp, reg_exp[i].flag); match = exp.exec(html); if(match && match.length && reg_exp[i].index){ matches[reg_exp[i].field] = trim(match[reg_exp[i].index]); find = true; } else if(match && match.length){ matches[reg_exp[i].field] = match; find = true; } } // this url will be send to site if(find === true){ matches.url = document.location.href; this.matches.push(matches); } // send count of matches this.port.postMessage({method:'matchesCount', data:{tab_id:this.tab_id, matches: this.matches}}); }
ã¹ã¯ãªãããããŒãžäžã§äœããèŠã€ããå ŽåããããèŠã€ãããã®ã¯ãã¹ãŠé åã«å ¥ããããçŸåšã®ããŒãžã®URLãè¿œå ããŠããèŠã€ãããã®ãèŠãŠ...ããšèšã£ãŠbg.jsã«éãè¿ããŸãã ããã«å¿ããŠã bg.jsã¯å ¥åããŒã¿ã解æããRegExpãäœããèŠã€ããå Žåãã¢ã€ã³ã³ã«äžèŽæ°ïŒ1ã2ãªã©ïŒã
chrome.browserAction.setBadgeText({text: this.tabs[id].matches_count});
ã
ãããã¯ãã¹ãŠã bg.jsããã³script_in_content.jsãã³ãã«ã®ãã€ã©ã€ãã§ãã
次ã«ã popupã«ã€ããŠèª¬æããŸãã ãŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ã¢ã€ã³ã³ãã¯ãªãã¯ãããšã login.htmlãã©ãŒã ã衚瀺ãããŸãã
ãããŒãžã£ãŒã¯äŒæ¥ãµã€ãããããŒã¿ãå ¥åãã[ãã°ã€ã³]ãã¯ãªãã¯ãããšã次ã®ããšãèµ·ãããŸãã
login.html
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <script type="text/javascript" src="login.js"></script> <link type="text/css" rel="stylesheet" href="login.css"> <title>Grabber popup</title> </head> <body> <div class="body"> <div class="emptyLogin"> <div id="error_message"> </div> <form name="login_form" action="" method="get" id="popup_login_form"> <table> <tbody> <tr> <td align="right"> E-mail:</td> <td><input type="text" name="login" value="" tabindex="1"></td> </tr> <tr> <td align="right">:</td> <td><input type="password" name="pass" value="" tabindex="2"></td> </tr> <tr> <td colspan="2" align="center"><input type="submit" value="Login" class="button"></td> </tr> </tbody> </table> </form> </div> <div id="loader"><img src="ajax-loader.gif" title="Loding" alt="Loading"></div> </div> </body> </html>
login.js
/** * OnLoad function * * @return void */ window.onload = function(){ // set some events handlers document.getElementById('popup_login_form').onsubmit = function(obj){ // fade popup document.getElementById('loader').style.display = 'block'; document.getElementById('error_message').innerHTML = ' '; if(obj.target.elements && obj.target.elements.length && (obj.target.elements.length === 3)){ var data = {}; data.login = obj.target.elements[0].value; data.pass = obj.target.elements[1].value; setTimeout(function(){ var bg_wnd = chrome.extension.getBackgroundPage(); var result = bg_wnd.bg.loginUser(data); if(result && result.status && (result.status === 'error')) document.getElementById('error_message').innerHTML = result.mess; else{ // set new popup html code and close popup window bg_wnd.bg.setPopup('find.html'); window.close(); } // hide fade on popup document.getElementById('loader').style.display = 'none'; }, 500); } return false; }; }
login.jsã®ã¿ã¹ã¯ã¯ããã©ãŒã ã§
onsubmit
ããã³ã°ããããŠãŒã¶ãŒå/ãã¹ã¯ãŒããbackground.htmlïŒbg.jsïŒã«éä¿¡ããããšã§ãã
ããã¯ã次ã®æ§æã䜿çšããŠè¡ãããŸãïŒã芧ã®ãšãã ã bg.jsãªããžã§ã¯ãã®ã¡ãœãããçŽæ¥åŒã³åºãããšãã§ããŸãïŒã
var bg_wnd = chrome.extension.getBackgroundPage(); var result = bg_wnd.bg.loginUser(data);
bg_wnd.bg.loginUser(data)
ã¯ãµãŒããŒã«ããŒã¿ãéä¿¡ãããã¹ãŠãæ£åžžã§ããã°ããããã¢ããlogin.htmlãfind.htmlã眮ãæãã
ãŠãŒã¶ãŒããŒã¿ã¯å€æ°ã«æ ŒçŽãããŸãã 次ã®ããã«ãããã¢ãããå€æŽããŸãã
/** * Function will be called from login.js and others places */ setPopup: function(popup_file) { chrome.browserAction.setPopup({tabId: this.active_tab.tabId, popup: popup_file}); },
ãŠãŒã¶ãŒããããã¢ããlogin.htmlãéããŠãYour E-mailïŒããã£ãŒã«ãã«ã«ãŒãœã«ã眮ãããã¹ã¯ãŒãã«ç§»åããããšãæåŸ ããŠïŒæåã«ïŒ TabããŒãæŒããšããŠãŒã¶ãŒã¯äžæºã«ãªãããã©ãŒã«ã¹ã¯å€æŽãããŸããã ãã®ãã°ã¯äŸç¶ãšããŠé¢é£ããŠããŸãã
ããã§ãã»ãã®å°ãæ®ã£ãã
ãã°ã€ã³ã«æåãããããããã¢ãããfind.htmlã«å€æŽããŸã ã
find.html
<!DOCTYPE html> <html> <head> <meta http-equiv="content-type" content="text/html; charset=UTF-8"> <script type="text/javascript" src="find.js"></script> <link type="text/css" rel="stylesheet" href="find.css"> <title>Grabber</title> </head> <body> <div class="body"> <div class="carsRows" id="popup_cars_rows"> <h3 style="text-align: center; margin: 5px 0;"> </h3> <form name="cars_form" action="" method="get" id="popup_cars_form"> <table id="popup_cars_table"> <thead> <tr> <th class="make"></th> <th class="info"></th> <th class="addBtn"> </th> </tr> </thead> <tbody> </tbody> </table> </form> </div> <div class="carsRows" id="popup_cars_rows_none" style="display: none;"> <h3 style="text-align: center; margin: 5px 0;"> </h3> </div> <div id="loader"><img src="ajax-loader.gif" title="Loding" alt="Loading"></div> </div> </body> </html>
find.js
/** * OnLoad function * * @return void */ window.onload = function(){ // set new popup html code and close popup window window.bg_wnd = chrome.extension.getBackgroundPage(); var rows = window.bg_wnd.bg.getMatches(); // function render popup renderPopup(rows); } /** * Function set cars into html * * @param array $rows * @return void */ function renderPopup(rows) { if(rows.length === 0){ document.getElementById('popup_cars_rows').style.display = 'none'; document.getElementById('popup_cars_rows_none').style.display = 'block'; return 0; } else{ document.getElementById('popup_cars_rows').style.display = 'block'; document.getElementById('popup_cars_rows_none').style.display = 'none'; } for (var i = 0, cnt = rows.length; i < cnt; i++) renderRow(rows[i]); } /** * Function set cars into html * * @param object $row * @return void */ function renderRow(row) { var tbl = document.getElementById('popup_cars_table').children[1]; // add divided row var td = tbl.insertRow(-1).insertCell(-1); td.setAttribute('colspan', '3'); td.innerHTML = '<hr style="border: 1px solid #909090; width: 75%">'; var tr = tbl.insertRow(-1); var td1 = tr.insertCell(-1); var td2 = tr.insertCell(-1); var td3 = tr.insertCell(-1); var vacancy = []; var city = []; var hash = { vacancy: '', city: '', } var table_row = []; for(key in row){ if(hash[key]){ if(key == 'vacancy') vacancy.push(row[key]); if(key == 'city') city.push(row[key]); } } td1.innerHTML = vacancy.join(' ');; td2.innerHTML = city.join(' '); td3.innerHTML = (row.url === '')?'<b><em></em></b>':'<input type="button" value="" name="cars[]" class="button"><input type="hidden" value="'+row.url+'" name="url[]">'; td3.children[0].addEventListener('click', function(){addToGrabber(event)}, false); } function addToGrabber(e) { // hide fade on popup document.getElementById('loader').getElementsByTagName('img')[0].style.marginTop = (window.innerHeight/2-10)+'px'; document.getElementById('loader').style.display = 'block'; if(e && e.srcElement){ var url = e.srcElement.parentNode.children[1].value; setTimeout(function(){ var result = window.bg_wnd.bg.addUrlToGrabber(url); e.srcElement.parentNode.innerHTML = '<b><em></em></b>'; // hide fade on popup document.getElementById('loader').style.display = 'none'; }, 500); } }
find.htmlãèªã¿èŸŒãŸãããšããã«ã find.jsãåŒãç¶ããŸãã ãã®ã¿ã¹ã¯ã¯ãbg.jsã«ãçŸåšã®ããŒãžã«äœããããŸããããšå°ãã bg.jsãäžãããã®ã衚瀺ããããšã§ã ã
/** * OnLoad function * * @return void */ window.onload = function(){ // set new popup html code and close popup window window.bg_wnd = chrome.extension.getBackgroundPage(); var rows = window.bg_wnd.bg.getMatches(); // function render popup renderPopup(rows); }
ã¿ãŒã³ããŒãœãªã¥ãŒã·ã§ã³ã®ããã«èŠããŸãã

[è¿œå ]ãã¿ã³ã䜿çšãããšãã©ã®ããã«æ©èœããããç解ã§ãããšæããŸãã æåŸã«ããã®å šäœãã©ã®ããã«ãããã°ãããŠããããè¿°ã¹ãããšæããŸãã
background.html - bg.jsããã³lib.jsã¹ã¯ãªããã®åäœã確èªããã«ã¯ã chromeïŒ//æ¡åŒµæ©èœããŒãžã®background.htmlãªã³ã¯ãã¯ãªãã¯ããŸãã

script_in_content.js-ããŒãžã®ã³ã³ããã¹ãã§å®è¡ããããããããŒãžãå®å šã«æ€æ»ãããšã©ãŒåºåã衚瀺ãããã³ã³ãœãŒã«ãç£èŠã§ããŸãã
login.htmlããã³find.html-éçºè ããŒã«ã衚瀺ããã«ã¯ãã¢ããªã±ãŒã·ã§ã³ã¢ã€ã³ã³ãã¯ãªãã¯ããããŠã¹ã®å³ãã¿ã³ã§ããŒãžæ€æ»ãéžæããå¿ èŠããããŸã ã

PSã JavaScriptãHTMLã«è²Œãä»ããå Žåããã¹ãŠã®JavaScriptã¯jsãã¡ã€ã«ã«å«ãŸããŠããå¿ èŠããããŸã-chromeã¯èªããŸãã
ãŸããããã€ãã®ãªã³ã¯ïŒ
ããã¥ã¡ã³ãã®å ŽåïŒ manifest.json ã Chromeã®API
github.comïŒ ãœãŒã¹ã³ãŒã
PSS x256ã«ãããšãå°å ¥ãä¿®æ£ããŸããã