/****************************************************************************
* Copyright 2008-2011 ThoughtWorks, Inc.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* Initial Contributors:
* Håkan Råberg
* Manish Chakravarty
* Pavan K S
***************************************************************************/
package com.thoughtworks.krypton.driver.web.browser.wait;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;
import org.eclipse.swt.browser.BrowserFunction;
import org.eclipse.swt.browser.LocationEvent;
import org.eclipse.swt.browser.LocationListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.thoughtworks.krypton.driver.web.browser.BrowserFamily;
import com.thoughtworks.krypton.driver.web.browser.BrowserSession;
import com.thoughtworks.krypton.driver.web.browser.JavascriptException;
public class DocumentReadyWaitStrategy implements WaitStrategy, LocationListener {
Logger log = LoggerFactory.getLogger(getClass());
private BrowserSession session;
private boolean isDomReady = true;
private boolean unloaded;
private BrowserFunction documentIsReady;
Map<String, Pattern> exclusionPatterns = new HashMap<String, Pattern>();
public void init(BrowserSession session) {
this.session = session;
session.getBrowser().addLocationListener(this);
addURLExclusionPattern("javascript:.*");
addURLExclusionPattern("about:blank");
addURLExclusionPattern("about:config");
// This obviously needs to be configurable somehow.
addURLExclusionPattern(".*analytics.live.com.*");
addURLExclusionPattern(".*www.google.com/ig/ifpc_relay.*");
addURLExclusionPattern(".*doubleclick.net.*");
addURLExclusionPattern(".*adbrite.*");
}
public void changed(final LocationEvent event) {
if (isExcluded(event.location)) {
return;
}
if (event.top && BrowserFamily.IE != session.getBrowserFamily()) {
isDomReady = false;
if (documentIsReady != null) {
documentIsReady.dispose();
}
documentIsReady = new BrowserFunction(session.getBrowser(), "documentIsReady") {
public Object function(Object[] arguments) {
isDomReady = true;
log.debug("DOM is ready: {}", event.location);
return null;
}
};
session.inject("twist-domready.js", getClass());
session.execute("Twist.DomReady.ready(documentIsReady)");
} else {
// TODO: We only need the window.location.reload override here
// really.
session.inject("twist-domready.js", getClass());
isDomReady = true;
}
}
public void changing(LocationEvent event) {
String location = event.location;
if (isExcluded(location)) {
log.trace("skipping excluded {}", location);
return;
}
log.trace("changing: {} {}", location, exclusionPatterns.values());
isDomReady = false;
unloaded = false;
}
public boolean isBusy() {
if (BrowserFamily.IE == session.getBrowserFamily()) {
if (isDomReady) {
return false;
}
boolean canScrollDocument = canScrollDocument();
if (!canScrollDocument) {
unloaded = true;
}
isDomReady = unloaded && canScrollDocument;
}
return !isDomReady;
}
private boolean canScrollDocument() {
try {
session.execute("document.documentElement.doScroll('left');");
return true;
} catch (JavascriptException documentIsNotReady) {
return false;
}
}
private boolean isExcluded(String location) {
for (Pattern pattern : exclusionPatterns.values()) {
if (pattern.matcher(location).matches()) {
return true;
}
}
return false;
}
public void addURLExclusionPattern(String pattern) {
exclusionPatterns.put(pattern, Pattern.compile(pattern));
}
public void removeURLExclusionPattern(String pattern) {
exclusionPatterns.remove(pattern);
}
}