├── src ├── .DS_Store └── bg │ ├── background.js │ └── functions.js ├── icons ├── icon16.png ├── icon19.png ├── icon48.png └── icon128.png └── manifest.json /src/.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyleladd/Localhost-Switcher/master/src/.DS_Store -------------------------------------------------------------------------------- /icons/icon16.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyleladd/Localhost-Switcher/master/icons/icon16.png -------------------------------------------------------------------------------- /icons/icon19.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyleladd/Localhost-Switcher/master/icons/icon19.png -------------------------------------------------------------------------------- /icons/icon48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyleladd/Localhost-Switcher/master/icons/icon48.png -------------------------------------------------------------------------------- /icons/icon128.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kyleladd/Localhost-Switcher/master/icons/icon128.png -------------------------------------------------------------------------------- /manifest.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "Localhost Switcher", 3 | "version": "0.0.1", 4 | "manifest_version": 2, 5 | "description": "Easily switch between localhost and your ip address.", 6 | "homepage_url": "http://kyleladd.us", 7 | "icons": { 8 | "16": "icons/icon16.png", 9 | "48": "icons/icon48.png", 10 | "128": "icons/icon128.png" 11 | }, 12 | "background": { 13 | "scripts": ["src/bg/background.js","src/bg/functions.js"], 14 | "persistent": false 15 | }, 16 | "page_action": { 17 | "default_icon": "icons/icon19.png", 18 | "default_title": "Localhost Switcher" 19 | }, 20 | "permissions": [ 21 | "declarativeContent", 22 | "tabs", 23 | "webNavigation", 24 | "*://*/*" 25 | ] 26 | } -------------------------------------------------------------------------------- /src/bg/background.js: -------------------------------------------------------------------------------- 1 | // Show page action icon in omnibar. 2 | function showPageAction( tabId, changeInfo, tab ) { 3 | chrome.pageAction.show(tabId); 4 | }; 5 | // Call the above function when the url of a tab changes. 6 | chrome.tabs.onUpdated.addListener(showPageAction); 7 | 8 | var alreadyClicked = false; 9 | var clickType = "single"; 10 | //Add Default Listener provided by chrome.api.* 11 | chrome.pageAction.onClicked.addListener(function (tab) 12 | { //Check for previous click 13 | if (alreadyClicked) { 14 | //Yes, Previous Click Detected 15 | //Clear timer already set in earlier Click 16 | clearTimeout(timer); 17 | clickType = "double"; 18 | init(); 19 | //Clear all Clicks 20 | alreadyClicked = false; 21 | return; 22 | } 23 | //Set Click to true 24 | alreadyClicked = true; 25 | //Add a timer to detect next click to a sample of 250 26 | timer = setTimeout(function () { 27 | //No more clicks so, this is a single click 28 | clickType = "single"; 29 | //Clear all timers 30 | clearTimeout(timer); 31 | init(); 32 | //Clear all Clicks 33 | alreadyClicked = false; 34 | }, 250); 35 | }); 36 | 37 | function init() { 38 | var chromeurl = window.location.href; // Returns full URL 39 | chrome.tabs.query({'active': true, 'lastFocusedWindow': true}, function (tabs) { 40 | var tab = tabs[0]; 41 | var url = tabs[0].url; 42 | var redirectLink = ""; 43 | if(isLocalhost(url)){ 44 | getIPs(function(ips){ 45 | var localIPs = []; 46 | var ipV6s = []; 47 | var publicIPs = []; 48 | 49 | for(var i in ips){ 50 | var ip = ips[i]; 51 | if (ip.match(/^(192\.168\.|169\.254\.|10\.|172\.(1[6-9]|2\d|3[01]))/)){ 52 | //local IPs 53 | localIPs.push(ip); 54 | } 55 | else if (ip.match(/^[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7}$/)){ 56 | //IPv6 addresses 57 | ipV6s.push(ip); 58 | } 59 | else{ 60 | //assume the rest are public IPs 61 | publicIPs.push(ip); 62 | } 63 | } 64 | if(publicIPs.length<0){ 65 | redirectLink = publicIPs[0]; 66 | } 67 | else if(localIPs.length>0){ 68 | redirectLink = localIPs[0]; 69 | } 70 | navigateRedirect(tab,clickType,getIPLink(url,redirectLink)); 71 | }); 72 | } 73 | else{ 74 | redirectLink = getLocalhostLink(url); 75 | navigateRedirect(tab,clickType,redirectLink); 76 | } 77 | }); 78 | } 79 | function navigateRedirect(tab,clickType,redirectTo){ 80 | if(clickType=="single"){ 81 | chrome.tabs.getSelected(null, function(tab){ 82 | chrome.tabs.update(tab.id, {url: redirectTo}); 83 | }); 84 | } 85 | else{ 86 | chrome.tabs.create({ url: redirectTo }); 87 | } 88 | } -------------------------------------------------------------------------------- /src/bg/functions.js: -------------------------------------------------------------------------------- 1 | function isLocalhost(url){ 2 | // Should just remove the port instead of using contains 3 | return (getTLDomain(url).toLowerCase().indexOf("localhost") !== -1); 4 | } 5 | 6 | function getIPs(callback) { 7 | var ips = []; 8 | 9 | var RTCPeerConnection = window.RTCPeerConnection || 10 | window.webkitRTCPeerConnection || window.mozRTCPeerConnection; 11 | 12 | var pc = new RTCPeerConnection({ 13 | // Don't specify any stun/turn servers, otherwise you will 14 | // also find your public IP addresses. 15 | iceServers: [] 16 | }); 17 | // Add a media line, this is needed to activate candidate gathering. 18 | pc.createDataChannel(''); 19 | 20 | // onicecandidate is triggered whenever a candidate has been found. 21 | pc.onicecandidate = function(e) { 22 | if (!e.candidate) { // Candidate gathering completed. 23 | pc.close(); 24 | callback(ips); 25 | return; 26 | } 27 | var candidate = e.candidate.candidate; 28 | //match just the IP address 29 | var ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/ 30 | try{ 31 | var ip_addr = ip_regex.exec(candidate)[1]; 32 | 33 | //remove duplicates 34 | if (ips.indexOf(ip_addr) === -1) { 35 | ips.push(ip_addr); 36 | } 37 | } 38 | catch(err){} 39 | }; 40 | pc.createOffer(function(sdp) { 41 | pc.setLocalDescription(sdp); 42 | }, function onerror() {}); 43 | } 44 | 45 | function getLocalhostLink(url){ 46 | var localLink = ""; 47 | var protocol = url.substring(0,getFirstPosition(url,"://",false)); 48 | // production link starts with protocol 49 | localLink = protocol; 50 | var port = getPort(url); 51 | // add the TLDomain 52 | localLink += "localhost" + port + "/"; 53 | // add the rest of the url after the tld 54 | localLink += url.substring(getPosition(url, "/", 3)+1,url.length); 55 | return localLink; 56 | } 57 | function getIPLink(url,ip){ 58 | var ipLink = ""; 59 | var protocol = url.substring(0,getFirstPosition(url,"://",false)); 60 | // link starts with protocol 61 | ipLink = protocol; 62 | var port = getPort(url); 63 | // add the TLDomain 64 | ipLink += ip + port + "/"; 65 | // add the rest of the url after the tld 66 | ipLink += url.substring(getPosition(url, "/", 3)+1,url.length); 67 | return ipLink; 68 | } 69 | 70 | function getTLDomain(url){ 71 | var protocolEndPos = getFirstPosition(url,"://",false); 72 | var endOfTLDpos = getPosition(url,"/",3); 73 | var tld = url.substring(0,endOfTLDpos); 74 | 75 | var ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/ 76 | if(url.substring(protocolEndPos,endOfTLDpos).match(ip_regex)){ 77 | return url.substring(protocolEndPos,endOfTLDpos); 78 | } 79 | var numOfPeriods = (tld.match(/\./g) || []).length; 80 | if(numOfPeriods>=2){ 81 | // + 1 for the length of the '.' 82 | var startOftld = getPosition(tld,".", numOfPeriods-1)+1; 83 | return tld.substring(startOftld,endOfTLDpos); 84 | } 85 | return url.substring(protocolEndPos,endOfTLDpos); 86 | } 87 | function getPort(url){ 88 | var tld = getTLDomain(url); 89 | if(tld.indexOf(":") === -1){ 90 | return ""; 91 | } 92 | return tld.substring(tld.indexOf(":"),tld.length); 93 | } 94 | 95 | function getPosition(haystack, needle, position) { 96 | return haystack.split(needle, position).join(needle).length; 97 | } 98 | 99 | // beginning:true or end:false boolean 100 | function getFirstPosition(haystack,needle,beginning){ 101 | var position; 102 | position = haystack.indexOf(needle); 103 | if (beginning==false){ 104 | position = position + needle.length; 105 | } 106 | return position; 107 | } --------------------------------------------------------------------------------