diff --git a/LICENSE b/LICENSE index 413da7f..2d1b943 100644 --- a/LICENSE +++ b/LICENSE @@ -1,5 +1,6 @@ MIT License +Copyright (c) 2020 Jakub Jáchym Copyright (c) 2017 Loïc HALL Permission is hereby granted, free of charge, to any person obtaining a copy diff --git a/README.md b/README.md index 3374093..d08ab48 100644 --- a/README.md +++ b/README.md @@ -1,9 +1,10 @@ -# Xdebug-ext +# Xdebug-ext+ -This is an extension for Mozilla Firefox 57+ (Quantum). You can download it from there : https://addons.mozilla.org/en-US/developers/addon/xdebug-ext-quantum/ +This is an extension for Mozilla Firefox 57+ (Quantum). It can be installed to Firefox from +[Mozilla Add-on directory](https://addons.mozilla.org/en-US/firefox/addon/xdebug-ext-plus/). -It is a port of the Easiest Xdebug extension, but only the XDEBUG_SESSION cookie is supported for nom. Feel free to ask for other features if you need them. +It is a fork of [Xdebug-ext extension](https://github.com/lhall-adexos/xdebug-ext/). ## Bug report -If you feel something is wrong, feel free to submit an issue : https://github.com/lhall-adexos/xdebug-ext/issues \ No newline at end of file +If you feel something is wrong, feel free to submit an [issue at GitHub](https://github.com/JakubJachym/xdebug-ext-plus/issues). \ No newline at end of file diff --git a/background.js b/background.js index bbec057..7a07620 100644 --- a/background.js +++ b/background.js @@ -1,31 +1,27 @@ -var currentTab; -var currentState; +let currentTab; +let currentState; /* * Enable or disable Debugging */ function toggleButton(event) { - console.log('toggleButton'); - console.log(typeof event); - console.log(event); - - function onExecuted(result) { - browser.tabs.executeScript( - currentTab.id, { - file: "cookies.js" - }); - } - - function onError(error) { - console.log(`Can't execute script: ${error}, for current tab ID ` + currentTab.id); - } - - var userTriggered = typeof event === 'object'; - var executing = browser.tabs.executeScript( - currentTab.id, { - code: "var currentState = "+ currentState +"; var userTriggered = " + userTriggered + ";" - }); - executing.then(onExecuted, onError); + function onExecuted() { + browser.tabs.executeScript( + currentTab.id, { + file: "cookies.js" + }); + } + + function onError(error) { + console.log(`Can't execute script: ${error}, for current tab ID ` + currentTab.id); + } + + const userTriggered = (typeof event === 'object'); + const executing = browser.tabs.executeScript( + currentTab.id, { + code: "var currentState = " + currentState + "; var userTriggered = " + userTriggered + ";" + }); + executing.then(onExecuted, onError); } browser.browserAction.onClicked.addListener(toggleButton); @@ -34,50 +30,48 @@ browser.browserAction.onClicked.addListener(toggleButton); * Switches currentTab to reflect the currently active tab */ function updateActiveTab(e) { - console.log('Event', e); - function isSupportedProtocol(urlString) { - var supportedProtocols = ["https:", "http:", "ftp:", "file:"]; - var url = document.createElement('a'); - url.href = urlString; - return supportedProtocols.indexOf(url.protocol) != -1; - } - - function updateTab(tabs) { - if (tabs[0]) { - currentTab = tabs[0]; - console.log('Current tab is ' + currentTab.id); - if (isSupportedProtocol(currentTab.url)) { - toggleButton(); - } - } + function isSupportedProtocol(urlString) { + const supportedProtocols = ["https:", "http:", "ftp:", "file:"]; + let url = document.createElement('a'); + url.href = urlString; + + return (supportedProtocols.indexOf(url.protocol) !== -1); + } + + function updateTab(tabs) { + if (tabs[0]) { + currentTab = tabs[0]; + if (isSupportedProtocol(currentTab.url)) { + toggleButton(); + } } + } - var gettingActiveTab = browser.tabs.query({active: true, currentWindow: true}); - gettingActiveTab.then(updateTab); + const gettingActiveTab = browser.tabs.query({active: true, currentWindow: true}); + gettingActiveTab.then(updateTab); } function updateButton(result) { - if (typeof currentTab.id === 'undefined') { - console.log('No current tab yet') - return; - } - - browser.browserAction.setIcon({ - path: result ? { - 32: "data/icons/debug_32_active.png", - 48: "data/icons/debug_32_active.png" - } : { - 32: "data/icons/debug_48_inactive.png", - 48: "data/icons/debug_48_inactive.png" - }, - tabId: currentTab.id - }); - - browser.browserAction.setTitle({ - title: result ? 'Disable Debugging' : 'Enable Debugging', - tabId: currentTab.id - }); + if (typeof currentTab.id === 'undefined') { + return; + } + + browser.browserAction.setIcon({ + path: result ? { + 32: "data/icons/debug_32_active.png", + 48: "data/icons/debug_32_active.png" + } : { + 32: "data/icons/debug_48_inactive.png", + 48: "data/icons/debug_48_inactive.png" + }, + tabId: currentTab.id + }); + + browser.browserAction.setTitle({ + title: result ? 'Disable Debugging' : 'Enable Debugging', + tabId: currentTab.id + }); } // listen to tab URL changes @@ -93,11 +87,10 @@ browser.windows.onFocusChanged.addListener(updateActiveTab); //browser.browserAction.onClicked.addListener(updateActiveTab); function notify(message) { - console.log(message); - if (typeof message.state !== 'undefined') { - updateButton(message.state); - currentState = message.state; - } + if (typeof message.state !== 'undefined') { + updateButton(message.state); + currentState = message.state; + } } // Listen to content scripts messages diff --git a/cookies.js b/cookies.js index 0935458..7dfecad 100644 --- a/cookies.js +++ b/cookies.js @@ -2,137 +2,136 @@ * http://www.quirksmode.org/js/cookies.html */ if (typeof options === "undefined") { - function onError(error) { - console.log(`Can't get var: ${error}`); - } + function onError(error) { + console.log(`Can't get var: ${error}`); + } + + function onGot(item) { + options.checkCookies.XDEBUG_SESSION = item.idekey || "PHPSTORM"; + options.samesite = item.cookieSameSite || "Strict"; + options.secure = item.cookieSecure || false; + } + + options = { + cookieName: "XDEBUG_SESSION", + checkCookies: { + XDEBUG_SESSION: '', + /*XDEBUG_TRACE: '', + XDEBUG_PROFILE: ''*/ + }, + samesite: "Strict", + secure: false, + }; + + let getting = browser.storage.local.get(["idekey", "cookieSameSite", "cookieSecure"]); + getting.then(onGot, onError); +} - function onGot(item) { - var idekey = "PHPSTORM"; - if (item.idekey) { - idekey = item.idekey; - } - options.checkCookies.XDEBUG_SESSION = idekey; - } - var options = { - cookieName: "XDEBUG_SESSION", - checkCookies: { - XDEBUG_SESSION: '', - /*XDEBUG_TRACE: '', - XDEBUG_PROFILE: ''*/ - } - }; - - var getting = browser.storage.local.get("idekey"); - getting.then(onGot, onError); -} +function createCookie(name, value, days, samesite = "Lax", secure = false) { + let expires = ""; + if (days) { + let date = new Date(); + date.setTime(date.getTime() + (days * 24 * 60 * 60 * 1000)); + expires = "; expires=" + date.toUTCString(); + } -function createCookie(name, value, days) { - if (days) { - var date = new Date(); - date.setTime(date.getTime()+(days*24*60*60*1000)); - var expires = "; expires=" + date.toGMTString(); - } else { - var expires = ""; - } + if (typeof document.cookie != 'undefined') { + browser.runtime.sendMessage("Cookie " + name + " created with value " + value); + + let cookieStr = name + "=" + value + expires + "; path=/; SameSite=" + samesite; + + if (secure || samesite === "None") { + cookieStr += "; Secure"; + } - if (typeof document.cookie != 'undefined') { - browser.runtime.sendMessage("Cookie " + name + " created with value " + value); - document.cookie = name + "=" + value + expires + "; path=/"; - } + document.cookie = cookieStr; + } } function readCookie(name) { - var nameEQ = name + "="; - - if (typeof document.cookie == 'undefined') { - //console.log('this doc has no cookies'); - return null; - } - - var ca = document.cookie.split(';'); - for (var i=0;i < ca.length;i++) { - var c = ca[i]; - while (c.charAt(0)==' ') - c = c.substring(1,c.length); - if (c.indexOf(nameEQ) == 0) - return c.substring(nameEQ.length,c.length); - } - - return null; + let nameEQ = name + "="; + + if (typeof document.cookie === 'undefined') { + //console.log('this doc has no cookies'); + return null; + } + + let ca = document.cookie.split(';'); + for (let i = 0; i < ca.length; i++) { + let c = ca[i]; + while (c.charAt(0) === ' ') + c = c.substring(1, c.length); + if (c.indexOf(nameEQ) === 0) + return c.substring(nameEQ.length, c.length); + } + + return null; } function eraseCookie(name) { - createCookie(name, "", -1); + createCookie(name, "", -1); } function isSet(name) { - return readCookie(name) !== null; + return readCookie(name) !== null; } browser.runtime.sendMessage(options); browser.runtime.sendMessage({currentState: currentState, userTriggered: userTriggered}); + if (userTriggered === false) { - // tab changed or page loaded - - var result = {}; - for (var cookieName in options.checkCookies) - { - browser.runtime.sendMessage("Checking cookie " + cookieName); - result[cookieName] = isSet(cookieName); - - // if user changes values, we must immediately update cookies after any tab changing or page loading - if (isSet(cookieName)) - { - var currentValue = readCookie(cookieName); - var newValue = options.checkCookies[cookieName]; - browser.runtime.sendMessage("Cookie found with value " + currentValue); - if (newValue != currentValue) - { - browser.runtime.sendMessage("Cookie values mismatch, resetting ("+ currentValue + " -> "+ newValue +")"); - eraseCookie(cookieName); - createCookie(cookieName, newValue, 1); - } - } - } - - browser.runtime.sendMessage({"state": result[cookieName]}); -} -else -{ - // widget button pressed - var cookieName = options.cookieName; - var cookieValue = options.checkCookies[cookieName]; - browser.runtime.sendMessage({"debug": 'Button pressed'}); - - if (!isSet(cookieName)) - { - browser.runtime.sendMessage({"debug": 'Needs to be set'}); - // sometimes URL is null e.g. when we're on about:addons under linux (is it true?) - if (typeof document.URL == 'string' && document.URL.substring(0, 4) == 'http') - { - createCookie(cookieName, cookieValue, 1); - - // Cookies can be disabled - var state = isSet(cookieName); - if (!state) { -// console.log('Couldnt set cookie! url: '+document.URL); - alert('Please enable cookies for this page'); - } - - browser.runtime.sendMessage({"state": state}); - } - else - { - browser.runtime.sendMessage({"state": false}); - } - } - else - { - browser.runtime.sendMessage({"debug": 'Needs to be removed'}); - eraseCookie(cookieName); - browser.runtime.sendMessage({"state": false}); - } -} + // tab changed or page loaded + let result = {}; + + for (const cookieName in options.checkCookies) { + browser.runtime.sendMessage("Checking cookie " + cookieName); + result[cookieName] = isSet(cookieName); + + // if user changes values, we must immediately update cookies after any tab changing or page loading + if (isSet(cookieName)) { + let currentValue = readCookie(cookieName); + let newValue = options.checkCookies[cookieName]; + let samesite = options.samesite; + let secure = options.secure; + browser.runtime.sendMessage("Cookie found with value " + currentValue); + if (newValue !== currentValue) { + browser.runtime.sendMessage("Cookie values mismatch, resetting (" + currentValue + " -> " + newValue + ")"); + eraseCookie(cookieName); + createCookie(cookieName, newValue, 1, samesite, secure); + } + } + browser.runtime.sendMessage({"state": result[cookieName]}); + } +} else { + // widget button pressed + let cookieName = options.cookieName; + let cookieValue = options.checkCookies[cookieName]; + let samesite = options.samesite; + let secure = options.secure; + browser.runtime.sendMessage({"debug": 'Button pressed'}); + + if (!isSet(cookieName)) { + browser.runtime.sendMessage({"debug": 'Needs to be set'}); + // sometimes URL is null e.g. when we're on about:addons under linux (is it true?) + if (typeof document.URL === 'string' && document.URL.substring(0, 4) === 'http') { + createCookie(cookieName, cookieValue, 1, samesite, secure); + + // Cookies can be disabled + let state = isSet(cookieName); + if (!state) { + alert('Please enable cookies for this page'); + } + + browser.runtime.sendMessage({"state": state}); + } else { + browser.runtime.sendMessage({"state": false}); + } + } else { + browser.runtime.sendMessage({"debug": 'Needs to be removed'}); + eraseCookie(cookieName); + browser.runtime.sendMessage({"state": false}); + } +} diff --git a/manifest.json b/manifest.json index 20b53a2..bc9d37b 100644 --- a/manifest.json +++ b/manifest.json @@ -1,10 +1,9 @@ { - "description": "Adds a simple button to inject a Xdebug cookie.", "manifest_version": 2, - "name": "Xdebug-ext", - "version": "1.2", - "homepage_url": "https://github.com/lhall-adexos/xdebug-ext", + "name": "Xdebug-ext+", + "version": "1.0", + "homepage_url": "https://github.com/JakubJachym/xdebug-ext-plus", "icons": { "48": "data/icons/debug_48_active.png" }, diff --git a/options.html b/options.html index 4b41832..516c1af 100644 --- a/options.html +++ b/options.html @@ -1,29 +1,56 @@ - + + Xdebug-ext+ Options -

Extension options

- Learn how to setup your web server and use Xdebug : Learn more. - + Learn how to setup your web server and use Xdebug: Learn more.

+ Settings saved.
diff --git a/options.js b/options.js index 240e5e9..0cc3627 100644 --- a/options.js +++ b/options.js @@ -1,23 +1,48 @@ function saveOptions(e) { - e.preventDefault(); - browser.storage.local.set({ - idekey: document.querySelector("#idekey").value - }); + e.preventDefault(); + browser.storage.local.set({ + idekey: document.querySelector("#idekey").value, + cookieSameSite: document.querySelector("#cookie_samesite").value, + cookieSecure: (document.querySelector("#cookie_secure").value === "1"), + }); + + document.querySelector("#msg_settings_saved").classList.remove("u-isHidden"); + window.setTimeout(function () { + document.querySelector("#msg_settings_saved").classList.add("u-isHidden"); + }, 3000); } function restoreOptions() { - function setCurrentChoice(result) { - document.querySelector("#idekey").value = result.idekey || "PHPSTORM"; - } + function setCurrentChoice(result) { + document.querySelector("#idekey").value = result.idekey || "PHPSTORM"; + document.querySelector("#cookie_samesite").value = result.cookieSameSite || "Strict"; + document.querySelector("#cookie_secure").value = (result.cookieSecure === true) ? "1" : "0"; + } + + function onError(error) { + console.log(`Error: ${error}`); + } - function onError(error) { - console.log(`Error: ${error}`); - } + const getting = browser.storage.local.get(["idekey", "cookieSameSite", "cookieSecure"]); + getting.then(setCurrentChoice, onError); + + handleSecureOption(); +} - var getting = browser.storage.local.get("idekey"); - getting.then(setCurrentChoice, onError); +function handleSecureOption() { + const secureSelect = document.querySelector("#cookie_secure"); + const secureHint = document.querySelector("#cookie_secure_hint"); + if (document.querySelector("#cookie_samesite").value === "None") { + secureSelect.value = "1"; + secureSelect.disabled = true; + secureHint.classList.remove("u-isHidden"); + } else { + secureSelect.disabled = false; + secureHint.classList.add("u-isHidden"); + } } document.addEventListener("DOMContentLoaded", restoreOptions); -document.querySelector("form").addEventListener("submit", saveOptions); \ No newline at end of file +document.querySelector("form").addEventListener("submit", saveOptions); +document.querySelector("#cookie_samesite").addEventListener("change", handleSecureOption); diff --git a/styles.css b/styles.css index 473283f..b7c29b2 100644 --- a/styles.css +++ b/styles.css @@ -1,6 +1,5 @@ body.options { - background-color: rgba(217, 222, 255, 0.7); - padding: 20px; + padding: 20px 0; } h1 { @@ -11,29 +10,100 @@ h1 { margin: 0; padding: 0; } + .options ul li { list-style: none; - border-left: 3px solid #1726b8; - padding: 10px 0 10px 15px; + padding: 10px 0; margin-bottom: 15px; background: white; } -.options ul li:nth-of-type(2) { - border-color: #1d6218; + +.options ul li h2 { + padding: 0; + margin: 0; } -.options ul li:nth-of-type(3) { - border-color: #892d1e; +.options ul li input { + width: 20em; + margin: 0; + padding: 0.25em 0.5em; } -.options ul li h2 { padding : 0; margin: 0;} +.options ul li select { + width: 10em; + margin: 0; + padding: 0.25em 0.5em; +} + .options ul li input[type=checkbox] { -moz-transform: scale(1.5); /* FF */ -webkit-transform: scale(1.5); /* Safari and Chrome */ padding: 10px; margin-right: 10px; } -.options .buttons { text-align: left; } + +.options .formItemContainer { + margin-bottom: 0.5em; + display: flex; + align-items: center; +} + +.options .formItem { + display: flex; + align-items: center; + justify-content: space-between; +} + +.options .formItem input, +.options .formItem select { + flex-grow: 2; +} + +.options .buttons { + text-align: left; +} + .options form button[type=submit] { font-size: 1.3em; width: 15%; text-align: center; +} + +.options form label { + display: inline-flex; + width: 5em; + margin: 0.2em 0; +} + +.options .u-isHidden { + display: none; +} + +.options .help { + margin-left: 0.5em; +} + +.options .samesiteSecureInfo { + margin-left: 5.1em; +} + +.msg { + margin-left: 1em; +} + +.msg-ok { + color: #1d6218; +} + +@media only screen and (max-width: 400px) { + .options .formItemContainer { + flex-direction: column; + align-items: normal; + } + + .options .formItemContainer > * { + margin-right: 5px; + } + + .options .samesiteSecureInfo { + margin-left: 0; + } } \ No newline at end of file diff --git a/xdebug-ext.zip b/xdebug-ext.zip deleted file mode 100644 index 397d03c..0000000 Binary files a/xdebug-ext.zip and /dev/null differ