long /*int*/ getSiteWindow() {
    /*
     * As of XULRunner 4, XULRunner's printing facilities on Windows destroy
     * the HWND that is returned from here once the print dialog is dismissed
     * (originating bug: https://bugzilla.mozilla.org/show_bug.cgi?id=588735 ).
     * For this scenario it is now expected that the handle that is returned
     * here is a child of the browser handle, not the browser handle itself.
     *
     * The other scenario that requests this handle is the Mozilla.getBrowser()
     * implementation.  This method's GetSiteWindow() invocation is surrounded
     * by boolean flags to help differentiate it from the printing scenario,
     * since Mozilla.getBrowser() does not destroy the handle it receives back.
     *
     * All children that are created here are stored and then destroyed once
     * the current page is left.  This is guard code that should only be needed
     * if Mozilla.getSiteWindow() is ever invoked by a path other than one of
     * the two described above.
     */
    if (!MozillaVersion.CheckVersion(MozillaVersion.VERSION_XR10) || Mozilla.IsGettingSiteWindow) {
      return getHandle();
    }

    Composite child = new Composite(browser, SWT.NONE);
    childWindows.add(child);
    return child.handle;
  }
  void init() {
    if (MozillaVersion.CheckVersion(MozillaVersion.VERSION_XR10)) {
      /*
       * In XULRunner versions > 4, sending WM_GETDLGCODE to a WM_KEYDOWN's MSG hwnd answers 0
       * instead of the expected DLGC_WANTALLKEYS.  This causes the default traversal framework
       * perform traversals outside of the Browser when it should not.  Hook a Traverse listener
       * to work around these problems.
       */
      browser.addListener(
          SWT.Traverse,
          event -> {
            switch (event.detail) {
              case SWT.TRAVERSE_RETURN:
                {
                  /* always veto the traversal */
                  event.doit = false;
                  break;
                }
              case SWT.TRAVERSE_TAB_NEXT:
              case SWT.TRAVERSE_TAB_PREVIOUS:
                {
                  /* veto the traversal whenever an element in the browser has focus */
                  long /*int*/[] result = new long /*int*/[1];
                  int rc = XPCOM.NS_GetServiceManager(result);
                  if (rc != XPCOM.NS_OK) Mozilla.error(rc);
                  if (result[0] == 0) Mozilla.error(XPCOM.NS_NOINTERFACE);
                  nsIServiceManager serviceManager = new nsIServiceManager(result[0]);
                  result[0] = 0;
                  byte[] aContractID =
                      MozillaDelegate.wcsToMbcs(null, XPCOM.NS_FOCUSMANAGER_CONTRACTID, true);
                  rc =
                      serviceManager.GetServiceByContractID(
                          aContractID,
                          IIDStore.GetIID(nsIFocusManager.class, MozillaVersion.VERSION_XR10),
                          result);
                  serviceManager.Release();

                  if (rc == XPCOM.NS_OK && result[0] != 0) {
                    nsIFocusManager focusManager = new nsIFocusManager(result[0]);
                    result[0] = 0;
                    rc = focusManager.GetFocusedElement(result);
                    focusManager.Release();
                    event.doit = result[0] == 0;
                    if (rc == XPCOM.NS_OK && result[0] != 0) {
                      new nsISupports(result[0]).Release();
                    }
                  }
                  break;
                }
            }
          });

      /* children created in getSiteHandle() should be destroyed whenever a page is left */
      browser.addLocationListener(
          new LocationAdapter() {
            @Override
            public void changing(LocationEvent event) {
              Iterator<Composite> it = childWindows.iterator();
              while (it.hasNext()) {
                it.next().dispose();
              }
              childWindows.clear();
            }
          });
    }
  }