Skip to content

Commit

Permalink
Allow cookies to be set by javascript. Fixes eclipse-birt#32.
Browse files Browse the repository at this point in the history
  • Loading branch information
hollingsworthd committed Feb 16, 2016
1 parent f814ecf commit 4c520bd
Show file tree
Hide file tree
Showing 10 changed files with 184 additions and 25 deletions.
2 changes: 1 addition & 1 deletion src/com/machinepublishers/jbrowserdriver/Context.java
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ void init(final JBrowserDriverServer driver) {
capabilities.set(new CapabilitiesServer());
navigation.set(new NavigationServer(
new AtomicReference<JBrowserDriverServer>(driver), this, statusCode));
options.set(new OptionsServer(this, SettingsManager.settings().cookieStore(), timeouts));
options.set(new OptionsServer(this, timeouts));
} catch (RemoteException e) {
LogsServer.instance().exception(e);
}
Expand Down
157 changes: 157 additions & 0 deletions src/com/machinepublishers/jbrowserdriver/CookieStore.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
/*
* jBrowserDriver (TM)
* Copyright (C) 2014-2016 Machine Publishers, LLC
*
* Sales and support: ops@machinepublishers.com
* Updates: https://github.com/MachinePublishers/jBrowserDriver
*
* 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.
*/
package com.machinepublishers.jbrowserdriver;

import java.io.IOException;
import java.io.Serializable;
import java.net.CookieHandler;
import java.net.URI;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.apache.http.cookie.Cookie;
import org.apache.http.cookie.CookieOrigin;
import org.apache.http.cookie.CookieSpec;
import org.apache.http.cookie.MalformedCookieException;
import org.apache.http.impl.client.BasicCookieStore;
import org.apache.http.impl.cookie.LaxCookieSpecProvider;
import org.apache.http.message.BasicHeader;

public class CookieStore extends CookieHandler implements org.apache.http.client.CookieStore, Serializable {

private static final CookieSpec spec = new LaxCookieSpecProvider().create(null);
private final org.apache.http.client.CookieStore store = new BasicCookieStore();

@Override
public Map<String, List<String>> get(URI uri, Map<String, List<String>> requestHeaders) throws IOException {
final String reqHost = canonicalHost(uri.getHost());
final String reqPath = canonicalPath(uri.getPath());
final boolean reqSecure = isSecure(uri.getScheme());
final boolean reqJavascript = isJavascript(uri.getScheme());
StringBuilder builder = new StringBuilder();
if (reqJavascript) {
List<Cookie> list;
synchronized (store) {
store.clearExpired(new Date());
list = store.getCookies();
}
for (Cookie cookie : list) {
if ((!cookie.isSecure() || reqSecure)
&& reqHost.endsWith(canonicalHost(cookie.getDomain()))
&& reqPath.startsWith(canonicalPath(cookie.getPath()))) {
if (builder.length() > 0) {
builder.append(';');
}
builder.append(cookie.getName());
builder.append('=');
builder.append(cookie.getValue());
}
}
}
String cookies = builder.length() == 0 ? null : builder.toString();
Map<String, List<String>> map;
if (cookies != null) {
map = new HashMap<String, List<String>>();
map.put("Cookie", Arrays.asList(cookies));
} else {
map = Collections.emptyMap();
}
return map;
}

@Override
public void put(URI uri, Map<String, List<String>> responseHeaders) throws IOException {
if (isJavascript(uri.getScheme())) {
for (Map.Entry<String, List<String>> entry : responseHeaders.entrySet()) {
for (String value : entry.getValue()) {
try {
List<Cookie> cookies = spec.parse(new BasicHeader(entry.getKey(), value),
new CookieOrigin(uri.getHost(), uri.getPort(), uri.getPath(), isSecure(uri.getScheme())));
for (Cookie cookie : cookies) {
synchronized (store) {
store.addCookie(cookie);
}
}
} catch (MalformedCookieException e) {
LogsServer.instance().warn(
"Malformed cookie for cookie named " + entry.getKey() + ". " + e.getMessage());
}
}
}
}
}

private static boolean isSecure(String scheme) {
return "https".equalsIgnoreCase(scheme) || "javascripts".equalsIgnoreCase(scheme);
}

private static boolean isJavascript(String scheme) {
return "javascripts".equalsIgnoreCase(scheme) || "javascript".equalsIgnoreCase(scheme);
}

private static String canonicalHost(String host) {
if (host == null || host.isEmpty()) {
return "";
}
return host.startsWith(".") ? host.toLowerCase() : "." + host.toLowerCase();
}

private static String canonicalPath(String path) {
if (path == null || path.isEmpty()) {
return "";
}
String canonical = path;
canonical = canonical.startsWith("/") ? canonical : "/" + canonical;
canonical = canonical.endsWith("/") ? canonical : canonical + "/";
return canonical.toLowerCase();
}

@Override
public void addCookie(Cookie cookie) {
synchronized (store) {
store.addCookie(cookie);
}
}

@Override
public List<Cookie> getCookies() {
synchronized (store) {
return store.getCookies();
}
}

@Override
public boolean clearExpired(Date date) {
synchronized (store) {
return store.clearExpired(date);
}
}

@Override
public void clear() {
synchronized (store) {
store.clear();
}
}
}
6 changes: 0 additions & 6 deletions src/com/machinepublishers/jbrowserdriver/HttpListener.java
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,8 @@
import java.util.concurrent.atomic.AtomicLong;

import com.sun.webkit.LoadListenerClient;
import com.sun.webkit.network.CookieManager;

class HttpListener implements LoadListenerClient {
static {
//TODO set a cookie manager that extends Java's CookieHandler and implements Apache's CookieStore
CookieManager.setDefault(null);
}

private static final Map<Integer, String> states;
private static final Map<Integer, String> errors;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,7 @@
import com.machinepublishers.jbrowserdriver.Util.Sync;
import com.sun.javafx.webkit.Accessor;
import com.sun.webkit.WebPage;
import com.sun.webkit.network.CookieManager;

import javafx.embed.swing.JFXPanel;

Expand All @@ -68,6 +69,7 @@ class JBrowserDriverServer extends UnicastRemoteObject implements JBrowserDriver
* RMI entry point.
*/
public static void main(String[] args) {
CookieManager.setDefault(new CookieStore());
if (Settings.headless()) {
System.setProperty("glass.platform", "Monocle");
System.setProperty("monocle.platform", "Headless");
Expand Down Expand Up @@ -165,7 +167,7 @@ public Object perform() {
}
});
Accessor.getPageFor(context.get().item().engine.get()).stop();
SettingsManager.settings().cookieStore().clear();
((CookieStore) CookieManager.getDefault()).clear();
StatusMonitor.instance().clearStatusMonitor();
LogsServer.instance().clear();
SettingsManager.register(settings);
Expand Down
8 changes: 4 additions & 4 deletions src/com/machinepublishers/jbrowserdriver/OptionsServer.java
Original file line number Diff line number Diff line change
Expand Up @@ -27,22 +27,22 @@
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;

import org.apache.http.client.CookieStore;
import org.apache.http.impl.cookie.BasicClientCookie;
import org.openqa.selenium.Cookie;

import com.sun.webkit.network.CookieManager;

class OptionsServer extends UnicastRemoteObject implements OptionsRemote,
org.openqa.selenium.WebDriver.Options {
private static final CookieStore cookieStore = (CookieStore) CookieManager.getDefault();
private final Context context;
private final ImeHandlerServer imeHandler = new com.machinepublishers.jbrowserdriver.ImeHandlerServer();
private final CookieStore cookieStore;
private final AtomicReference<com.machinepublishers.jbrowserdriver.TimeoutsServer> timeouts;

OptionsServer(final Context context, final CookieStore cookieStore,
OptionsServer(final Context context,
final AtomicReference<com.machinepublishers.jbrowserdriver.TimeoutsServer> timeouts)
throws RemoteException {
this.context = context;
this.cookieStore = cookieStore;
this.timeouts = timeouts;
}

Expand Down
9 changes: 0 additions & 9 deletions src/com/machinepublishers/jbrowserdriver/Settings.java
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,6 @@
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import org.apache.http.client.CookieStore;
import org.apache.http.impl.client.BasicCookieStore;

import com.machinepublishers.jbrowserdriver.StreamInjectors.Injector;

/**
Expand Down Expand Up @@ -378,7 +375,6 @@ public Settings build() {
private final boolean saveMedia;
private final boolean saveAttachments;
private final String script;
private final BasicCookieStore cookieStore;
private final boolean ignoreDialogs;
private final boolean cache;
private final File cacheDir;
Expand All @@ -393,7 +389,6 @@ private Settings(Settings.Builder builder) {
this.proxy = builder.proxy;
this.saveMedia = builder.saveMedia;
this.saveAttachments = builder.saveAttachments;
this.cookieStore = new BasicCookieStore();
this.ignoreDialogs = builder.ignoreDialogs;
this.cache = builder.cache;
this.cacheDir = builder.cacheDir;
Expand Down Expand Up @@ -450,10 +445,6 @@ String script() {
return script;
}

CookieStore cookieStore() {
return cookieStore;
}

boolean ignoreDialogs() {
return ignoreDialogs;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,10 @@
import org.apache.http.ssl.TrustStrategy;
import org.apache.http.util.EntityUtils;

import com.sun.webkit.network.CookieManager;

class StreamConnection extends HttpURLConnection implements Closeable {
private static final CookieStore cookieStore = (CookieStore) CookieManager.getDefault();
private static final File attachmentsDir;
private static final File mediaDir;
private static final File cacheDir;
Expand Down Expand Up @@ -469,7 +472,7 @@ public void connect() throws IOException {
config.get().setProxy(new HttpHost(proxy.host(), proxy.port()));
}
}
context.get().setCookieStore(SettingsManager.settings().cookieStore());
context.get().setCookieStore(cookieStore);
context.get().setRequestConfig(config.get().build());
StatusMonitor.instance().addStatusMonitor(url, this);
}
Expand Down
11 changes: 9 additions & 2 deletions src/com/machinepublishers/jbrowserdriver/diagnostics/Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ private Test() {
test(driver.findElement(By.xpath("//a[contains(@href,'1')]")).getAttribute("id").equals("anchor1"));

/*
* Set cookies
* Cookie manager
*/
driver.manage().addCookie(new Cookie("testname", "testvalue"));
test(driver.manage().getCookieNamed("testname").getValue().equals("testvalue"));
Expand Down Expand Up @@ -155,7 +155,14 @@ private Test() {
test(driver.getCurrentUrl().endsWith("/redirect/site2"));
test(driver.manage().getCookieNamed("JSESSIONID").getValue().equals("ABC123"));

//TODO handle cookies set by JS
/*
* Cookies set by Javascript
*/
test("jsCookieValue1".equals(driver.manage().getCookieNamed("jsCookieName1").getValue()));
test("jsCookieValue2".equals(driver.manage().getCookieNamed("jsCookieName2").getValue()));
test("jsCookieValue3".equals(driver.manage().getCookieNamed("jsCookieName3").getValue()));
test("jsCookieValue4".equals(driver.manage().getCookieNamed("jsCookieName4").getValue()));

} catch (Throwable t) {
errors.add("Test #" + (curTest + 1) + " -- " + toString(t));
} finally {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,5 +3,9 @@
</head>
<body id="iframebody">
test iframe
<script>
document.cookie ='jsCookieName3=jsCookieValue3';
document.cookie ='jsCookieName4=jsCookieValue4';
</script>
</body>
</html>
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,8 @@
<span id="testspan"></span>

<script>
document.cookie ='cookieName=cookieValue'
document.cookie ='jsCookieName1=jsCookieValue1';
document.cookie ='jsCookieName2=jsCookieValue2';
</script>
<iframe src="iframe.htm" name="testiframe"></iframe>
</body>
Expand Down

0 comments on commit 4c520bd

Please sign in to comment.