chromium/chrome/test/data/devtools/target_list/background.js

// Copyright 2013 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

var REMOTE_DEBUGGER_HOST = 'localhost:9222';

function requestUrl(path, callback, opt_method) {
  var req = new XMLHttpRequest();
  req.open(opt_method || 'GET', 'http://' + REMOTE_DEBUGGER_HOST + path, true);
  req.onload = function() {
    if (req.status == 200)
      callback(req.responseText);
    else
      req.onerror();
  };
  req.onerror = function() {
    chrome.test.fail('XHR failed: ' + req.status);
  };
  req.send(null);
}


function checkTarget(targets, url, type, opt_title, opt_faviconUrl) {
  var target =
      targets.filter(function(t) { return t.url == url }) [0];
  if (!target)
    chrome.test.fail('Cannot find a target with url ' + url);

  var wsAddress = REMOTE_DEBUGGER_HOST + '/devtools/page/' + target.id;

  chrome.test.assertEq(
      '/devtools/inspector.html?ws=' + wsAddress,
      target.devtoolsFrontendUrl);
  // On some platforms (e.g. Chrome OS) target.faviconUrl might be empty for
  // a freshly created tab. Ignore the check then.
  if (target.faviconUrl && opt_faviconUrl)
    chrome.test.assertEq(opt_faviconUrl, target.faviconUrl);
  chrome.test.assertEq(opt_title || target.url, target.title);
  chrome.test.assertEq(type, target.type);
  chrome.test.assertEq('ws://' + wsAddress, target.webSocketDebuggerUrl);

  return target;
}

function waitForTab(filter, callback) {
  var fired = false;
  function onUpdated(updatedTabId, changeInfo, updatedTab) {
    if (!filter(updatedTab) && !fired)
      return;

    chrome.tabs.onUpdated.removeListener(onUpdated);
    if (!fired) {
      fired = true;
      callback(updatedTab);
    }
  }

  chrome.tabs.onUpdated.addListener(onUpdated);

  chrome.tabs.query({}, function(tabs) {
    if (!fired) {
      for (var i = 0; i < tabs.length; ++i)
        if (filter(tabs[i])) {
          fired = true;
          callback(tabs[i]);
        }
    }
  });
}

function listenOnce(event, func) {
  var listener = function() {
    event.removeListener(listener);
    func.apply(null, arguments)
  };
  event.addListener(listener);
}

function runNewPageTest(devtoolsUrl, expectedUrl) {
  var json;
  var newTab;
  var pendingCount = 2;

  function checkResult() {
    if (--pendingCount)
      return;
    chrome.test.assertEq(newTab.url, expectedUrl);
    chrome.test.assertEq(json.url, expectedUrl);
    chrome.test.assertTrue(newTab.active);
    chrome.test.succeed();
  }

  function onCreated(createdTab) {
    waitForTab(
      function(tab) {
        return tab.id == createdTab.id &&
               tab.active &&
               tab.status == "complete";
      },
      function(tab) {
        newTab = tab;
        checkResult();
      });
  }

  listenOnce(chrome.tabs.onCreated, onCreated);

  requestUrl(devtoolsUrl,
      function(text) {
        json = JSON.parse(text);
        checkResult();
      }, 'PUT');
}

var extensionTargetId;
var extensionTabId;
var extensionDevtoolsFrontendUrl;
var extensionWebSocketDebuggerUrl;

chrome.test.runTests([
  function discoverTargets() {
    var testPageUrl = chrome.extension.getURL('test_page.html');

    chrome.tabs.create({url: testPageUrl});
    waitForTab(
        function(tab) {
          return tab.url == testPageUrl && tab.status == "complete";
        },
        function() {
          requestUrl('/json', function(text) {
            var targets = JSON.parse(text);
            checkTarget(targets, 'about:blank', 'page');
            checkTarget(targets,
                chrome.extension.getURL('_generated_background_page.html'),
                'background_page',
                'Remote Debugger Test');
            var target = checkTarget(targets,
                testPageUrl, 'page', 'Test page',
                chrome.extension.getURL('favicon.png'));

            extensionTargetId = target.id;
            extensionDevtoolsFrontendUrl = target.devtoolsFrontendUrl;
            extensionWebSocketDebuggerUrl = target.webSocketDebuggerUrl;

            chrome.test.succeed();
          });
        });
  },

  function versionInfo() {
    requestUrl('/json/version',
        function(text) {
          var versionInfo = JSON.parse(text);
          chrome.test.assertTrue(/^Chrome\//.test(versionInfo["Browser"]));
          chrome.test.assertTrue("Protocol-Version" in versionInfo);
          chrome.test.assertTrue("User-Agent" in versionInfo);
          chrome.test.assertTrue("WebKit-Version" in versionInfo);
          chrome.test.succeed();
        });
  },

  function activatePage() {
    requestUrl('/json/activate/' + extensionTargetId,
        function(text) {
          chrome.test.assertEq(text, "Target activated");
          waitForTab(
              function(tab) {
                return tab.active &&
                       tab.status == "complete" &&
                       tab.title == 'Test page';
              },
              function (tab) {
                extensionTabId = tab.id;
                chrome.test.succeed();
              });
        });
  },

  function checkDebuggerUI() {
    requestUrl(extensionDevtoolsFrontendUrl, function(text) {
      chrome.test.assertTrue(/blink-dev-tools/.test(text));
      chrome.test.succeed();
    });
  },

  function checkWebSocketAPI() {
   var socket = new WebSocket(extensionWebSocketDebuggerUrl);

    socket.onopen = function () {
      var command = {
        method: "Runtime.evaluate",
        params: {"expression": "1+1"},
        id: 1
      }

      socket.send(JSON.stringify(command));
    };

    socket.onerror = function (error) {
      chrome.test.fail('WebSocket error ' + error);
    };

    socket.onmessage = function(e) {
      var message = JSON.parse(e.data);

      chrome.test.assertEq(1, message.id);
      chrome.test.assertEq(2, message.result.result.value);
      chrome.test.assertEq("number", message.result.result.type);
      chrome.test.assertTrue(typeof message.wasThrown === "undefined");
      socket.close();
    };

    socket.onclose = function() {
      chrome.test.succeed();
    }
  },

  function closePage() {
    function onRemoved(tabId) {
      chrome.test.assertEq(tabId, extensionTabId);
      chrome.test.succeed();
    }

    listenOnce(chrome.tabs.onRemoved, onRemoved);

    requestUrl('/json/close/' + extensionTargetId, function(text) {
      chrome.test.assertEq(text, "Target is closing");
    });
  },

  function newSpecificPage() {
    runNewPageTest('/json/new?chrome://version/', "chrome://version/");
  },

  function newDefaultPage() {
    runNewPageTest('/json/new', "about:blank");
  }
]);