1 | // Copyright 2014 Selenium committers |
2 | // Copyright 2014 Software Freedom Conservancy |
3 | // |
4 | // Licensed under the Apache License, Version 2.0 (the "License"); |
5 | // you may not use this file except in compliance with the License. |
6 | // You may obtain a copy of the License at |
7 | // |
8 | // http://www.apache.org/licenses/LICENSE-2.0 |
9 | // |
10 | // Unless required by applicable law or agreed to in writing, software |
11 | // distributed under the License is distributed on an "AS IS" BASIS, |
12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
13 | // See the License for the specific language governing permissions and |
14 | // limitations under the License. |
15 | |
16 | 'use strict'; |
17 | |
18 | var url = require('url'), |
19 | util = require('util'); |
20 | |
21 | var Binary = require('./binary').Binary, |
22 | Profile = require('./profile').Profile, |
23 | decodeProfile = require('./profile').decode, |
24 | webdriver = require('..'), |
25 | executors = require('../executors'), |
26 | httpUtil = require('../http/util'), |
27 | net = require('../net'), |
28 | portprober = require('../net/portprober'); |
29 | |
30 | |
31 | /** |
32 | * Configuration options for the FirefoxDriver. |
33 | * @constructor |
34 | */ |
35 | var Options = function() { |
36 | /** @private {Profile} */ |
37 | this.profile_ = null; |
38 | |
39 | /** @private {Binary} */ |
40 | this.binary_ = null; |
41 | |
42 | /** @private {webdriver.logging.Preferences} */ |
43 | this.logPrefs_ = null; |
44 | |
45 | /** @private {webdriver.ProxyConfig} */ |
46 | this.proxy_ = null; |
47 | }; |
48 | |
49 | |
50 | /** |
51 | * Sets the profile to use. The profile may be specified as a |
52 | * {@link Profile} object or as the path to an existing Firefox profile to use |
53 | * as a template. |
54 | * |
55 | * @param {(string|!Profile)} profile The profile to use. |
56 | * @return {!Options} A self reference. |
57 | */ |
58 | Options.prototype.setProfile = function(profile) { |
59 | if (typeof profile === 'string') { |
60 | profile = new Profile(profile); |
61 | } |
62 | this.profile_ = profile; |
63 | return this; |
64 | }; |
65 | |
66 | |
67 | /** |
68 | * Sets the binary to use. The binary may be specified as the path to a Firefox |
69 | * executable, or as a {@link Binary} object. |
70 | * |
71 | * @param {(string|!Binary)} binary The binary to use. |
72 | * @return {!Options} A self reference. |
73 | */ |
74 | Options.prototype.setBinary = function(binary) { |
75 | if (typeof binary === 'string') { |
76 | binary = new Binary(binary); |
77 | } |
78 | this.binary_ = binary; |
79 | return this; |
80 | }; |
81 | |
82 | |
83 | /** |
84 | * Sets the logging preferences for the new session. |
85 | * @param {webdriver.logging.Preferences} prefs The logging preferences. |
86 | * @return {!Options} A self reference. |
87 | */ |
88 | Options.prototype.setLoggingPreferences = function(prefs) { |
89 | this.logPrefs_ = prefs; |
90 | return this; |
91 | }; |
92 | |
93 | |
94 | /** |
95 | * Sets the proxy to use. |
96 | * |
97 | * @param {webdriver.ProxyConfig} proxy The proxy configuration to use. |
98 | * @return {!Options} A self reference. |
99 | */ |
100 | Options.prototype.setProxy = function(proxy) { |
101 | this.proxy_ = proxy; |
102 | return this; |
103 | }; |
104 | |
105 | |
106 | /** |
107 | * Converts these options to a {@link webdriver.Capabilities} instance. |
108 | * |
109 | * @return {!webdriver.Capabilities} A new capabilities object. |
110 | */ |
111 | Options.prototype.toCapabilities = function(opt_remote) { |
112 | var caps = webdriver.Capabilities.firefox(); |
113 | if (this.logPrefs_) { |
114 | caps.set(webdriver.Capability.LOGGING_PREFS, this.logPrefs_); |
115 | } |
116 | if (this.proxy_) { |
117 | caps.set(webdriver.Capability.PROXY, this.proxy_); |
118 | } |
119 | if (this.binary_) { |
120 | caps.set('firefox_binary', this.binary_); |
121 | } |
122 | if (this.profile_) { |
123 | caps.set('firefox_profile', this.profile_); |
124 | } |
125 | return caps; |
126 | }; |
127 | |
128 | |
129 | /** |
130 | * A WebDriver client for Firefox. |
131 | * |
132 | * @param {(Options|webdriver.Capabilities|Object)=} opt_config The |
133 | * configuration options for this driver, specified as either an |
134 | * {@link Options} or {@link webdriver.Capabilities}, or as a raw hash |
135 | * object. |
136 | * @param {webdriver.promise.ControlFlow=} opt_flow The flow to |
137 | * schedule commands through. Defaults to the active flow object. |
138 | * @constructor |
139 | * @extends {webdriver.WebDriver} |
140 | */ |
141 | var Driver = function(opt_config, opt_flow) { |
142 | var caps; |
143 | if (opt_config instanceof Options) { |
144 | caps = opt_config.toCapabilities(); |
145 | } else { |
146 | caps = new webdriver.Capabilities(opt_config); |
147 | } |
148 | |
149 | var binary = caps.get('firefox_binary') || new Binary(); |
150 | if (typeof binary === 'string') { |
151 | binary = new Binary(binary); |
152 | } |
153 | |
154 | var profile = caps.get('firefox_profile') || new Profile(); |
155 | |
156 | caps.set('firefox_binary', null); |
157 | caps.set('firefox_profile', null); |
158 | |
159 | var serverUrl = portprober.findFreePort().then(function(port) { |
160 | var prepareProfile; |
161 | if (typeof profile === 'string') { |
162 | prepareProfile = decodeProfile(profile).then(function(dir) { |
163 | var profile = new Profile(dir); |
164 | profile.setPreference('webdriver_firefox_port', port); |
165 | return profile.writeToDisk(); |
166 | }); |
167 | } else { |
168 | profile.setPreference('webdriver_firefox_port', port); |
169 | prepareProfile = profile.writeToDisk(); |
170 | } |
171 | |
172 | return prepareProfile.then(function(dir) { |
173 | return binary.launch(dir); |
174 | }).then(function() { |
175 | var serverUrl = url.format({ |
176 | protocol: 'http', |
177 | hostname: net.getLoopbackAddress(), |
178 | port: port, |
179 | pathname: '/hub' |
180 | }); |
181 | |
182 | return httpUtil.waitForServer(serverUrl, 45 * 1000).then(function() { |
183 | return serverUrl; |
184 | }); |
185 | }); |
186 | }); |
187 | |
188 | var executor = executors.createExecutor(serverUrl); |
189 | var driver = webdriver.WebDriver.createSession(executor, caps, opt_flow); |
190 | |
191 | webdriver.WebDriver.call(this, driver.getSession(), executor, opt_flow); |
192 | }; |
193 | util.inherits(Driver, webdriver.WebDriver); |
194 | |
195 | |
196 | // PUBLIC API |
197 | |
198 | |
199 | exports.Binary = Binary; |
200 | exports.Driver = Driver; |
201 | exports.Options = Options; |
202 | exports.Profile = Profile; |