Remove forwarder as it's not supported in W3C anymore.
diff --git a/lib/support/forwarder.dart b/lib/support/forwarder.dart
deleted file mode 100644
index dc44938..0000000
--- a/lib/support/forwarder.dart
+++ /dev/null
@@ -1,218 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// 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.
-
-library webdriver.support.forwarder;
-
-import 'dart:async' show Future;
-import 'dart:convert' show json, utf8;
-import 'dart:io' show ContentType, Directory, File, HttpRequest, HttpStatus;
-
-import 'package:path/path.dart' as path;
-import 'package:webdriver/async_core.dart'
-    show By, WebDriver, WebDriverException;
-
-final _contentTypeJson = ContentType('application', 'json', charset: 'utf-8');
-
-/// Attribute on elements used to locate them on passed WebDriver commands.
-const wdElementIdAttribute = 'wd-element-id';
-
-/// [WebDriverForwarder] accepts [HttpRequest]s corresponding to a variation on
-/// the WebDriver wire protocol and forwards them to a WebDriver instance.
-///
-/// The primary difference between this and the standard wire protocol is in
-/// the use of WebElement ids. When you need to refer to an element in a request
-/// (URI or JSON body), then you should add an 'wd-element-id' attribute to the
-/// corresponding element with a unique identifier, and use that identifier as
-/// the element id for that element. This class will then search for the
-/// corresponding element and in the document and will substitute an actual
-/// WebElement id for the given identifier in the request.
-///
-/// This forwarder supports two additional commands that control how it searches
-/// for elements:
-///   POST '/enabledeep': enables searching through all Shadow DOMs in the
-///     document for the corresponding element (but will fail on browsers that
-///     don't support the '/deep/' css selector combinator).
-///   POST '/disabledeep': disables searching in Shadow DOMs of the document.
-///
-/// This forwarder also supports two additional commands for grabbing the
-/// browser contents and saving it to the file system.
-///   POST '/screenshot': takes a 'file' arg and will capture a screenshot
-///     of the browser and save it to the specified file name in [outputDir].
-///   POST '/source': takes a 'file' arg and will capture the current page's
-///     source and save it to the specified file name in [outputDir].
-///
-/// See https://code.google.com/p/selenium/wiki/JsonWireProtocol for
-/// documentation of other commands.
-class WebDriverForwarder {
-  /// [WebDriver] instance to forward commands to.
-  final WebDriver driver;
-
-  /// Path prefix that all forwarded commands will have.
-  final Pattern prefix;
-
-  /// Directory to save screenshots and page source to.
-  final Directory outputDir;
-
-  /// Search for elements in all shadow doms of the current document.
-  bool useDeep;
-
-  WebDriverForwarder(this.driver,
-      {this.prefix = '/webdriver', Directory outputDir, this.useDeep = false})
-      : this.outputDir = outputDir == null
-            ? Directory.systemTemp.createTempSync()
-            : outputDir;
-
-  /// Forward [request] to [driver] and respond to the request with the returned
-  /// value or any thrown exceptions.
-  Future<void> forward(HttpRequest request) async {
-    try {
-      if (!request.uri.path.startsWith(prefix)) {
-        request.response.statusCode = HttpStatus.notFound;
-        return;
-      }
-      request.response.statusCode = HttpStatus.ok;
-      request.response.headers.contentType = _contentTypeJson;
-
-      var endpoint = request.uri.path.replaceFirst(prefix, '');
-      if (endpoint.startsWith('/')) {
-        endpoint = endpoint.substring(1);
-      }
-      Map<dynamic, dynamic> params;
-      if (request.method == 'POST') {
-        String requestBody = await utf8.decodeStream(request.cast<List<int>>());
-        if (requestBody != null && requestBody.isNotEmpty) {
-          params = json.decode(requestBody) as Map<dynamic, dynamic>;
-        }
-      }
-      var value = await _forward(request.method, endpoint, params);
-      request.response
-          .add(utf8.encode(json.encode({'status': 0, 'value': value})));
-    } on WebDriverException catch (e) {
-      request.response.add(utf8.encode(json.encode({
-        'status': e.statusCode,
-        'value': {'message': e.message}
-      })));
-    } catch (e) {
-      request.response.add(utf8.encode(json.encode({
-        'status': 13,
-        'value': {'message': e.toString()}
-      })));
-    } finally {
-      await request.response.close();
-    }
-  }
-
-  Future<dynamic> _forward(String method, String endpoint,
-      [Map<dynamic, dynamic> params]) async {
-    List<String> endpointTokens = path.split(endpoint);
-    if (endpointTokens.isEmpty) {
-      endpointTokens = [''];
-    }
-    switch (endpointTokens[0]) {
-      case 'enabledeep':
-        // turn on Shadow DOM support, don't forward
-        useDeep = true;
-        return null;
-      case 'disabledeep':
-        // turn off Shadow DOM support, don't forward
-        useDeep = false;
-        return null;
-      case 'screenshot':
-        if (method == 'POST') {
-          // take a screenshot and save to file system
-          var file = File(path.join(outputDir.path, params['file']));
-          await file.writeAsBytes(await driver.captureScreenshotAsList());
-          return null;
-        }
-        break;
-      case 'source':
-        if (method == 'POST') {
-          // grab page source and save to file system
-          await File(path.join(outputDir.path, params['file']))
-              .writeAsString(await driver.pageSource);
-          return null;
-        }
-        break;
-      case 'element':
-        // process endpoints of the form /element/[id]/...
-        if (endpointTokens.length >= 2) {
-          endpointTokens[1] = await _findElement(endpointTokens[1]);
-        }
-        // process endpoint /element/[id]/equals/[id]
-        if (endpointTokens.length == 4 && endpointTokens[2] == 'equals') {
-          endpointTokens[3] = await _findElement(endpointTokens[3]);
-        }
-        break;
-      case 'touch':
-      case 'moveto':
-        // several /touch/... endpoints and the /moveto endpoint have an
-        // optional 'element' param with a WebElement id value
-        if (params['element'] != null) {
-          params = Map.from(params);
-          params['element'] = await _findElement(params['element']);
-        }
-        break;
-      case 'execute':
-      case 'execute_async':
-        // /execute and /execute_async allow arbitrary JSON objects with
-        // embedded WebElememt ids.
-        params = await _deepCopy(params) as Map<dynamic, dynamic>;
-        break;
-    }
-
-    switch (method) {
-      case 'GET':
-        return await driver.getRequest(path.joinAll(endpointTokens));
-      case 'DELETE':
-        return await driver.deleteRequest(path.joinAll(endpointTokens));
-      case 'POST':
-        return await driver.postRequest(path.joinAll(endpointTokens), params);
-      default:
-        throw 'unsupported method $method';
-    }
-  }
-
-  Future<String> _findElement(String id) async {
-    var selector = "[$wdElementIdAttribute='$id']";
-    if (useDeep) {
-      selector = '* /deep/ $selector';
-    }
-    var elements = await driver.findElements(By.cssSelector(selector)).toList();
-    return elements.single.id;
-  }
-
-  dynamic _deepCopy(dynamic source) async {
-    if (source is Map) {
-      var copy = {};
-
-      for (var key in source.keys) {
-        var value = source[key];
-        if (key == 'ELEMENT') {
-          copy['ELEMENT'] = await _findElement(value);
-        } else {
-          copy[await _deepCopy(key)] = await _deepCopy(value);
-        }
-      }
-      return copy;
-    } else if (source is Iterable) {
-      var copy = [];
-      for (var value in source) {
-        copy.add(await _deepCopy(value));
-      }
-      return copy;
-    } else {
-      return source;
-    }
-  }
-}
diff --git a/test/configs/async_io_config.dart b/test/configs/async_io_config.dart
index b45d49b..ddc7a4a 100644
--- a/test/configs/async_io_config.dart
+++ b/test/configs/async_io_config.dart
@@ -39,9 +39,6 @@
       desired: capabilities, uri: getWebDriverUri(spec), spec: spec);
 }
 
-String get forwarderTestPagePath =>
-    path.join(testHomePath, 'support', 'forwarder_test_page.html');
-
 Future<HttpServer> createTestServerAndGoToTestPage(WebDriver driver) async {
   final server = await createLocalServer();
   server.listen((request) {
diff --git a/test/support/forwarder_test.dart b/test/support/forwarder_test.dart
deleted file mode 100644
index 5b1c31e..0000000
--- a/test/support/forwarder_test.dart
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2015 Google Inc. All Rights Reserved.
-//
-// 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.
-
-@TestOn('vm')
-library webdriver.support.forwarder_test;
-
-import 'dart:io';
-
-import 'package:test/test.dart';
-import 'package:webdriver/io.dart';
-import 'package:webdriver/support/forwarder.dart';
-
-import '../configs/async_io_config.dart' as config;
-
-const buttonClicked = 'Button clicked';
-const buttonNotClicked = 'Button not clicked';
-
-void main() {
-  group('WebDriverForwarder', () {
-    WebDriver driver;
-    WebDriverForwarder forwarder;
-    HttpServer server;
-    WebDriver forwardedDriver;
-    Uri address;
-
-    setUp(() async {
-      driver = await config.createTestDriver();
-      forwarder = WebDriverForwarder(driver, prefix: '/webdriver/session/1');
-
-      server = await config.createLocalServer();
-      server.listen((request) {
-        if (request.uri.path.startsWith('/webdriver')) {
-          forwarder.forward(request);
-        } else if (request.method == 'GET' &&
-            request.uri.path.endsWith('test_page.html')) {
-          String testPagePath = config.forwarderTestPagePath;
-          File file = File(testPagePath);
-          request.response
-            ..statusCode = HttpStatus.ok
-            ..headers.set('Content-type', 'text/html');
-          file.openRead().pipe(request.response);
-        } else {
-          request.response
-            ..statusCode = HttpStatus.notFound
-            ..close();
-        }
-      });
-      address = Uri.http('localhost:${server.port}', '/webdriver/');
-      forwardedDriver =
-          fromExistingSessionSync('1', WebDriverSpec.JsonWire, uri: address);
-
-      await forwardedDriver.get(address.resolve('/test_page.html'));
-    });
-
-    tearDown(() async {
-      try {
-        await forwardedDriver.quit();
-      } catch (e) {
-        print('Ignored error quitting forwardedDriver: $e');
-      }
-      try {
-        await server.close(force: true);
-      } catch (e) {
-        print('Ignored error quitting server: $e');
-      }
-      try {
-        await driver.quit();
-      } catch (e) {
-        print('Ignored error quitting driver: $e');
-      }
-    });
-
-    test('get url', () async {
-      expect(await forwardedDriver.currentUrl, endsWith('test_page.html'));
-    });
-
-    test('click button', () async {
-      expect(await forwardedDriver.getRequest('element/div/text'),
-          buttonNotClicked);
-
-      await forwardedDriver.postRequest('element/button/click', {'button': 0});
-      expect(
-          await forwardedDriver.getRequest('element/div/text'), buttonClicked);
-    });
-
-    test('moveto/click', () async {
-      expect(await forwardedDriver.getRequest('element/div/text'),
-          buttonNotClicked);
-
-      await forwardedDriver.postRequest('moveto', {'element': 'button'});
-      await forwardedDriver.mouse.click();
-
-      expect(
-          await forwardedDriver.getRequest('element/div/text'), buttonClicked);
-    });
-
-    test('execute_script', () async {
-      expect(await forwardedDriver.getRequest('element/div/text'),
-          buttonNotClicked);
-
-      await forwardedDriver.execute('arguments[0].el.click();', [
-        {
-          'el': {'ELEMENT': 'button'}
-        }
-      ]);
-
-      expect(
-          await forwardedDriver.getRequest('element/div/text'), buttonClicked);
-    });
-
-    test('element equals', () async {
-      expect(
-          await forwardedDriver.getRequest('element/div/equals/div'), isTrue);
-      expect(await forwardedDriver.getRequest('element/div/equals/button'),
-          isFalse);
-    });
-
-    // TODO(DrMarcII) add test that actually uses shadow dom
-    test('enable/disable deep', () async {
-      await forwardedDriver.postRequest('disabledeep');
-
-      expect(await forwardedDriver.getRequest('element/div/text'),
-          buttonNotClicked);
-
-      await forwardedDriver.postRequest('element/button/click', {'button': 0});
-      expect(
-          await forwardedDriver.getRequest('element/div/text'), buttonClicked);
-
-      await forwardedDriver.postRequest('enabledeep');
-      await forwardedDriver.refresh();
-
-      expect(await forwardedDriver.getRequest('element/div/text'),
-          buttonNotClicked);
-
-      await forwardedDriver.postRequest('element/button/click', {'button': 0});
-      expect(
-          await forwardedDriver.getRequest('element/div/text'), buttonClicked);
-    });
-
-    test('window close', () async {
-      await (await forwardedDriver.window).close();
-    });
-  }, timeout: const Timeout(Duration(minutes: 2)));
-}
diff --git a/test/support/forwarder_test_page.html b/test/support/forwarder_test_page.html
deleted file mode 100644
index 4102c94..0000000
--- a/test/support/forwarder_test_page.html
+++ /dev/null
@@ -1,36 +0,0 @@
-<!DOCTYPE html>
-
-<!--
-Copyright 2015 Google Inc. All Rights Reserved.
-
-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.
--->
-
-<html>
-<head lang="en">
-    <meta charset="UTF-8">
-    <title></title>
-</head>
-<body>
-
-<input type="button" wd-element-id="button" onclick="buttonClicked()" value="button">
-
-<div wd-element-id="div">Button not clicked</div>
-
-<script>
-    function buttonClicked() {
-        document.querySelector('[wd-element-id="div"]').textContent = 'Button clicked';
-    }
-</script>
-</body>
-</html>