// 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 is called after the process is closed, before the done future
  // is completed.
  // 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 returns when the process exits. It is also the return value
  // of close()
  Future done;

  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 (process != null) {
      if (process.kill(ProcessSignal.SIGKILL)) {
        _logEvent("Successfully sent kill signal to process.");
      } else {
        _logEvent("Sending kill signal failed.");
      }
      return done;
    } else {
      _logEvent("The process is already dead.");
      return new Future.immediate(true);
    }
  }

  /**
   * 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;
      // Used to notify when exiting, and as a return value on calls to
      // close().
      var doneCompleter = new Completer();
      done = doneCompleter.future;

      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((_) {
          process = null;
          if (_cleanup != null) {
            _cleanup();
          }
          doneCompleter.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";

  /**
   * Directories where safari stores state. We delete these if the deleteCache
   * is set
   */
  static const List<String> CACHE_DIRECTORIES =
      const ["Library/Caches/com.apple.Safari",
             "Library/Safari",
             "Library/Saved Application State/com.apple.Safari.savedState",
             "Library/Caches/Metadata/Safari"];


  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<bool> deleteIfExists(Iterator<String> paths) {
    if (!paths.moveNext()) return new Future.immediate(true);
    Directory directory = new Directory(paths.current);
    return directory.exists().then((exists) {
      if (exists) {
        _logEvent("Deleting ${paths.current}");
        return directory.delete(recursive: true)
	    .then((_) => deleteIfExists(paths))
	    .catchError((error) {
	      _logEvent("Failure trying to delete ${paths.current}: $error");
	      return false;
	    });
      } else {
        _logEvent("${paths.current} is not present");
        return deleteIfExists(paths);
      }
    });
  }

  // Clears the cache if the static deleteCache flag is set.
  // Returns false if the command to actually clear the cache did not complete.
  Future<bool> clearCache() {
    if (!deleteCache) return new Future.immediate(true);
    var home = Platform.environment['HOME'];
    Iterator iterator = CACHE_DIRECTORIES.map((s) => "$home/$s").iterator;
    return deleteIfExists(iterator);
  }

  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");
    return allowPopUps().then((success) {
      if (!success) {
        return false;
      }
      return clearCache().then((cleared) {
        if (!cleared) {
          _logEvent("Could not clear cache");
          return false;
        }
        // Get the version and log that.
        return getVersion().then((version) {
          _logEvent("Got version: $version");
          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((error) {
          _logEvent("Running $binary --version failed with $error");
          return false;
        });
      });
    });
  }

  String toString() => "Safari";

  // Delete the user specific browser cache and profile data.
  // Safari only have one per user, and you can't specify one by command line.
  static bool deleteCache = false;

}


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((_) {
      // 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;
  }
}
