@Override
  public void afterNavigateTo(final String url, final WebDriver driver) {
    savePage(driver, "afterNavigateTo", url);

    if (WebDriverUtils.isHtmlUnitDriver(driver)
        && config.getBoolean(WebConstants.HTMLUNIT_SAVE_COMPLETE, false)) {
      Page page =
          WebDriverUtils.getHtmlUnitDriverWebClient(driver).getCurrentWindow().getEnclosedPage();

      if (page instanceof HtmlPage && page.getUrl() != WebClient.URL_ABOUT_BLANK) {
        String urlString = page.getUrl().toString();
        log.trace("Dumping HTML file with resources: " + urlString);

        DumpFileCreator dumpFileCreator = dumpFileCreatorProvider.get();
        File htmlFile =
            dumpFileCreator.createDumpFile(
                new File(moduleArchiveDirProvider.get(), "htmldump"), "html", urlString, null);
        try {
          if (htmlFile.exists()) {
            htmlFile.delete();
          }
          ((HtmlPage) page).save(htmlFile);
        } catch (Exception ex) {
          log.error("Error dumping HTML file from URL: " + urlString, ex);
        }
      }
    }
  }
  /**
   * Saves the currently displayed browser window. The page title is used for the filename -
   * preceded by some identifying information (thread, counter). Pages of the same type are
   * collected inside the same subdirectory. The subdirectory uses {@link
   * SaveOutput#getIdentifier()} for its name. If an alert is present, saving is not supported and
   * thus skipped.
   *
   * @param action the event which triggered to save the page. Will be included in the filename.
   * @param triggeredBy the object which triggered the event (e.g. a button or a link)
   */
  protected void savePage(final WebDriver driver, final String action, final String triggeredBy) {
    try {
      // this updates the driver's window handles, so a subsequent call to
      // getWindowHandle() fails if the window no longer exists
      driver.getWindowHandles();
      driver.getWindowHandle();
    } catch (NoSuchWindowException ex) {
      // Window is already closed. Saving the page could cause problems, e. g.
      // ChromeDriver ould hang.
      return;
    }
    File moduleArchiveDir = moduleArchiveDirProvider.get();
    if (moduleArchiveDir == null) {
      return;
    }

    if (config.getBoolean(JFunkConstants.ARCHIVE_DO_NOT_SAVE_WHEN_ALERT, false)) {
      try {
        // Saving the page does not work if an alert is present
        driver.switchTo().alert();
        log.trace("Cannot save page. Alert is present.");
        return;
      } catch (NoAlertPresentException ex) {
        // ignore
      } catch (UnsupportedOperationException ex) {
        // ignore
        // HtmlUnit does not support alerts
      } catch (Exception ex) {
        // ignore
      }
    }

    for (SaveOutput saveOutput : SaveOutput.values()) {
      boolean saveSwitch = saveOutputMap.get(saveOutput);
      if (!saveSwitch) {
        // Saving is disabled by property
        continue;
      }

      File f = null;
      try {
        f =
            dumpFileCreatorProvider
                .get()
                .createDumpFile(
                    new File(moduleArchiveDir, saveOutput.getIdentifier()),
                    saveOutput.getExtension(),
                    driver.getCurrentUrl(),
                    action);

        if (f == null) {
          return;
        }

        switch (saveOutput) {
          case HTML:
            StringBuilder html = new StringBuilder();
            html.append("<!-- Requested URL: ");
            html.append(driver.getCurrentUrl());
            html.append(" -->");
            html.append(IOUtils.LINE_SEPARATOR);
            html.append(driver.getPageSource());
            writeStringToFile(f, html.toString(), "UTF-8");
            copyFile(f, new File(moduleArchiveDir, JFunkConstants.LASTPAGE_HTML));
            log.trace(
                "Saving page: filename={}, action={}, trigger={}, response={}",
                f.getName(),
                action,
                triggeredBy,
                driver.getCurrentUrl());
            break;
          case PNG:
            if (driver instanceof TakesScreenshot) {
              File tmpFile = ((TakesScreenshot) driver).getScreenshotAs(OutputType.FILE);
              if (tmpFile != null) {
                copyFile(tmpFile, f);
                log.trace(
                    "Saving page: filename={}, action={}, trigger={}, response={}",
                    f.getName(),
                    action,
                    triggeredBy,
                    driver.getCurrentUrl());
                deleteQuietly(tmpFile);
              }
            }
            break;
          case HTML_VALIDATION:
            /*
             * JFunkWebDriver.getPageSource() doesn't return the complete page source
             * e.g. DOCTYPE is missing. Therefore we are using a more complicated way to
             * retrieve the "real" page source. However, this only works when using
             * HtmlUnitDriver.
             */
            if (WebDriverUtils.isHtmlUnitDriver(driver)) {
              String content =
                  ((HtmlPage)
                          WebDriverUtils.getHtmlUnitDriverWebClient(driver)
                              .getCurrentWindow()
                              .getEnclosedPage())
                      .getWebResponse()
                      .getContentAsString();
              writeStringToFile(f, content, "UTF-8");
              HtmlValidatorUtil.validateHtml(f.getParentFile(), config, f);
            }
            break;
          default:
            throw new IllegalStateException("unknown enum constant");
        }
      } catch (Exception ex) {
        log.error("Could not save file: {}. {}", f, ex.getMessage());
        return;
      }
    }
  }