I'm trying to put together a quick Firefox sidebar for internal use only.
I'm struggling a bit in understanding how sidebar and main browser window communicate. What I want to do exactly is call existing javascript functions that reside in the main browser window only.
My code looks like this;
ff-sidebar.xul
<checkbox label="Button hover" checked="false" oncommand="add_enhance(this)"/>
ff-sidebar.js
function add_enhance(cb){
if (cb.checked) {
// this bit is wrong I know
window.content.document.NEWSTYLE.buttonHover();
}
}
So the question is, how do I call a function called NEWSTYLE.buttonHover() that lives in the main window?
Theoretically, this should work:
window.content.NEWSTYLE.buttonHover();
window.content points to the browser content window and the variable NEWSTYLE is defined on this window. In reality things are a bit more messy due to security mechanisms - privileged code cannot access objects of unprivileged code directly. Instead you get to access them through XPCNativeWrapper (see https://developer.mozilla.org/en/XPCNativeWrapper). Technical details changed somewhat in Firefox 4 but essentially it is still the same.
The easiest way to do what you want without introducing security issues is changing the location of the content window to a javascript: URL. Like this:
window.content.location.href = "javascript:void NEWSTYLE.buttonHover()";
You won't be able to get the result of this function but it doesn't look like you need it.
Related
Introductory comments: As an experiment, I'm debugging some code with JSFiddle. I have no trouble adding debugger; statements or displaying stuff in alert(); windows. My problem is with the Chrome Console: I'd like to use it to print out the values of variables.
Illustrative example: On JSFiddle, I put the following code in the JavaScript box.
var sampleVar = "test value";
After the code has run, it seems that I have no way of viewing the variable values. I can view them before the program's run to completion, by adding a debugger; statement and evaluating sampleVar on the console. (As shown by this (ridiculously simple) JSFiddle and this screenshot.)
Further extrapolation: But I'd like to be able to open up the complete program and probe through it's variables. Is there a way for me to do that? I tried opening up the console and evaluating sampleVar but it appears to be undefined on the top-level scope. (As shown in this screenshot.)
Restatement of question Where is JSFiddle putting my variables? How do I access them?
Postscript: Sorry for linking to imgur, I thought adding the pictures directly would distract from the question.
Notable comparison: Contrast this difficulty debugging JSFiddle with the ease of debugging JSBin. If I open a "Console" frame in JSBin I can recall the variables I declared in my code, no problem.
Where is JSFiddle putting my variables? How do I access them?
It's putting it where you're telling it to. JSFiddle defaults to put all your code in a window.onload function which means everything you declare with var is local to that callback. (You can of course set properties on window explicitly). Here is such an example.
This setting is changeable from the left hand menu - if you move it to head or body you will have access to them from the developer tools. Moreover, it's worth mentioning that if you invoke the debugger while that code is running you will have access to those variables even if they are in a closure.
The code is evaluated in an iframe on a different domain (fiddle.jsshell.net). This is done for security reasons.
edit: In Firebug, you can use cd(document.querySelector('iframe').contentWindow);, in Chrome you can use the dropdown next to the filter icon to switch frames.
Does anyone know how to open new with specific size?
brackets object does not contain any function to do that - there's only 2 brackets.app and brackets.fs object. Also if you try to open new window with window.open("http://stackoverflow.com","some title","width=500,height=500"); it won't set the window size.
Any ideas/suggestions?
It looks like a bug in brackets-shell that the size you specify is getting ignored. (It could also be bug in CEF, the underlying Chromium wrapper that brackets-shell uses, but this implies it normally works in vanilla CEF – I'm guessing it's broken by the brackets-shell code that remembers your last window size across launches).
However, it's not a good idea to open an arbitrary website inside the Brackets shell itself. For one thing, you won't get back/forward buttons, or an address bar, or any of the other standard browser functionality. If you want to open an external website, use NativeApp.openURLInDefaultBrowser() instead (though just like clicking a link in any other app, you won't get to pick the window size). Or if you're building some UI that's more like a Brackets feature (not a remote URL), then it'd be much easier to use in-window popups instead – see the Dialogs API.
That is how you open a new window, and set the size. I would assume you are coming across something else in your code, that is causing an error that you are not seeing.
Try binding it to a event call, like during a click event. Posting the code this applies to will help.
I'm guessing it's broken by the brackets-shell code that remembers your last window size across launches
Can anyone point to this code so I can take a look at it? Just get me close...
I have written a function to remove an iFrame, however the iFrame I want to remove is called in another php-script. I am wondering how i can refer to this script. This is the code for when the iFrame would be in the same script:
function removeFrame(framename,action){
iFrameObject = document.getElementById(framename);
iFrameObject.style.display = action;
}
So i want something like 'otherpage.php.document.getElementbyId(framename)' but I don't really know how to do this..
Before I answer your question, I would highly recommend avoiding situations like this - communication between frames - if at all possible because it becomes messy very quickly.
However, you can accomplished what you're asking for with a small modification to your code. The amended function will when invoked from the iframe or from the parent window itself. Keep in mind, though, that inter-window communication are subject to the same origin policy.
function removeFrame(framename,action){
iFrameObject = window.parent.document.getElementById(framename);
iFrameObject.style.display = action;
}
This change involves pointing to the current window's parent, which in the case of the iframe is the page that embeds it. When the current window has no real parent window, window.parent references the current window (which explains why this function works on the parent page or within an iframe).
I know that this question was asked earlier but the OP didn't get any suitable answer.
So the question is:
How to access page context to call some js function in FF overlay (toolbar in my case).
I have <toolbarbutton> element with onclick="nextTrack()". nextTrack declared in the included JS file. Function executes when I press toolbar button, but I cannot exec function that I'm sure exists on the page.
I cannot modify the page, because it is an external site, but I really want to make my extension.
Of course I can (and I am) use something like mainDocument.getElementById("player_play").click(), but page already has an audioPlayer object that has all ability I need: play, pause, next, prev etc.
For more cleanliness I make an extension to control an audio player for vkontakte social network (well known social network in exUSSR countries). So you can look at example page here, maybe it can be helpfull: http://vk.com/wall6843477_2327.
When you start listening the bar with controls must appear you can find lot of stuff like audioPlayer.nextTrack(); audioPlayer.prevTrack(); etc.
You aren't accessing content directly, you are rather going through XPCNativeWrapper. This means that all JavaScript properties defined by the content page are invisible (which is a security feature). In your case, the simplest secure solution is to use the javascript: protocol:
mainDocument.defaultView.location.href = "javascript:void audioPlayer.play()";
This way you won't be able to get a result back but from it seems that you don't need to.
I am looking into ways to extend Firefox pop-up blocking from an extension. One option is replacing window.open() (or rather Window.prototype.open()) in the webpage by a wrapper function. An important requirement is that this manipulation cannot be detected or reverted by the webpage. For example, if I simply do this:
Window.prototype.open = wrapper;
The webpage can easily revert the change by doing:
delete Window.prototype.open;
Instead I can use Object.defineProperty() to set advanced property flags:
Object.defineProperty(Window.prototype, "open", {value: wrapper, configurable: false});
The webpage can no longer revert this change but it can still detect it: delete Window.prototype.open normally changes the value of Window.prototype.open (different instance of the same function it seems), here delete won't have any effect at all. Also, Window.prototype.open = "test";delete Window.prototype.open; will produce inconsistent results (different ones depending on whether writable: false flag is specified for the property).
Is there anything else that I can do to emulate the behavior of the original property (short of using binary XPCOM components which has way too many issues of its own)?
You might try using the nsIWindowWatcher interface to register your own window creator (nsIWindowCreator). That way you can control whether a new window is opened without affecting the window object itself (and thus remaining invisible to web sites).
I'm not sure whether the inability to change the implementation of window.open() without this being detectable is a bug. Perhaps it's just not considered an important requirement for methods like Object.defineProperty. But it might be worth filing a bug to see what others think about making this an option in the future. After all, ad blocking is a major use case.
In the end I had to give up on using JavaScript proxies for the job. Even though with some effort I can create a wrapper for window.open() that behaves exactly like the original (bug 650299 needs to be considered), there doesn't seem to be a proper way to replace the original window.open() function. The changed property will always behave differently from the original one, too bad.
So I decided to go with a different approach as a pop-up blocking solution: listen for content-document-global-created notification and have a look at the subject (the new window) as well as its opener. Windows with a non-null opener are pop-up windows of some kind. One can look at the URLs and decide whether the pop-up should be blocked. To block one would call window.stop() (stops all network activities before any network requests are sent) and window.close(). The latter has to be called asynchronously (with a delay) because it will cause a crash otherwise as the initialization of the window continues. Some notes on this approach:
For pop-ups opening in a new window the window will still show up but disappear immediately. This seems to be unavoidable.
For the web page it looks like its pop-up window opened but was closed immediately - this isn't how the built-in pop-up blocker works, more like an external pop-up blocking application.
New windows always load about:blank first before changing to their actual destination. For same-origin pop-ups the latter won't send a new content-document-global-created notification which is unfortunate.
All in all: not perfect but usable. And it is very simple, nowhere near the amount of code required for JavaScript proxies.
Web browsers intentionally prevent this behavior, it's for maintaing the security of web e.g. when you use iFrame you don't want that iFrame to mess up or hack your page.
But instead of manipulating the window object properties why not to create a wrapper for the window object and override window by the wrapper locally?
Example:
// Copy window object to wraper
var wrapper = {};
for(prop in window) {
wrapper[prop] = window[prop];
}
wrapper.open = function yourNewOpenFunction() {
/// do your custom code here
}
(function fakeScope(window){
window.open(); // this is wrapper.open
}(wrapper));
BTW this affects only the body inside fakeScope() function, and cannot be applied globally.
it striked me this morning: you can use Object.freeze(Window.prototype); !
test have shown, that methods protected with this cannon be deleted, but they can be easily detected.
old answer:
What about ES:Harmony Proxies ?
http://brendaneich.com/2010/11/proxy-inception/
Of course, they are unstable, but they are working in Firefox 4+, and you are not the man, who is afraid of difficulties ;)