In my chrome application that processes many pages automatically, I need
to get rid of interactive messages (alert, prompt, confirm, ...) that
could happen while browsing a site, and simulate a default action (like
click Ok or Cancel button).
Does anyone see a way to hook into firefox and intercept those dialogs
before they require a human intervention to resume the process ?
Thanks,
/mig
See:
* mozilla/source/netwerk/base/public/nsIPrompt.idl
*
mozilla/source/embedding/components/windowwatcher/public/nsIPromptService.idl
/Håkan
However, in some situations, I need to be able to perform alert, prompt, ...
If I override nsIPrompt.idl for instance, I can decide whether or not I
must fake the dialog. In case I should not, is there a way to call the
former interface ?
/mig
You can't override nsIPrompt, that is just an interface, there's no
contract ID/CID associated with it.
Anyway, if you want to forward this to the previously registered
component, just get it by CID.
You are right about not overriding nsIPrompt. I don't know how to access
the previous component by CID.
Anyway, I have something that almost works. I created a component with
nsIPromptService CID and "@mozilla.org/embedcomp/prompt-service;1" ID.
Just before registering this component, I get the former prompt service
and store it. If I do so after registration, I get into a stack overflow.
Beside of that, I create a new nsIPromptEnableService interface and
related service, with enable() and disable() methods for the application
to allow or disallow prompting, and a isEnabled() function for my new
prompt service to decide if the alert-like function should be invoked
from the former prompt service.
It is working just fine for alert, confirm, promptUsernameAndPassword
functions, but strangely enough, it doesn't work for prompt(). If a
javascript code invokes the function prompt("Enter your name"), none of
my code is called and nothing happens.
I suspected the JS prompt() function to use nsIPrompt on
"@mozilla.org/network/default-prompt;1" instead of nsIPromptService, so
I wrote another component to override this, but I still don't get anything.
/mig
> Anyway, I have something that almost works. I created a component with
> nsIPromptService CID and "@mozilla.org/embedcomp/prompt-service;1" ID.
> Just before registering this component, I get the former prompt service
> and store it. If I do so after registration, I get into a stack overflow.
Humm, in fact, it does not work so well ...
I did not realize the registration only occurs once in the extension's
life. So, catching the previous service before registration only works
the first time I run firefox with my extension.
So, accessing the prompt service with:
var legacyService =
Components.classes["@mozilla.org/embedcomp/prompt-service;1"].
getService(Components.interfaces.nsIPromptService)
... does not work because I get my own service object.
>> Anyway, if you want to forward this to the previously registered
>> component, just get it by CID.
I don't really understand "get it by CID". Is it different from what I do ?
Another alternative would be to create a new interface and service as a
clone of nsIPromptService. So that I can call it from my own prompt
service version without the risk of recursion.
The drawback is that the original nsPromptService is written in C++, and
I would like to avoid code that needs to be compiled on several
platforms. So far, I could develop my extension in JS only.
I could rewrite the whole prompt service in JS, but this is a bit of
work and it may lead to compatibility problems with further versions of
firefox. However, this is my best option so far unless someone gives me
a better idea.
Cheers,
/mig
Don't do that. Use an own CID.
To get the previous one by CID:
var realService =
Components.classesByID["{A2112D6A-0E28-421f-B46A-25C0B308CBD0}"]
.getService(Components.interfaces.nsIPromptService);
> and "@mozilla.org/embedcomp/prompt-service;1" ID.
> Just before registering this component, I get the former prompt service
> and store it. If I do so after registration, I get into a stack overflow.
Of course, since if you get it after registration, you get yourself...
> It is working just fine for alert, confirm, promptUsernameAndPassword
> functions, but strangely enough, it doesn't work for prompt(). If a
> javascript code invokes the function prompt("Enter your name"), none of
> my code is called and nothing happens.
Hmm, I'm not sure why this isn't working...
> I suspected the JS prompt() function to use nsIPrompt on
> "@mozilla.org/network/default-prompt;1" instead of nsIPromptService, so
> I wrote another component to override this, but I still don't get anything.
That's only used for proxy authentication, IIRC.
This works just fine. Many thanks Christian !
In fact, I realized that I mixed up interface (nsIPromptService) and
service (@mozilla.org/embedcomp/prompt-service;1) CIDs. How did you get
the service CID (A2112D6A-0E28-421f-B46A-25C0B308CBD0) from ?
>> It is working just fine for alert, confirm, promptUsernameAndPassword
>> functions, but strangely enough, it doesn't work for prompt(). If a
>> javascript code invokes the function prompt("Enter your name"), none
>> of my code is called and nothing happens.
>
> Hmm, I'm not sure why this isn't working...
Even if the JS prompt() function does not invoke my code, I get it
called when for instance I add a new config entry from about:config
Do you have an idea where I can get in the source the implementation for
the javascript prompt function ?
Thanks again,
/mig
I could get it to work.
The window prompt method is not using
@mozilla.org/embedcomp/prompt-service;1 but
@mozilla.org/wallet/single-sign-on-prompt;1 instead.
And for some reasons I ignore, having overriden prompt-service, the
single-sign-on-prompt does not work anymore for the 'prompt' function.
So I have also overriden single-sign-on-prompt and make it call the
legacy prompt-service to display the prompt dialog.
As a result, I have lost the 'single sign on' feature for prompt (I
didn't understand what I really lost there), and everything else is
working ok.
/mig
You're welcome!
> In fact, I realized that I mixed up interface (nsIPromptService) and
> service (@mozilla.org/embedcomp/prompt-service;1) CIDs. How did you get
> the service CID (A2112D6A-0E28-421f-B46A-25C0B308CBD0) from ?
Ah. Interface IDs are usually called IIDs (or the more generic UUID of
course), not CID which stands for class ID.
The way I did it was search Mozilla's source code for
NS_PROMPTSERVICE_CID defines, and then I picked the right one... but
another way to do it is to look in compreg.dat in a build w/o your
extension's override registered and check the CID for the contract ID
you are looking for.
You can also do this programmatically
(http://lxr.mozilla.org/seamonkey/source/xpcom/components/nsIComponentRegistrar.idl#223);
again, do it in a build where your override isn't registered.
Component viewer (cview) is a third possibility, and maybe the easiest
one. Seems to be available from addons.mozilla.org.
> Even if the JS prompt() function does not invoke my code, I get it
> called when for instance I add a new config entry from about:config
That one probably calls the prompt service directly, JavaScript's prompt
doesn't, although it should end up calling it in the end.
> Do you have an idea where I can get in the source the implementation for
> the javascript prompt function ?
The code is here:
http://lxr.mozilla.org/seamonkey/source/dom/src/base/nsGlobalWindow.cpp#3268
which calls:
http://lxr.mozilla.org/seamonkey/source/dom/src/base/nsGlobalWindow.cpp#3225
I hope that helps...
> Ah. Interface IDs are usually called IIDs (or the more generic UUID of
> course), not CID which stands for class ID.
>
> The way I did it was search Mozilla's source code for
> NS_PROMPTSERVICE_CID defines, and then I picked the right one... but
> another way to do it is to look in compreg.dat in a build w/o your
> extension's override registered and check the CID for the contract ID
> you are looking for.
> You can also do this programmatically
> (http://lxr.mozilla.org/seamonkey/source/xpcom/components/nsIComponentRegistrar.idl#223);
> again, do it in a build where your override isn't registered.
>
> Component viewer (cview) is a third possibility, and maybe the easiest
> one. Seems to be available from addons.mozilla.org.
>> Do you have an idea where I can get in the source the implementation
>> for the javascript prompt function ?
> The code is here:
> http://lxr.mozilla.org/seamonkey/source/dom/src/base/nsGlobalWindow.cpp#3268
>
> which calls:
> http://lxr.mozilla.org/seamonkey/source/dom/src/base/nsGlobalWindow.cpp#3225
Many good advices. Thanks again.
/mig
Yeah, but that's supposed to call the prompt service again...
> And for some reasons I ignore, having overriden prompt-service, the
> single-sign-on-prompt does not work anymore for the 'prompt' function.
Hrm, ok...
> As a result, I have lost the 'single sign on' feature for prompt (I
> didn't understand what I really lost there), and everything else is
> working ok.
I don't know the Firefox UI here, but you probably lost the "Remember
password" feature.