function doDispatchOperation(app, e) {
  const container = util.getElement(
        e, ELEMENT_NOT_FOUND);
  // TODO: refactor dispatcher to simplify and move logic externally.
  const redirectUrl = dispatcher.getRedirectUrl(app);
  switch (dispatcher.getMode(app)) {
    case Config.WidgetMode.CALLBACK:
      // If redirect URL available, save in non persistent storage.
      // Developer could directly go to
      // http://www.widgetpage.com/?signInSuccessUrl=http%3A%2F%2Fwww.google.com
      // On success this should redirect to google.com the same as when
      // mode=select is passed in query parameters.
      if (redirectUrl) {
        storage.setRedirectUrl(redirectUrl, app.getAppId());
      }
      // Avoid UI flicker if there is no pending redirect.
      if (app.isPendingRedirect()) {
        handler.handle(
            HandlerName.CALLBACK, app, container);
      } else {
        // No pending redirect. Skip callback screen.
        common.handleSignInStart(
            app,
            container,
            // Pass sign-in email hint if available.
            app.getSignInEmailHint());
      }
      break;

    case Config.WidgetMode.RESET_PASSWORD:
      handler.handle(
          HandlerName.PASSWORD_RESET,
          app,
          container,
          getActionCode(),
          // Check if continue URL is available. if so, display a button to
          // redirect to it.
          getContinueCallback());
      break;

    case Config.WidgetMode.RECOVER_EMAIL:
      handler.handle(
          HandlerName.EMAIL_CHANGE_REVOCATION,
          app,
          container,
          getActionCode());
      break;

    case Config.WidgetMode.REVERT_SECOND_FACTOR_ADDITION:
      handler.handle(
          HandlerName.REVERT_SECOND_FACTOR_ADDITION,
          app,
          container,
          getActionCode());
      break;

    case Config.WidgetMode.VERIFY_EMAIL:
      handler.handle(
          HandlerName.EMAIL_VERIFICATION,
          app,
          container,
          getActionCode(),
          // Check if continue URL is available. if so, display a button to
          // redirect to it.
          getContinueCallback());
      break;

    case Config.WidgetMode.VERIFY_AND_CHANGE_EMAIL:
      handler.handle(
          HandlerName.VERIFY_AND_CHANGE_EMAIL,
          app,
          container,
          getActionCode(),
          // Check if continue URL is available. if so, display a button to
          // redirect to it.
          getContinueCallback());
      break;

    case Config.WidgetMode.SIGN_IN:
      // Complete signin.
      handler.handle(
          HandlerName.EMAIL_LINK_SIGN_IN_CALLBACK,
          app,
          container,
          util.getCurrentUrl());
      // Clear URL from email sign-in related query parameters to avoid
      // re-running on reload.
      app.clearEmailSignInState();
      break;

    case Config.WidgetMode.SELECT:
      // If redirect URL available, save in non-persistent storage.
      if (redirectUrl) {
        storage.setRedirectUrl(redirectUrl, app.getAppId());
      }
      // Renders provider sign-in or simulates sign in with email click in the
      // beginning sign-in page.
      common.handleSignInStart(app, container);
      break;

    default:
      // firebaseui.auth.widget.dispatcher.getMode() guaranteed to return a
      // valid mode. Reaching here means we have an unhandled operation.
      throw new Error('Unhandled widget operation.');
  }
  // By default, UI is shown so invoke the uiShown callback.
  const uiShownCallback = app.getConfig().getUiShownCallback();
  if (uiShownCallback) {
    uiShownCallback();
  }
}
@param {!AuthUI} app The FirebaseUI instance.
@param {string|!Element} e The container element or the query selector.