/*******************************************************************************
* Copyright (c) 2010 Red Hat, Inc. and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Libor Zoubek, Red Hat - initial API and implementation
* Ketan Padegaonkar - cleanup to conform to SWTBot standards
*******************************************************************************/
package org.eclipse.swtbot.swt.finder.widgets;
import org.eclipse.swt.browser.Browser;
import org.eclipse.swt.browser.ProgressEvent;
import org.eclipse.swt.browser.ProgressListener;
import org.eclipse.swtbot.swt.finder.ReferenceBy;
import org.eclipse.swtbot.swt.finder.SWTBot;
import org.eclipse.swtbot.swt.finder.SWTBotWidget;
import org.eclipse.swtbot.swt.finder.exceptions.WidgetNotFoundException;
import org.eclipse.swtbot.swt.finder.finders.UIThreadRunnable;
import org.eclipse.swtbot.swt.finder.results.Result;
import org.eclipse.swtbot.swt.finder.results.VoidResult;
import org.eclipse.swtbot.swt.finder.utils.Credentials;
import org.eclipse.swtbot.swt.finder.utils.internal.Assert;
import org.eclipse.swtbot.swt.finder.waits.DefaultCondition;
import org.hamcrest.SelfDescribing;
/**
* This represents a {@link Browser} widget.
*
* @author Libor Zoubek <lzoubek [at] redhat [dot] com>
*/
@SWTBotWidget(clasz = Browser.class, preferredName = "browser", referenceBy = { ReferenceBy.LABEL })
public class SWTBotBrowser extends AbstractSWTBotControl<Browser> {
private final InternalProgressListener progressListener;
private final static BrowserAuthenticationListener authListener = new BrowserAuthenticationListener();
/**
* Constructs an instance of this object with the given browser
*
* @param browser the widget.
* @throws WidgetNotFoundException if the widget is <code>null</code> or widget has been disposed.
* @since 2.0
*/
public SWTBotBrowser(Browser browser) {
this(browser, null);
}
/**
* Constructs an instance of this object with the given browser
*
* @param browser the widget.
* @param description the description of the widget, this will be reported by {@link #toString()}
* @throws WidgetNotFoundException if the widget is <code>null</code> or widget has been disposed.
* @since 2.0
*/
public SWTBotBrowser(Browser browser, SelfDescribing description) {
super(browser, description);
progressListener = new InternalProgressListener(this);
authListener.init(widget);
}
/**
* Loads given URI into browser, the page is loaded asynchronously (see {@link #isPageLoaded()})
*
* @param url
*/
public void setUrl(final String url) {
UIThreadRunnable.syncExec(new VoidResult() {
public void run() {
progressListener.setDone(false);
widget.addProgressListener(progressListener);
boolean result = widget.setUrl(url);
if (!result) {
progressListener.setDone(true);
widget.removeProgressListener(progressListener);
}
}
});
}
/**
* @return the current URL or an empty String if there is no current URL
*/
public String getUrl() {
waitForPageLoaded();
return UIThreadRunnable.syncExec(new Result<String>() {
public String run() {
return widget.getUrl();
}
});
}
@Override
public String getText() {
waitForPageLoaded();
return super.getText();
}
/**
* Executes script in browser asynchronously
*
* @param script
*/
public void execute(final String script) {
waitForPageLoaded();
UIThreadRunnable.asyncExec(new VoidResult() {
public void run() {
widget.execute(script);
}
});
}
/**
* @return the receiver's back command enabled state
*/
public boolean isBackEnabled() {
return UIThreadRunnable.syncExec(new Result<Boolean>() {
public Boolean run() {
return widget.isBackEnabled();
}
});
}
/**
* @return the receiver's forward command enabled state
*/
public boolean isForwardEnabled() {
return UIThreadRunnable.syncExec(new Result<Boolean>() {
public Boolean run() {
return widget.isForwardEnabled();
}
});
}
/**
* Navigate to the previous session history item.
*/
public void back() {
UIThreadRunnable.asyncExec(new VoidResult() {
public void run() {
progressListener.setDone(false);
widget.addProgressListener(progressListener);
boolean result = widget.back();
if (!result) {
progressListener.setDone(true);
widget.removeProgressListener(progressListener);
}
}
});
}
/**
* Navigate to the next session history item.
*/
public void forward() {
UIThreadRunnable.asyncExec(new VoidResult() {
public void run() {
progressListener.setDone(false);
widget.addProgressListener(progressListener);
boolean result = widget.forward();
if (!result) {
progressListener.setDone(true);
widget.removeProgressListener(progressListener);
}
}
});
}
/**
* Refreshes browser
*/
public void refresh() {
UIThreadRunnable.asyncExec(new VoidResult() {
public void run() {
widget.refresh();
}
});
}
/**
* @return <code>true</code> by default or when page was completely loaded by browser after asynchronous page load
* invoked by {@link #goURL(String)} was finished, this method returns false only during page loading
*/
public boolean isPageLoaded() {
return progressListener.isDone();
}
/**
* Waits until browser loads page.
*
* @throws TimeoutException if page is not loaded after default timeout
*/
public void waitForPageLoaded() {
new SWTBot().waitUntil(new WaitForBrowserLoadsPage(this));
}
/**
* Sets credentials, which will be used when page requires authentication, if both username and password set to null
* authentication (if requested) will be canceled
* <p>
* <b>Note:</b> Credentials are shared by all {@link SWTBotBrowser} instances.
* </p>
* instances
*
* @param username the username
* @param password the password
*/
public void setCredentials(String username, String password) {
setCredentials(new Credentials(username, password));
}
/**
* Sets credentials, which will be used when page requires authentication, if both username and password set to null
* authentication (if requested) will be canceled
* <p>
* <b>Note:</b> Credentials are shared by all {@link SWTBotBrowser} instances.
* </p>
* instances
*
* @param credentials the credentials with the username and password
*/
public void setCredentials(Credentials credentials) {
authListener.setCredentials(credentials);
}
/**
* Gets credentials.
*
* @return the credentials containing the username and password.
*/
public Credentials getCredentials() {
return authListener.getCredentials();
}
/**
* This represents internal progress listener notified when browser finishes loading of URL
*
* @author Libor Zoubek <lzoubek [at] redhat [dot] com>
*/
class InternalProgressListener implements ProgressListener {
private final SWTBotBrowser browser;
private boolean done = true;
public InternalProgressListener(SWTBotBrowser browser) {
this.browser = browser;
}
public synchronized boolean isDone() {
return done;
}
public synchronized void setDone(boolean done) {
this.done = done;
}
public void changed(ProgressEvent event) {
}
public void completed(ProgressEvent event) {
setDone(true);
browser.widget.removeProgressListener(this);
}
}
private static final class WaitForBrowserLoadsPage extends DefaultCondition {
private final SWTBotBrowser browser;
public WaitForBrowserLoadsPage(SWTBotBrowser browser) {
Assert.isNotNull(browser, "The browser can not be null"); //$NON-NLS-1$
this.browser = browser;
}
public String getFailureMessage() {
return "Browser dit not finish loading page before timeout."; //$NON-NLS-1$
}
public boolean test() throws Exception {
return browser.isPageLoaded();
}
}
}