1 package com.atlassian.webdriver;
2
3 import java.util.regex.Matcher;
4 import java.util.regex.Pattern;
5
6 import com.atlassian.browsers.BrowserConfig;
7 import com.atlassian.fugue.retry.ExceptionHandler;
8 import com.atlassian.fugue.retry.RetryFactory;
9 import com.atlassian.pageobjects.browser.Browser;
10 import com.atlassian.pageobjects.util.BrowserUtil;
11 import com.atlassian.webdriver.browsers.chrome.ChromeBrowser;
12 import com.atlassian.webdriver.browsers.firefox.FirefoxBrowser;
13 import com.atlassian.webdriver.browsers.ie.IeBrowser;
14
15 import com.gargoylesoftware.htmlunit.BrowserVersion;
16 import com.gargoylesoftware.htmlunit.WebClient;
17 import com.google.common.base.Supplier;
18
19 import org.openqa.selenium.WebDriver;
20 import org.openqa.selenium.htmlunit.HtmlUnitDriver;
21 import org.slf4j.Logger;
22 import org.slf4j.LoggerFactory;
23
24
25
26
27
28 public class WebDriverFactory
29 {
30 private static final Logger log = LoggerFactory.getLogger(WebDriverFactory.class);
31 private static final Pattern browserPathPattern = Pattern.compile("^([A-Za-z0-9_.-]+):path=(.*)$");
32
33 private static final int GET_DRIVER_RETRY_COUNT = Integer.getInteger("webdriver.init.retry", 1);
34
35 private WebDriverFactory() {}
36
37 public static AtlassianWebDriver getDriver()
38 {
39 return getDriver(null);
40 }
41
42 public static String getBrowserProperty()
43 {
44 return System.getProperty("webdriver.browser", "firefox");
45 }
46
47 public static Browser getBrowser()
48 {
49 String browserProperty = getBrowserProperty();
50
51 return getBrowser(browserProperty);
52 }
53
54 public static Browser getBrowser(String browserProperty)
55 {
56 if (RemoteWebDriverFactory.matches(browserProperty))
57 {
58 return RemoteWebDriverFactory.getBrowser(browserProperty);
59 }
60
61 Matcher matcher = browserPathPattern.matcher(browserProperty);
62
63 if (matcher.matches())
64 {
65 browserProperty = matcher.group(1);
66 }
67
68 return Browser.typeOf(browserProperty);
69 }
70
71 public static AtlassianWebDriver getDriver(final BrowserConfig browserConfig)
72 {
73 Supplier<AtlassianWebDriver> runnable = new Supplier<AtlassianWebDriver>()
74 {
75 public AtlassianWebDriver get()
76 {
77 return getDriverNoRetry(browserConfig);
78 }
79 };
80 ExceptionHandler exceptionLogger = new ExceptionHandler()
81 {
82 public void handle(RuntimeException ex)
83 {
84 log.warn("Error creating WebDriver object, retrying.. ({})", ex.toString());
85 log.debug("Error creating WebDriver object - stack trace", ex);
86 }
87 };
88 return RetryFactory.create(runnable, GET_DRIVER_RETRY_COUNT, exceptionLogger).get();
89 }
90
91 private static AtlassianWebDriver getDriverNoRetry(BrowserConfig browserConfig)
92 {
93 WebDriver driver;
94 String browserPath = null;
95
96 String BROWSER = getBrowserProperty();
97
98 if (RemoteWebDriverFactory.matches(BROWSER))
99 {
100 log.info("Loading RemoteWebDriverFactory driver " + BROWSER);
101 return RemoteWebDriverFactory.getDriver(BROWSER);
102 }
103
104 Matcher matcher = browserPathPattern.matcher(BROWSER);
105
106 if (matcher.matches())
107 {
108 BROWSER = matcher.group(1);
109 browserPath = matcher.group(2);
110 }
111
112 Browser browserType = Browser.typeOf(BROWSER);
113
114 switch (browserType)
115 {
116 case FIREFOX:
117
118 if (browserPath == null && browserConfig != null)
119 {
120 driver = FirefoxBrowser.getFirefoxDriver(browserConfig);
121 }
122 else if (browserPath != null)
123 {
124 driver = FirefoxBrowser.getFirefoxDriver(browserPath);
125 }
126 else
127 {
128 driver = FirefoxBrowser.getFirefoxDriver();
129 }
130 break;
131
132 case CHROME:
133
134 if (browserPath == null && browserConfig != null)
135 {
136 driver = ChromeBrowser.getChromeDriver(browserConfig);
137 }
138
139 else if (browserPath != null)
140 {
141 driver = ChromeBrowser.getChromeDriver(browserPath);
142 }
143 else
144 {
145 driver = ChromeBrowser.getChromeDriver();
146 }
147 break;
148
149 case IE:
150 driver = IeBrowser.createIeDriver(browserPath, browserConfig);
151 break;
152
153 case HTMLUNIT_NOJS:
154 driver = newHtmlUnitDriver(false);
155 break;
156
157 case HTMLUNIT:
158 driver = newHtmlUnitDriver(true);
159 break;
160
161 case IPHONE_SIMULATOR:
162 throw new UnsupportedOperationException("iPhone simulator is no longer a supported Browser Type. " +
163 "Use remote iPhone driver instead");
164
165 case IPHONE:
166
167 throw new RuntimeException("iPhone driver must be configured with a url parameter");
168
169 case IPAD:
170
171 throw new RuntimeException("iPad driver must be configured with a url parameter");
172
173 case ANDROID_EMULATOR:
174 throw new UnsupportedOperationException("Android emulator is no longer a supported Browser Type. " +
175 "Use remote Android driver instead");
176
177 case ANDROID:
178
179 throw new RuntimeException("Android driver must be configured with a url parameter");
180
181 case SAFARI:
182 throw new UnsupportedOperationException("Safari is not a supported Browser Type");
183
184 case OPERA:
185 throw new UnsupportedOperationException("Opera is not a supported Browser Type");
186
187 default:
188 log.error("Unknown browser: {}, defaulting to firefox.", BROWSER);
189 browserType = Browser.FIREFOX;
190 driver = FirefoxBrowser.getFirefoxDriver();
191 }
192
193 BrowserUtil.setCurrentBrowser(browserType);
194
195 return new DefaultAtlassianWebDriver(driver, browserType);
196 }
197
198 private static HtmlUnitDriver newHtmlUnitDriver(boolean javascriptEnabled)
199 {
200 final HtmlUnitDriver driver = new HtmlUnitDriver(BrowserVersion.FIREFOX_38)
201 {
202 @Override
203 protected WebClient modifyWebClient(final WebClient client)
204 {
205
206 client.getOptions().setThrowExceptionOnScriptError(false);
207 return client;
208 }
209 };
210 driver.setJavascriptEnabled(javascriptEnabled);
211 return driver;
212 }
213 }