15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2011 The Chromium Authors. All rights reserved.
25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file.
45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function Console() {
65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)}
75821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Console.Type = {
95821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  LOG: "log",
105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  DEBUG: "debug",
115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  INFO: "info",
125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  WARN: "warn",
135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  ERROR: "error",
145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GROUP: "group",
155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GROUP_COLLAPSED: "groupCollapsed",
165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  GROUP_END: "groupEnd"
175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)Console.addMessage = function(type, format, args) {
205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome.extension.sendRequest({
215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      command: "sendToConsole",
225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      tabId: chrome.devtools.tabId,
235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      args: escape(JSON.stringify(Array.prototype.slice.call(arguments, 0)))
245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  });
255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Generate Console output methods, i.e. Console.log(), Console.debug() etc.
285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)(function() {
295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var console_types = Object.getOwnPropertyNames(Console.Type);
305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (var type = 0; type < console_types.length; ++type) {
315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var method_name = Console.Type[console_types[type]];
325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Console[method_name] = Console.addMessage.bind(Console, method_name);
335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)})();
355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)function ChromeFirePHP() {
375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeFirePHP.handleFirePhpHeaders = function(har_entry) {
405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var response_headers = har_entry.response.headers;
415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var wf_header_map = {};
425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var had_wf_headers = false;
435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (var i = 0; i < response_headers.length; ++i) {
455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var header = response_headers[i];
465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (/^X-Wf-/.test(header.name)) {
475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      wf_header_map[header.name] = header.value;
485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      had_wf_headers = true;
495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var proto_header = wf_header_map["X-Wf-Protocol-1"];
535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!had_wf_headers || !this._checkProtoVersion(proto_header))
545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var message_objects = this._buildMessageObjects(wf_header_map);
575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  message_objects.sort(function(a, b) {
585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var aFile = a.File || "";
595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var bFile = b.File || "";
605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (aFile !== bFile)
615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        return aFile.localeCompare(bFile);
625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var aLine = a.Line !== undefined ? a.Line : -1;
635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var bLine = b.Line !== undefined ? b.Line : -1;
645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      return aLine - bLine;
655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  });
665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var context = { pageRef: har_entry.pageref };
685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (var i = 0; i < message_objects.length; ++i)
695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    this._processLogMessage(message_objects[i], context);
705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (context.groupStarted)
715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Console.groupEnd();
725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeFirePHP._processLogMessage = function(message, context) {
755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var meta = message[0];
765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!meta) {
775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Console.error("No Meta in FirePHP message");
785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var body = message[1];
825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var type = meta.Type;
835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!type) {
845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Console.error("No Type for FirePHP message");
855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  switch (type) {
895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case "LOG":
905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case "INFO":
915821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case "WARN":
925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case "ERROR":
935821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      if (!context.groupStarted) {
945821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        context.groupStarted = true;
955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        Console.groupCollapsed(context.pageRef || "");
965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      }
975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Console.addMessage(Console.Type[type], "%s%o",
985821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)          (meta.Label ? meta.Label + ": " : ""), body);
995821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1005821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case "EXCEPTION":
1015821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case "TABLE":
1025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case "TRACE":
1035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case "GROUP_START":
1045821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    case "GROUP_END":
1055821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     // FIXME: implement
1065821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)     break;
1075821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1085821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1095821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1105821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeFirePHP._buildMessageObjects = function(header_map)
1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles){
1125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const normal_header_prefix = "X-Wf-1-1-1-";
1135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return this._collectMessageObjectsForPrefix(header_map, normal_header_prefix);
1155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1165821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeFirePHP._collectMessageObjectsForPrefix = function(header_map, prefix) {
1185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var results = [];
1195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  const header_regexp = /(?:\d+)?\|(.+)/;
1205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var json = "";
1215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (var i = 1; ; ++i) {
1225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var name = prefix + i;
1235821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var value = header_map[name];
1245821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!value)
1255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1275821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var match = value.match(header_regexp);
1285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (!match) {
1295821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Console.error("Failed to parse FirePHP log message: " + value);
1305821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      break;
1315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    var json_part = match[1];
1335821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    json += json_part.substring(0, json_part.lastIndexOf("|"));
1345821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    if (json_part.charAt(json_part.length - 1) === "\\")
1355821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      continue;
1365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    try {
1375821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      var message = JSON.parse(json);
1385821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      results.push(message);
1395821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    } catch(e) {
1405821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      Console.error("Failed to parse FirePHP log message: " + json);
1415821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    }
1425821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    json = "";
1435821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1445821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return results;
1455821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)ChromeFirePHP._checkProtoVersion = function(proto_header) {
1485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!proto_header) {
1495821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Console.warn("WildFire protocol header not found");
1505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1515821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1525821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1535821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var match = /http:\/\/meta\.wildfirehq\.org\/Protocol\/([^\/]+)\/(.+)/.exec(
1545821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      proto_header);
1555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!match) {
1565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Console.warn("Invalid WildFire protocol header");
1575821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return;
1585821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var proto_name = match[1];
1605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var proto_version = match[2];
1615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (proto_name !== "JsonStream" || proto_version !== "0.2") {
1625821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Console.warn(
1635821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        "Unknown FirePHP protocol version: %s (expecting JsonStream/0.2)",
1645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        proto_name + "/" + proto_version);
1655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    return false;
1665821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1675821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  return true;
1685821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)};
1695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1705821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)chrome.devtools.network.addRequestHeaders({
1715821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    "X-FirePHP-Version": "0.0.6"
1725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)});
1735821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)chrome.devtools.network.getHAR(function(result) {
1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  var entries = result.entries;
1765821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  if (!entries.length) {
1775821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    Console.warn("ChromeFirePHP suggests that you reload the page to track" +
1785821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)        " FirePHP messages for all the requests");
1795821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  }
1805821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  for (var i = 0; i < entries.length; ++i)
1815821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)    ChromeFirePHP.handleFirePhp_headers(entries[i]);
1825821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)
1835821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)  chrome.devtools.network.onRequestFinished.addListener(
1845821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)      ChromeFirePHP.handleFirePhpHeaders.bind(ChromeFirePHP));
1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)});
186