{ "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 } }
Do not have a few pages.
Do not use this page. Use browser actions instead.
<!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>
/** * 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() { } }
chrome.tabs.onActivated.addListener(function(info) { window.bg.onActivated(info); });
chrome.tabs.onUpdated.addListener(function(id, info, tab) { ..... });
chrome.browserAction.onClicked.addListener(function(tab) { window.bg.onClicked(tab); });
chrome.extension.onConnect.addListener(function(port){ port.onMessage.addListener(factory); });
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 everything is loaded, we continue our debriefing.if(!id || !tab || !tab.url || (tab.url.indexOf('http:') == -1))
if the user has opened a non-website (checking for https - forgot, just now noticed :)), but for example the settings tab or ftp, etc., then we do nothingwindow.bg.push(tab);
- we save information about the current tabchrome.tabs.executeScript(id, {code:"initialization()"});
- now we are ordering script_in_content.js to execute the initialization () functionwindow.bg.tabs[id].port_info.postMessage({method:'setTabId', data:id})
- we send data to script_in_content.jschrome.browserAction.setPopup({popup: "find.html"});
- set the popup page if the user has logged in before // 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}}); } }
chrome.extension.onConnect.addListener(function(port){ port.onMessage.addListener(factory); });
initialization()
, setTabId()
, setHosts()
and run()
. Of most interest is window.popup.run (). There, the domain name of the server of the open page is checked, and if this name matches the list of sites that interest us (data from which must be transferred to the corporate resource) - find = true;
and send the request window.bg.mustParsed(obj)
to 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()
page in script_in_content.js . /** * 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}}); }
chrome.browserAction.setBadgeText({text: this.tabs[id].matches_count});
. <!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>
/** * 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; }; }
onsubmit
on the form, and send the login / password to background.html (bg.js) , var bg_wnd = chrome.extension.getBackgroundPage(); var result = bg_wnd.bg.loginUser(data);
bg_wnd.bg.loginUser(data)
sends data to the server, if everything is fine, popup login.html is replaced by 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}); },
<!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>
/** * 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); } }
/** * 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); }
Source: https://habr.com/ru/post/198778/
All Articles