Mozilla Addon SDK - Problem with Reddit example on 2nd page - javascript

I got this problem during development of my own addon, but I get the same with the reddit example, so I'll use that for simplicity.
Using the exact code from the example found here, this is what happens.
Reddit Example
This example add-on creates a panel containing the mobile version of Reddit. When the user clicks on the title of a story in the panel, the add-on opens the linked story in a new tab in the main browser window.
To accomplish this the add-on needs to run a content script in the context of the Reddit page which intercepts mouse clicks on each title link and fetches the link's target URL. The content script then needs to send the URL to the add-on script.
main.js:
var data = require("self").data;
var reddit_panel = require("panel").Panel({
width: 240,
height: 320,
contentURL: "http://www.reddit.com/.mobile?keep_extension=True",
contentScriptFile: [data.url("jquery-1.4.4.min.js"),
data.url("panel.js")]
});
reddit_panel.port.on("click", function(url) {
require("tabs").open(url);
});
require("widget").Widget({
id: "open-reddit-btn",
label: "Reddit",
contentURL: "http://www.reddit.com/static/favicon.ico",
panel: reddit_panel
});
panel.js:
$(window).click(function (event) {
var t = event.target;
// Don't intercept the click if it isn't on a link.
if (t.nodeName != "A")
return;
// Don't intercept the click if it was on one of the links in the header
// or next/previous footer, since those links should load in the panel itself.
if ($(t).parents('#header').length || $(t).parents('.nextprev').length)
return;
// Intercept the click, passing it to the addon, which will load it in a tab.
event.stopPropagation();
event.preventDefault();
self.port.emit('click', t.toString());
});
The icon is displayed in the bar, and clicking it launches the panel. Clicking a link within the panel opens it in a new tab - just as described and expected.
Clicking the "next page" link within the tab successfully fetches the next page, within the panel - as expected.
Clicking a link on the 2nd page does NOT open it in a tab, it opens it WITHIN the panel.
Here's my guess: When the page reloads within the panel, it does not reload the script specified in the contentScriptFile. Does anyone else experience this? And is there a workaround?
I'm using SDK 1.0 and FF 5.0
Question cross-posted on the Addon forum here

Recieved this answer at the Mozilla forum, and will post here as well for future reference.
Perhaps you are seeing Bug 667664 - Panel content scripts don't work after reloading or changing location. I think the workaround is to load the content in an iframe.
Which I believe might be the case, I'll try this during the day and report back.
EDIT: iframe seems to do the trick

Related

Open other webiste in new tab alogn with my website

I have a website-1 (www.example.com). When a customer reaches out to my website, the other website-2 (www.example2.com) should be open in a new tab corresponding with the website (www.example.com).
How to do this
I would like to add to Daan Teppema's answer.
Add rel property in the tag, if the website is not safe or untrusted add noopener. but if you are directing within your website remove the noreferrer for SEO tracking purposes.
Example 2
This will keep your website tab open and in the meantime open a new tab with the link you've provided.
You can do an <a> element with the target="_blank" attribute.
Like so:
Example 2
If you want them both to load, then you can make it go to the second one in another tab with javascript using the window.onload event.
Like so:
window.onload = function() {
window.open(url, '_blank').focus();
};

Javascript to reload a new tab page

window.open("http://google.com", '_blank');
var childWindow = "http://google.com";
childWindow.location.href = "http://google.com";
I have an eventAddListener that loads http://google.com on a new tab with a button press, but right after it opens the new tab of google.com, I want it to REFRESH again. NOT my base page but the NEW tab page, by itself. The code I showed is just one of the examples out of 5 pages worth of google search which don't work.
UPDATE:
var win = window.open('google.com', 'New Window'); setTimeout(function () { var win = window.open('google.com', 'New Window'); },3000);
This is the best i could come up with. It opens new tab and "Reloads" the new tab rather than refresh it.
What I want is for example, you click on new tab, you paste a link then press enter, which EXECUTES the link. I basically want a javascript function which EXECUTES the link.
You can't do this.
In order to trigger a reload in the new tab/window you need to run JS in that tab/window.
The same origin policy prevents this.
If you had control over the new page then you could have an event listener running in it and post a message asking that listener to trigger a refresh.
Obviously you can't do that with Google's page.
This question, however, reads like an XY problem. If the goal is to display fresh (and not old, cached, out of date) information and the target page is not a third party one then you shouldn't be using JS to hack your way around caching. Instead set better caching rules on the target page in the first place.
I worked on something similar in the past few weeks and the code below worked for me.
index.html
<button onclick="openTab()">New Tab</button>
<script>
function openTab(){
//this opens a new tab while creating a variable name for that tab
var newTab = window.open("https://google.com","_blank");
//this refreshes that new tab
newTab.location.reload();
}
</script>
Just to prove that this works on the new tab I used the code
<script>
function openTab(){
//this opens a new tab while creating a variable name for that tab
var newTab = window.open("https://google.com","_blank");
//this will alert in the new tab
newTab.alert("New Tab");
//before the following reload code takes effect
//this refreshes that new tab
newTab.location.reload();
}
</script>
Hopefully that's what you are looking for.
From my understanding you want the new tab to refresh once opened with JavaScript instead of the current tab where you run the JavaScript code from.
That's not directly possible. The JavaScript code will only run for the tab it was executed in. The newly opened tab does not know that JavaScript code should be running. The current tab cannot pass over instructions for the new tab to execute.
However, you can select the newly opened tab manually first and then execute Javascript code to refresh the page. But that probably defeats the purpose of what you're trying to do.

bookmarklet that works on 2 pages

I'm using a bookmarklet to inject javascript into a webpage. I am trying to login into my gmail account(that part works) and in my gmail account automatically click Sent folder as the page loads. This is the starting page:
This is the code I am using in bookmarklet:
javascript:
document.getElementById('Email').value='myEmail#gmail.com';
document.getElementById('next').click();
setTimeout(function(){
document.getElementById('Passwd').value='myPassword';
document.getElementById('signIn').click();},1000);
setTimeout(function(){
document.getElementsByClassName("J-Ke n0 aBU")[0].click();
},6000);
J-Ke n0 aBU is the class of Sent folder. This code logins into my account, but it doesn't click Sent folder.
I noticed similar behavior on other websites; whenever a new page loads or refreshes, the bookmarklet stops working.
Why is that and what is the correct way of using the same bookmarklet on different page than it was originally clicked.
Disclaimer: I don't have gmail, so I didn't test this for gmail specifically.
This answer exists to address your comment:
What about iframes. Is theoretically possible to use gmail login in an iframe and therefore when the iframe changes to another page this doesnt have effect on the bookmarklet?
Yes, it is technically possible to have a persistent bookmarklet using iframes (or, deity forbid, a frameset).
As long as your parent window (and it's containing iframe) remain on the same domain, it should work according to cross-domain spec.
It is however possible (depending on used method) to (un-)intentionally 'counter-act' this (which, depending on used counter-action, can still be circumvented, etc..).
Navigate to website, then execute bookmarklet which:
Creates iframe.
Sets onload-handler to iframe.
Replaces current web-page content with iframe (to window's full width and height).
Set iframe's source to current url (reloading the currently open page in your injected iframe).
Then the iframe's onload-handler's job is to detect (using url/title/page-content) what page is loaded and which (if any) actions should be taken.
Example (minify (strip comments and unneeded whitespace) using Dean Edward's Packer v3):
javascript:(function(P){
var D=document
, B=D.createElement('body')
, F=D.createElement('iframe')
; //end vars
F.onload=function(){
var w=this.contentWindow //frame window
, d=w.document //frame window document
; //end vars
//BONUS: update address-bar and title.
//Use location.href instead of document.URL to include hash in FF, see https://stackoverflow.com/questions/1034621/get-current-url-in-web-browser
history.replaceState({}, D.title=d.title, w.location.href );
P(w, d); //execute handler
};
D.body.parentNode.replaceChild(B, D.body); //replace body with empty body
B.parentNode.style.cssText= B.style.cssText= (
F.style.cssText= 'width:100%;height:100%;margin:0;padding:0;border:0;'
) + 'overflow:hidden;' ; //set styles for html, body and iframe
//B.appendChild(F).src=D.URL; //doesn't work in FF if parent url === iframe url
//B.appendChild(F).setAttribute('src', D.URL); //doesn't work in FF if parent url === iframe url
B.appendChild(F).contentWindow.location.replace(D.URL); //works in FF
}(function(W, D){ //payload function. W=frame window, D=frame window document
alert('loaded');
// perform tests on D.title, W.location.href, page content, etc.
// and perform tasks accordingly
}));
Note: one of the obvious methods to minify further is to utilize bracket-access with string-variables for things like createElement, contentWindow, etc.
Here is an example function-body for the payload-function (from above bookmarklet) to be used on http://www.w3schools.com (sorry, I couldn't quickly think of another target):
var tmp;
if(D.title==='W3Schools Online Web Tutorials'){
//scroll colorpicker into view and click it after 1 sec
tmp=D.getElementById('main').getElementsByTagName('img')[0].parentNode;
tmp.focus();
tmp.scrollIntoView();
W.setTimeout(function(){tmp.click()},1000);
return;
}
if(D.title==='HTML Color Picker'){
//type color in input and click update color button 'ok'
tmp=D.getElementById('entercolorDIV');
tmp.scrollIntoView();
tmp.querySelector('input').value='yellow';
tmp.querySelector('button').click();
//click 5 colors with 3 sec interval
tmp=D.getElementsByTagName('area');
tmp[0].parentNode.parentNode.scrollIntoView();
W.setTimeout(function(){tmp[120].click()},3000);
W.setTimeout(function(){tmp[48].click()},6000);
W.setTimeout(function(){tmp[92].click()},9000);
W.setTimeout(function(){tmp[31].click()},12000);
W.setTimeout(function(){tmp[126].click()},15000);
return;
}
above example (inside bookmarklet) minified:
javascript:(function(P){var D=document,B=D.createElement('body'),F=D.createElement('iframe');F.onload=function(){var w=this.contentWindow,d=w.document;history.replaceState({},D.title=d.title,w.location.href);P(w,d)};D.body.parentNode.replaceChild(B,D.body);B.parentNode.style.cssText=B.style.cssText=(F.style.cssText='width:100%;height:100%;margin:0;padding:0;border:0;')+'overflow:hidden;';B.appendChild(F).contentWindow.location.replace(D.URL)}(function(W,D){var tmp;if(D.title==='W3Schools Online Web Tutorials'){tmp=D.getElementById('main').getElementsByTagName('img')[0].parentNode;tmp.focus();tmp.scrollIntoView();W.setTimeout(function(){tmp.click()},1000);return}if(D.title==='HTML Color Picker'){tmp=D.getElementById('entercolorDIV');tmp.scrollIntoView();tmp.querySelector('input').value='yellow';tmp.querySelector('button').click();tmp=D.getElementsByTagName('area');tmp[0].parentNode.parentNode.scrollIntoView();W.setTimeout(function(){tmp[120].click()},3000);W.setTimeout(function(){tmp[48].click()},6000);W.setTimeout(function(){tmp[92].click()},9000);W.setTimeout(function(){tmp[31].click()},12000);W.setTimeout(function(){tmp[126].click()},15000);return}}));
Hope this helps (you get started)!
As JavaScript is executed in the context of the current page only, it's not possible to execute JavaScript which spans over more than one page. So whenever a second page is loaded, execution of the JavaScript of the first page get's halted.
If it would be possible to execute JavaScript on two pages, an attacker could send you to another page, read your personal information there and send it to another server in his control with AJAX (e.g. your mails).
A solution for your issue would be to use Selenium IDE for Firefox (direct link to the extension). Originally designed for automated testing, it can also be used to automate your browser.

How to open a link inside an iframe from a hta in the default browser

What I need is just like How can I open a link in the default web browser from an HTA?, but with the restriction that the link sits inside an iframe.
The iframe's loads a page in our server.
Idea: can the iframe's redirect be detected & prevented, so then we'd run code like in https://stackoverflow.com/a/185581/66372. How?
Update 1
To be clear: the problem we're trying to solve is that when the user clicks on any link, it opens in the default browser.
One option similar to mplungjan's answer, is to capture the click event for all links in the iframe's DOM. Is there a more generic option that works at the iframe, document or body level? (and thus also works with delayed loads and any other tricks)
Something like this, which should be perfectly allowed in an HTA which has elevated rights
window.onload=function() {
window.frames["iframe_in_this_document"].onload=function() {
var links = this.document.getElementsByTagName("a");
for (var i=0;i<links.length;i++) {
url = links[i].href;
if (url) links[i].onclick=function() {
var shell = new ActiveXObject("WScript.Shell");
shell.run(this.href);
return false;
}
}
}

Google Chrome opens window.open(someurl) just fine...but page/window with clicked link also opens someurl.com

As the title says "Google Chrome opens window.open(someurl) just fine...but page/window with clicked link also opens someurl.com.
When I click the "Click here" link with the onclick="shpop..." call attached, my pop up opens /facebook_login.php' correctly...BUT...at the same time, the original window opens /facebook_login.php too!
This happens in Chrome and IE, but FF is fine and doing just what i want..
I have this link:
Click here
I know I could remove the href="/facebook_login.php" and replace with href="#" .. but I need the link to work if js is disabled.
I have this js code imported in my tag:
function shpop(u,t,w,v)
{
var text = encodeURI(t);
var uri = encodeURI(u);
var h = document.location.href;
h = encodeURI(h);
var wwidth='600'; /*popup window width*/
var wheight='300'; /*popup window height*/
if(v=='' || undefined==v)v=document.domain; /*popup name/title */
switch(w){
case 'loginfb':
var url = '/facebook_login.php';
wwidth='980';
wheight='600';
break;
}
window.open(url,v,'width='+wwidth+',height='+wheight);
return false
}
Any ideas?
what is with returning false, and having false in the onclick?
This
onclick="shpop('','','loginfb','');return false"
Just needs to be
onclick="return shpop('','','loginfb','');"
If the onclick returns any error, the link will still open up. Do you see any errors in the JavaScript console? I wonder if the browsers are freaking out about any . in the window name from using document.domain. Try giving it a name.
onclick="return shpop('','','loginfb','foobar');"
According to the latest browser statistics - well last time it was measured anyway (2008) only 5% of users had Javascript disabled. Nowadays it's likely to be less. Consider that all browsers have it enabled by default. Therefore it's generally only advanced users that for whatever reason choose to disable javascript, and will therefore understand that there's a good chance any website they visit won't work as expected - Facebook, Google, Amazon - everyone uses javascript these days. It's perfectly acceptable to assume the user is using it, with one overall <noscript> version at the start of your page for those users if you really really want to cover all your bases :)
Here is the simplest solution:
<a href="/facebook_login.php"
target="FBpopup"
onclick="window.open('about:blank','FBpopup','width=980,height=600')">
Click here
</a>
You don't need return false because you actually want the link to execute.
The trick is to use the same window name in both the window.open and in the link target.
window.open will create the popup, then your login page will run in that popup.
If popups are blocked or Javascript is disabled, your login page will run in a new tab.

Categories