Firefox Tab Tearing kills my NPPlugin - firefox

I have an NPAPI Plugin that runs in Firefox, but any time that the tab is "torn off" (by dragging the tab into space so a new window is formed), the plugin is destroyed and recreated. The problem is that the plugin needs to be initialized with information from an Ajax call, and I cannot find any way in Javascript to detect this, so the plugin is not getting the necessary initialization information.
So, any ideas as to how to detect this event and/or make the plugin not be destroyed/recreated when the tab is torn off?

What operating system are you dealing with? If it is actually destroying your plugin and recreating it, you could always have the plugin attempt to call a javascript method on startup.
Specify the name of the function in a param tag and then on plugin startup, attempt to get a reference to that method by calling NPN_GetProperty on the window NPObject (which you can get by calling NPN_GetValue(NPNVWindowNPObject, &npobjectptr) and then calling NPN_GetProperty(npp, npobjectptr, NPN_GetStringIdentifier(functionname), &destObj)
Then you can invoke that method with a reference to your plugin (which you can get again with NPN_GetValue) and the js function will know that it's time to initialize your plugin (again?).
You could do other things as well, such as store initialization data in global space and try to figure out a way to detect that it should be the same plugin instance... not sure how to be sure it's supposed to be the same one, though.

Related

How to export a constructor from privileged scope to a less-privileged scope in Firefox Add-on SDK

I'm trying to write a Firefox extension which hooks into WebAudio and adds a 'master-gain' to all AudioContexts.
I am trying to do this by overriding the AudioContext constructor in the window namespace. This way I can return a GainNode (which is internally connected to the destination) when the user tries to access destination. It's a hack, but I think it might be useful.
I'm currently struggling at exporting my newAudioContext constructor from the addon script(privileged scope) into the page script (less-privileged).
I tried...
unsafeWindow.AudioContext = cloneInto(newAudioContext,unsafeWindow);
But I still get the original AudioContext in the page script.
I also tried
exportFunction(newAudioContext, unsafeWindow, {defineAs: "AudioContext"});
but that exports it as a function and not as a constructor.
I understand that structured cloning has limitations, but are there any other ways I can override the window.AudioContext from an AddOn?
If you need to run more complex code (e.g. object construction) in the unprivileged context you can simply import a script into the target window (after waiving xrays) through the mozIJSSubScriptLoader.
Any function that needs to call into privileged code can be patched into its prototype from the chrome side after the script has been loaded.
You can do this before DOM parsing - and thus before any content script execution - by listening to the DOMWindowCreated event.
You will have to do this from a frame script, since the addon-sdk's page-mod sandboxes don't have enough privileges to access the script loader.
Keeping interaction with the unsafe window to a minimum, i.e. either running code wholly in the privileged environment with xrays or completely in the untrusted environment with the minimal amount of glue methods between those two seems like good security hygiene anyway.
Of course you should be aware that content code will be able to pick apart and modify any classes you create in content. It is untrusted after all.

npp_destroy gets called immediately after npp_new

I am trying to make a NPAPI plugin for chrome on Mac. I have written a basic npapi plugin and a basic manifest.json and background.html to load it. My background.html has a embed tag to fetch the plugin by Mimetype.
Now when I load my unpackaged extension from Chrome and try to debug the c++ code (in xcode4), I found that the functions are getting called in following order:
NP_Initialize
NP_GetEntryPoints
NPP_New
NPP_Destroy
After this when I click on the extension icon, the popup.html should get executed. My popup.html has these lines:
line 1:
var pluginObj = document.getElementById("pluginId");
line 2:
pluginObj.Myfunction();
But on line 1, NP_Getvalue() function doesnt get called and so a "scriptable NPObject" is not instantiated. On line 2, the Chrome JavaScript console says:
Error in event handler for 'undefined': Object #<HTMLEmbedElement> has no method 'Myfunction' TypeError: Object #<HTMLEmbedElement> has no method 'Myfunction'
Why does the NPP_Destroy functions gets called immediately after the NPP_New function?
Have you done drawing and event model negotiation in your plugin? Starting with Chrome 22 for Mac, the long-deprecated QuickDraw and Carbon models are no longer supported, and if your plugin doesn't negotiate modern models, it will be destroyed just after init. See here for example code that does this.
(Yes, it's unfortunate that the default models for 32-bit plugins are the old, deprecated models, but there's no way to change that in the spec due to all the existing plugins that expect the old behavior.)

How to show a Carbon dialog as part of a plugin for an application with an existing event loop?

I'm writing a plugin for an application and need to use Carbon to show a dialog. I have everything set up including the event handler, but I cannot possibly call RunApplicationEventLoop() because this would stall the host application.
How can I fix this? Will I need to create a separate thread and call RunApplicationEventLoop() from there?
-Joe
What makes you think you need to call RunApplicationEventLoop? The host app is presumably running an event loop, probably either using RunApplicationEventLoop or NSApplicationMain. By the way, would your dialog be modal? Modal is easier.

Handling CGEventTaps in an NPAPI plugin

I'm trying to create an NPAPI plugin to listen to the Media Keys on a macbook and pass that to javascript to control things like pandora or soundcloud. I'm using Spotify's SPMediaKeyTap library, which just wraps CGEventTap running on a separate thread.
My problem is that I use npn_invoke to call back to javascript. This works normally, but when it's triggered from the CGEventTap callback, it crashes the plugin. I realize this needs to be run from the plugin thread, and I've tried to pass it back to the main thread both by using [NSObject performSelectorOnMainThread] and [NSObject performSelector:onThread] with the thread i've stored away in the main plugin threads create method. Both of these solutions still crash on any npn call. Is there anything else that goes on when handling a CGEventTap event that causes state to be invalid for NPN browser interaction calls?
Don't try to second guess the threading model by saving the thread like you are; just use performSelectorOnMainThread to call NPN methods. I do this all the time and it works fine, so I'm guessing that something with your method of cross-thread marshalling isn't working the way it needs to.

NSDocumentController not quitting app properly on review unsaved documents in Cocoa/Objective-C

I've been banging my head on walls trying to solve this.
My app uses a subclass of NSDocument, NSDocumentController and also NSWindowController. The issue is that when I create a document and make a modification, and also if I create more than one document the same way, if I choose Quit while documents are unsaved, I get the proper dialogs to ask wether I want to Review unsaved docs, Cancel or Not save, but whenever I select to Review and then save a document, I get to save, but after saving the first document, first, that document is NOT closed, and I am not asked to save the others. On top of this, My App's Quit menu item becomes grayed out.
I created another skeleton app to do the same thing, and of course, all works normally. I checked my connections in the nib file, and cannot see anything wrong, or different from the test app. Although there is a lot more in my app.
I am not currently overriding the reviewUnsavedDocumentsWithAlertTitle:cancellable:delegate:didReviewAllSelector:contextInfo: method, but when I do, I get the same problem, since I call Super's version of it after doing some special clean-up work. But again, not overriding this yields the same result.
One thing I do notice, is that in my own App, I get the following messages in the Log as I run it, which I do not get in my test app:
[Switching to process 9997 thread 0x7667]
[Switching to process 9997 thread 0x903]
Which makes it look like I am doing something multi-threaded here without knowing. My test app doesn't switch to another thread.
I'm not sure how to check if all my connexions are ok and why these threads are being switched to and where they come from.
Since I get the error wether or not I override the NSDocumentController methods like the one above or the closeAllDocumentsWithDelegate:didCloseAllSelector:contextInfo: I imagine the error comes from somewhere else.
Maybe my NSDocument subclass's saving methods are creating the issue, but they return the appropriate values once the save has occurred, I get no error and the files are all fine.
I'd like to override the -didCloseAllSelector or -didReviewAllSelector, but I'm a bit challenged with this. I'm not sure how to build the method, since this:
- (void)documentController:(NSDocumentController *)controller
didCloseAll:(BOOL)didCloseAll contextInfo:(void *)contextInfo;
{
NSLog(#"All documents closed");
}
is never called. Is this a symptom? Tried the same for the -didReviewAllSelecter which never gets called.
Finally, I was overriding a method in my "NSDocument" subclass which I should not have. Removing this fixed it.
I guess you have to be really careful what you override!
The method was writeToFile:ofType:originalFile:saveOperation: which I no longer had to do.
Not sure exactly what was wrong, but it may help others to know to look there.

Resources