I'm writing a greasemonkey script to keep session open on a webapp I use for work.
Which javascript command would you use to create some feedback with the server and ensure the session doesn't fall without having to bother the user making a complete refresh of the page?
I've solved the issue using:
function keepAlive() {
var httpRequest = new XMLHttpRequest();
httpRequest.open('GET', "/restricted_file_url");
httpRequest.send(null);
}
setInterval(keepAlive, 840000); //My session expires at 15 minutes
Using some tips from Jesse's answer, here's the complete code.
You will need to update the #match param with your site's domain
// ==UserScript==
// #name Auto session extender
// #namespace http://obive.net/
// #version 0.2
// #description Automatically extend server-side session
// #author Charlie Hayes
// #match http://obive.net/
// #grant GM_getValue
// #grant GM_setValue
// #noframes
// ==/UserScript==
(function() {
'use strict';
console.log('The session for this site will be extended automatically via userscript.');
var minute = 60*1000;
var refreshTime = 15 * minute;
var iframe = document.createElement("iframe");
iframe.style.width = 0;
iframe.style.height=0;
var loc = window.location;
var src = loc.protocol +'//' + loc.host + loc.pathname;
src += loc.search ? (loc.search + '&') : '?';
src += 'sessionextendercachebuster=';
var reloadIframe = function(){
var time = new Date().getTime();
var lastRefresh = GM_getValue('lastRefresh');
var timeSinceLastRefresh = time - lastRefresh;
if (!lastRefresh || timeSinceLastRefresh > refreshTime - minute) {
console.log('Auto-extending session');
iframe.src = src + time;
GM_setValue('lastRefresh',time);
setTimeout(reloadIframe, refreshTime);
setTimeout(function(){
// Unload the iframe contents since it might be taking a lot of memory
iframe.src='about:blank';
},10000);
}else{
console.log('Another tab/window probably refreshed the session, waiting a bit longer');
setTimeout(reloadIframe, refreshTime - timeSinceLastRefresh - minute);
}
};
setTimeout(reloadIframe, refreshTime);
document.body.appendChild(iframe);
})();
Second choice
If you absolutely insist on using Greasemonkey, any element.click() method on any event that submits an XMLHTTPrequest should do.
First choice
If you are willing to use a solution that does not require you to write a Greasemonkey script:
ReloadEvery 3.0.0, by Jaap Haitsma
This reloads web pages every so many seconds or minutes. The function is accessible via the context menu (the menu you get when you right click on a web page) or via a drop down menu on the reload button.
It's not what you asked for, but unless you simply want to brush up on your javascript skills, this is probably the most straight-forward method for solving your problem.
If you want to write JavaScript to solve this (the other answers are a lot easier and I would recommend going the easier route), here's what I would do:
Call document.createElement("iframe") to create an iframe
Size the iframe to 0x0, style.display = "none", set the ID to something, and set the src property to a page on the site that will extend your session
Use document.body.appendChild to add the iframe to the page
Using setTimeout refresh the iFrame using window.frames['iframeID'].location.reload(true); and also call setTimeout to refresh the page again.
See if the other answers would work because using JavaScript seems like it would be more trouble than it's worth.
I can definitely recommend the solution suggested by dreftymac!
If you don't want to worry about remembering to click the reloadevery option, your grease monkey script is simply
window.location.href = window.location.href
This is presuming you don't want to keep the page constantly refreshing, as suggested by others.
Ordinarily, if you were simply looking to ping the server, you would probably do best to do something like use an image that you know exists on the remote server, and check it's height - thus creating traffic.
However, your problem (I presume) needs to access some limited area of the website, in order to keep the session active... with this being the case (and the fact that you can't directly ping), find a page that is 'restricted' and do an Ajax call, or similar. Don't quote me on this, as I'm by no means a JavaScript expert... just throwing out a potential solution.
Related
I have created a cookie banner related plugin for my site and now I would like to run the tracking code scripts once the user accepts the cookie banner.
I was able to inject the code with insertAdjacentHTML and now I would like to figure out how to execute this code so that the related tracking cookies are triggered.
I have seen eval(), but I have also seen that it is not a recommended function and it opens a security hole.
This is my code:
http.onreadystatechange = function() { //Call a function when the state changes.
if(http.readyState == 4 && http.status == 200) {
var con_cod = JSON.parse(this.responseText);
var consents = con_cod["consents"];
var head = document.getElementsByTagName("head")[0];
var code_before_end_head = con_cod["code_before_end_head"];
head.lastElementChild.insertAdjacentHTML("afterend", code_before_end_head);
var now = new Date();
var time = now.getTime();
var expireTime = time + 24 * 60 * 60 * 1000;
now.setTime(expireTime);
document.cookie = cookie_name+'='+JSON.stringify(consents)+'; expires='+now.toUTCString()+'; SameSite=None; Secure; path=/';
}
}
http.send(params);
How can I solve this situation? Of course I could also make the page reload, but this is not a good user experience for my visitors.
UPDATE:
I am using the code given here as recommended in the comments:
Jquery cookie monitor
I am now able to see when the cookie is created and modified and give a response accordingly.
I am currently using alerts to make sure of this, but now I would need to run external JavaScript code such as Hotjar or Google Analytics code that if it is just injected (which I am doing) will not run.
This for example is the Hotjar JavaScript code that I am trying to run unsuccessfully:
<!-- Hotjar Tracking Code -->
<script id="gcbi-statistics">
(function(h,o,t,j,a,r){
h.hj=h.hj||function(){(h.hj.q=h.hj.q||[]).push(arguments)};
h._hjSettings={hjid:7349271,hjsv:6};
a=o.getElementsByTagName('head')[0];
r=o.createElement('script');r.async=1;
r.src=t+h._hjSettings.hjid+j+h._hjSettings.hjsv;
a.appendChild(r);
})(window,document,'https://static.hotjar.com/c/hotjar-','.js?sv=');
</script>
I was able to find a much simpler solution.
This is the code I used to inject the various scripts and have them run once inserted:
// Remove comments and HTML tags using the replace function and a regular expression
var plainText = code_before_end_head[key_cod].replace(/<!--[\s\S]*?-->|<[^>]*>/g, '');
// Create a new script element
const script = document.createElement('script');
// Assigns an ID to the script element
script.id = 'gcbi-'+key_con;
// Assigns the code to be executed to the script element
script.innerHTML = plainText;
// Injects the script element into the head section of the document
document.head.appendChild(script);
There was no need to use the listenCookieChange function since everything is done via AJAX.
The code shown above was just inserted inside the request when receiving response from the PHP file.
I hope it can help!
UPDATE:
I stopped using an array (As I originally was when I first posted this)
I seem to be having issues with my script. I don't know why, but when the web page unloads, the window.SpecificURL doesn't save. I know the script to get it is fine, the script to store it is as well. Is there something I am missing? Here is my code:
var UWDV = window.UWDV = "UserWindowDataV2"; // What Version Is The User Window Data Stored As
setTimeout(function(){ // Wait So Stuff Can Load
if (!window.SpecificURL){ // If Not A Special URL To Load
window.SpecificURL = GetCookie(UWDV); // Get The User's Last Known State
var WSURL = window.SpecificURL; // Set Variable
// if (typeof WSURL[0]!=="string" || WSURL[0].length < 2){SetCookie(UWDV, ["home"]); WSURL = ["home"];} // If It Glitched, Fix Automatically
console.log(WSURL);
fillpage(WSURL); // Load Page PC
mobileload(WSURL); // Load Page Mobile
window.SpecificURLReady = true;
}
}, 100);
window.addEventListener("unload", function(){SetCookie(window.UWDV, window.SpecificURL);}); // Add Save Page Status Function
(FYI: The fillpage & mobileload functions set window.SpecificURL to whatever the choice was.)
(FYI2: This is fired 2 seconds after the website loads)
I fixed it by switching from Arrays to save data, to a string. Sorry for any inconvenience to someone trying to solve this!
A page I use a lot has a mildly useless timeout feature, such that after one hour it will automatically log the user out. I'm trying to write an extension for chrome that would extend this timeout period to ten hours, however as I have never written an extension before I'm running into problems. I know content scripts cannot influence page variables directly, however I have been trying to use Method 2 on this page which I haven't been able to get to work.
The code in the website for the timeout is basic:
var x = 3600
var y = 1;
var z = 300
x = x-y
setTimeout("startClock()", 1000)
function startClock(){
x = x-y
setTimeout("startClock()", 1000)
if(x==z){
alert("Your Session is about to expire. After a period of inactivity (60 minutes), all current session information is removed and you will be required to log in again.");
} else if (x==0) {
document.location.href = "content?module=home&page=homepg&logoutFinal=1";
}
I wrote a basic manifest file for the extension that uses content_scripts to call contentscript.js, which is virtually the same as what was given in the Method 2 example.
var actualCode = ['var x = 36000'].join('\n');
var script = document.createElement('script');
script.textContent = actualCode;
(document.head||document.documentElement).appendChild(script);
script.parentNode.removeChild(script);
My current desire is to have an extension that automatically resets the value of x to 36000 seconds, or 10 hours upon the page refresh.
After troubleshooting for some time, I discovered that the entire problem was an issue in the manifest.json, specifically the matches section. The code given above works, and so do the methods given in the document that I linked to.
Thanks to devnull69 for the quick response, I attempted that method and after solving the problem in manifest.json, it worked to remove the timeout entirely.
tl;dr: A bookmarklet that opens in a new tab: random link (with specified multiple html-classes) from a specified domain and code that works with current logins. Thank you.
short version of butchered code:
javascript:
(
var % 20 site = domain.com
function() {
window.location.host == site
void(window.open(document.links[Math.floor(document.querySelectorAll("a.class1, a.class2"))].href, '_blank'))
}();
//beautified with: http://jsbeautifier.org/
To whom it may concern:
I have searched around for a while and even considered switching services but although some come close or are similar to my particular request, none have served to address everything the request entails.
Execute the script on a specific domain even when no page from said domain is currently open. If login authentication for attaining the information or data for execution is required, read or work in conjunction with existing session.
Fetch from a specific domain host, a random link out of all links on that domain with a certain html-class (or indeed otherwise) using preferably, css-selectors.
Open the results in a new tab.
From butchering such similarities, the result became something like this:
//bookmarklet
javascript:
//anonymous function+ wrapped code before execution
(
// function global variables for quick substitution
var %20 site = domain.com
function(){
//set domain for script execution
window.location.host == site
//open new tab for
void(window.open(document.links
//random link
[Math.floor
//with specific classes (elements found with css selectors)
(document.querySelectorAll("a.class1, a.class2"))
]//end random-query
.href,'_blank' //end page-open
)//end link-open
)//end "void"
}//end function defintion
//execute
();
//(tried) checked with:
//http://www.javascriptlint.com/online_lint.php
Lastly, i have attained at most, basic css knowledge. I apologise if this request has anybody headdesking, palming or otherwise in gtfo mode. It is only too sad there is apparently no tag for "Warning: I DIY-ed this stuff" in StackExchange. However, i still would like answers that go into a bit of depth of explaining why and what each correction and modification is.
Thank you presently, for your time and effort.
Theoretically, the following code should do what you want:
window.addEventListener('load', function ( ) {
var query = 'a.class1[href], a.class2[href]';
var candidates = document.querySelectorAll(query);
var choice = Math.floor(Math.random() * candidates.length);
window.open(candidates.item(choice).href, 'randomtab');
}, true);
window.location.href = 'http://domain.com';
But it doesn't, because the possibility to retain event listeners across a page unload could be abused and browsers protect you against such abuse.
Instead, you can manually load the domain of your choice and then click a simpler bookmarklet with the following code:
var query = 'a.class1[href], a.class2[href]';
var candidates = document.querySelectorAll(query);
var choice = Math.floor(Math.random() * candidates.length);
window.open(candidates.item(choice).href, 'randomtab');
You could wrap the above in javascript:(function ( ) { ... })(); and minify as before, but it already works if you just minify it and only slap a javascript: in front.
I understand your situation of being an absolute beginner and posting "DIY" code, but I'm still not going to explain step-by-step why this code works and yours doesn't. The first version of the code above is complex to explain to a beginner, and the list of issues with the code in the question is too long to discuss all of them. You'll be better off by studying more Javascript; a good resource with tutorials is MDN.
I'm trying to write a greasemonkey script that will automatically perform the Steam store age check before allowing you to view mature game content.
My problem is that after the form is submitted, the website automatically redirects to a new page, and the rest of the greasemonkey script doesn't get a chance to execute:
// ==UserScript==
// #name agecheck
// #include http://store.steampowered.com/agecheck/*
// #version 1.17
// #modified 11/23/2012
// #grant GM_xmlhttpRequest
// ==/UserScript==
//Mini script for doing steam age checks automatically (used when scraping steam sites)
if (/agecheck/i.test (location.pathname) ) {
var ageForm = document.querySelector ("#agegate_box form");
ageForm.querySelector ("[name='ageDay']").value = 18;
ageForm.querySelector ("[name='ageMonth']").value = 'August';
ageForm.querySelector ("[name='ageYear']").value = 1987;
ageForm.submit();
setTimeout( function(){ window.close(); }, 10000); //Never gets to run
}
To verify the code is valid, if I simply comment out the ageForm.submit(); statement, the tab closes after 10 seconds as desired.
How can I get the window to close after submitting the form?
You can create an invisible iframe and set form's target attribute to point to that iframe. Thus the page location wont change. An example is in this question.
If you want a pure JS solution, you can check this question, as it explains how to add a callback to submit() method.
I've solved the problem using the following code which loads the result of the form submission in a hidden frame rather than allowing the form to change the current window location (which was halting the greasemonkey script):
if (/agecheck/i.test (location.pathname) ) {
var ageForm = document.querySelector ("#agegate_box form");
ageForm.querySelector ("[name='ageDay']").value = 18;
ageForm.querySelector ("[name='ageMonth']").value = 'August';
ageForm.querySelector ("[name='ageYear']").value = 1987;
var newFrame = document.createElement('frame');
newFrame.name = "PostResult"
document.body.appendChild(newFrame);
ageForm.target = newFrame.name;
ageForm.submit();
setTimeout( function(){ window.close(); }, 10000);
}
Thanks to G. Kayaalp for the tip.