Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

How to prevent interactive dialogs ?

7 views
Skip to first unread message

Michel Gutierrez

unread,
May 3, 2006, 10:41:57 AM5/3/06
to
Hi all,

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

Håkan Waara

unread,
May 4, 2006, 9:03:13 AM5/4/06
to
These dialogs are invoked via the nsIPromptService/nsIPrompt
interfaces. Just overriding either or both of those with your own
service (that doesn't do anything) should work.

See:

* mozilla/source/netwerk/base/public/nsIPrompt.idl
*
mozilla/source/embedding/components/windowwatcher/public/nsIPromptService.idl

/Håkan

Michel Gutierrez

unread,
May 4, 2006, 10:14:33 AM5/4/06
to Håkan Waara

Thanks, that sounds like an excellent advice.

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

Christian Biesinger

unread,
May 4, 2006, 3:40:04 PM5/4/06
to dev-tec...@lists.mozilla.org
Michel Gutierrez wrote:
> 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 ?

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.

Michel Gutierrez

unread,
May 4, 2006, 7:23:29 PM5/4/06
to Christian Biesinger, dev-tec...@lists.mozilla.org

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

Michel Gutierrez

unread,
May 5, 2006, 5:01:17 AM5/5/06
to Christian Biesinger, dev-tec...@lists.mozilla.org
>>> 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 ?

> 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

Christian Biesinger

unread,
May 5, 2006, 5:48:07 AM5/5/06
to dev-tec...@lists.mozilla.org
Michel Gutierrez wrote:
> Anyway, I have something that almost works. I created a component with
> nsIPromptService CID

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.

Michel Gutierrez

unread,
May 5, 2006, 7:46:57 AM5/5/06
to Christian Biesinger, dev-tec...@lists.mozilla.org
Christian Biesinger wrote:
> To get the previous one by CID:
> var realService =
> Components.classesByID["{A2112D6A-0E28-421f-B46A-25C0B308CBD0}"]
> .getService(Components.interfaces.nsIPromptService);

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

Michel Gutierrez

unread,
May 5, 2006, 12:11:19 PM5/5/06
to Christian Biesinger, dev-tec...@lists.mozilla.org

>>> 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 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

Christian Biesinger

unread,
May 5, 2006, 1:03:26 PM5/5/06
to dev-tec...@lists.mozilla.org
Michel Gutierrez wrote:
> This works just fine. Many thanks Christian !

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...

Michel Gutierrez

unread,
May 5, 2006, 1:22:12 PM5/5/06
to Christian Biesinger, dev-tec...@lists.mozilla.org
Christian Biesinger wrote:
>
>> 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.

>> Do you have an idea where I can get in the source the implementation

>> for the javascript prompt function ?

Many good advices. Thanks again.
/mig

Christian Biesinger

unread,
May 5, 2006, 1:32:45 PM5/5/06
to dev-tec...@lists.mozilla.org
Michel Gutierrez wrote:
> The window prompt method is not using
> @mozilla.org/embedcomp/prompt-service;1 but
> @mozilla.org/wallet/single-sign-on-prompt;1 instead.

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.

0 new messages