Add support for IPv6 (#653)

diff --git a/CHANGELOG.md b/CHANGELOG.md
index 98d9d98..3b18785 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -6,6 +6,9 @@
   makes it possible to safely share `Future`s and `Stream`s between tests and
   their tear-downs.
 
+* Properly allocate ports when debugging Chrome and Dartium in an IPv6-only
+  environment.
+
 ## 0.12.22
 
 * Add a `retry` option to `test()` and `group()` functions, as well
diff --git a/lib/src/util/io.dart b/lib/src/util/io.dart
index 95474f7..4820857 100644
--- a/lib/src/util/io.dart
+++ b/lib/src/util/io.dart
@@ -137,13 +137,27 @@
   return value;
 }
 
+/// Whether this computer supports binding to IPv6 addresses.
+var _maySupportIPv6 = true;
+
 /// Returns a port that is probably, but not definitely, not in use.
 ///
 /// This has a built-in race condition: another process may bind this port at
 /// any time after this call has returned. If at all possible, callers should
 /// use [getUnusedPort] instead.
 Future<int> getUnsafeUnusedPort() async {
-  var socket = await RawServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0);
+  var socket;
+  if (_maySupportIPv6) {
+    try {
+      socket = await ServerSocket.bind(InternetAddress.LOOPBACK_IP_V6, 0,
+          v6Only: true);
+    } on SocketException {
+      _maySupportIPv6 = false;
+    }
+  }
+  if (!_maySupportIPv6) {
+    socket = await RawServerSocket.bind(InternetAddress.LOOPBACK_IP_V4, 0);
+  }
   var port = socket.port;
   await socket.close();
   return port;