add_task(function* () {
  let browser = yield addTab(MAIN_DOMAIN + "doc_innerHTML.html");
  let doc = browser.contentDocument;

  initDebuggerServer();
  let client = new DebuggerClient(DebuggerServer.connectPipe());
  let form = yield connectDebuggerClient(client);
  let front = TimelineFront(client, form);
  let rec = yield front.start({ withMarkers: true });

  front.once("doc-loading", e => {
    ok(false, "Should not be emitting doc-loading events.");
  });

  executeSoon(() => doc.location.reload());

  yield waitForMarkerType(front, MARKER_NAMES, () => true, e => e, "markers");
  yield front.stop(rec);

  ok(true, "Found the required marker names.");

  // Wait some more time to make sure the 'doc-loading' events never get fired.
  yield DevToolsUtils.waitForTime(1000);

  yield closeDebuggerClient(client);
  gBrowser.removeCurrentTab();
});
add_task(function* () {
  let browser = yield addTab(MAIN_DOMAIN + "timeline-iframe-parent.html");
  let doc = browser.contentDocument;

  initDebuggerServer();
  let client = new DebuggerClient(DebuggerServer.connectPipe());
  let form = yield connectDebuggerClient(client);
  let front = TimelineFront(client, form);

  info("Start timeline marker recording");
  yield front.start({ withMarkers: true });

  // Check that we get markers for a few iterations of the timer that runs in
  // the child frame.
  for (let i = 0; i < 3; i++) {
    yield wait(300); // That's the time the child frame waits before changing styles.
    let markers = yield once(front, "markers");
    ok(markers.length, "Markers were received for operations in the child frame");
  }

  info("Stop timeline marker recording");
  yield front.stop();
  yield closeDebuggerClient(client);
  gBrowser.removeCurrentTab();
});
add_task(function* () {
  let browser = yield addTab(MAIN_DOMAIN + "doc_innerHTML.html");
  let doc = browser.contentDocument;

  initDebuggerServer();
  let client = new DebuggerClient(DebuggerServer.connectPipe());
  let form = yield connectDebuggerClient(client);
  let front = TimelineFront(client, form);
  let rec = yield front.start({ withMarkers: true, withDocLoadingEvents: true });

  yield new Promise(resolve => {
    front.once("doc-loading", resolve);
    doc.location.reload();
  });

  ok(true, "At least one doc-loading event got fired.");

  yield waitForMarkerType(front, MARKER_NAMES, () => true, e => e, "markers");
  yield front.stop(rec);

  ok(true, "Found the required marker names.");

  yield client.close();
  gBrowser.removeCurrentTab();
});
add_task(function* () {
  let browser = yield addTab(MAIN_DOMAIN + "doc_innerHTML.html");
  let doc = browser.contentDocument;

  initDebuggerServer();
  let client = new DebuggerClient(DebuggerServer.connectPipe());
  let form = yield connectDebuggerClient(client);
  let front = TimelineFront(client, form);
  let rec = yield front.start({ withDocLoadingEvents: true });

  waitForMarkerType(front, MARKER_NAMES, () => true, e => e, "markers").then(e => {
    ok(false, "Should not be emitting doc-loading markers.");
  });

  yield new Promise(resolve => {
    front.once("doc-loading", resolve);
    doc.location.reload();
  });

  ok(true, "At least one doc-loading event got fired.");

  yield front.stop(rec);

  // Wait some more time to make sure the 'doc-loading' markers never get fired.
  yield DevToolsUtils.waitForTime(1000);

  yield client.close();
  gBrowser.removeCurrentTab();
});
add_task(async function() {
  const browser = await addTab(MAIN_DOMAIN + "doc_innerHTML.html");

  initDebuggerServer();
  const client = new DebuggerClient(DebuggerServer.connectPipe());
  const form = await connectDebuggerClient(client);
  const front = TimelineFront(client, form);
  const rec = await front.start({ withMarkers: true });

  front.once("doc-loading", e => {
    ok(false, "Should not be emitting doc-loading events.");
  });

  ContentTask.spawn(browser, null, function() {
    content.location.reload();
  });

  await waitForMarkerType(front, MARKER_NAMES, () => true, e => e, "markers");
  await front.stop(rec);

  ok(true, "Found the required marker names.");

  // Wait some more time to make sure the 'doc-loading' events never get fired.
  await DevToolsUtils.waitForTime(1000);

  await client.close();
  gBrowser.removeCurrentTab();
});
add_task(function* () {
  yield addTab("data:text/html;charset=utf-8,mop");

  initDebuggerServer();
  let client = new DebuggerClient(DebuggerServer.connectPipe());
  let form = yield connectDebuggerClient(client);
  let front = TimelineFront(client, form);

  ok(front, "The TimelineFront was created");

  let isActive = yield front.isRecording();
  ok(!isActive, "The TimelineFront is not initially recording");

  info("Flush any pending reflows");
  ContentTask.spawn(gBrowser.selectedBrowser, {}, () => {
    // forceSyncReflow
    content.document.body.innerHeight;
  });

  info("Start recording");
  yield front.start({ withMarkers: true });

  isActive = yield front.isRecording();
  ok(isActive, "The TimelineFront is now recording");

  info("Change some style on the page to cause style/reflow/paint");
  let onMarkers = once(front, "markers");
  ContentTask.spawn(gBrowser.selectedBrowser, {}, () => {
    content.document.body.style.padding = "10px";
  });
  let markers = yield onMarkers;

  ok(true, "The markers event was fired");
  ok(markers.length > 0, "Markers were returned");

  info("Flush pending reflows again");
  ContentTask.spawn(gBrowser.selectedBrowser, {}, () => {
    // forceSyncReflow
    content.document.body.innerHeight;
  });

  info("Change some style on the page to cause style/paint");
  onMarkers = once(front, "markers");
  ContentTask.spawn(gBrowser.selectedBrowser, {}, () => {
    content.document.body.style.backgroundColor = "red";
  });
  markers = yield onMarkers;

  ok(markers.length > 0, "markers were returned");

  yield front.stop();

  isActive = yield front.isRecording();
  ok(!isActive, "Not recording after stop()");

  yield client.close();
  gBrowser.removeCurrentTab();
});
add_task(function* () {
  let browser = yield addTab("data:text/html;charset=utf-8,mop");
  let doc = browser.contentDocument;

  initDebuggerServer();
  let client = new DebuggerClient(DebuggerServer.connectPipe());
  let form = yield connectDebuggerClient(client);
  let front = TimelineFront(client, form);

  info("Start timeline marker recording");
  yield front.start({ withMemory: true, withTicks: true });

  let updatedMemory = 0;
  let updatedTicks = 0;

  front.on("memory", (delta, measurement) => {
    ok(delta > 0, "The delta should be a timestamp.");
    ok(measurement, "The measurement should not be null.");
    ok(measurement.total > 0, "There should be a 'total' value in the measurement.");
    info("Received 'memory' event at " + delta + " with " + measurement.toSource());
    updatedMemory++;
  });

  front.on("ticks", (delta, ticks) => {
    ok(delta > 0, "The delta should be a timestamp.");
    ok(ticks, "The ticks should not be null.");
    info("Received 'ticks' event with " + ticks.toSource());
    updatedTicks++;
  });

  ok((yield waitUntil(() => updatedMemory > 1)),
    "Some memory measurements were emitted.");
  ok((yield waitUntil(() => updatedTicks > 1)),
    "Some refresh driver ticks were emitted.");

  info("Stop timeline marker recording");
  yield front.stop();
  yield closeDebuggerClient(client);
  gBrowser.removeCurrentTab();
});