// Copyright (c) 2013, the Dart project authors.  Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
library browser;

import "dart:async";
import "dart:core";
import "dart:io";

import 'android.dart';
import 'utils.dart';

/** Class describing the interface for communicating with browsers. */
abstract class Browser {
  StringBuffer _stdout = new StringBuffer();
  StringBuffer _stderr = new StringBuffer();
  StringBuffer _usageLog = new StringBuffer();
  // This function is called when the process is closed.
  Completer _processClosedCompleter = new Completer();
  // This is called after the process is closed, after _processClosedCompleter
  // has been called, but before onExit. Subclasses can use this to cleanup
  // any browser specific resources (temp directories, profiles, etc)
  // The function is expected to do it's work synchronously.
  Function _cleanup;

  /** The version of the browser - normally set when starting a browser */
  String version = "";
  /**
   * The underlying process - don't mess directly with this if you don't
   * know what you are doing (this is an interactive process that needs
   * special threatment to not leak).
   */
  Process process;

  Function logger;

  /**
   * Id of the browser
   */
  String id;

  /** Print everything (stdout, stderr, usageLog) whenever we add to it */
  bool debugPrint = false;

  // This future will be lazily set when calling close() and will complete once
  // the process did exit.
  Future browserTerminationFuture;

  Browser();

  factory Browser.byName(String name) {
    if (name == 'ff' || name == 'firefox') {
      return new Firefox();
    } else if (name == 'chrome') {
      return new Chrome();
    } else if (name == 'safari') {
      return new Safari();
    } else {
      throw "Non supported browser";
    }
  }

  static const List<String> SUPPORTED_BROWSERS =
      const ['safari', 'ff', 'firefox', 'chrome'];

  static const List<String> BROWSERS_WITH_WINDOW_SUPPORT =
      const ['safari', 'ff', 'firefox', 'chrome'];

  // TODO(kustermann): add standard support for chrome on android
  static bool supportedBrowser(String name) {
    return SUPPORTED_BROWSERS.contains(name);
  }

  void _logEvent(String event) {
    String toLog = "$this ($id) - $event \n";
    if (debugPrint) print("usageLog: $toLog");
    if (logger != null) logger(toLog);
    _usageLog.write(toLog);
  }

  void _addStdout(String output) {
    if (debugPrint) print("stdout: $output");
    _stdout.write(output);
  }

  void _addStderr(String output) {
    if (debugPrint) print("stderr: $output");
    _stderr.write(output);
  }

  Future close() {
    _logEvent("Close called on browser");
    if (browserTerminationFuture == null) {
      var completer = new Completer();
      browserTerminationFuture = completer.future;

      if (process != null) {
        _processClosedCompleter.future.then((_) {
          process = null;
          completer.complete(true);
          if (_cleanup != null) {
            _cleanup();
          }
        });

        if (process.kill(ProcessSignal.SIGKILL)) {
          _logEvent("Successfully sent kill signal to process.");
        } else {
          _logEvent("Sending kill signal failed.");
        }
      } else {
        _logEvent("The process is already dead.");
        completer.complete(true);
      }
    }
    return browserTerminationFuture;
  }

  /**
   * Start the browser using the supplied argument.
   * This sets up the error handling and usage logging.
   */
  Future<bool> startBrowser(String command, List<String> arguments) {
    return Process.start(command, arguments).then((startedProcess) {
      process = startedProcess;
      Completer stdoutDone = new Completer();
      Completer stderrDone = new Completer();

      process.stdout.transform(new StringDecoder()).listen((data) {
        _addStdout(data);
      }, onError: (error) {
        // This should _never_ happen, but we really want this in the log
        // if it actually does due to dart:io or vm bug.
        _logEvent("An error occured in the process stdout handling: $error");
      }, onDone: () {
        stdoutDone.complete(true);
      });

      process.stderr.transform(new StringDecoder()).listen((data) {
        _addStderr(data);
      }, onError: (error) {
        // This should _never_ happen, but we really want this in the log
        // if it actually does due to dart:io or vm bug.
        _logEvent("An error occured in the process stderr handling: $error");
      },  onDone: () {
        stderrDone.complete(true);
      });

      process.exitCode.then((exitCode) {
        _logEvent("Browser closed with exitcode $exitCode");
        Future.wait([stdoutDone.future, stderrDone.future]).then((_) {
          _processClosedCompleter.complete(exitCode);
        });
      });
      return true;
    }).catchError((error) {
      _logEvent("Running $command $arguments failed with $error");
      return false;
    });
  }

  /**
   * Get any stdout that the browser wrote during execution.
   */
  String get stdout => _stdout.toString();
  String get stderr => _stderr.toString();
  String get usageLog => _usageLog.toString();

  String toString();
  /** Starts the browser loading the given url */
  Future<bool> start(String url);
}

class Safari extends Browser {
  /**
   * The binary used to run safari - changing this can be nececcary for
   * testing or using non standard safari installation.
   */
  const String binary = "/Applications/Safari.app/Contents/MacOS/Safari";

  /**
   * We get the safari version by parsing a version file
   */
  const String versionFile = "/Applications/Safari.app/Contents/version.plist";


  Future<bool> allowPopUps() {
    var command = "defaults";
    var args = ["write", "com.apple.safari",
                "com.apple.Safari.ContentPageGroupIdentifier."
                "WebKit2JavaScriptCanOpenWindowsAutomatically",
                "1"];
    return Process.run(command, args).then((result) {
        if (result.exitCode != 0) {
          _logEvent("Could not disable pop-up blocking for safari");
          return false;
        }
        return true;
    });
  }

  Future<String> getVersion() {
    /**
     * Example of the file:
     * <?xml version="1.0" encoding="UTF-8"?>
     * <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
     * <plist version="1.0">
     * <dict>
     *	     <key>BuildVersion</key>
     * 	     <string>2</string>
     * 	     <key>CFBundleShortVersionString</key>
     * 	     <string>6.0.4</string>
     * 	     <key>CFBundleVersion</key>
     * 	     <string>8536.29.13</string>
     * 	     <key>ProjectName</key>
     * 	     <string>WebBrowser</string>
     * 	     <key>SourceVersion</key>
     * 	     <string>7536029013000000</string>
     * </dict>
     * </plist>
     */
    File f = new File(versionFile);
    return f.readAsLines().then((content) {
      bool versionOnNextLine = false;
      for (var line in content) {
        if (versionOnNextLine) return line;
        if (line.contains("CFBundleShortVersionString")) {
          versionOnNextLine = true;
        }
      }
      return null;
    });
  }

  void _createLaunchHTML(var path, var url) {
    var file = new File("${path}/launch.html");
    var randomFile = file.openSync(FileMode.WRITE);
    var content = '<script language="JavaScript">location = "$url"</script>';
    randomFile.writeStringSync(content);
    randomFile.close();
  }

  Future<bool> start(String url) {
    _logEvent("Starting Safari browser on: $url");
    // Get the version and log that.
    return allowPopUps().then((success) {
      if (!success) {
        return new Future.immediate(false);
      }
      return getVersion().then((version) {
        _logEvent("Got version: $version");
        var args = ["'$url'"];
        return new Directory('').createTemp().then((userDir) {
          _cleanup = () { userDir.deleteSync(recursive: true); };
          _createLaunchHTML(userDir.path, url);
          var args = ["${userDir.path}/launch.html"];
          return startBrowser(binary, args);
        });
      }).catchError((e) {
        _logEvent("Running $binary --version failed with $e");
        return false;
      });
    });
  }

  String toString() => "Safari";
}


class Chrome extends Browser {
  /**
   * The binary used to run chrome - changing this can be nececcary for
   * testing or using non standard chrome installation.
   */
  const String binary = "google-chrome";

  Future<bool> start(String url) {
    _logEvent("Starting chrome browser on: $url");
    // Get the version and log that.
    return Process.run(binary, ["--version"]).then((var versionResult) {
      if (versionResult.exitCode != 0) {
        _logEvent("Failed to chrome get version");
        _logEvent("Make sure $binary is a valid program for running chrome");
        return new Future.immediate(false);
      }
      version = versionResult.stdout;
      _logEvent("Got version: $version");

      return new Directory('').createTemp().then((userDir) {
        _cleanup = () { userDir.deleteSync(recursive: true); };
        var args = ["--user-data-dir=${userDir.path}", url,
                    "--disable-extensions", "--disable-popup-blocking",
                    "--bwsi", "--no-first-run"];
        return startBrowser(binary, args);

      });
    }).catchError((e) {
      _logEvent("Running $binary --version failed with $e");
      return false;
    });
  }

  String toString() => "Chrome";
}

class AndroidChrome extends Browser {
  const String viewAction = 'android.intent.action.VIEW';
  const String mainAction = 'android.intent.action.MAIN';
  const String chromePackage = 'com.android.chrome';
  const String browserPackage = 'com.android.browser';
  const String firefoxPackage = 'org.mozilla.firefox';
  const String turnScreenOnPackage = 'com.google.dart.turnscreenon';

  AndroidEmulator _emulator;
  AdbDevice _adbDevice;

  AndroidChrome(this._adbDevice);

  Future<bool> start(String url) {
    var browserIntent = new Intent(
        viewAction, browserPackage, '.BrowserActivity', url);
    var chromeIntent = new Intent(viewAction, chromePackage, '.Main', url);
    var firefoxIntent = new Intent(viewAction, firefoxPackage, '.App', url);
    var turnScreenOnIntent =
        new Intent(mainAction, turnScreenOnPackage, '.Main');

    var testing_resources_dir =
        new Path('third_party/android_testing_resources');
    if (!new Directory.fromPath(testing_resources_dir).existsSync()) {
      DebugLogger.error("$testing_resources_dir doesn't exist. Exiting now.");
      exit(1);
    }

    var chromeAPK = testing_resources_dir.append('com.android.chrome-1.apk');
    var turnScreenOnAPK = testing_resources_dir.append('TurnScreenOn.apk');
    var chromeConfDir = testing_resources_dir.append('chrome_configuration');
    var chromeConfDirRemote = new Path('/data/user/0/com.android.chrome/');

    return _adbDevice.waitForBootCompleted().then((_) {
      return _adbDevice.forceStop(chromeIntent.package);
    }).then((_) {
      return _adbDevice.killAll();
    }).then((_) {
      return _adbDevice.adbRoot();
    }).then((_) {
      return _adbDevice.installApk(turnScreenOnAPK);
    }).then((_) {
      return _adbDevice.installApk(chromeAPK);
    }).then((_) {
      return _adbDevice.pushData(chromeConfDir, chromeConfDirRemote);
    }).then((_) {
      return _adbDevice.chmod('777', chromeConfDirRemote);
    }).then((_) {
      return _adbDevice.startActivity(turnScreenOnIntent).then((_) => true);
    }).then((_) {
      return _adbDevice.startActivity(chromeIntent).then((_) => true);
    });
  }

  Future<bool> close() {
    if (_adbDevice != null) {
      return _adbDevice.forceStop(chromePackage).then((_) {
        return _adbDevice.killAll().then((_) => true);
      });
    }
    return new Future.immediate(true);
  }

  String toString() => "chromeOnAndroid";
}

class Firefox extends Browser {
  /**
   * The binary used to run firefox - changing this can be nececcary for
   * testing or using non standard firefox installation.
   */
  const String binary = "firefox";

  const String enablePopUp =
      'user_pref("dom.disable_open_during_load", false);';
  const String disableDefaultCheck =
      'user_pref("browser.shell.checkDefaultBrowser", false);';

  Future _createPreferenceFile(var path) {
    var file = new File("${path.toString()}/user.js");
    var randomFile = file.openSync(FileMode.WRITE);
    randomFile.writeStringSync(enablePopUp);
    randomFile.writeStringSync(disableDefaultCheck);
    randomFile.close();
  }


  Future<bool> start(String url) {
    _logEvent("Starting firefox browser on: $url");
    // Get the version and log that.
    return Process.run(binary, ["--version"]).then((var versionResult) {
      if (versionResult.exitCode != 0) {
        _logEvent("Failed to firefox get version");
        _logEvent("Make sure $binary is a valid program for running firefox");
        return new Future.immediate(false);
      }
      version = versionResult.stdout;
      _logEvent("Got version: $version");

      return new Directory('').createTemp().then((userDir) {
        _createPreferenceFile(userDir.path);
        _cleanup = () { userDir.deleteSync(recursive: true); };
        var args = ["-profile", "${userDir.path}",
                    "-no-remote", "-new-instance", url];
        return startBrowser(binary, args);

      });
    }).catchError((e) {
      _logEvent("Running $binary --version failed with $e");
      return false;
    });
  }

  String toString() => "Firefox";
}


/**
 * Describes the current state of a browser used for testing.
 */
class BrowserTestingStatus {
// TODO(ricow): Add prefetching to the browsers. We spend a lot of time waiting
// for the next test. Handling timeouts is the hard part of this!

  Browser browser;
  BrowserTest currentTest;
  // This is currently not used for anything except for error reporting.
  // Given the usefulness of this in debugging issues this should not be
  // removed even when we have really stable system.
  BrowserTest lastTest;
  bool timeout = false;
  BrowserTestingStatus(Browser this.browser);
}


/**
 * Describes a single test to be run int the browser.
 */
class BrowserTest {
  // TODO(ricow): Add timeout callback instead of the string passing hack.
  Function doneCallback;
  String url;
  int timeout;
  Stopwatch stopwatch;
  // We store this here for easy access when tests time out (instead of
  // capturing this in a closure)
  Timer timeoutTimer;

  // Used for debugging, this is simply a unique identifier assigned to each
  // test.
  int id;
  static int _idCounter = 0;

  BrowserTest(this.url, this.doneCallback, this.timeout) {
    id = _idCounter++;
  }
}


/**
 * Encapsulates all the functionality for running tests in browsers.
 * The interface is rather simple. After starting the runner tests
 * are simply added to the queue and a the supplied callbacks are called
 * whenever a test completes.
 */
class BrowserTestRunner {
  String local_ip;
  String browserName;
  int maxNumBrowsers;
  // Used to send back logs from the browser (start, stop etc)
  Function logger;
  int browserIdCount = 0;

  bool underTermination = false;

  List<BrowserTest> testQueue = new List<BrowserTest>();
  Map<String, BrowserTestingStatus> browserStatus =
      new Map<String, BrowserTestingStatus>();

  var adbDeviceMapping = new Map<String, AdbDevice>();
  // This cache is used to guarantee that we never see double reporting.
  // If we do we need to provide developers with this information.
  // We don't add urls to the cache until we have run it.
  Map<int, String> testCache = new Map<int, String>();
  List<int> doubleReportingTests = new List<int>();

  BrowserTestingServer testingServer;

  BrowserTestRunner(this.local_ip, this.browserName, this.maxNumBrowsers);

  Future<bool> start() {
    // If [browserName] doesn't support opening new windows, we use new iframes
    // instead.
    bool useIframe =
        !Browser.BROWSERS_WITH_WINDOW_SUPPORT.contains(browserName);
    testingServer = new BrowserTestingServer(local_ip, useIframe);
    return testingServer.start().then((_) {
      testingServer.testDoneCallBack = handleResults;
      testingServer.nextTestCallBack = getNextTest;
      return getBrowsers().then((browsers) {
        var futures = [];
        for (var browser in browsers) {
          var url = testingServer.getDriverUrl(browser.id);
          var future = browser.start(url).then((success) {
            if (success) {
              browserStatus[browser.id] = new BrowserTestingStatus(browser);
            }
            return success;
          });
          futures.add(future);
        }
        return Future.wait(futures).then((values) {
          return !values.contains(false);
        });
      });
    });
  }

  Future<List<Browser>> getBrowsers() {
    // TODO(kustermann): This is a hackisch way to accomplish it and should
    // be encapsulated
    var browsersCompleter = new Completer();
    if (browserName == 'chromeOnAndroid') {
      AdbHelper.listDevices().then((deviceIds) {
        if (deviceIds.length > 0) {
          var browsers = [];
          for (int i = 0; i < deviceIds.length; i++) {
            var id = "BROWSER$i";
            var device = new AdbDevice(deviceIds[i]);
            adbDeviceMapping[id] = device;
            var browser = new AndroidChrome(device);
            browsers.add(browser);
            // We store this in case we need to kill the browser.
            browser.id = id;
          }
          browsersCompleter.complete(browsers);
        } else {
          throw new StateError("No android devices found.");
        }
      });
    } else {
      var browsers = [];
      for (int i = 0; i < maxNumBrowsers; i++) {
        var id = "BROWSER$browserIdCount";
        browserIdCount++;
        var browser = getInstance();
        browsers.add(browser);
        // We store this in case we need to kill the browser.
        browser.id = id;
      }
      browsersCompleter.complete(browsers);
    }
    return browsersCompleter.future;
  }

  var timedOut = [];

  void handleResults(String browserId, String output, int testId) {
    var status = browserStatus[browserId];
    DebugLogger.info("Handling result for browser ${browserId}");
    if (testCache.containsKey(testId)) {
      doubleReportingTests.add(testId);
      return;
    }

    if (status.timeout) {
      // We don't do anything, this browser is currently being killed and
      // replaced.
    } else if (status.currentTest != null) {
      status.currentTest.timeoutTimer.cancel();
      status.currentTest.stopwatch.stop();

      if (status.currentTest.id != testId) {
        print("Expected test id ${status.currentTest.id} for"
              "${status.currentTest.url}");
        print("Got test id ${testId}");
        print("Last test id was ${status.lastTest.id} for "
              "${status.currentTest.url}");
        throw("This should never happen, wrong test id");
      }
      testCache[testId] = status.currentTest.url;
      DebugLogger.info("Size of output for test $testId : ${output.length}");
      Stopwatch watch = new Stopwatch()..start();
      status.currentTest.doneCallback(output,
                                      status.currentTest.stopwatch.elapsed);
      watch.stop();
      DebugLogger.info("Handling of test $testId took : ${watch.elapsed}");
      status.lastTest = status.currentTest;
      status.currentTest = null;
    } else {
      print("\nThis is bad, should never happen, handleResult no test");
      print("URL: ${status.lastTest.url}");
      print(output);
      terminate().then((_) {
        exit(1);
      });
    }
  }

  void handleTimeout(BrowserTestingStatus status) {
    // We simply kill the browser and starts up a new one!
    // We could be smarter here, but it does not seems like it is worth it.
    DebugLogger.info("Handling timeout for browser ${status.browser.id}");
    status.timeout = true;
    timedOut.add(status.currentTest.url);
    var id = status.browser.id;
    status.browser.close().then((closed) {
      if (!closed) {
        // Very bad, we could not kill the browser.
        print("could not kill browser $id");
        return;
      }
      // We don't want to start a new browser if we are terminating.
      if (underTermination) return;
      var browser;
      var new_id = id;
      if (browserName == 'chromeOnAndroid') {
        browser = new AndroidChrome(adbDeviceMapping[id]);
      } else {
        browserStatus.remove(id);
        browser = getInstance();
        new_id = "BROWSER$browserIdCount";
        browserIdCount++;
        browserStatus[new_id] = new BrowserTestingStatus(browser);
      }
      browser.id = new_id;
      browser.start(testingServer.getDriverUrl(new_id)).then((success) {
        // We may have started terminating in the mean time.
        if (underTermination) {
          browser.close().then((success) {
            // We should never hit this, print it out.
            if (!success) {
              print("Could not kill browser ($id) started due to timeout");
            }
          });
          return;
        }
        if (success) {
          browserStatus[browser.id] = new BrowserTestingStatus(browser);
        } else {
          // TODO(ricow): Handle this better.
          print("This is bad, should never happen, could not start browser");
          exit(1);
        }
      });
    });
    status.currentTest.stopwatch.stop();
    status.currentTest.doneCallback("TIMEOUT",
                                    status.currentTest.stopwatch.elapsed);
    status.currentTest = null;
  }

  BrowserTest getNextTest(String browserId) {
    if (testQueue.isEmpty) return null;
    var status = browserStatus[browserId];
    if (status == null) return null;
    DebugLogger.info("Handling getNext for browser "
                     "${browserId} timeout status: ${status.timeout}");

    // We are currently terminating this browser, don't start a new test.
    if (status.timeout) return null;
    BrowserTest test = testQueue.removeLast();
    if (status.currentTest == null) {
      status.currentTest = test;
    } else {
      // TODO(ricow): Handle this better.
      print("This is bad, should never happen, getNextTest all full");
      print("This happened for browser $browserId");
      print("Old test was: ${status.currentTest.url}");
      print("Timed out tests:");
      for (var v in timedOut) {
        print("  $v");
      }
      exit(1);
    }
    Timer timer = new Timer(new Duration(seconds: test.timeout),
                            () { handleTimeout(status); });
    status.currentTest.timeoutTimer = timer;
    status.currentTest.stopwatch = new Stopwatch()..start();
    return test;
  }

  void queueTest(BrowserTest test) {
    testQueue.add(test);
  }

  void printDoubleReportingTests() {
    if (doubleReportingTests.length == 0) return;
    // TODO(ricow): die on double reporting.
    // Currently we just report this here, we could have a callback to the
    // encapsulating environment.
    print("");
    print("Double reporting tests");
    for (var id in doubleReportingTests) {
      print("  ${testCache[id]}");
    }
  }

  Future<bool> terminate() {
    var futures = [];
    underTermination = true;
    testingServer.underTermination = true;
    for (BrowserTestingStatus status in browserStatus.values) {
      futures.add(status.browser.close());
    }
    return Future.wait(futures).then((values) {
      testingServer.httpServer.close();
      testingServer.errorReportingServer.close();
      printDoubleReportingTests();
      return !values.contains(false);
    });
  }

  Browser getInstance() {
    var browser = new Browser.byName(browserName);
    browser.logger = logger;
    return browser;
  }
}

class BrowserTestingServer {
  /// Interface of the testing server:
  ///
  /// GET /driver/BROWSER_ID -- This will get the driver page to fetch
  ///                           and run tests ...
  /// GET /next_test/BROWSER_ID -- returns "WAIT" "TERMINATE" or "url#id"
  /// where url is the test to run, and id is the id of the test.
  /// If there are currently no available tests the waitSignal is send
  /// back. If we are in the process of terminating the terminateSignal
  /// is send back and the browser will stop requesting new tasks.
  /// POST /report/BROWSER_ID?id=NUM -- sends back the dom of the executed
  ///                                   test

  final String local_ip;

  const String driverPath = "/driver";
  const String nextTestPath = "/next_test";
  const String reportPath = "/report";
  const String waitSignal = "WAIT";
  const String terminateSignal = "TERMINATE";

  var testCount = 0;
  var httpServer;
  var errorReportingServer;
  bool underTermination = false;
  bool useIframe = false;

  Function testDoneCallBack;
  Function nextTestCallBack;

  BrowserTestingServer(this.local_ip, this.useIframe);

  Future start() {
    return HttpServer.bind(local_ip, 0).then((createdServer) {
      httpServer = createdServer;
      void handler(HttpRequest request) {
        DebugLogger.info("Handling request to: ${request.uri.path}");
        if (request.uri.path.startsWith(reportPath)) {
          var browserId = request.uri.path.substring(reportPath.length + 1);
          var testId = int.parse(request.queryParameters["id"].split("=")[1]);

          handleReport(request, browserId, testId);
          // handleReport will asynchroniously fetch the data and will handle
          // the closing of the streams.
          return;
        }
        var textResponse = "";
        if (request.uri.path.startsWith(driverPath)) {
          var browserId = request.uri.path.substring(driverPath.length + 1);
          textResponse = getDriverPage(browserId);
        } else if (request.uri.path.startsWith(nextTestPath)) {
          var browserId = request.uri.path.substring(nextTestPath.length + 1);
          textResponse = getNextTest(browserId);
        } else {
          DebugLogger.info("Handling non standard request to: "
                           "${request.uri.path}");
        }
        request.response.write(textResponse);
        request.listen((_) {}, onDone: request.response.close);
        request.response.done.then((_) {
          DebugLogger.info("Done handling request to: ${request.uri.path}");
        }).catchError((error) {
          if (!underTermination) {
            print("URI ${request.uri}");
            print("Textresponse $textResponse");
            throw "Error returning content to browser: $error";
          }
      });
      }
      void errorHandler(e) {
        if (!underTermination) print("Error occured in httpserver: $e");
      };

      httpServer.listen(handler, onError: errorHandler);

      // Set up the error reporting server that enables us to send back
      // errors from the browser.
      return HttpServer.bind(local_ip, 0).then((createdReportServer) {
        errorReportingServer = createdReportServer;
        void errorReportingHandler(HttpRequest request) {
          StringBuffer buffer = new StringBuffer();
          request.transform(new StringDecoder()).listen((data) {
            buffer.write(data);
          }, onDone: () {
              String back = buffer.toString();
              request.response.headers.set("Access-Control-Allow-Origin", "*");

              request.response.done.catchError((error) {
                DebugLogger.error("Error getting error from browser"
                                  "on uri ${request.uri.path}: $error");
              });
              request.response.close();
              DebugLogger.error("Error from browser on : "
                               "${request.uri.path}, data:  $back");
          }, onError: (error) { print(error); });
        }
        errorReportingServer.listen(errorReportingHandler,
                                    onError: errorHandler);
        return true;
      });
    });
  }

  void handleReport(HttpRequest request, String browserId, var testId) {
    StringBuffer buffer = new StringBuffer();
    request.transform(new StringDecoder()).listen((data) {
      buffer.write(data);
      }, onDone: () {
        String back = buffer.toString();
        request.response.close();
        testDoneCallBack(browserId, back, testId);
        DebugLogger.info("Done handling request to: ${request.uri.path}");
      }, onError: (error) { print(error); });
  }

  String getNextTest(String browserId) {
    var nextTest = nextTestCallBack(browserId);
    if (underTermination) {
      // Browsers will be killed shortly, send them a terminate signal so
      // that they stop pulling.
      return terminateSignal;
    } else if (nextTest == null) {
      // We don't currently have any tests ready for consumption, wait.
      return waitSignal;
    } else {
      return "${nextTest.url}#id=${nextTest.id}";
    }
  }

  String getDriverUrl(String browserId) {
    if (httpServer == null) {
      print("Bad browser testing server, you are not started yet. Can't "
            "produce driver url");
      exit(1);
      // This should never happen - exit immediately;
    }
    return "http://$local_ip:${httpServer.port}/driver/$browserId";
  }


  String getDriverPage(String browserId) {
    var errorReportingUrl =
        "http://$local_ip:${errorReportingServer.port}/$browserId";
    String driverContent = """
<!DOCTYPE html><html>
<head>
  <title>Driving page</title>
  <script type='text/javascript'>

    function startTesting() {
      var number_of_tests = 0;
      var current_id;
      var last_reported_id;
      var testing_window;
      // We use this to determine if we did actually get back a start event
      // from the test we just loaded.
      var did_start = false;

      var embedded_iframe = document.getElementById('embedded_iframe');
      var use_iframe = ${useIframe};
      var start = new Date();

      function newTaskHandler() {
        if (this.readyState == this.DONE) {
          if (this.status == 200) {
            if (this.responseText == '$waitSignal') {
              setTimeout(getNextTask, 500);
            } else if (this.responseText == '$terminateSignal') {
              // Don't do anything, we will be killed shortly.
            } else {
              var elapsed = new Date() - start;
              reportError('Done getting task at: ' + elapsed);
              // TODO(ricow): Do something more clever here.
              if (nextTask != undefined) alert('This is really bad');
              // The task is send to us as:
              // URL#ID
              var split = this.responseText.split('#');
              var nextTask = split[0];
              current_id = split[1];
              did_start = false;
              run(nextTask);
            }
          } else {
            reportError('Could not contact the server and get a new task');
          }
        }
      }

      function getNextTask() {
        var elapsed = new Date() - start;
        reportError('Getting task at: ' + elapsed);
        var client = new XMLHttpRequest();
        client.onreadystatechange = newTaskHandler;
        client.open('GET', '$nextTestPath/$browserId');
        client.send();
      }

      function run(url) {
        number_of_tests++;
        document.getElementById('number').innerHTML = number_of_tests;
        if (use_iframe) {
          embedded_iframe.src = url;
        } else {
          if (testing_window == undefined) {
            testing_window = window.open(url);
          } else {
            testing_window.location = url;
          }
        }
      }

      window.onerror = function (message, url, lineNumber) {
        if (url) {
          reportError(url + ':' + lineNumber + ':' + message);
        } else {
          reportError(message);
        }
      }

      function reportError(msg) {
        var client = new XMLHttpRequest();
        function handleReady() {
          if (this.readyState == this.DONE && this.status != 200) {
            // We could not report, pop up to notify if running interactively.
            alert(this.status);
          }
        }
        client.onreadystatechange = handleReady;
        client.open('POST', '$errorReportingUrl?test=1');
        client.setRequestHeader('Content-type',
                                'application/x-www-form-urlencoded');
        client.send(msg);
      }

      function reportMessage(msg) {
        if (msg == 'STARTING') {
          did_start = true;
          return;
        }
        var client = new XMLHttpRequest();
        function handleReady() {
          if (this.readyState == this.DONE) {
            if (this.status == 200) {
              if (last_reported_id != current_id && did_start) {
                var elapsed = new Date() - start;
                reportError('Done sending results at: ' + elapsed);
                getNextTask();
                last_reported_id = current_id;
              }
            } else {
              reportError('Error sending result to server');
            }
          }
        }
        client.onreadystatechange = handleReady;
        // If did_start is false it means that we did actually set the url on
        // the testing_window, but this is a report left in the event loop or
        // a callback because the page did not load yet.
        // In both cases this is a double report from the last test.
        var posting_id = did_start ? current_id : last_reported_id;
        client.open('POST', '$reportPath/${browserId}?id=' + posting_id);
        client.setRequestHeader('Content-type',
                                'application/x-www-form-urlencoded');
        client.send(msg);
        var elapsed = new Date() - start;
        reportError('Sending results at: ' + elapsed);
      }

      function messageHandler(e) {
        var msg = e.data;
        if (typeof msg != 'string') return;
        reportMessage(msg);
      }

      window.addEventListener('message', messageHandler, false);
      waitForDone = false;

      getNextTask();
    }

  </script>
</head>
  <body onload="startTesting()">
    Dart test driver, number of tests: <div id="number"></div>
    <iframe id="embedded_iframe"></iframe>
  </body>
</html>
""";
    return driverContent;
  }
}
