private void createScene() {

    // Fixes issue with blank BurpKitty tabs
    if (Thread.currentThread().getContextClassLoader() == null) {
      System.err.println("Warning: context class loader for JFX thread returned null.");
      Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader());
    }

    createMasterPane();
    createDetailPane();
    masterDetailPane = new CollapsibleSplitPane(masterPane, detailPane);
    masterDetailPane.setOrientation(Orientation.VERTICAL);
    masterDetailPane.expandedProperty().bind(isDetailNodeVisible);

    scene = new Scene(masterDetailPane);

    setScene(scene);
  }
  private void createDetailPane() {
    detailPane = new TabPane();

    javaScriptConsoleTab = new JavaScriptConsoleTab(webEngine);
    addErrorListener(javaScriptConsoleTab::handleError);
    addAlertListener(javaScriptConsoleTab::handleAlert);

    crossSiteScriptingTrackerTab = new CrossSiteScriptingTrackerTab(webEngine);
    addAlertListener(crossSiteScriptingTrackerTab::handleAlert);

    pageResourcesTab = new PageResourcesTab(webEngine);

    Tab javaScriptEditorTab = new Tab("BurpScript IDE");
    javaScriptEditorTab
        .selectedProperty()
        .addListener(
            (observable, oldValue, newValue) -> {
              if (newValue) masterDetailPane.setDividerPositions(0.5);
            });
    JavaScriptEditor javaScriptEditor = new JavaScriptEditor(webEngine, controller, false);
    javaScriptEditor.setJavaScriptConsoleTab(javaScriptConsoleTab);
    javaScriptEditorTab.setContent(javaScriptEditor);

    Tab trafficBrowserTab = new Tab("Network");
    trafficBrowser = new TrafficBrowser();
    trafficBrowserTab.setContent(trafficBrowser);

    Debugger debugger = webEngine.impl_getDebugger();
    debugger.setEnabled(true);
    debugger.sendMessage("{\"id\": 1, \"method\":\"Network.enable\"}");
    debugger.setMessageCallback(
        new Callback<String, Void>() {

          ConcurrentHashMap<String, Traffic> trafficState = new ConcurrentHashMap<>();

          @Override
          public Void call(String param) {
            JsonParser parser = new JsonParser();
            JsonObject object = parser.parse(param).getAsJsonObject();

            String method = object.get("method").getAsString();
            JsonObject params = object.getAsJsonObject("params");
            JsonObject request = params.getAsJsonObject("request");
            JsonObject response = params.getAsJsonObject("response");
            String requestId = params.get("requestId").getAsString();

            Instant timeStamp;
            JsonElement epochObject = params.get("timestamp");
            if (epochObject != null) {
              double epoch = epochObject.getAsDouble();
              timeStamp =
                  Instant.ofEpochSecond(
                      (long) Math.floor(epoch), (long) (epoch * 1000000000 % 1000000000));
            } else {
              timeStamp = Instant.now();
            }

            Traffic traffic = null;

            switch (method) {
              case "Network.requestWillBeSent":
                URL url = null;
                String urlString = request.get("url").getAsString();

                try {
                  url = new URL(urlString);
                } catch (MalformedURLException e) {
                  //                            e.printStackTrace();
                }
                trafficState.put(
                    requestId,
                    new Traffic(
                        (url == null) ? urlString : url.getFile(),
                        timeStamp,
                        (url == null) ? "" : url.getHost(),
                        request.get("method").getAsString(),
                        params.get("documentURL").getAsString()));
                break;
              case "Network.responseReceived":
                traffic = trafficState.get(requestId);
                JsonObject headers = response.getAsJsonObject("headers");
                JsonElement contentType = headers.get("Content-Type");
                JsonElement contentLength = headers.get("Content-Length");
                traffic.setType((contentType == null) ? "" : contentType.getAsString());
                JsonElement requestLine = headers.get("");
                if (requestLine != null) {
                  String[] requestLineParts = requestLine.getAsString().split(" ", 3);
                  traffic.setStatusCode(new Integer(requestLineParts[1]));
                  traffic.setStatusText(requestLineParts[2]);
                  traffic.setSize((contentLength == null) ? "0" : contentLength.getAsString());
                } else {
                  traffic.setStatusCode(200);
                  traffic.setStatusText("OK");
                  traffic.setSize("0");
                }
                break;
              case "Network.loadingFinished":
                traffic = trafficState.get(requestId);
                traffic.setEndTime(timeStamp);
                trafficBrowser.getTraffic().add(traffic);
                trafficState.remove(requestId);
                if (traffic.getEndTime().isAfter(trafficBrowser.getEndTime())) {
                  trafficBrowser.setEndTime(traffic.getEndTime());
                }
            }
            return null;
          }
        });

    detailPane
        .getTabs()
        .addAll(
            javaScriptConsoleTab,
            crossSiteScriptingTrackerTab,
            pageResourcesTab,
            trafficBrowserTab,
            javaScriptEditorTab
            //                new ImagesTab(webEngine)
            );

    detailPane.setTabClosingPolicy(TabPane.TabClosingPolicy.UNAVAILABLE);
  }