2015-04-04 09:53:59 -07:00
|
|
|
// Licensed to the Software Freedom Conservancy (SFC) under one
|
|
|
|
|
// or more contributor license agreements. See the NOTICE file
|
|
|
|
|
// distributed with this work for additional information
|
|
|
|
|
// regarding copyright ownership. The SFC licenses this file
|
|
|
|
|
// to you 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
|
2014-11-12 19:33:37 +00:00
|
|
|
//
|
2015-04-04 09:53:59 -07:00
|
|
|
// http://www.apache.org/licenses/LICENSE-2.0
|
2014-11-12 19:33:37 +00:00
|
|
|
//
|
2015-04-04 09:53:59 -07:00
|
|
|
// 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.
|
JasonLeyba: Drop JSONP for using WebDriverJs in the browser and rely solely on CORS. This means using WebDriverJs in the browser will only be supported by WebKit, Firefox, IE8+, and Opera 12+.
Unfortunately, the various browser implementations of CORS are not consistent:
* IE's XDomainRequest object may only generate requests that could be generated using a HTML form. This means it cannot generate the DELETE requests required by the JsonWireProtocol.
* WebKit's implementation of CORS does not follow the spec and forbids redirects.
* If the server returns an error response (e.g., 4xx or 5xx), IE and Opera's implementations will fire the on error handler, but without the server's response text. This renders IE and Opera incapable of handling command failures in the standard JSON protocol.
To work around this issues, I've defined a single end-point on the server to handle all CORS-based requests: /xdrpc (cross-domain rpc). This end-point accepts POST requests with a JSON body of the form {method:string, path:string, data:!Object}
The server will decode the command in the request body and route it to the correct command handler. The command response will always be returned as a standard JSON response object: {status:number, value:*}. The response will always be sent with a 200 response, so clients must rely on the response's "status" field to determine whether the command succeeded.
This has been tested against Chrome, Firefox, IE, and Opera Next (12.0a)
r15330
2012-01-01 02:15:34 +00:00
|
|
|
|
|
|
|
|
goog.provide('webdriver.http.CorsClient');
|
|
|
|
|
|
2016-05-19 15:08:51 -07:00
|
|
|
goog.require('goog.Promise');
|
2014-11-07 23:43:52 -08:00
|
|
|
goog.require('webdriver.http.Client');
|
JasonLeyba: Drop JSONP for using WebDriverJs in the browser and rely solely on CORS. This means using WebDriverJs in the browser will only be supported by WebKit, Firefox, IE8+, and Opera 12+.
Unfortunately, the various browser implementations of CORS are not consistent:
* IE's XDomainRequest object may only generate requests that could be generated using a HTML form. This means it cannot generate the DELETE requests required by the JsonWireProtocol.
* WebKit's implementation of CORS does not follow the spec and forbids redirects.
* If the server returns an error response (e.g., 4xx or 5xx), IE and Opera's implementations will fire the on error handler, but without the server's response text. This renders IE and Opera incapable of handling command failures in the standard JSON protocol.
To work around this issues, I've defined a single end-point on the server to handle all CORS-based requests: /xdrpc (cross-domain rpc). This end-point accepts POST requests with a JSON body of the form {method:string, path:string, data:!Object}
The server will decode the command in the request body and route it to the correct command handler. The command response will always be returned as a standard JSON response object: {status:number, value:*}. The response will always be sent with a 200 response, so clients must rely on the response's "status" field to determine whether the command succeeded.
This has been tested against Chrome, Firefox, IE, and Opera Next (12.0a)
r15330
2012-01-01 02:15:34 +00:00
|
|
|
goog.require('webdriver.http.Response');
|
|
|
|
|
|
|
|
|
|
|
2012-09-09 05:20:57 +00:00
|
|
|
|
JasonLeyba: Drop JSONP for using WebDriverJs in the browser and rely solely on CORS. This means using WebDriverJs in the browser will only be supported by WebKit, Firefox, IE8+, and Opera 12+.
Unfortunately, the various browser implementations of CORS are not consistent:
* IE's XDomainRequest object may only generate requests that could be generated using a HTML form. This means it cannot generate the DELETE requests required by the JsonWireProtocol.
* WebKit's implementation of CORS does not follow the spec and forbids redirects.
* If the server returns an error response (e.g., 4xx or 5xx), IE and Opera's implementations will fire the on error handler, but without the server's response text. This renders IE and Opera incapable of handling command failures in the standard JSON protocol.
To work around this issues, I've defined a single end-point on the server to handle all CORS-based requests: /xdrpc (cross-domain rpc). This end-point accepts POST requests with a JSON body of the form {method:string, path:string, data:!Object}
The server will decode the command in the request body and route it to the correct command handler. The command response will always be returned as a standard JSON response object: {status:number, value:*}. The response will always be sent with a 200 response, so clients must rely on the response's "status" field to determine whether the command succeeded.
This has been tested against Chrome, Firefox, IE, and Opera Next (12.0a)
r15330
2012-01-01 02:15:34 +00:00
|
|
|
/**
|
|
|
|
|
* Communicates with a WebDriver server, which may be on a different domain,
|
|
|
|
|
* using the <a href="http://www.w3.org/TR/cors/">cross-origin resource sharing
|
|
|
|
|
* </a> (CORS) extension to WebDriver's JSON wire protocol.
|
|
|
|
|
*
|
|
|
|
|
* <p>Each command from the standard JSON protocol will be encoded in a
|
|
|
|
|
* JSON object with the following form:
|
|
|
|
|
* {method:string, path:string, data:!Object}
|
|
|
|
|
*
|
|
|
|
|
* <p>The encoded command is then sent as a POST request to the server's /xdrpc
|
|
|
|
|
* endpoint. The server will decode the command, re-route it to the appropriate
|
|
|
|
|
* handler, and then return the command's response as a standard JSON response
|
|
|
|
|
* object. The JSON responses will <em>always</em> be returned with a 200
|
|
|
|
|
* response from the server; clients must rely on the response's "status" field
|
|
|
|
|
* to determine whether the command succeeded.
|
|
|
|
|
*
|
|
|
|
|
* <p>This client cannot be used with the standard wire protocol due to
|
|
|
|
|
* limitations in the various browser implementations of the CORS specification:
|
|
|
|
|
* <ul>
|
|
|
|
|
* <li>IE's <a href="http://goo.gl/6l3kA">XDomainRequest</a> object is only
|
|
|
|
|
* capable of generating the types of requests that may be generated through
|
|
|
|
|
* a standard <a href="http://goo.gl/vgzAU">HTML form</a> - it can not send
|
|
|
|
|
* DELETE requests, as is required in the wire protocol.
|
|
|
|
|
* <li>WebKit's implementation of CORS does not follow the spec and forbids
|
|
|
|
|
* redirects: https://bugs.webkit.org/show_bug.cgi?id=57600
|
|
|
|
|
* This limitation appears to be intentional and is documented in WebKit's
|
|
|
|
|
* Layout tests:
|
|
|
|
|
* //LayoutTests/http/tests/xmlhttprequest/access-control-and-redirects.html
|
2015-02-28 21:27:06 +01:00
|
|
|
* <li>If the server does not return a 2xx response, IE
|
|
|
|
|
* implementation will fire the XDomainRequest/XMLHttpRequest object's
|
JasonLeyba: Drop JSONP for using WebDriverJs in the browser and rely solely on CORS. This means using WebDriverJs in the browser will only be supported by WebKit, Firefox, IE8+, and Opera 12+.
Unfortunately, the various browser implementations of CORS are not consistent:
* IE's XDomainRequest object may only generate requests that could be generated using a HTML form. This means it cannot generate the DELETE requests required by the JsonWireProtocol.
* WebKit's implementation of CORS does not follow the spec and forbids redirects.
* If the server returns an error response (e.g., 4xx or 5xx), IE and Opera's implementations will fire the on error handler, but without the server's response text. This renders IE and Opera incapable of handling command failures in the standard JSON protocol.
To work around this issues, I've defined a single end-point on the server to handle all CORS-based requests: /xdrpc (cross-domain rpc). This end-point accepts POST requests with a JSON body of the form {method:string, path:string, data:!Object}
The server will decode the command in the request body and route it to the correct command handler. The command response will always be returned as a standard JSON response object: {status:number, value:*}. The response will always be sent with a 200 response, so clients must rely on the response's "status" field to determine whether the command succeeded.
This has been tested against Chrome, Firefox, IE, and Opera Next (12.0a)
r15330
2012-01-01 02:15:34 +00:00
|
|
|
* onerror handler, but without the corresponding response text returned by
|
2015-02-28 21:27:06 +01:00
|
|
|
* the server. This renders IE incapable of handling command
|
JasonLeyba: Drop JSONP for using WebDriverJs in the browser and rely solely on CORS. This means using WebDriverJs in the browser will only be supported by WebKit, Firefox, IE8+, and Opera 12+.
Unfortunately, the various browser implementations of CORS are not consistent:
* IE's XDomainRequest object may only generate requests that could be generated using a HTML form. This means it cannot generate the DELETE requests required by the JsonWireProtocol.
* WebKit's implementation of CORS does not follow the spec and forbids redirects.
* If the server returns an error response (e.g., 4xx or 5xx), IE and Opera's implementations will fire the on error handler, but without the server's response text. This renders IE and Opera incapable of handling command failures in the standard JSON protocol.
To work around this issues, I've defined a single end-point on the server to handle all CORS-based requests: /xdrpc (cross-domain rpc). This end-point accepts POST requests with a JSON body of the form {method:string, path:string, data:!Object}
The server will decode the command in the request body and route it to the correct command handler. The command response will always be returned as a standard JSON response object: {status:number, value:*}. The response will always be sent with a 200 response, so clients must rely on the response's "status" field to determine whether the command succeeded.
This has been tested against Chrome, Firefox, IE, and Opera Next (12.0a)
r15330
2012-01-01 02:15:34 +00:00
|
|
|
* failures in the standard JSON protocol.
|
|
|
|
|
* </ul>
|
|
|
|
|
*
|
|
|
|
|
* @param {string} url URL for the WebDriver server to send commands to.
|
|
|
|
|
* @constructor
|
|
|
|
|
* @implements {webdriver.http.Client}
|
|
|
|
|
* @see <a href="http://www.w3.org/TR/cors/">CORS Spec</a>
|
2015-03-17 19:15:20 -04:00
|
|
|
* @see <a href="https://github.com/SeleniumHQ/selenium/wiki/JsonWireProtocol">
|
JasonLeyba: Drop JSONP for using WebDriverJs in the browser and rely solely on CORS. This means using WebDriverJs in the browser will only be supported by WebKit, Firefox, IE8+, and Opera 12+.
Unfortunately, the various browser implementations of CORS are not consistent:
* IE's XDomainRequest object may only generate requests that could be generated using a HTML form. This means it cannot generate the DELETE requests required by the JsonWireProtocol.
* WebKit's implementation of CORS does not follow the spec and forbids redirects.
* If the server returns an error response (e.g., 4xx or 5xx), IE and Opera's implementations will fire the on error handler, but without the server's response text. This renders IE and Opera incapable of handling command failures in the standard JSON protocol.
To work around this issues, I've defined a single end-point on the server to handle all CORS-based requests: /xdrpc (cross-domain rpc). This end-point accepts POST requests with a JSON body of the form {method:string, path:string, data:!Object}
The server will decode the command in the request body and route it to the correct command handler. The command response will always be returned as a standard JSON response object: {status:number, value:*}. The response will always be sent with a 200 response, so clients must rely on the response's "status" field to determine whether the command succeeded.
This has been tested against Chrome, Firefox, IE, and Opera Next (12.0a)
r15330
2012-01-01 02:15:34 +00:00
|
|
|
* JSON wire protocol</a>
|
|
|
|
|
*/
|
|
|
|
|
webdriver.http.CorsClient = function(url) {
|
|
|
|
|
if (!webdriver.http.CorsClient.isAvailable()) {
|
|
|
|
|
throw Error('The current environment does not support cross-origin ' +
|
|
|
|
|
'resource sharing');
|
|
|
|
|
}
|
|
|
|
|
|
2013-03-10 13:56:37 -07:00
|
|
|
/** @private {string} */
|
JasonLeyba: Drop JSONP for using WebDriverJs in the browser and rely solely on CORS. This means using WebDriverJs in the browser will only be supported by WebKit, Firefox, IE8+, and Opera 12+.
Unfortunately, the various browser implementations of CORS are not consistent:
* IE's XDomainRequest object may only generate requests that could be generated using a HTML form. This means it cannot generate the DELETE requests required by the JsonWireProtocol.
* WebKit's implementation of CORS does not follow the spec and forbids redirects.
* If the server returns an error response (e.g., 4xx or 5xx), IE and Opera's implementations will fire the on error handler, but without the server's response text. This renders IE and Opera incapable of handling command failures in the standard JSON protocol.
To work around this issues, I've defined a single end-point on the server to handle all CORS-based requests: /xdrpc (cross-domain rpc). This end-point accepts POST requests with a JSON body of the form {method:string, path:string, data:!Object}
The server will decode the command in the request body and route it to the correct command handler. The command response will always be returned as a standard JSON response object: {status:number, value:*}. The response will always be sent with a 200 response, so clients must rely on the response's "status" field to determine whether the command succeeded.
This has been tested against Chrome, Firefox, IE, and Opera Next (12.0a)
r15330
2012-01-01 02:15:34 +00:00
|
|
|
this.url_ = url + webdriver.http.CorsClient.XDRPC_ENDPOINT;
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Resource URL to send commands to on the server.
|
|
|
|
|
* @type {string}
|
|
|
|
|
* @const
|
|
|
|
|
*/
|
|
|
|
|
webdriver.http.CorsClient.XDRPC_ENDPOINT = '/xdrpc';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Tests whether the current environment supports cross-origin resource sharing.
|
|
|
|
|
* @return {boolean} Whether cross-origin resource sharing is supported.
|
|
|
|
|
* @see http://www.w3.org/TR/cors/
|
|
|
|
|
*/
|
|
|
|
|
webdriver.http.CorsClient.isAvailable = function() {
|
|
|
|
|
return typeof XDomainRequest !== 'undefined' ||
|
|
|
|
|
(typeof XMLHttpRequest !== 'undefined' &&
|
|
|
|
|
goog.isBoolean(new XMLHttpRequest().withCredentials));
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
/** @override */
|
2015-11-13 14:12:26 -08:00
|
|
|
webdriver.http.CorsClient.prototype.send = function(request) {
|
|
|
|
|
var url = this.url_;
|
2016-05-19 15:08:51 -07:00
|
|
|
return new goog.Promise(function(fulfill, reject) {
|
JasonLeyba: Drop JSONP for using WebDriverJs in the browser and rely solely on CORS. This means using WebDriverJs in the browser will only be supported by WebKit, Firefox, IE8+, and Opera 12+.
Unfortunately, the various browser implementations of CORS are not consistent:
* IE's XDomainRequest object may only generate requests that could be generated using a HTML form. This means it cannot generate the DELETE requests required by the JsonWireProtocol.
* WebKit's implementation of CORS does not follow the spec and forbids redirects.
* If the server returns an error response (e.g., 4xx or 5xx), IE and Opera's implementations will fire the on error handler, but without the server's response text. This renders IE and Opera incapable of handling command failures in the standard JSON protocol.
To work around this issues, I've defined a single end-point on the server to handle all CORS-based requests: /xdrpc (cross-domain rpc). This end-point accepts POST requests with a JSON body of the form {method:string, path:string, data:!Object}
The server will decode the command in the request body and route it to the correct command handler. The command response will always be returned as a standard JSON response object: {status:number, value:*}. The response will always be sent with a 200 response, so clients must rely on the response's "status" field to determine whether the command succeeded.
This has been tested against Chrome, Firefox, IE, and Opera Next (12.0a)
r15330
2012-01-01 02:15:34 +00:00
|
|
|
var xhr = new (typeof XDomainRequest !== 'undefined' ?
|
|
|
|
|
XDomainRequest : XMLHttpRequest);
|
2015-11-13 14:12:26 -08:00
|
|
|
xhr.open('POST', url, true);
|
JasonLeyba: Drop JSONP for using WebDriverJs in the browser and rely solely on CORS. This means using WebDriverJs in the browser will only be supported by WebKit, Firefox, IE8+, and Opera 12+.
Unfortunately, the various browser implementations of CORS are not consistent:
* IE's XDomainRequest object may only generate requests that could be generated using a HTML form. This means it cannot generate the DELETE requests required by the JsonWireProtocol.
* WebKit's implementation of CORS does not follow the spec and forbids redirects.
* If the server returns an error response (e.g., 4xx or 5xx), IE and Opera's implementations will fire the on error handler, but without the server's response text. This renders IE and Opera incapable of handling command failures in the standard JSON protocol.
To work around this issues, I've defined a single end-point on the server to handle all CORS-based requests: /xdrpc (cross-domain rpc). This end-point accepts POST requests with a JSON body of the form {method:string, path:string, data:!Object}
The server will decode the command in the request body and route it to the correct command handler. The command response will always be returned as a standard JSON response object: {status:number, value:*}. The response will always be sent with a 200 response, so clients must rely on the response's "status" field to determine whether the command succeeded.
This has been tested against Chrome, Firefox, IE, and Opera Next (12.0a)
r15330
2012-01-01 02:15:34 +00:00
|
|
|
|
|
|
|
|
xhr.onload = function() {
|
2015-11-13 14:12:26 -08:00
|
|
|
fulfill(webdriver.http.Response.fromXmlHttpRequest(
|
2013-06-13 17:16:23 -07:00
|
|
|
/** @type {!XMLHttpRequest} */ (xhr)));
|
JasonLeyba: Drop JSONP for using WebDriverJs in the browser and rely solely on CORS. This means using WebDriverJs in the browser will only be supported by WebKit, Firefox, IE8+, and Opera 12+.
Unfortunately, the various browser implementations of CORS are not consistent:
* IE's XDomainRequest object may only generate requests that could be generated using a HTML form. This means it cannot generate the DELETE requests required by the JsonWireProtocol.
* WebKit's implementation of CORS does not follow the spec and forbids redirects.
* If the server returns an error response (e.g., 4xx or 5xx), IE and Opera's implementations will fire the on error handler, but without the server's response text. This renders IE and Opera incapable of handling command failures in the standard JSON protocol.
To work around this issues, I've defined a single end-point on the server to handle all CORS-based requests: /xdrpc (cross-domain rpc). This end-point accepts POST requests with a JSON body of the form {method:string, path:string, data:!Object}
The server will decode the command in the request body and route it to the correct command handler. The command response will always be returned as a standard JSON response object: {status:number, value:*}. The response will always be sent with a 200 response, so clients must rely on the response's "status" field to determine whether the command succeeded.
This has been tested against Chrome, Firefox, IE, and Opera Next (12.0a)
r15330
2012-01-01 02:15:34 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
xhr.onerror = function() {
|
2015-11-13 14:12:26 -08:00
|
|
|
reject(Error([
|
JasonLeyba: Drop JSONP for using WebDriverJs in the browser and rely solely on CORS. This means using WebDriverJs in the browser will only be supported by WebKit, Firefox, IE8+, and Opera 12+.
Unfortunately, the various browser implementations of CORS are not consistent:
* IE's XDomainRequest object may only generate requests that could be generated using a HTML form. This means it cannot generate the DELETE requests required by the JsonWireProtocol.
* WebKit's implementation of CORS does not follow the spec and forbids redirects.
* If the server returns an error response (e.g., 4xx or 5xx), IE and Opera's implementations will fire the on error handler, but without the server's response text. This renders IE and Opera incapable of handling command failures in the standard JSON protocol.
To work around this issues, I've defined a single end-point on the server to handle all CORS-based requests: /xdrpc (cross-domain rpc). This end-point accepts POST requests with a JSON body of the form {method:string, path:string, data:!Object}
The server will decode the command in the request body and route it to the correct command handler. The command response will always be returned as a standard JSON response object: {status:number, value:*}. The response will always be sent with a 200 response, so clients must rely on the response's "status" field to determine whether the command succeeded.
This has been tested against Chrome, Firefox, IE, and Opera Next (12.0a)
r15330
2012-01-01 02:15:34 +00:00
|
|
|
'Unable to send request: POST ', url,
|
|
|
|
|
'\nPerhaps the server did not respond to the preflight request ',
|
|
|
|
|
'with valid access control headers?'
|
|
|
|
|
].join('')));
|
|
|
|
|
};
|
|
|
|
|
|
2012-04-25 23:46:12 +00:00
|
|
|
// Define event handlers for all events on the XDomainRequest. Apparently,
|
|
|
|
|
// if we don't do this, IE9+10 will silently abort our request. Yay IE.
|
|
|
|
|
// Note, we're not using goog.nullFunction, because it tends to get
|
|
|
|
|
// optimized away by the compiler, which leaves us where we were before.
|
|
|
|
|
xhr.onprogress = xhr.ontimeout = function() {};
|
|
|
|
|
|
2015-06-18 14:22:02 -07:00
|
|
|
xhr.send(JSON.stringify({
|
JasonLeyba: Drop JSONP for using WebDriverJs in the browser and rely solely on CORS. This means using WebDriverJs in the browser will only be supported by WebKit, Firefox, IE8+, and Opera 12+.
Unfortunately, the various browser implementations of CORS are not consistent:
* IE's XDomainRequest object may only generate requests that could be generated using a HTML form. This means it cannot generate the DELETE requests required by the JsonWireProtocol.
* WebKit's implementation of CORS does not follow the spec and forbids redirects.
* If the server returns an error response (e.g., 4xx or 5xx), IE and Opera's implementations will fire the on error handler, but without the server's response text. This renders IE and Opera incapable of handling command failures in the standard JSON protocol.
To work around this issues, I've defined a single end-point on the server to handle all CORS-based requests: /xdrpc (cross-domain rpc). This end-point accepts POST requests with a JSON body of the form {method:string, path:string, data:!Object}
The server will decode the command in the request body and route it to the correct command handler. The command response will always be returned as a standard JSON response object: {status:number, value:*}. The response will always be sent with a 200 response, so clients must rely on the response's "status" field to determine whether the command succeeded.
This has been tested against Chrome, Firefox, IE, and Opera Next (12.0a)
r15330
2012-01-01 02:15:34 +00:00
|
|
|
'method': request.method,
|
|
|
|
|
'path': request.path,
|
|
|
|
|
'data': request.data
|
|
|
|
|
}));
|
2015-11-13 14:12:26 -08:00
|
|
|
});
|
JasonLeyba: Drop JSONP for using WebDriverJs in the browser and rely solely on CORS. This means using WebDriverJs in the browser will only be supported by WebKit, Firefox, IE8+, and Opera 12+.
Unfortunately, the various browser implementations of CORS are not consistent:
* IE's XDomainRequest object may only generate requests that could be generated using a HTML form. This means it cannot generate the DELETE requests required by the JsonWireProtocol.
* WebKit's implementation of CORS does not follow the spec and forbids redirects.
* If the server returns an error response (e.g., 4xx or 5xx), IE and Opera's implementations will fire the on error handler, but without the server's response text. This renders IE and Opera incapable of handling command failures in the standard JSON protocol.
To work around this issues, I've defined a single end-point on the server to handle all CORS-based requests: /xdrpc (cross-domain rpc). This end-point accepts POST requests with a JSON body of the form {method:string, path:string, data:!Object}
The server will decode the command in the request body and route it to the correct command handler. The command response will always be returned as a standard JSON response object: {status:number, value:*}. The response will always be sent with a 200 response, so clients must rely on the response's "status" field to determine whether the command succeeded.
This has been tested against Chrome, Firefox, IE, and Opera Next (12.0a)
r15330
2012-01-01 02:15:34 +00:00
|
|
|
};
|