We're looking for a user researcher to understand the needs of developers and designers. Is this you or someone you know? Check out the post: https://mzl.la/2IGzdXS

Embedding Tips

What is a service?

A service is a singleton object implementing one or more XPCOM interfaces and registered with Gecko during startup. Normally it provide some functionality that is required from lots of places such as looking up preference settings, creating new windows, locating files, displaying prompt or password dialog boxes and so on.

Embedders may wish to override some of the default service implementations with their own. For example, the default prompt service uses XUL to render prompt dialogs and embedders may wish to render them in a way more appropriate for their application and platform..

How do I load a page?

Get thensIWebNavigation interface on your webbrowser and call the loadURI method with the appropriate URI and flags. This interface also has methods for reloading, stopping a load and going back and forward in the history.

How do I block a load?

Implement the nsIWebProgressListener interface and register it with the appropriate web browser object via the nsIWebBrowser::addWebBrowserListener() method. Use the callbacks for after-the-fact cancellation. Alternatively, implement a nsIURIContentListener as described below.

How do I watch/intercept a load before it happens?

Implement the nsIURIContentListener interface, and register it with the appropriate web browser object via the nsIWebBrowser::parentURIContentListener attribute. Watch for changes in nsIURIContentListener::OnStartURIOpen(). You can abort the URI load at this point if you don't want it to proceed.

If necessary you may also implement the nsIURIContentListener::IsPreferred(), returning PR_TRUE to ensure you are always the preferred URI handler and are called no matter what the content type.

How do I copy items to the clipboard?

Obtain the nsIClipboardCommands interface from the appropriate web browser object via nsIServiceProvider::GetInterface (or the do_GetInterface() helper method).

How do I save a document or data to disk?

Query for the nsIWebBrowserPersist interface implemented on the web browser object and call the saveURI() or saveDocument() methods on that.

Alternatively, create a standalone webbrowser persist object and call the nsIWebBrowserPersist interface on that to save URIs and documents. This is recommended if you intend anything other than the uri or document your browser is looking at. Register your own nsIWebProgressListener object to listen for progress and state notifications.

How do I save / upload a document / data to a web or ftp site?

Again, use the webbrowser persist object, but specify a remote location as the target URI.

Your web progress listener must also implement nsIAuthPrompt if you want to be able to upload to a password protected location (e.g. an ftp site). The nsIAuthPrompt interface allows the networking layer to pose a user / password prompt to obtain the values needed for authentication. Your own implementation should pose this dialog, or fill in the values that are needed for the upload to succeed.

How do I know when saving is done, monitor progress etc.?

Register your ownnsIWebProgressListener object to listen for progress and state notifications.

Here is a simple example which demonstrates the principle. The SimplePersist() function takes a string URL and a string file path. In response it creates a persist object, creates a listener and starts the operation. As the operation progresses, methods on the listener such as OnStateChange, OnProgressChange etc. are called, allowing the embedder to know what is happening. When the operation is completed, the OnStateChange will be notified by a combination of STATE_STOP | STATE_IS_NETWORK state flags.

You may also use the progress listener to query the request supplied in OnStateChange for more information. For example, if you wanted to check the server response headers, you might check OnStateChange for STATE_START | STATE_IS_REQUEST flags, and from the nsIRequest argument QI fornsIHttpChanne and call methods on that to determine response codes and other information from the server.

It is left as an exercise to make this sample synchronous, i.e. wait for persistence to complete before returning. Hint, add a native message processing loop after the call to SaveURI that terminates when OnStateChange indicates persistence has finished..

How do I print a page?

Query the web browser object for nsIWebBrowserPrint. Call the nsIWebBrowserPrint::Print() method supplying a print settings object (e.g. that returned from nsIWebBrowserPrint::GetGlobalPrintSettings) that you wish to print the page with.

How do I print preview a page?

Query the web browser object for the nsIWebBrowserPrint interface. Call the nsIWebBrowserPrint::PrintPreview() method supplying a print settings object (e.g. that returned from nsIWebBrowserPrint::GetGlobalPrintSettings()) that you wish to preview the page with.

The nsIWebBrowserPrint::PrintPreviewNavigate() method can be used to step through the pages.

When finished with preview mode, call nsIWebBrowserPrint::ExitPrintPreview().

How do I get popup windows working?

Implement and register a nsIWindowCreator object with the window watcher service. The nsIWindowCreator::CreateChromeWindow method will be called whenever Gecko needs to open a new window. This method should create the new browser window in the specified style and hand back the nsIWebBrowserChrome interface to it.

nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
if (wwatch) {

I need the JavaScript inside the browser window to talk to my embedding client. How do I do it?

At startup use the category manager to register properties of the global object in JavaScript like this:

nsCOMPtr<nsICategoryManager> catman =
  if (!catman)
    return NS_ERROR_FAILURE;

  nsXPIDLCString previous;
                         "my_prop_name", "my_prop_contract_id",
                         PR_TRUE, PR_TRUE, getter_Copies(previous));

This will cause a component with the contract id my_prop_contract_id to be lazily created when the my_prop_name is resolved in any JavaScript window scope.

If you want to create your component multiple times within the browser window, you can use a JavaScript constructor instead of a JavaScript property:

catman->AddCategoryEntry("JavaScript global constructor",
                         "my_prop_name", "my_prop_contract_id",
                         PR_TRUE, PR_TRUE, getter_Copies(previous));

That way you will be able to do:

var my_comp = new my_prop_name();

This was taken from WeirdAl's excellent "Burning Chrome" article.

How do I specify alternate locations for profiles?

Specify a profile directory in your implementation of nsIDirectoryServiceProvider passed to XRE_InitEmbedding. Use XRE_NotifyProfile to make gecko actually use a profile location.

How do I change the user agent string?

The default useragent is set using the value from your application.ini/nsXREAppData. You can override this default using the "general.useragent.override" preference.

How do I display my own message, alert and prompt boxes?

You need to implement and register your own prompt service.

How do I get the DOM document from the web browser object?

nsCOMPtr<nsIDOMDocument> doc;
nsCOMPtr<nsIDOMWindow> window;
if (window) {

What is the docshell?

A description of the docshell may be found here.

How do I implement context menus?

Make your chrome object implement the nsIContextMenuListener or nsIContextMenuListener2. The nsIContextMenuListener::OnShowContextMenu() method will be called with the DOM node that the context applies, the DOM event plus some flag combinations that assist in determining what menu to display (document, link, image, selected text etc.)

How do I implement tool tips?

Make your chrome object implement the nsITooltipListener interface. Methods to hide or show the tool tips will automatically be called upon it when the user hovers over an item with TITLE text. The contract ID is defined here.

For an example, see BrowserImpl.cpp in mfcembed and its simple CBrowserToolTip class implemented in MFC.

How do I disable drag/drop support?

When setting up your browser add a hook to the command manager which points to your nsIWebBrowserChrome implementation. This implementation should also implement nsIClipboardDragDropHooks. Deny the drop by setting the return value of the AllowDrop() function.

nsCOMPtr<nsICommandManager> CommandManager = do_GetInterface(iWebBrowser);
if (CommandManager)
  nsCOMPtr<nsIDOMWindow> theDOMWindow = do_GetInterface(iWebBrowser); 
  nsCOMPtr<nsICommandParams> cmdParamsObj = do_CreateInstance(NS_COMMAND_PARAMS_CONTRACTID,&rv);
  cmdParamsObj->SetISupportsValue("addhook", reinterpret_cast<nsISupports*>(iChromeImplementation));
  CommandManager->DoCommand("cmd_clipboardDragDropHook", cmdParamsObj, theDOMWindow);

Document Tags and Contributors

Last updated by: SphinxKnight,