View Javadoc

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   * Checks the System property webdriver.browser to see what browser driver to return. Defaults to
26   * firefox.
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                 // iPhones can only be driven via a RemoteWebDriver
167                 throw new RuntimeException("iPhone driver must be configured with a url parameter");
168 
169             case IPAD:
170                 // iPads can only be driven via a RemoteWebDriver
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                 // Android can only be driven via a RemoteWebDriver
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                 // "real" browsers don't throw script errors back to webdriver, so stop htmlunit from doing it too
206                 client.getOptions().setThrowExceptionOnScriptError(false);
207                 return client;
208             }
209         };
210         driver.setJavascriptEnabled(javascriptEnabled);
211         return driver;
212     }
213 }