/*******************************************************************************
 * Copyright (c) 2000, 2018 IBM Corporation and others.
 *
 * This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License 2.0
 * which accompanies this distribution, and is available at
 * https://www.eclipse.org/legal/epl-2.0/
 *
 * SPDX-License-Identifier: EPL-2.0
 *
 * Contributors:
 *     IBM Corporation - initial API and implementation
 *******************************************************************************/
package org.eclipse.swt.tests.junit;

import static org.eclipse.swt.browser.LocationListener.changedAdapter;
import static org.eclipse.swt.browser.LocationListener.changingAdapter;
import static org.eclipse.swt.browser.ProgressListener.completedAdapter;
import static org.eclipse.swt.browser.VisibilityWindowListener.showAdapter;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeFalse;
import static org.junit.Assume.assumeTrue;

import java.io.IOException;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.time.Instant;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.atomic.AtomicIntegerArray;
import java.util.concurrent.atomic.AtomicReference;
import java.util.concurrent.atomic.AtomicReferenceArray;
import java.util.function.Supplier;

import org.eclipse.swt.SWT;
import org.eclipse.swt.SWTException;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.BrowserFunction;
import org.eclipse.swt.browser.CloseWindowListener;
import org.eclipse.swt.browser.LocationAdapter;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.LocationListener;
import org.eclipse.swt.browser.OpenWindowListener;
import org.eclipse.swt.browser.ProgressAdapter;
import org.eclipse.swt.browser.ProgressEvent;
import org.eclipse.swt.browser.ProgressListener;
import org.eclipse.swt.browser.StatusTextListener;
import org.eclipse.swt.browser.TitleListener;
import org.eclipse.swt.browser.VisibilityWindowAdapter;
import org.eclipse.swt.browser.VisibilityWindowListener;
import org.eclipse.swt.browser.WindowEvent;
import org.eclipse.swt.graphics.Point;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;

/**
 * Automated Test Suite for class org.eclipse.swt.browser.Browser
 *
 * @see org.eclipse.swt.browser.Browser
 */
public class Test_org_eclipse_swt_browser_Browser extends Test_org_eclipse_swt_widgets_Composite {

	// CONFIG
	/** This forces tests to display the shell/browser for a brief moment. Useful to see what's going on with broken jUnits */
	boolean debug_show_browser = false; // true to display browser.
	int     debug_show_browser_timeout_seconds = 2; // if above set to true, then how long should the browser be shown for.
													// This is independent of whether test passes or fails.

	boolean debug_verbose_output = false;

	int secondsToWaitTillFail; // configured in setUp() to allow individual tests to override this.
	// CONFIG END

	@Rule
	public TestName name = new TestName();

	Browser browser;
	boolean isChromium = false, isEdge = false;

	static int[] webkitGtkVersionInts = new int[3];

	/** Accumiliate logs, print only if test case fails. Cleared for each test case. */
	StringBuilder testLog;
	private void testLogAppend(String msg) {
		testLog.append("  " + msg + "\n");
	}


@Override
@Before
public void setUp() {
	super.setUp();
	secondsToWaitTillFail = Math.max(15, debug_show_browser_timeout_seconds);

	// If webkit crashes, it's very hard to tell which jUnit caused the JVM crash.
	// To get around this, we print each test's name and if there is a crash, it will be printed right after.
	// This is kept for future use as sometimes crashes can appear out of the blue with no changes in SWT code.
	// E.g an upgrade from WebkitGtk2.16 to WebkitGtk2.18 caused random crashes because dispose logic was changed.
	System.out.println("Running Test_org_eclipse_swt_browser_Browser#" + name.getMethodName());

	shell.setLayout(new FillLayout());
	browser = new Browser(shell, SWT.NONE);

	isChromium = browser.getBrowserType().equals("chromium");
	isEdge = browser.getBrowserType().equals("edge");

	String shellTitle = name.getMethodName();
	if (SwtTestUtil.isGTK && browser.getBrowserType().equals("webkit")) {

		// Note, webkitGtk version is only available once Browser is instantiated.
		String webkitGtkVersionStr = System.getProperty("org.eclipse.swt.internal.webkitgtk.version"); //$NON-NLS-1$

		shellTitle = shellTitle + " Webkit version: " + webkitGtkVersionStr;
	}
	shell.setText(shellTitle);
	setWidget(browser); // For browser to occupy the whole shell, not just half of it.

	testLog = new StringBuilder("\nTest log:\n");
}


/**
 * Test that if Browser is constructed with the parent being "null", Browser throws an exception.
 */
@Override
@Test(expected = IllegalArgumentException.class)
public void test_ConstructorLorg_eclipse_swt_widgets_CompositeI() {
	Browser browser = new Browser(shell, SWT.NONE);
	browser.dispose();
	browser = new Browser(shell, SWT.BORDER);
	// System.out.println("Test_org_eclipse_swt_browser_Browser#test_Constructor*#getBrowserType(): " + browser.getBrowserType());
	browser.dispose();
	browser = new Browser(null, SWT.NONE); // Should throw.
}


@Test
public void test_evalute_Cookies () {
	final AtomicBoolean loaded = new AtomicBoolean(false);
	browser.addProgressListener(ProgressListener.completedAdapter(event -> loaded.set(true)));

	// Using JavaScript Cookie API on local (file) URL gives DOM Exception 18
	browser.setUrl("http://www.eclipse.org/swt");
	shell.open();
	waitForPassCondition(loaded::get);

	// Set the cookies
	// document.cookie behaves different from other global vars
	browser.evaluate("document.cookie = \"cookie1=value1\";");
	browser.evaluate("document.cookie = \"cookie2=value2\";");

	// Retrieve entire cookie store
	String res = (String) browser.evaluate("return document.cookie;");

	assertTrue(!res.isEmpty());
}

@Test
public void test_ClearAllSessionCookies () {
	// clearSessions will only work for Webkit2 when >= 2.16
	assumeTrue(webkitGtkVersionInts[1] >= 16);

	final AtomicBoolean loaded = new AtomicBoolean(false);
	browser.addProgressListener(ProgressListener.completedAdapter(event -> loaded.set(true)));

	// Using JavaScript Cookie API on local (file) URL gives DOM Exception 18
	browser.setUrl("http://www.eclipse.org/swt");
	shell.open();
	waitForPassCondition(loaded::get);

	// Set the cookies
	Browser.setCookie("cookie1=value1", "http://www.eclipse.org/swt");
	Browser.setCookie("cookie2=value2", "http://www.eclipse.org/swt");

	// Get the cookies
	String v1 = Browser.getCookie("cookie1", "http://www.eclipse.org/swt");
	String v2 = Browser.getCookie("cookie2", "http://www.eclipse.org/swt");
	assertEquals("value1", v1);
	assertEquals("value2", v2);

	Browser.clearSessions();

	// Should be empty
	String e1 = Browser.getCookie("cookie1", "http://www.eclipse.org/swt");
	String e2 = Browser.getCookie("cookie2", "http://www.eclipse.org/swt");
	assertTrue(e1 == null || e1.isEmpty());
	assertTrue(e2 == null || e2.isEmpty());
}

@Test
public void test_get_set_Cookies() {
	// set/get cookies will only work for WebKit2.20+
	assumeTrue(webkitGtkVersionInts[1] >= 20);
	final AtomicBoolean loaded = new AtomicBoolean(false);
	browser.addProgressListener(ProgressListener.completedAdapter(event -> loaded.set(true)));

	// Using JavaScript Cookie API on local (file) URL gives DOM Exception 18
	browser.setUrl("http://www.eclipse.org/swt");
	shell.open();
	waitForPassCondition(loaded::get);

	// Set the cookies
	Browser.setCookie("cookie1=value1", "http://www.eclipse.org/swt");
	Browser.setCookie("cookie2=value2", "http://www.eclipse.org/swt");

	// Get the cookies
	String v1 = Browser.getCookie("cookie1", "http://www.eclipse.org/swt");
	assertEquals("value1", v1);
	String v2 = Browser.getCookie("cookie2", "http://www.eclipse.org/swt");
	assertEquals("value2", v2);
}

@Override
@Test
public void test_getChildren() {
	// Win32's Browser is a special case. It has 1 child by default, the OleFrame.
	// See Bug 499387 and Bug 511874
	if (SwtTestUtil.isWindows && !isChromium && !isEdge) {
		int childCount = composite.getChildren().length;
		String msg = "Browser on Win32 is a special case, the first child is an OleFrame (ActiveX control). Actual child count is: " + childCount;
		assertTrue(msg, childCount == 1);
	} else {
		super.test_getChildren();
	}
}

@Test
public void test_CloseWindowListener_closeShell() {
	Display display = Display.getCurrent();
	Shell shell = new Shell(display);
	Browser browser = new Browser(shell, SWT.NONE);
	browser.addCloseWindowListener(event -> {}); // shouldn't throw
	shell.close();
}

@Test(expected = IllegalArgumentException.class)
public void test_CloseWindowListener_addWithNullArg() {
	browser.addCloseWindowListener(null);
}

@Test(expected = IllegalArgumentException.class)
public void test_CloseWindowListener_removeWithNullArg() {
	browser.removeCloseWindowListener(null);
}

@Test
public void test_CloseWindowListener_addAndRemove () {
	CloseWindowListener listener = event -> {};
	for (int i = 0; i < 100; i++) browser.addCloseWindowListener(listener);
	for (int i = 0; i < 100; i++) browser.removeCloseWindowListener(listener);
}

@Test
public void test_CloseWindowListener_close () {
	AtomicBoolean browserCloseListenerFired = new AtomicBoolean(false);
	browser.addCloseWindowListener(	e -> {
		disposedIntentionally= true;
		browserCloseListenerFired.set(true);
	});
	browser.setText("<script language='JavaScript'>window.close()</script>");
	shell.open();
	boolean passed = waitForPassCondition(browserCloseListenerFired::get);
	assertTrue("Test timed out.", passed);
}

@Test
public void test_LocationListener_adapter_closeShell() {
	Display display = Display.getCurrent();
	Shell shell = new Shell(display);
	Browser browser = new Browser(shell, SWT.NONE);
	LocationAdapter adapter = new LocationAdapter() {};
	browser.addLocationListener(adapter); // shouldn't throw
	shell.close();
}

@Test(expected = IllegalArgumentException.class)
public void test_LocationListener_addWithNullArg() {
	browser.addLocationListener(null);
}

@Test(expected = IllegalArgumentException.class)
public void test_LocationListener_removeWithNullArg() {
	browser.removeLocationListener(null);
}

@Test
public void test_LocationListener_addAndRemove() {
	LocationListener listener = new LocationListener() {
		@Override
		public void changed(LocationEvent event) {
		}
		@Override
		public void changing(LocationEvent event) {
		}
	};
	for (int i = 0; i < 100; i++) browser.addLocationListener(listener);
	for (int i = 0; i < 100; i++) browser.removeLocationListener(listener);
}

@Test
public void test_LocationListener_changing() {
	AtomicBoolean changingFired = new AtomicBoolean(false);
	browser.addLocationListener(changingAdapter(e -> changingFired.set(true)));
	shell.open();
	if (isChromium) {
		browser.setUrl("about:version");
	} else { // Chromium cannot fire changing event for setText
		browser.setText("Hello world");
	}
	boolean passed = waitForPassCondition(changingFired::get);
	assertTrue("LocationListener.changing() event was never fired", passed);
}
@Test
public void test_LocationListener_changed() {
	AtomicBoolean changedFired = new AtomicBoolean(false);
	browser.addLocationListener(changedAdapter(e ->	changedFired.set(true)));
	shell.open();
	browser.setText("Hello world");
	boolean passed = waitForPassCondition(changedFired::get);
	assertTrue("LocationListener.changed() event was never fired", passed);
}
@Test
public void test_LocationListener_changingAndOnlyThenChanged() {
	// Test proper order of events.
	// Check that 'changed' is only fired after 'changing' has fired at least once.
	AtomicBoolean changingFired = new AtomicBoolean(false);
	AtomicBoolean changedFired = new AtomicBoolean(false);
	AtomicBoolean changedFiredTooEarly = new AtomicBoolean(false);
	AtomicBoolean finished = new AtomicBoolean(false);

	browser.addLocationListener(new LocationListener() {
		@Override
		public void changing(LocationEvent event) { // Multiple changing events can occur during a load.
				changingFired.set(true);
		}
		@Override
		public void changed(LocationEvent event) {
			if (!changingFired.get())
				changedFiredTooEarly.set(true);

			changedFired.set(true);
			finished.set(true);
		}
	});
	shell.open();
	if (isChromium) {
		browser.setUrl("about:version");
	} else { // Chromium cannot fire changing event for setText
		browser.setText("Hello world");
	}
	waitForPassCondition(finished::get);

	if (finished.get() && changingFired.get() && changedFired.get() && !changedFiredTooEarly.get()) {
		return; // pass
	} else if (!finished.get()) {
		fail("Test timed out. 'changed()' never fired");
	} else {
		if (changedFiredTooEarly.get())
			fail("changed() was fired before changing(). Wrong signal order");
		else if (!changingFired.get())
			fail("changing() was never fired");
		else  {
			fail("LocationListener test failed. changing():" + changingFired.get()
			+ "  changed():" + changedFired.get() + " changedFiredTooEarly:" + changedFiredTooEarly.get());
		}
	}
}

@Test
public void test_LocationListener_then_ProgressListener() {
	AtomicBoolean locationChanged = new AtomicBoolean(false);
	AtomicBoolean progressChanged = new AtomicBoolean(false);
	AtomicBoolean progressChangedAfterLocationChanged = new AtomicBoolean(false);

	browser.addLocationListener(changedAdapter(event ->	locationChanged.set(true)));

	browser.addProgressListener(completedAdapter(event -> {
		if (locationChanged.get()) {
			progressChangedAfterLocationChanged.set(true);
		}
		progressChanged.set(true);
	}));

	shell.open();
	browser.setText("Hello world");

	waitForPassCondition(progressChanged::get);
	String errorMsg = "\nUnexpected listener states. Expecting true for all, but have:\n"
			+ "Location changed: " + locationChanged.get() + "\n"
			+ "ProgressChangedAfterLocationChanged: " + progressChangedAfterLocationChanged.get() + "\n"
			+ "progressChanged: " + progressChanged.get();

	assertTrue(errorMsg, progressChangedAfterLocationChanged.get());
}

@Test
/**
 * "event.doit = false" in Location.changing() should stop 'Loction.changed & progress.completed' from getting fired.
 */
public void test_LocationListener_ProgressListener_cancledLoad () {

	AtomicBoolean locationChanging = new AtomicBoolean(false);
	AtomicBoolean unexpectedLocationChanged = new AtomicBoolean(false);
	AtomicBoolean unexpectedProgressCompleted = new AtomicBoolean(false);

	browser.addLocationListener(new LocationListener() {
		@Override
		public void changing(LocationEvent event) {
			event.doit = false;
			locationChanging.set(true);
		}
		@Override
		public void changed(LocationEvent event) {
			if (event.location.length() != 0) { // See footnote 1
				unexpectedLocationChanged.set(true);
			}
		}
	});

	browser.addProgressListener(completedAdapter(event -> {
		String location = browser.getUrl();
		if (location.length() != 0) { // See footnote 1
			unexpectedProgressCompleted.set(true);
		}
	}));
	shell.open();
	if (isChromium) {
	    browser.setUrl("about:version");
	} else { // Chromium cannot fire changing event for setText
	    browser.setText("You should not see this message.");
	}

	// We must wait for events *not* to fire.
	// On Gtk, Quadcore (Intel i7-4870HQ pci-e SSD, all events fire after ~80ms.
	// For stability, wait 1000 ms.
	waitForMilliseconds(1000);

	boolean passed = locationChanging.get() && !unexpectedLocationChanged.get() && !unexpectedProgressCompleted.get();
	String errMsg = "\nUnexpected event fired. \n"
			+ "LocationChanging (should be true): " + locationChanging.get() + "\n"
			+ "LocationChanged unexpectedly (should be false): " + unexpectedLocationChanged.get() + "\n"
			+ "ProgressChanged unexpectedly (should be false): " + unexpectedProgressCompleted.get() + "\n";


	assertTrue(errMsg, passed);

	/* FOOTNOTE 1
	 *
	 * Feature on Internet Explorer. If there is no current location, IE still fires a DocumentComplete
	 * following the BeforeNavigate2 cancel event. This DocumentComplete event contains an empty URL
	 * since the URL in BeforeNavigate2 was correctly cancelled.
	 * The test considers it is OK to send a Location.changed and a Progress.completed events after
	 * a Location.changing cancel true - at the condition that the current location is empty,
	 * otherwise it is considered that the location was not successfully cancelled.
	 */
}


@Test
/** Ensue that only one changed and one completed event are fired for url changes */
public void test_LocationListener_ProgressListener_noExtraEvents() {
	AtomicInteger changedCount = new AtomicInteger(0);
	AtomicInteger completedCount = new AtomicInteger(0);

	browser.addLocationListener(changedAdapter(e ->	changedCount.incrementAndGet()));

	browser.addProgressListener(completedAdapter(e -> completedCount.incrementAndGet()));

	shell.open();
	browser.setText("Hello world");

	// We have to wait to check that no extra events are fired.
	// On Gtk, Quad Core, pcie this takes 80 ms. ~1000ms for stability.
	waitForMilliseconds(600);
	boolean passed = changedCount.get() == 1 && completedCount.get() == 1;
	String errorMsg = "\nIncorrect event sequences. Events missing or too many fired:"
			+ "\nExpected one of each, but received:"
			+ "\nChanged count: " + changedCount.get()
			+ "\nCompleted count: " + completedCount.get();
	assertTrue(errorMsg, passed);
}

@Test
public void test_OpenWindowListener_closeShell() {
	Display display = Display.getCurrent();
	Shell shell = new Shell(display);
	Browser browser = new Browser(shell, SWT.NONE);
	browser.addOpenWindowListener(event -> {});
	shell.close();
}

@Test(expected = IllegalArgumentException.class)
public void test_OpenWindowListener_addWithNulArg() {
	browser.addOpenWindowListener(null);
}

@Test(expected = IllegalArgumentException.class)
public void test_OpenWindowListener_removeWithNullArg() {
	browser.removeOpenWindowListener(null);
}

@Test
public void test_OpenWindowListener_addAndRemove() {
	OpenWindowListener listener = event -> {};
	for (int i = 0; i < 100; i++) browser.addOpenWindowListener(listener);
	for (int i = 0; i < 100; i++) browser.removeOpenWindowListener(listener);
}

@Test
public void test_OpenWindowListener_openHasValidEventDetails() {
	AtomicBoolean openFiredCorrectly = new AtomicBoolean(false);
	final Browser browserChild = new Browser(shell, SWT.None);
	browser.addOpenWindowListener(event -> {
		assertTrue("Expected Browser1 instance, but have another instance", (Browser) event.widget == browser);
		assertTrue("Expected event.browser to be null", event.browser == null);
		openFiredCorrectly.set(true);
		event.browser = browserChild;
	});

	shell.open();
	browser.setText("<html><script type='text/javascript'>window.open('about:blank')</script>\n" +
			"<body>This test uses javascript to open a new window.</body></html>");

	boolean passed = waitForPassCondition(openFiredCorrectly::get);
	assertTrue("Test timed out. OpenWindow event not fired.", passed);
}

/** Test that a script 'window.open()' opens a child popup shell. */
@Test
public void test_OpenWindowListener_open_ChildPopup() {
	AtomicBoolean childCompleted = new AtomicBoolean(false);

	Shell childShell = new Shell(shell, SWT.None);
	childShell.setText("Child shell");
	childShell.setLayout(new FillLayout());
	final Browser browserChild = new Browser(childShell, SWT.NONE);

	browser.addOpenWindowListener(event -> {
		event.browser = browserChild;
	});

	browserChild.addVisibilityWindowListener(showAdapter(event -> {
		childShell.open();
		browserChild.setText("Child Browser");
	}));
	//Triggers test to finish.
	browserChild.addProgressListener(completedAdapter(event -> childCompleted.set(true)));

	shell.open();

	browser.setText("<html>"
			+ "<script type='text/javascript'>"
			+ "var newWin = window.open('about:blank');" // opens child window.
			+ "</script>\n" +
			"<body>This test uses javascript to open a new window.</body></html>");

	boolean passed = waitForPassCondition(childCompleted::get);

	String errMsg = "\nTest timed out.";
	assertTrue(errMsg, passed);
}

/** Validate event order : Child's visibility should come before progress completed event */
@Test
public void test_OpenWindow_Progress_Listener_ValidateEventOrder() {
	AtomicBoolean windowOpenFired = new AtomicBoolean(false);
	AtomicBoolean childCompleted = new AtomicBoolean(false);
	AtomicBoolean visibilityShowed = new AtomicBoolean(false);

	Shell childShell = new Shell(shell, SWT.None);
	childShell.setText("Child shell");
	childShell.setLayout(new FillLayout());
	final Browser browserChild = new Browser(childShell, SWT.NONE);

	browser.addOpenWindowListener(event -> {
		event.browser = browserChild;
		assertFalse("OpenWindowListenr should have been fired first", visibilityShowed.get() || childCompleted.get()); // Validate event order.
		windowOpenFired.set(true);
	});

	browserChild.addVisibilityWindowListener(showAdapter(event -> {
		childShell.open();
		assertTrue("Child Visibility.show should have fired before progress completed",
				windowOpenFired.get() && !childCompleted.get()); // Validate event order.
		visibilityShowed.set(true);
	}));

	browserChild.addProgressListener(completedAdapter(event -> {
		assertTrue("Child's Progress Completed before parent's expected events",
				windowOpenFired.get() && visibilityShowed.get()); // Validate event order.
		childCompleted.set(true); // Triggers test to finish.
		browserChild.setText("Child Browser!");
	}));

	shell.open();

	browser.setText("<html>"
			+ "<script type='text/javascript'>"
			+ "var newWin = window.open('about:blank');" // opens child window.
			+ "</script>\n" +
			"<body>This test uses javascript to open a new window.</body></html>");

	boolean passed = waitForPassCondition(() -> windowOpenFired.get() && visibilityShowed.get() && childCompleted.get());

	String errMsg = "\nTest timed out."
			+"\nExpected true for the below, but have:"
			+"\nWindoOpenFired:" + windowOpenFired.get()
			+"\nVisibilityShowed:" + visibilityShowed.get()
			+"\nChildCompleted:" + childCompleted.get();
	assertTrue(errMsg, passed);
}

@Test
public void test_ProgressListener_newProgressAdapter() {
	new ProgressAdapter() {};
}

@Test
public void test_ProgressListener_newProgressAdapter_closeShell() {
	Display display = Display.getCurrent();
	Shell shell = new Shell(display);
	Browser browser = new Browser(shell, SWT.NONE);
	browser.addProgressListener(new ProgressAdapter() {});
	shell.close();
}

@Test
public void test_ProgressListener_newListener_closeShell() {
	Display display = Display.getCurrent();
	Shell shell = new Shell(display);
	Browser browser = new Browser(shell, SWT.NONE);
	browser.addProgressListener(new ProgressListener() {
		@Override
		public void changed(ProgressEvent event) {
		}
		@Override
		public void completed(ProgressEvent event) {
		}
	});
	shell.close();
}

@Test(expected = IllegalArgumentException.class)
public void test_ProgressListener_addWithNullArg() {
	browser.addProgressListener(null);
}

@Test(expected = IllegalArgumentException.class)
public void test_ProgressListener_removeWithNullArg() {
	browser.removeProgressListener(null);
}

@Test
public void test_ProgressListener_addAndRemove() {
	ProgressListener listener = new ProgressListener() {
		@Override
		public void changed(ProgressEvent event) {
		}
		@Override
		public void completed(ProgressEvent event) {
		}
	};
	for (int i = 0; i < 100; i++) browser.addProgressListener(listener);
	for (int i = 0; i < 100; i++) browser.removeProgressListener(listener);
}

@Test
public void test_ProgressListener_completed_Called() {
	AtomicBoolean childCompleted = new AtomicBoolean(false);
	ProgressListener l = new ProgressListener() {

		@Override
		public void completed(ProgressEvent event) {
			childCompleted.set(true);
		}

		@Override
		public void changed(ProgressEvent event) {

		}
	};
	browser.addProgressListener(l);
	browser.setText("<html><body>This test ensures that the completed listener is called.</body></html>");
	shell.open();
	boolean passed = waitForPassCondition(childCompleted::get);
	assertTrue(passed);
}

@Test(expected = IllegalArgumentException.class)
public void test_StatusTextListener_addWithNull() {
	browser.addStatusTextListener(null);
}

@Test(expected = IllegalArgumentException.class)
public void test_StatusTextListener_removeWithNullArg() {
	browser.removeStatusTextListener(null);
}

@Test
public void test_StatusTextListener_addAndRemove() {
	StatusTextListener listener = event -> {
	};
	for (int i = 0; i < 100; i++) browser.addStatusTextListener(listener);
	for (int i = 0; i < 100; i++) browser.removeStatusTextListener(listener);
}

/**
 * Test if hovering over a hyperlink triggers status Text change listener.
 * Logic:
 * 1) Create a page that has a hyper link (covering the whole page)
 * 2) Move shell to top left corner
 * 3) Upon compleation of page load, move cursor across whole shell.
 *    (Note, in current jUnit, browser sometimes only takes up half the shell).
 * 4) StatusTextListener should get triggered. Test passes.
 * 5) Else timeout & fail.
 *
 * Set variable "debug_show_browser" to true to see this being performed at human-observable speed.
 *
 * Note: Historically one could execute some javascript to change status bar (window.status=txt).
 * But most browsers don't support this anymore. Only hovering over a hyperlink changes status.
 *
 * StatusTextListener may be triggerd upon page load also. So this test can pass if
 * a page load sets the status text (on older browsers) or passes when the mouse hovers
 * over the hyperlink (newer Webkit2+) browser.
 */
@Test
public void test_StatusTextListener_hoverMouseOverLink() {
	assumeFalse(isEdge); // no API in Edge for this

	AtomicBoolean statusChanged = new AtomicBoolean(false);
	int size = 500;

	// 1) Create a page that has a hyper link (covering the whole page)
	Browser browser = new Browser(shell, SWT.NONE);
	StringBuilder longhtml = new StringBuilder();
	for (int i = 0; i < 200; i++) {
		longhtml.append("text text text text text text text text text text text text text text text text text text text text text text text text<br>");
	}
	browser.setText("<a href='http://localhost'>" + longhtml + "</a>");

	// 2) Move shell to top left corner
	shell.setLocation(0, 0);
	shell.setSize(size, size);

	browser.addProgressListener(completedAdapter(event -> {
		// * 3) Upon compleation of page load, move cursor across whole shell.
		// * (Note, in current jUnit, browser sometimes only takes up half the shell).
		Display display = event.display;
		Point cachedLocation = display.getCursorLocation();
		display.setCursorLocation(20, 10);
		browser.getBounds();
		for (int i = 0; i < size; i = i + 5) {
			display.setCursorLocation(i, i);
			waitForMilliseconds(debug_show_browser ? 3 : 1); // Move mouse slower during debug.
		}
		display.setCursorLocation(cachedLocation); // for convenience of developer. Not needed for test.

	}));

	browser.addStatusTextListener(event -> {
		statusChanged.set(true);
	});

	shell.open();
	boolean passed = waitForPassCondition(statusChanged::get);
	String msg = "Mouse movent over text was suppose to trigger StatusTextListener. But it didn't";
	assertTrue(msg, passed);
}

@Test
public void test_TitleListener_addListener_closeShell() {
	Display display = Display.getCurrent();
	Shell shell = new Shell(display);
	Browser browser = new Browser(shell, SWT.NONE);
	browser.addTitleListener(event -> {
	});
	shell.close();
}

@Test(expected = IllegalArgumentException.class)
public void test_TitleListener_addwithNull() {
	browser.addTitleListener(null);
}

@Test(expected = IllegalArgumentException.class)
public void test_TitleListener_removeWithNullArg() {
	browser.removeTitleListener(null);
}

@Test
public void test_TitleListener_addAndRemove() {
	TitleListener listener = event -> {};
	for (int i = 0; i < 100; i++) browser.addTitleListener(listener);
	for (int i = 0; i < 100; i++) browser.removeTitleListener(listener);
}

@Test
public void test_TitleListener_event() {
	AtomicBoolean titleListenerFired = new AtomicBoolean(false);
	browser.addTitleListener(event -> titleListenerFired.set(true));
	browser.setText("<html><title>Hello world</title><body>Page with a title</body></html>");
	shell.open();
	boolean passed = waitForPassCondition(titleListenerFired::get);
	String errMsg = "Title listener never fired. Test timed out.";
	assertTrue(errMsg, passed);
}


@Test
public void test_setText() {
	String expectedTitle = "Website Title";
	Runnable browserSetFunc = () -> {
		String html = "<html><title>Website Title</title><body>Html page with custom title</body></html>";
		boolean opSuccess = browser.setText(html);
		assertTrue("Expecting setText() to return true", opSuccess);
	};
	validateTitleChanged(expectedTitle, browserSetFunc);
}

@Test
public void test_setUrl_local() {
	String expectedTitle = "Website Title";
	Runnable browserSetFunc = () -> {

		String pluginPath = System.getProperty("PLUGIN_PATH");
		testLogAppend("PLUGIN_PATH: " + pluginPath);

		String url;
		// Depending on how the jUnit test is ran, (gui/maven/ant), url for local file needs to be acquired differently.
		if (pluginPath != null) {
			url = pluginPath + "/data/testWebsiteWithTitle.html";
		} else {
			// used when ran from Eclipse gui.
			url = Test_org_eclipse_swt_browser_Browser.class.getClassLoader().getResource("testWebsiteWithTitle.html").toString();
		}

		testLogAppend("URL: " + url);

		boolean opSuccess = browser.setUrl(url);
		assertTrue("Expecting setUrl() to return true" + testLog.toString(), opSuccess);
	};
	validateTitleChanged(expectedTitle, browserSetFunc);
}

/** This test requires working Internet connection */
@Test
public void test_setUrl_remote() {

	// This test sometimes times out if build server has a bad connection. Thus for this test we have a longer timeout.
	secondsToWaitTillFail = 35;

	String url = "http://example.com"; // example.com loads very quickly and conveniently has a consistent title

	// Skip this test if we don't have a working Internet connection.
	assumeTrue("Skipping test due to bad internet connection", checkInternet(url));
	testLog.append("checkInternet() passed");

	String expectedTitle = "Example Domain";
	Runnable browserSetFunc = () -> {
		testLog.append("Setting Browser url to:" + url);
		boolean opSuccess = browser.setUrl(url);
		assertTrue("Expecting setUrl() to return true", opSuccess);
	};
	validateTitleChanged(expectedTitle, browserSetFunc);
}

/** This test requires working Internet connection */
@Test
public void test_setUrl_remote_with_post() {
	// This test sometimes times out if build server has a bad connection. Thus for this test we have a longer timeout.
	secondsToWaitTillFail = 35;

	String url = "https://bugs.eclipse.org/bugs/buglist.cgi";

	// Skip this test if we don't have a working Internet connection.
	assumeTrue("Skipping test due to bad internet connection", checkInternet(url));
	testLog.append("checkInternet() passed");

	Runnable browserSetFunc = () -> {
		testLog.append("Setting Browser url to:" + url);
		boolean opSuccess = browser.setUrl(
				url, "bug_severity=enhancement&bug_status=NEW&email1=rgrunber&emailassigned_to1=1&emailtype1=substring",
				null);
		assertTrue("Expecting setUrl() to return true", opSuccess);
	};

	final AtomicReference<Boolean> completed = new AtomicReference<>(false);
	browser.addProgressListener(completedAdapter(event -> {
		testLog.append("ProgressListener fired");
		completed.set(true);
	}));
	browserSetFunc.run();
	shell.open();

	boolean hasFinished = waitForPassCondition(() -> completed.get().booleanValue());
	assertTrue("Test timed out. ProgressListener not fired " + testLog.toString(), hasFinished);

	// Even a successful empty query returns about 10000 chars of HTML
	int numChars = browser.getText().length();
	assertTrue("Response data contained " + numChars + " chars.", numChars > 10000);
}

private void validateTitleChanged(String expectedTitle, Runnable browserSetFunc) {
	final AtomicReference<String> actualTitle = new AtomicReference<>("");
	browser.addTitleListener(event ->  {
		testLog.append("TitleListener fired");
		assertTrue("event title is empty" + testLog.toString(), event.title != null);
		actualTitle.set(event.title);
	});
	browserSetFunc.run();
	shell.open();

	boolean hasFinished = waitForPassCondition(() -> actualTitle.get().length() != 0
			&& !actualTitle.get().contains("about:blank")); // Windows sometimes does 2 loads, one "about:blank", and one actual load.
	boolean passed = hasFinished && actualTitle.get().equals(expectedTitle);
	String errMsg = "";
	if (!hasFinished)
		errMsg = "Test timed out. TitleListener not fired";
	else if (!actualTitle.get().equals(expectedTitle)) {
		errMsg = "\nExpected title and actual title do not match."
				+ "\nExpected: " + expectedTitle
				+ "\nActual: " + actualTitle;
	}
	assertTrue(errMsg + testLog.toString(), passed);
}

@Test
public void test_VisibilityWindowListener_newAdapter() {
	new VisibilityWindowAdapter() {};
}

@Test
public void test_VisibilityWindowListener_newAdapter_closeShell() {
	Display display = Display.getCurrent();
	Shell shell = new Shell(display);
	Browser browser = new Browser(shell, SWT.NONE);
	browser.addVisibilityWindowListener(new VisibilityWindowAdapter(){});
	shell.close();
}

@Test
public void test_VisibilityWindowListener_newListener_closeShell() {
	Display display = Display.getCurrent();
	Shell shell = new Shell(display);
	Browser browser = new Browser(shell, SWT.NONE);
	browser.addVisibilityWindowListener(new VisibilityWindowListener() {
		@Override
		public void hide(WindowEvent event) {
		}
		@Override
		public void show(WindowEvent event) {
		}
	});
	shell.close();
}

@Test(expected = IllegalArgumentException.class)
public void test_VisibilityWindowListener_addWithNull() {
	browser.addVisibilityWindowListener(null);
}

@Test(expected = IllegalArgumentException.class)
public void test_VisibilityWindowListener_removeWithNullArg() {
	browser.removeVisibilityWindowListener(null);
}

@Test
public void test_VisibilityWindowListener_addAndRemove() {
	VisibilityWindowListener listener = new VisibilityWindowListener() {
		@Override
		public void hide(WindowEvent event) {
		}
		@Override
		public void show(WindowEvent event) {
		}
	};
	for (int i = 0; i < 100; i++) browser.addVisibilityWindowListener(listener);
	for (int i = 0; i < 100; i++) browser.removeVisibilityWindowListener(listener);
}

/** Verify that if multiple child shells are open, no duplicate visibility events are sent. */
@Test
public void test_VisibilityWindowListener_multiple_shells() {
		assumeTrue(!isChromium); // this fails sometimes due cef limitation, can be enabled on newer versions.
		AtomicBoolean secondChildCompleted = new AtomicBoolean(false);
		AtomicInteger childCount = new AtomicInteger(0);

		browser.addOpenWindowListener(event -> {
			Shell childShell = new Shell(shell);
			childShell.setText("Child shell " + childCount.get());
			childShell.setLayout(new FillLayout());
			Browser browserChild = new Browser(childShell, SWT.NONE);
			event.browser = browserChild;
			browserChild.setText("Child window");
			browserChild.addVisibilityWindowListener(new VisibilityWindowAdapter() {
				AtomicInteger invocationCount = new AtomicInteger(1);
				AtomicInteger childID = new AtomicInteger(childCount.get());
				@Override
				public void show(WindowEvent event) {
					if (childID.get() == 0 && invocationCount.get() >= 2) {
						// Certain browsers fire multiple show events for no good reason. Further show events
						// are considered 'legal' as long as they don't contain size and location information.
						if (event.location != null || event.size != null) {
							fail("Child browser's visibility show listener should only be fired once");
						}
					}
					invocationCount.incrementAndGet();
				}
			});

			if (childCount.get() == 1) {
				browserChild.addProgressListener(new ProgressAdapter() {
					@Override
					public void completed(ProgressEvent event) {
						secondChildCompleted.set(true);
					}
				});
			}
			childShell.open();
			childCount.incrementAndGet();
		});

		shell.open();
		browser.setText("<html>"
				+ "<script type='text/javascript'>"
				+ "window.open('about:blank');" // opens child window.
				+ "window.open('about:blank');"
				+ "</script>\n" +
				"<body>This test uses javascript to open a new window.</body></html>");

		boolean passed = waitForPassCondition(secondChildCompleted::get);

		String errMsg = "\nTest timed out.";
		assertTrue(errMsg, passed);
}

/**
 *  Validate that when javascript opens a new window and specifies size,
 *  it's size is passed to the visibility event correctly.
 */
@Test
public void test_VisibilityWindowListener_eventSize() {
	shell.setSize(200,300);
	AtomicBoolean childCompleted = new AtomicBoolean(false);
	AtomicReference<Point> result = new AtomicReference<>(new Point(0,0));

	Shell childShell = new Shell(shell);
	childShell.setSize(250, 350);
	childShell.setText("Child shell");
	childShell.setLayout(new FillLayout());
	final Browser browserChild = new Browser(childShell, SWT.NONE);

	browser.addOpenWindowListener(event -> {
		event.browser = browserChild;
		testLog.append("openWindowListener fired");
	});

	browserChild.addVisibilityWindowListener(showAdapter(event -> {
		testLog.append("Visibilty show eventfired.\nEvent size: " + event.size);
		result.set(event.size);
		childShell.open();
		childCompleted.set(true);
	}));

	shell.open();
	browser.setText("<html>"
			+ "<script type='text/javascript'>"
			+ "window.open('javascript:\"Child Window\"','', \"height=200,width=300\")\n"
			+ "</script>\n" +
			"<body>This test uses javascript to open a new window.</body></html>");

	boolean finishedWithoutTimeout = waitForPassCondition(childCompleted::get);
	browserChild.dispose();

	boolean passed = false;
	if (SwtTestUtil.isCocoa) {
		// On Cocoa, event height/width aren't respected if declared by javascript.
		passed = finishedWithoutTimeout && result.get().x != 0 && result.get().y != 0;
	} else
		passed = finishedWithoutTimeout && result.get().x == 300 && result.get().y == 200;

	String errMsg = finishedWithoutTimeout ?
			"Incorrect size received:"
			+ "\nexpected width=300, actual:" + result.get().x
			+ "\nexpected height=100, actual:" + result.get().y
			: "test timed out. Child's visibility Window listener didn't trigger";
	assertTrue(errMsg + testLog.toString(), passed);
}

@Override
@Test
public void test_isVisible() {
	// Note. This test sometimes crashes with webkit1 because shell.setVisible() calls g_main_context_iteration(). See Bug 509411
	// To reproduce, try running test suite 20 times in a loop.
	super.test_isVisible();
}

/**
 * Test that going back in history, when no new pages were visited, returns false.
 */
@Test
public void test_back() {
	for (int i = 0; i < 2; i++) {
		browser.back();
	}
	/* returning 10 times in history - expecting false is returned */
	boolean result = browser.back();
	assertFalse(result);
}

@Test(expected = IllegalArgumentException.class)
public void test_setTextNull() {
	browser.setText(null);
}

@Test(expected = IllegalArgumentException.class)
public void test_setUrlWithNullArg() {
	browser.setUrl(null);
}


/**
 * Logic:
 * - Load a page. Turn off javascript (which takes effect on next pageload)
 * - Load a second page. Try to execute some javascript. If javascript is exectuted then fail.
 */
@Test
public void test_setJavascriptEnabled() {
	AtomicInteger pageLoadCount = new AtomicInteger(0);
	AtomicBoolean testFinished = new AtomicBoolean(false);
	AtomicBoolean testPassed = new AtomicBoolean(false);

	browser.addProgressListener(completedAdapter(event -> {
		pageLoadCount.incrementAndGet();
		if (pageLoadCount.get() == 1) {
			browser.setJavascriptEnabled(false);
			browser.setText("Second page with javascript dissabled");
		} else if (pageLoadCount.get() == 2) {
			Boolean expectedNull = null;
			try {
				expectedNull = (Boolean) browser.evaluate("return true");
			} catch (Exception e) {
				fail("1) if javascript is dissabled, browser.evaluate() should return null. But an Exception was thrown");
			}
			assertNull("2) Javascript should not have executed. But not-null was returned:" + expectedNull,
					expectedNull);

			testPassed.set(true);
			testFinished.set(true);
		}
	}));

	shell.open();
	browser.setText("First page with javascript enabled. This should not be visiable as a second page should load");

	waitForPassCondition(testFinished::get);
	assertTrue("3) Javascript was executed on the second page. But it shouldn't have", testPassed.get());
}

/** Check that if there are two browser instances, turning off JS in one instance doesn't turn off JS in the other instance. */
@Test
public void test_setJavascriptEnabled_multipleInstances() {

	AtomicInteger pageLoadCount = new AtomicInteger(1);
	AtomicInteger pageLoadCountSecondInstance = new AtomicInteger(1);

	AtomicBoolean instanceOneFinishedCorrectly = new AtomicBoolean(false);
	AtomicBoolean instanceTwoFinishedCorrectly = new AtomicBoolean(false);


	Browser browserSecondInsance = new Browser(shell, SWT.None);

	browser.addProgressListener(completedAdapter(event -> {
		if (pageLoadCount.get() == 1) {
			browser.setJavascriptEnabled(false);

			pageLoadCount.set(2);
			browser.setText("First instance, second page (with javascript turned off)");

			pageLoadCountSecondInstance.set(2);
			browserSecondInsance.setText("Second instance, second page (javascript execution not changed)");
		} else if (pageLoadCount.get() == 2) {
			pageLoadCount.set(3);

			Boolean shouldBeNull = (Boolean) browser.evaluate("return true");
			assertNull("1) Evaluate execution should be null, but 'true was returned'", shouldBeNull);
			instanceOneFinishedCorrectly.set(true);
		}
	}));

	browserSecondInsance.addProgressListener(new ProgressAdapter() {
		@Override
		public void completed(ProgressEvent event) {
			if (pageLoadCountSecondInstance.get() == 2) {
				pageLoadCountSecondInstance.set(3);

				Boolean shouldBeTrue = (Boolean) browserSecondInsance.evaluate("return true");
				assertTrue("2) Javascript should be executable in second instance (as javascript was not turned off), but it was not. "
						+ "Expected:'someStr', Actual:"+shouldBeTrue, shouldBeTrue);
				instanceTwoFinishedCorrectly.set(true);
			}
		}
	});

	browser.setText("First Instance, first page");
	browserSecondInsance.setText("Second instance, first page");

	shell.open();
	boolean passed = waitForPassCondition(() -> {return instanceOneFinishedCorrectly.get() && instanceTwoFinishedCorrectly.get();});

	String message = "3) Test timed out. Debug Info:\n" +
			"InstanceOneFinishedCorrectly: " + instanceOneFinishedCorrectly.get() + "\n" +
			"InstanceTwoFinishedCorrectly: " + instanceTwoFinishedCorrectly.get() + "\n" +
			"Instance 1 & 2 page counts: " + pageLoadCount.get() + " & " + pageLoadCountSecondInstance.get();

	assertTrue(message, passed);
}

/**
*  This test replicates what happens internally
*  if you click on a link in a javadoc popup hoverbox.
*  I.e, in a location listener, evaluation() is performed.
*
*  The goal of this test is to ensure there are no 'Freezes'/deadlocks if
*  javascript evaluation is invoked inside an SWT listener.
*
*  At time of writing, it also highlights that evaluation inside SWT listeners
*  is not consistent across browsers.
*/
@Test
public void test_LocationListener_evaluateInCallback() {
	AtomicBoolean changingFinished = new AtomicBoolean(false);
	AtomicBoolean changedFinished = new AtomicBoolean(false);
	browser.addLocationListener(new LocationListener() {
		@Override
		public void changing(LocationEvent event) {
			browser.evaluate("SWTchanging = true");
			changingFinished.set(true);
		}
		@Override
		public void changed(LocationEvent event) {
			browser.evaluate("SWTchanged = true");
			changedFinished.set(true);
		}
	});

	shell.open();
	if (isChromium) {
		browser.setUrl("about:version");
	} else { // Chromium cannot fire changing event for setText
		browser.setText("<body>Hello <b>World</b></body>");
	}
	// Wait till both listeners were fired.
	if (SwtTestUtil.isWindows && !isChromium) {
		waitForPassCondition(changingFinished::get); // Windows doesn't reach changedFinished.get();
	} else
		waitForPassCondition(() -> (changingFinished.get() && changedFinished.get()));

	// Inspect if evaluate() was executed correctly.
	Boolean changed = false;
	try { changed = (Boolean) browser.evaluate("return SWTchanged"); } catch (SWTException e) {}
	Boolean changing = false;
	try { changing = (Boolean) browser.evaluate("return SWTchanging"); } catch (SWTException e) {}


	String errMsg = "\n  changing:  fired:" +  changingFinished.get() + "    evaluated:" + changing +
					"\n  changed:   fired:" + changedFinished.get() + "    evaluated:" + changed;
	boolean passed = false;

	if (isChromium) {
		// On Chromium, evaluation in 'changing' fails.
		passed = changingFinished.get() && changedFinished.get() && changed; // && changing (broken)
	} else if (SwtTestUtil.isGTK) {
		// Evaluation works in all cases.
		passed = changingFinished.get() && changedFinished.get() && changed && changing;
	} else if (SwtTestUtil.isCocoa) {
		// On Cocoa, evaluation in 'changing' fails.
		passed = changingFinished.get() && changedFinished.get() && changed; // && changing (broken)
	} else if (SwtTestUtil.isWindows) {
		// On Windows, evaluation inside SWT listeners fails altogether.
		// Further, only 'changing' is fired if evaluation is invoked inside listeners.
		passed = changingFinished.get();
	}
	assertTrue(errMsg, passed);
}

/** Verify that evaluation works inside an OpenWindowListener */
@Test
public void test_OpenWindowListener_evaluateInCallback() {
	assumeTrue(!isChromium); // This works on Webkit1, but can sporadically fail, see Bug 509411
	AtomicBoolean eventFired = new AtomicBoolean(false);
	browser.addOpenWindowListener(event -> {
		browser.evaluate("SWTopenListener = true");
		eventFired.set(true);
		event.required = true;
	});
	shell.open();
	browser.evaluate("window.open('about:blank')");
	boolean fired = waitForPassCondition(eventFired::get);
	boolean evaluated = false;
	try { evaluated = (Boolean) browser.evaluate("return SWTopenListener"); } catch (SWTException e) {}
	boolean passed = fired && evaluated;
	String errMsg = "Event fired:" + fired + "   evaluated:" + evaluated;
	assertTrue(errMsg, passed);
}

/**
 * Test that going forward in history (without having gone back before) returns false.
 */
@Test
public void test_forward() {
	for (int i = 0; i < 2; i++) {
		browser.forward();
	}
	/* going forward 10 times in history - expecting false is returned */
	boolean result = browser.forward();
	assertFalse(result);
}

/**
 * Test that getUrl() returns a non-null string.
 */
@Test
public void test_getUrl() {
	String string = browser.getUrl();
	assertNotNull(string);
}


/**
 * Test of 'back in history' api.
 * - Test isBackEnabled() and back() return the same value.
 * - Test that going isBackEnabled still returns false if back was called multiple times.
 */
@Test
public void test_isBackEnabled() {

	/* back should return the same value that isBackEnabled previously returned */
	assertEquals(browser.isBackEnabled(), browser.back());

	for (int i = 0; i < 2; i++) {
		browser.back();
	}
	/* going back 10 times in history - expecting false is returned */
	boolean result = browser.isBackEnabled();
	assertFalse(result);
}

/**
 * Test of 'forward in history' api.
 * - Test isForwardEnabled() and forward() return the same value.
 * - Test that going isBackEnabled still returns false if back was called multiple times.
 */
@Test
public void test_isForwardEnabled() {
	/* forward should return the same value that isForwardEnabled previously returned */
	assertEquals(browser.isForwardEnabled(), browser.forward());

	for (int i = 0; i < 10; i++) {
		browser.forward();
	}
	/* going forward 10 times in history - expecting false is returned */
	boolean result = browser.isForwardEnabled();
	assertFalse(result);
}

/**
 * Test that refresh executes without throwing exceptions.
 * (Maybe we should actually load a page first?)
 */
@Test
public void test_refresh() {
	for (int i = 0; i < 2; i++) {
		browser.refresh();
	}
}

@Test
@Override
public void test_setFocus_toChild_afterOpen() {
	// The different browsers set focus to a different child
}

@Test
@Override
public void test_setFocus_toChild_beforeOpen() {
	// The different browsers set focus to a different child
}


/** Text without html tags */
@Test
public void test_getText() {
	if (SwtTestUtil.isWindows || isChromium) {
		// Window's Browser implementation returns the processed HTML rather than the original one.
		// The processed webpage has html tags added to it.
		getText_helper("helloWorld", "<html><head></head><body>helloWorld</body></html>");
	} else {
		// Linux Webkit1, Webkit2
		// Cocoa
		getText_helper("helloWorld", "helloWorld");
	}
}

@Test
public void test_getText_html() {
	String testString = "<html><head></head><body>hello<b>World</b></body></html>";
	getText_helper(testString, testString);
}

/** Ensure we get webpage before javascript processed it.
 *  E.g js would add 'style' tag to body after processing. */
@Test
public void test_getText_script() {
	String testString = "<html><head></head><body>hello World<script>document.body.style.backgroundColor = \"red\";</script></body></html>";
	if (SwtTestUtil.isWindows || isChromium) {
		// Window's Browser implementation returns the processed HTML rather than the original one.
		// The processed page injects "style" property into the body from the script.
		getText_helper(testString, "<html><head></head><body style=\"background-color: red;\">hello World<script>document.body.style.backgroundColor = \"red\";</script></body></html>");
	} else {
		// Linux Webkit1, Webkit2
		// Cocoa
		getText_helper(testString, testString);
	}

}

/** Ensure that 'DOCTYPE' is not stripped out of original string */
@Test
public void test_getText_doctype() {
	String testString = "<!DOCTYPE html><html><head></head><body>hello World</body></html>";
	if (SwtTestUtil.isWindows && !isChromium) {
		// Window's Browser implementation returns the processed HTML rather than the original one.
		// The processed page strips out DOCTYPE.
		getText_helper(testString, "<html><head></head><body>hello World</body></html>");
	} else  {
		// Linux Webkit1, Webkit2
		// Cocoa
		getText_helper(testString,testString);
	}
}

private void getText_helper(String testString, String expectedOutput) {
	AtomicReference<String> returnString= new AtomicReference<>("");
	AtomicBoolean finished = new AtomicBoolean(false);
	browser.setText(testString);
	browser.addProgressListener(completedAdapter(event -> {
		returnString.set(browser.getText());
		if (debug_verbose_output)
			System.out.println(returnString.get());
		finished.set(true);
	}));
	shell.open();
	waitForPassCondition(finished::get);
	boolean passed = returnString.get().equals(expectedOutput);
	String error_msg = finished.get() ?
			"Test did not return correct string.\n"
			+ "Expected:"+testString+"\n"
			+ "Actual:"+returnString.get()
			: "Test timed out";
	assertTrue(error_msg, passed);
}

/**
 * Test that a page load an be stopped (stop()) without throwing an exception.
 */
@Test
public void test_stop() {
	/* THIS TEST REQUIRES WEB ACCESS! How else can we really test the http:// part of a browser widget? */
	browser.setUrl("http://www.eclipse.org/swt");
	waitForMilliseconds(1000);
	browser.stop();
}

@Test(expected = IllegalArgumentException.class)
public void test_execute_withNullArg() {
	browser.execute(null);
}

/**
 * Test execute and windowCloseListener.
 * Close listener used to tell if execute actually worked in some meaningful way.
 */
@Test
public void test_execute_and_closeListener () {
	AtomicBoolean hasClosed = new AtomicBoolean(false);

	browser.setText("You should not see this page, it should have been closed by javascript");
	browser.addCloseWindowListener(e -> {
		hasClosed.set(true);
	});

	browser.execute("window.close()");

	shell.open();
	boolean passed = waitForPassCondition(hasClosed::get);
	if (passed)
		disposedIntentionally = true;
	String message = "Either browser.execute() did not work (if you still see the html page) or closeListener Was not triggered if "
			+ "browser looks disposed, but test still fails.";
	assertTrue(message, passed);
}


/**
 * Test the evaluate() api that returns a String type. Functionality based on Snippet308.
 * Only wait till success. Otherwise timeout after 3 seconds.
 */
@Test
public void test_evaluate_string() {
	final AtomicReference<String> returnValue = new AtomicReference<>();
	browser.addProgressListener(completedAdapter(event -> {
		String evalResult = (String) browser
				.evaluate("return document.getElementById('myid').childNodes[0].nodeValue;");
		returnValue.set(evalResult);
		if (debug_verbose_output)
			System.out.println("Node value: " + evalResult);
	}));

	browser.setText("<html><body><p id='myid'>HelloWorld</p></body></html>");
	shell.open();
	boolean passed = waitForPassCondition(()-> "HelloWorld".equals(returnValue.get()));
	assertTrue("Evaluation did not return a value. Or test timed out.", passed);
}

// Test where the script has the 'return' not in the beginning,
@Test
public void test_evaluate_returnMoved() {
	final AtomicReference<String> returnValue = new AtomicReference<>();
	browser.addProgressListener(completedAdapter(event -> {
		String evalResult = (String) browser.evaluate("var x = 1; return 'hello'");
		returnValue.set(evalResult);
	}));

	browser.setText("test text");
	shell.open();
	boolean passed = waitForPassCondition(()-> "hello".equals(returnValue.get()));
	assertTrue("Evaluation did not return a value. Or test timed out.", passed);
}

/**
 * Test the evaluate() api that returns a number (Double). Functionality based on Snippet308.
 * Only wait till success. Otherwise timeout after 3 seconds.
 */
@Test
public void test_evaluate_number_normal() {
	Double testNum = 123.0;
	boolean passed = evaluate_number_helper(testNum);
	assertTrue("Failed to evaluate number: " + testNum.toString(), passed);
}

/**
 * Test the evaluate() api that returns a number (Double). Functionality based on Snippet308.
 * Only wait till success. Otherwise timeout after 3 seconds.
 */
@Test
public void test_evaluate_number_negative() {
	Double testNum = -123.0;
	boolean passed = evaluate_number_helper(testNum);
	assertTrue("Failed to evaluate number: " + testNum.toString(), passed);
}

/**
 * Test the evaluate() api that returns a number (Double). Functionality based on Snippet308.
 * Only wait till success. Otherwise timeout after 3 seconds.
 */
@Test
public void test_evaluate_number_big() {
	Double testNum = 10000000000.0;
	boolean passed = evaluate_number_helper(testNum);
	assertTrue("Failed to evaluate number: " + testNum.toString(), passed);
}

boolean evaluate_number_helper(Double testNum) {
	final AtomicReference<Double> returnValue = new AtomicReference<>();
	browser.addProgressListener(completedAdapter(event -> {
		Double evalResult = (Double) browser.evaluate("return " + testNum.toString());
		returnValue.set(evalResult);
		if (debug_verbose_output)
			System.out.println("Node value: " + evalResult);
	}));

	browser.setText("<html><body>HelloWorld</body></html>");
	shell.open();
	boolean passed = waitForPassCondition(() -> testNum.equals(returnValue.get()));
	return passed;
}

/**
 * Test the evaluate() api that returns a boolean. Functionality based on Snippet308.
 * Only wait till success. Otherwise timeout after 3 seconds.
 */
@Test
public void test_evaluate_boolean() {
	final AtomicBoolean atomicBoolean = new AtomicBoolean(false);
	browser.addProgressListener(completedAdapter(event -> {
		Boolean evalResult = (Boolean) browser.evaluate("return true");
		atomicBoolean.set(evalResult);
		if (debug_verbose_output)
			System.out.println("Node value: " + evalResult);
	}));

	browser.setText("<html><body>HelloWorld</body></html>");
	shell.open();
	boolean passed = waitForPassCondition(atomicBoolean::get);
	assertTrue("Evaluation did not return a boolean. Or test timed out.", passed);
}

/**
 * Test the evaluate() api that returns null. Functionality based on Snippet308.
 * Only wait till success. Otherwise timeout after 3 seconds.
 */
@Test
public void test_evaluate_null() {
	// Boolen only used as dummy placeholder so the object is not null.
	final AtomicReference<Object> returnValue = new AtomicReference<>(true);
	browser.addProgressListener(completedAdapter(event -> {
		Object evalResult = browser.evaluate("return null");
		returnValue.set(evalResult);
		if (debug_verbose_output)
			System.out.println("Node value: " + evalResult);
	}));

	browser.setText("<html><body>HelloWorld</body></html>");
	shell.open();
	boolean passed = waitForPassCondition(() -> returnValue.get() == null);
	assertTrue("Evaluate did not return a null. Timed out.", passed);
}

/**
 * Test the evaluate() api that throws the invalid return value exception. Functionality based on Snippet308.
 * Only wait till success. Otherwise timeout after 3 seconds.
 */
@Test
public void test_evaluate_invalid_return_value() {
	if (SwtTestUtil.isWindows) {
		/* Bug 508210 . Inconsistent beahiour on windows at the moment.
		 * Fixing requires deeper investigation. Disabling newly added test for now.
		 */
		return;
	}

	final AtomicInteger exception = new AtomicInteger(-1);
	browser.addProgressListener(completedAdapter(event -> {
		try {
			browser.evaluate("return new Date()"); // Date is not supoprted as return value.
		} catch (SWTException e) {
			exception.set(e.code);
		}
	}));

	browser.setText("<html><body>HelloWorld</body></html>");
	shell.open();

	AtomicBoolean wrongExceptionCode = new AtomicBoolean(false);
	boolean passed = waitForPassCondition(() -> {
		if (exception.get() != -1) {
			if (exception.get() == SWT.ERROR_INVALID_RETURN_VALUE) {
				return true;
			} else if (exception.get() == SWT.ERROR_FAILED_EVALUATE) {
				wrongExceptionCode.set(true);
				return true;
			}
		}
		return false;
	});
	if (wrongExceptionCode.get()) {
		System.err.println("SWT Warning: test_evaluate_invalid_return_value threw wrong exception code."
				+ " Expected ERROR_INVALID_RETURN_VALUE but got ERROR_FAILED_EVALUATE");
	}
	String message = exception.get() == -1 ? "Exception was not thrown. Test timed out" : "Exception thrown, but wrong code: " + exception.get();
	assertTrue(message, passed);
}

/**
 * Test the evaluate() api that throws the evaluation failed exception. Functionality based on Snippet308.
 * Only wait till success. Otherwise timeout after 3 seconds.
 */
@Test
public void test_evaluate_evaluation_failed_exception() {
	final AtomicInteger exception = new AtomicInteger(-1);
	browser.addProgressListener(completedAdapter(event -> {
		try {
			browser.evaluate("return runSomeUndefinedFunctionInJavaScriptWhichCausesUndefinedError()");
		} catch (SWTException e) {
			exception.set(e.code);
		}
	}));

	browser.setText("<html><body>HelloWorld</body></html>");
	shell.open();
	AtomicReference<String> additionalErrorInfo = new AtomicReference<>("");
	boolean passed = waitForPassCondition(() -> {
		if (exception.get() != -1) {
			if (exception.get() == SWT.ERROR_FAILED_EVALUATE) {
				return true;
			} else  {
				additionalErrorInfo.set("Invalid exception thrown: " + exception.get());
			}
		}
		return false;
	});
	String message = "".equals(additionalErrorInfo.get()) ? "Javascript did not throw an error. Test timed out" :
		"Javascript threw an error, but not the right one." + additionalErrorInfo.get();
	assertTrue(message, passed);
}

/**
 * Test the evaluate() api that returns an array of numbers. Functionality based on Snippet308.
 * Only wait till success. Otherwise timeout after 3 seconds.
 */
@Test
public void test_evaluate_array_numbers() {

	// Small note:
	// evaluate() returns 'Double' type. Java doesn't have AtomicDouble
	// for convienience we simply convert double to int as we're dealing with integers anyway.
	final AtomicIntegerArray atomicIntArray = new AtomicIntegerArray(3);
	atomicIntArray.set(0, -1);
	browser.addProgressListener(completedAdapter(event -> {
		Object[] evalResult = (Object[]) browser.evaluate("return new Array(1,2,3)");
		atomicIntArray.set(0, ((Double) evalResult[0]).intValue());
		atomicIntArray.set(1, ((Double) evalResult[1]).intValue());
		atomicIntArray.set(2, ((Double) evalResult[2]).intValue());
		if (debug_verbose_output)
			System.out.println("Node value: " + evalResult);
	}));

	browser.setText("<html><body><p id='myid'>HelloWorld</p></body></html>");
	shell.open();
	AtomicReference<String> additionalErrorInfo = new AtomicReference<>("");
	boolean passed = waitForPassCondition(() -> {
		if (atomicIntArray.get(0) != -1) {
			if (atomicIntArray.get(0) == 1 && atomicIntArray.get(1) == 2 && atomicIntArray.get(2) == 3) {
				return true;
			} else {
				additionalErrorInfo.set("Resulting numbers in the array are not as expected");
			}
		}
		return false;
	});
	String message = "".equals(additionalErrorInfo.get()) ? "Javascript did not call java" : "Javasscript called java, but passed wrong values: " + additionalErrorInfo.get();
	assertTrue(message, passed);
}

/**
 * Test the evaluate() api that returns an array of strings. Functionality based on Snippet308.
 * Only wait till success. Otherwise timeout after 3 seconds.
 */
@Test
public void test_evaluate_array_strings () {

	final AtomicReferenceArray<String> atomicStringArray = new AtomicReferenceArray<>(3);
	atomicStringArray.set(0, "executing");
	browser.addProgressListener(completedAdapter(event -> {
		Object[] evalResult = (Object[]) browser.evaluate("return new Array(\"str1\", \"str2\", \"str3\")");
		atomicStringArray.set(0, (String) evalResult[0]);
		atomicStringArray.set(1, (String) evalResult[1]);
		atomicStringArray.set(2, (String) evalResult[2]);
		if (debug_verbose_output)
			System.out.println("Node value: " + evalResult);
	}));

	browser.setText("<html><body><p id='myid'>HelloWorld</p></body></html>");
	shell.open();
	AtomicReference<String> additionalErrorInfo = new AtomicReference<>("");
	boolean passed = waitForPassCondition(() -> {
		if (! "executing".equals(atomicStringArray.get(0))) {
			if (atomicStringArray.get(0).equals("str1")
					&& atomicStringArray.get(1).equals("str2")
					&& atomicStringArray.get(2).equals("str3")) {
				return true;
			} else
				additionalErrorInfo.set("Resulting strings in array are not as expected");
		}
		return false;
	});
	String message = "".equals(additionalErrorInfo.get()) ?
			"Expected an array of strings, but did not receive array or got the wrong result."
			: "Received a callback from javascript, but: " + additionalErrorInfo.get() + " : " + atomicStringArray.toString();
	assertTrue(message, passed);
}

/**
 * Test the evaluate() api that returns an array of mixed types. Functionality based on Snippet308.
 * Only wait till success. Otherwise timeout after 3 seconds.
 */
@Test
public void test_evaluate_array_mixedTypes () {
	final AtomicReferenceArray<Object> atomicArray = new AtomicReferenceArray<>(3);
	atomicArray.set(0, "executing");
	browser.addProgressListener(completedAdapter(event -> {
		Object[] evalResult = (Object[]) browser.evaluate("return new Array(\"str1\", 2, true)");
		atomicArray.set(2, evalResult[2]);
		atomicArray.set(1, evalResult[1]);
		atomicArray.set(0, evalResult[0]); // should be set last. to avoid loop below ending & failing to early.
		if (debug_verbose_output)
			System.out.println("Node value: " + evalResult);
	}));


	browser.setText("<html><body><p id='myid'>HelloWorld</p></body></html>");
	shell.open();
	AtomicReference<String> additionalErrorInfo = new AtomicReference<>("");
	boolean passed = waitForPassCondition(() -> {
		if (! "executing".equals(atomicArray.get(0))) {
			if (atomicArray.get(0).equals("str1")
					&& ((Double) atomicArray.get(1)) == 2
					&& ((Boolean) atomicArray.get(2))) {
				return true;
			} else
				additionalErrorInfo.set("Resulting String are not as exected");
		}
		return false;
	});
	String message = "".equals(additionalErrorInfo.get()) ? "Javascript did not call java" : "Javascript called java but passed wrong values: " + atomicArray.toString();
	assertTrue(message, passed);
}


ProgressListener callCustomFunctionUponLoad = completedAdapter(event ->	browser.execute("callCustomFunction()"));

/**
 * Test that javascript can call java.
 * loosely based on Snippet307.
 */
@Test
public void test_BrowserFunction_callback () {
	AtomicBoolean javaCallbackExecuted = new AtomicBoolean(false);

	class JavascriptCallback extends BrowserFunction { // Note: Local class defined inside method.
		JavascriptCallback(Browser browser, String name) {
			super(browser, name);
		}

		@Override
		public Object function(Object[] arguments) {
			javaCallbackExecuted.set(true);
			return null;
		}
	}

	String htmlWithScript = "<html><head>\n"
			+ "<script language=\"JavaScript\">\n"
			+ "function callCustomFunction() {\n"  // Define a javascript function.
			+ "     document.body.style.backgroundColor = 'red'\n"
			+ "		jsCallbackToJava()\n"        // This calls the javafunction that we registered.
			+ "}"
			+ "</script>\n"
			+ "</head>\n"
			+ "<body> I'm going to make a callback to java </body>\n"
			+ "</html>\n";

	browser.setText(htmlWithScript);
	new JavascriptCallback(browser, "jsCallbackToJava");

	browser.addProgressListener(callCustomFunctionUponLoad);

	shell.open();
	boolean passed = waitForPassCondition(javaCallbackExecuted::get);
	String message = "Java failed to get a callback from javascript. Test timed out";
	assertTrue(message, passed);
}

/**
 * Test that javascript can call java and pass an integer to java.
 * loosely based on Snippet307.
 */
@Test
public void test_BrowserFunction_callback_with_integer () {
	AtomicInteger returnInt = new AtomicInteger(0);

	class JavascriptCallback extends BrowserFunction { // Note: Local class defined inside method.
		JavascriptCallback(Browser browser, String name) {
			super(browser, name);
		}

		@Override
		public Object function(Object[] arguments) {
			Double returnedDouble = (Double) arguments[0];
			returnInt.set(returnedDouble.intValue()); // 5.0 -> 5
			return null;
		}
	}

	String htmlWithScript = "<html><head>\n"
			+ "<script language=\"JavaScript\">\n"
			+ "function callCustomFunction() {\n"  // Define a javascript function.
			+ "     document.body.style.backgroundColor = 'red'\n"
			+ "		jsCallbackToJava(5)\n"        // This calls the javafunction that we registered ** with value of 5.
			+ "}"
			+ "</script>\n"
			+ "</head>\n"
			+ "<body> I'm going to make a callback to java </body>\n"
			+ "</html>\n";

	browser.setText(htmlWithScript);
	new JavascriptCallback(browser, "jsCallbackToJava");

	browser.addProgressListener(callCustomFunctionUponLoad);

	shell.open();
	boolean passed = waitForPassCondition(() -> returnInt.get() == 5);
	String message = "Javascript should have passed an integer to java. But this did not happen";
	assertTrue(message, passed);
}



/**
 * Test that javascript can call java and pass a Boolean to java.
 * loosely based on Snippet307.
 */
@Test
public void test_BrowserFunction_callback_with_boolean () {
	AtomicBoolean javaCallbackExecuted = new AtomicBoolean(false);

	class JavascriptCallback extends BrowserFunction { // Note: Local class defined inside method.
		JavascriptCallback(Browser browser, String name) {
			super(browser, name);
		}

		@Override
		public Object function(Object[] arguments) {
			Boolean returnBool = (Boolean) arguments[0];
			javaCallbackExecuted.set(returnBool);
			return null;
		}
	}

	String htmlWithScript = "<html><head>\n"
			+ "<script language=\"JavaScript\">\n"
			+ "function callCustomFunction() {\n"  // Define a javascript function.
			+ "     document.body.style.backgroundColor = 'red'\n"
			+ "		jsCallbackToJava(true)\n"        // This calls the javafunction that we registered.
			+ "}"
			+ "</script>\n"
			+ "</head>\n"
			+ "<body> I'm going to make a callback to java </body>\n"
			+ "</html>\n";

	browser.setText(htmlWithScript);
	new JavascriptCallback(browser, "jsCallbackToJava");

	browser.addProgressListener(callCustomFunctionUponLoad);

	shell.open();
	boolean passed = waitForPassCondition(javaCallbackExecuted::get);
	String message = "Javascript did not pass a boolean back to java";
	assertTrue(message, passed);
}


/**
 * Test that javascript can call java and pass a String to java.
 * loosely based on Snippet307.
 */
@Test
public void test_BrowserFunction_callback_with_String () {
	final AtomicReference<String> returnValue = new AtomicReference<>();
	class JavascriptCallback extends BrowserFunction { // Note: Local class defined inside method.
		JavascriptCallback(Browser browser, String name) {
			super(browser, name);
		}

		@Override
		public Object function(Object[] arguments) {
			String returnString = (String) arguments[0];
			returnValue.set(returnString);
			return null;
		}
	}

	String htmlWithScript = "<html><head>\n"
			+ "<script language=\"JavaScript\">\n"
			+ "function callCustomFunction() {\n"  // Define a javascript function.
			+ "     document.body.style.backgroundColor = 'red'\n"
			+ "		jsCallbackToJava('hellojava')\n"        // This calls the javafunction that we registered.
			+ "}"
			+ "</script>\n"
			+ "</head>\n"
			+ "<body> I'm going to make a callback to java </body>\n"
			+ "</html>\n";

	browser.setText(htmlWithScript);
	new JavascriptCallback(browser, "jsCallbackToJava");

	browser.addProgressListener(callCustomFunctionUponLoad);

	shell.open();
	boolean passed = waitForPassCondition(() -> "hellojava".equals(returnValue.get()));
	String message = "Javascript was suppose to call java with a String. But it seems java did not receive the call or wrong value was passed";
	assertTrue(message, passed);
}


/**
 * Test that javascript can call java and pass multiple values to java.
 * loosely based on Snippet307.
 */
@Test
public void test_BrowserFunction_callback_with_multipleValues () {
	final AtomicReferenceArray<Object> atomicArray = new AtomicReferenceArray<>(3); // Strin, Double, Boolean
	atomicArray.set(0, "executing");

	class JavascriptCallback extends BrowserFunction { // Note: Local class defined inside method.
		JavascriptCallback(Browser browser, String name) {
			super(browser, name);
		}

		@Override
		public Object function(Object[] arguments) {
			atomicArray.set(1, arguments[1]);
			atomicArray.set(2, arguments[2]);
			atomicArray.set(0, arguments[0]); // item at index 0 should be set last for this test case.
			return null;
		}
	}

	String htmlWithScript = "<html><head>\n"
			+ "<script language=\"JavaScript\">\n"
			+ "function callCustomFunction() {\n"  // Define a javascript function.
			+ "     document.body.style.backgroundColor = 'red'\n"
			+ "		jsCallbackToJava('hellojava', 5, true)\n"        // This calls the javafunction that we registered.
			+ "}"
			+ "</script>\n"
			+ "</head>\n"
			+ "<body> I'm going to make a callback to java </body>\n"
			+ "</html>\n";

	browser.setText(htmlWithScript);
	new JavascriptCallback(browser, "jsCallbackToJava");

	browser.addProgressListener(callCustomFunctionUponLoad);

	shell.open();
//	Screenshots.takeScreenshot(getClass(), "test_BrowserFunction_callback_with_multipleValues__BeforeWaiting"); // Useful if investigating build failures on Hudson

	boolean passed = waitForPassCondition(() -> {
		if (atomicArray.get(0).equals("hellojava")
				&& ((Double) atomicArray.get(1)) == 5
				&& ((Boolean) atomicArray.get(2))) {
			return true;
		} else {
			return false;
		}
	});
//	Screenshots.takeScreenshot(getClass(), "test_BrowserFunction_callback_with_multipleValues__AfterWaiting");  // Useful if investigating build failures on Hudson

	String msg = "Values not set. Test timed out. Array should be [\"hellojava\", 5, true], but is: " + atomicArray.toString();
	assertTrue(msg, passed);
}


/**
 * Test that javascript can call java, java returns an Integer back to javascript.
 *
 * It's a bit tricky to tell if javascript actually received the correct value from java.
 * Solution: make a second function/callback that is called with the value that javascript received from java.
 *
 * Logic:
 *  1) Java registers function callCustomFunction() by setting html body.
 *  2) which in turn calls JavascriptCallback, which returns value 42 back to javascript.
 *  3) javascript then calls JavascriptCallback_javascriptReceivedJavaInt() and passes it value received from java.
 *  4) Java validates that the correct value (42) was passed to javascript and was passed back to java.
 *
 * loosely based on Snippet307.
 */
@Test
public void test_BrowserFunction_callback_with_javaReturningInt () {
	AtomicInteger returnInt = new AtomicInteger(0);

	class JavascriptCallback extends BrowserFunction { // Note: Local class defined inside method.
		JavascriptCallback(Browser browser, String name) {
			super(browser, name);
		}

		@Override
		public Object function(Object[] arguments) {
			return 42;
		}
	}

	class JavascriptCallback_javascriptReceivedJavaInt extends BrowserFunction { // Note: Local class defined inside method.
		JavascriptCallback_javascriptReceivedJavaInt(Browser browser, String name) {
			super(browser, name);
		}

		@Override
		public Object function(Object[] arguments) {
			Double returnVal = (Double) arguments[0];
			returnInt.set(returnVal.intValue());  // 4)
			return null;
		}
	}

	String htmlWithScript = "<html><head>\n"
			+ "<script language=\"JavaScript\">\n"
			+ "function callCustomFunction() {\n"  // Define a javascript function.
			+ "     document.body.style.backgroundColor = 'red'\n"
			+ "     var retVal = jsCallbackToJava()\n"  // 2)
			+ "		document.write(retVal)\n"        // This calls the javafunction that we registered. Set HTML body to return value.
			+ "     jsSuccess(retVal)\n"				// 3)
			+ "}"
			+ "</script>\n"
			+ "</head>\n"
			+ "<body> If you see this, javascript did not receive anything from Java. This page should just be '42' </body>\n"
			+ "</html>\n";
	// 1)
	browser.setText(htmlWithScript);
	new JavascriptCallback(browser, "jsCallbackToJava");
	new JavascriptCallback_javascriptReceivedJavaInt(browser, "jsSuccess");

	browser.addProgressListener(callCustomFunctionUponLoad);

	shell.open();
	boolean passed = waitForPassCondition(() -> returnInt.get() == 42);
	String message = "Java should have returned something back to javascript. But something went wrong";
	assertTrue(message, passed);
}


/**
 * Test that a callback works even after a new page is loaded.
 * I.e, BrowserFunctions should have to be re-initialized after a page load.
 *
 * Logic:
 * - load a page.
 * - Register java callback.
 * - call java callback from javascript. (exec)
 *
 * - java callback instantiates new page load.
 * - new page load triggers 'completed' listener
 * - completed listener calls the registered function again.
 *
 * - once regiseterd function is called a 2nd time, it sets the test to pass.
 */
@Test
public void test_BrowserFunction_callback_afterPageReload() {
	AtomicBoolean javaCallbackExecuted = new AtomicBoolean(false);
	AtomicInteger callCount = new AtomicInteger(0);

	class JavascriptCallback extends BrowserFunction { // Note: Local class defined inside method.
		JavascriptCallback(Browser browser, String name) {
			super(browser, name);
		}

		@Override
		public Object function(Object[] arguments) {
			if (callCount.get() == 0) {
				callCount.set(1);
				browser.setText("2nd page load");
			} else {
				javaCallbackExecuted.set(true);
			}
			return null;
		}
	}
	browser.setText("1st (initial) page load");
	new JavascriptCallback(browser, "jsCallbackToJava");
	browser.execute("jsCallbackToJava()");
	// see if function still works after a page change:
	browser.addProgressListener(completedAdapter(e -> browser.execute("jsCallbackToJava()")));

	shell.open();
	boolean passed = waitForPassCondition(javaCallbackExecuted::get);
	String message = "A javascript callback should work after a page has been reloaded. But something went wrong";
	assertTrue(message, passed);
}


/* custom */
/**
 * Wait for passTest to return true. Timeout otherwise.
 * @param passTest a Supplier lambda that returns true if pass condition is true. False otherwise.
 * @return true if test passes, false on timeout.
 */
protected boolean waitForPassCondition(final Supplier<Boolean> passTest) {
	return waitForPassCondition(passTest, 1000 * secondsToWaitTillFail);
}

private boolean waitForPassCondition(final Supplier<Boolean> passTest, int millisecondsToWait) {
	final AtomicBoolean passed = new AtomicBoolean(false);
	final Instant timeOut = Instant.now().plusMillis(millisecondsToWait);
	final Instant debug_showBrowserTimeout = Instant.now().plusSeconds(debug_show_browser_timeout_seconds);
	final Display display = shell.getDisplay();

	// This thread tests the pass-condition periodically.
	// Triggers fail if timeout occurs.
	new Thread(() -> {
		while (Instant.now().isBefore(timeOut)) {
			if (passTest.get()) {
				passed.set(true);
				break;
			}
			try {Thread.sleep(2);} catch (InterruptedException e) {e.printStackTrace();}
		}

		// If debug_show_browser is enabled, it only wakes up the display thread after the timeout occured.
		while (debug_show_browser && Instant.now().isBefore(debug_showBrowserTimeout)) {
			try {Thread.sleep(500);} catch (InterruptedException e) {e.printStackTrace();}
		}
		display.wake(); // timeout. Test failed by default.
	}).start();

	while (Instant.now().isBefore(timeOut)) {
		if (passed.get()) { // Logic to show browser window for longer if enabled.
			if (!debug_show_browser) break;
			if (Instant.now().isAfter(debug_showBrowserTimeout)) break;
		}

		if (!shell.isDisposed()) {
			if (!display.readAndDispatch()) {
				display.sleep();
			}
		}
	}
	return passed.get();
}

/** Contrary to Thread.wait(), this method allows swt's display to carry out actions. */
void waitForMilliseconds(final int milliseconds) {
	waitForPassCondition(() -> false, milliseconds);

}

/**
 * Check if Internet connection to a http url works.
 *
 * @param url a full url like http://www.example.com
 * @return true if server responded with correct code (200), false otherwise.
 */
private static Boolean checkInternet(String url) {
	HttpURLConnection connection = null;
	try {
		connection = (HttpURLConnection) new URL(url).openConnection();
		connection.setRequestMethod("HEAD");
		int code = connection.getResponseCode(); // 200 is success. See https://tools.ietf.org/html/rfc7231#section-6.3.1.
		if (code == 200)
			return true;
	} catch (MalformedURLException e) {
		System.err.println("Given url is malformed: " + url + "Try a fully formed url like: http://www.example.com");
		e.printStackTrace();
	} catch (IOException e) {
		// No connection was made.
	} finally {
		if (connection != null) {
			connection.disconnect();
		}
	}
	return false;
}

}
