User:Dolske/PromptRework

From MozillaWiki
Jump to: navigation, search

Prompting Rework

(rationale)

What we have now

Interfaces

Tangentially involved:

Prompt Types

nsIPrompt / nsIPromptService

  • alert() message + OK button
  • alertCheck() (adds a checkbox)
  • confirm() message + OK/Cancel buttons
  • confirmCheck() (adds a checkbox)
  • confirmEx() message + Yes/No/Never buttons
  • prompt() message + text field
  • promptPassword() message + password field
  • promptUsernameAndPassword()
    (nsIAuthPrompt also has similar, but slightly different, interfaces for these 3)
  • select() message + selection list

nsIPromptService2

  • promptAuth() takes channel + nsIAuthInformation
  • asyncPromptAuth() (not implemented)
    (nsIAuthPrompt2 also has similar interfaces for these 2, but does not allow the caller to specify a DOMWindow or checkbox)


How things tie together

HTTP Auth

In nsHttpChannel::PromptForIdentity():

  1. Get an instance of nsIAuthPrompt2
  2. Set up a nsIAuthInformation
  3. Call ::PromptAuth()
How does it get an nsIAuthPrompt2 instance? By using GetAuthPrompt()...
  1. do_GetInterface on the channel's mCallbacks to nsIAuthPromptProvider if that :works, call its ::GetAuthPrompt() otherwise use NS_QueryAuthPrompt2()
  2. do_GetInterface on the channels's mCallbacks to nsIAuthPromptwrap it with NS_WrapAuthPrompt (so it usuable as a nsIAuthPrompt2) NS_WARNING about this, so depricated?
What nsIAuthPrompt2 instance is it getting?
  1. nsDocShell.cpp has nsIAuthPromptProvider in it's implemented interfaces. In turn, it delegates to @mozilla.org/embedcomp/window-watcher;1 (nsIPromptFactory), by calling its ::GetPrompt(), asking for an nsIAuthPrompt2.
  2. WW tries calling NS_NewAuthPrompter2 (and if that fails, NS_NewAuthPrompter and wrapping it). That tries to create an instance of pwmgr's nsIPromptFactory (@mozilla.org/passwordmanager/authpromptfactory;1). If pwmgr isn't available, it falls back to its own nsPrompt implementation.

Password Manager

Ok, so something finally invoked the PromptAuth in nsLoginManagerPrompter.js...

It fetches any existing login, and invokes .promptAuth on the prompt service. (@mozilla.org/embedcomp/prompt-service;1, as a nsIPromptService2). Notice that this nsIAuthPrompt2::PromptAuth is calling nsIPromptService2::PromptAuth! Whee.

The ::PromptAuth there just bounces over to nsPrompt::PromptPasswordAdapter(). Now we're getting somewhere -- this builds up all the strings for the prompt, and then calls back to the caller's (nsPromptService's) ::PromptPassword or ::PromptUsernameAndPassword.

The ::PromptUsernameAndPassword then builds up a nsIDialogParamBlock (possibly the ugliest interface ever), and calls the DoDialog helper. It opens a window with the specified chrome url and passes the paramblock to it.

DOM window.alert(), .prompt(), .confirm()

I'm a little fuzzy on how the early steps of how a JS call gets hooked up to here, but the exact process shouldn't matter.

Interface on DOM window picked up via nsIDOMWindowInternal?

Callers should end up in nsGlobalWindow::Alert (or ::Prompt, etc).

These functions all basically:

  1. nsCOMPtr<nsIPrompt> prompter(do_GetInterface(mDocShell));
  2. Do some arg checking to defend against naughty page script
  3. prompter->Alert(), or Prompt(), or Confirm()

XXX - Prompt() seems to allow an aSavePassword arg. Is this spec'd anywhere? The pwmgr doesn't actually support that, but it seems to be cleared before we get there? Where?

Problems

A New Hope

nsIPromptFactory

  • nsIPrompt getPrompt(nsIID type)


nsIPromptService

  • nsIPrompt getPrompt(nsIID type, nsIDOMWindow parent)

??? nsIPromptFactory getFactory(nsIDOMWindow)


nsIPrompt (superclass)

  • showPrompt(callback [optional])


nsISimplePrompt

Example Use Cases

HTTP Auth

Multiple concurrent HTTP Auths

HTTP Auth interrupted by a Master Password Request

XMLHttpRequest

Random code that wants to show a prompt