




Function.prototype.bind = function(thisObject)
{
var func = this;
var args = Array.prototype.slice.call(arguments, 1);
function bound()
{
return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0)));
}
bound.toString = function() {
return "bound: " + func;
};
return bound;
}

Node.prototype.rangeOfWord = function(offset, stopCharacters, stayWithinNode, direction)
{
var startNode;
var startOffset = 0;
var endNode;
var endOffset = 0;

if (!stayWithinNode)
stayWithinNode = this;

if (!direction || direction === "backward" || direction === "both") {
var node = this;
while (node) {
if (node === stayWithinNode) {
if (!startNode)
startNode = stayWithinNode;
break;
}

if (node.nodeType === Node.TEXT_NODE) {
var start = (node === this ? (offset - 1) : (node.nodeValue.length - 1));
for (var i = start; i >= 0; --i) {
if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
startNode = node;
startOffset = i + 1;
break;
}
}
}

if (startNode)
break;

node = node.traversePreviousNode(stayWithinNode);
}

if (!startNode) {
startNode = stayWithinNode;
startOffset = 0;
}
} else {
startNode = this;
startOffset = offset;
}

if (!direction || direction === "forward" || direction === "both") {
node = this;
while (node) {
if (node === stayWithinNode) {
if (!endNode)
endNode = stayWithinNode;
break;
}

if (node.nodeType === Node.TEXT_NODE) {
var start = (node === this ? offset : 0);
for (var i = start; i < node.nodeValue.length; ++i) {
if (stopCharacters.indexOf(node.nodeValue[i]) !== -1) {
endNode = node;
endOffset = i;
break;
}
}
}

if (endNode)
break;

node = node.traverseNextNode(stayWithinNode);
}

if (!endNode) {
endNode = stayWithinNode;
endOffset = stayWithinNode.nodeType === Node.TEXT_NODE ? stayWithinNode.nodeValue.length : stayWithinNode.childNodes.length;
}
} else {
endNode = this;
endOffset = offset;
}

var result = this.ownerDocument.createRange();
result.setStart(startNode, startOffset);
result.setEnd(endNode, endOffset);

return result;
}

Node.prototype.traverseNextTextNode = function(stayWithin)
{
var node = this.traverseNextNode(stayWithin);
if (!node)
return;

while (node && node.nodeType !== Node.TEXT_NODE)
node = node.traverseNextNode(stayWithin);

return node;
}

Node.prototype.rangeBoundaryForOffset = function(offset)
{
var node = this.traverseNextTextNode(this);
while (node && offset > node.nodeValue.length) {
offset -= node.nodeValue.length;
node = node.traverseNextTextNode(this);
}
if (!node)
return { container: this, offset: 0 };
return { container: node, offset: offset };
}

Element.prototype.removeStyleClass = function(className) 
{
this.classList.remove(className);
}

Element.prototype.removeMatchingStyleClasses = function(classNameRegex)
{
var regex = new RegExp("(^|\\s+)" + classNameRegex + "($|\\s+)");
if (regex.test(this.className))
this.className = this.className.replace(regex, " ");
}

Element.prototype.addStyleClass = function(className) 
{
this.classList.add(className);
}

Element.prototype.hasStyleClass = function(className) 
{
return this.classList.contains(className);
}

Element.prototype.positionAt = function(x, y)
{
this.style.left = x + "px";
this.style.top = y + "px";
}

Element.prototype.pruneEmptyTextNodes = function()
{
var sibling = this.firstChild;
while (sibling) {
var nextSibling = sibling.nextSibling;
if (sibling.nodeType === this.TEXT_NODE && sibling.nodeValue === "")
this.removeChild(sibling);
sibling = nextSibling;
}
}

Element.prototype.isScrolledToBottom = function()
{

return this.scrollTop + this.clientHeight === this.scrollHeight;
}

Node.prototype.enclosingNodeOrSelfWithNodeNameInArray = function(nameArray)
{
for (var node = this; node && node !== this.ownerDocument; node = node.parentNode)
for (var i = 0; i < nameArray.length; ++i)
if (node.nodeName.toLowerCase() === nameArray[i].toLowerCase())
return node;
return null;
}

Node.prototype.enclosingNodeOrSelfWithNodeName = function(nodeName)
{
return this.enclosingNodeOrSelfWithNodeNameInArray([nodeName]);
}

Node.prototype.enclosingNodeOrSelfWithClass = function(className)
{
for (var node = this; node && node !== this.ownerDocument; node = node.parentNode)
if (node.nodeType === Node.ELEMENT_NODE && node.hasStyleClass(className))
return node;
return null;
}

Node.prototype.enclosingNodeWithClass = function(className)
{
if (!this.parentNode)
return null;
return this.parentNode.enclosingNodeOrSelfWithClass(className);
}

Element.prototype.query = function(query) 
{
return this.ownerDocument.evaluate(query, this, null, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue;
}

Element.prototype.removeChildren = function()
{
if (this.firstChild)
this.textContent = "";
}

Element.prototype.isInsertionCaretInside = function()
{
var selection = window.getSelection();
if (!selection.rangeCount || !selection.isCollapsed)
return false;
var selectionRange = selection.getRangeAt(0);
return selectionRange.startContainer === this || selectionRange.startContainer.isDescendant(this);
}

Element.prototype.createChild = function(elementName, className)
{
var element = document.createElement(elementName);
if (className)
element.className = className;
this.appendChild(element);
return element;
}

DocumentFragment.prototype.createChild = Element.prototype.createChild;

Element.prototype.__defineGetter__("totalOffsetLeft", function()
{
var total = 0;
for (var element = this; element; element = element.offsetParent)
total += element.offsetLeft + (this !== element ? element.clientLeft : 0);
return total;
});

Element.prototype.__defineGetter__("totalOffsetTop", function()
{
var total = 0;
for (var element = this; element; element = element.offsetParent)
total += element.offsetTop + (this !== element ? element.clientTop : 0);
return total;
});

Element.prototype.offsetRelativeToWindow = function(targetWindow)
{
var elementOffset = {x: 0, y: 0};
var curElement = this;
var curWindow = this.ownerDocument.defaultView;
while (curWindow && curElement) {
elementOffset.x += curElement.totalOffsetLeft;
elementOffset.y += curElement.totalOffsetTop;
if (curWindow === targetWindow)
break;

curElement = curWindow.frameElement;
curWindow = curWindow.parent;
}

return elementOffset;
}

Element.prototype.setTextAndTitle = function(text)
{
this.textContent = text;
this.title = text;
}

KeyboardEvent.prototype.__defineGetter__("data", function()
{


switch (this.type) {
case "keypress":
if (!this.ctrlKey && !this.metaKey)
return String.fromCharCode(this.charCode);
else
return "";
case "keydown":
case "keyup":
if (!this.ctrlKey && !this.metaKey && !this.altKey)
return String.fromCharCode(this.which);
else
return "";
}
});

Text.prototype.select = function(start, end)
{
start = start || 0;
end = end || this.textContent.length;

if (start < 0)
start = end + start;

var selection = window.getSelection();
selection.removeAllRanges();
var range = document.createRange();
range.setStart(this, start);
range.setEnd(this, end);
selection.addRange(range);
return this;
}

Element.prototype.__defineGetter__("selectionLeftOffset", function() {


var selection = window.getSelection();
if (!selection.containsNode(this, true))
return null;

var leftOffset = selection.anchorOffset;
var node = selection.anchorNode;

while (node !== this) {
while (node.previousSibling) {
node = node.previousSibling;
leftOffset += node.textContent.length;
}
node = node.parentNode;
}

return leftOffset;
});

Node.prototype.isWhitespace = isNodeWhitespace;
Node.prototype.displayName = nodeDisplayName;
Node.prototype.isAncestor = function(node)
{
return isAncestorNode(this, node);
};
Node.prototype.isDescendant = isDescendantNode;
Node.prototype.traverseNextNode = traverseNextNode;
Node.prototype.traversePreviousNode = traversePreviousNode;

String.prototype.hasSubstring = function(string, caseInsensitive)
{
if (!caseInsensitive)
return this.indexOf(string) !== -1;
return this.match(new RegExp(string.escapeForRegExp(), "i"));
}

String.prototype.findAll = function(string)
{
var matches = [];
var i = this.indexOf(string);
while (i !== -1) {
matches.push(i);
i = this.indexOf(string, i + string.length);
}
return matches;
}

String.prototype.lineEndings = function()
{
if (!this._lineEndings) {
this._lineEndings = this.findAll("\n");
this._lineEndings.push(this.length);
}
return this._lineEndings;
}

String.prototype.asParsedURL = function()
{






var match = this.match(/^([^:]+):\/\/([^\/:]*)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i);
if (!match)
return null;
var result = {};
result.scheme = match[1].toLowerCase();
result.host = match[2];
result.port = match[3];
result.path = match[4] || "/";
result.fragment = match[5];
return result;
}

String.prototype.escapeCharacters = function(chars)
{
var foundChar = false;
for (var i = 0; i < chars.length; ++i) {
if (this.indexOf(chars.charAt(i)) !== -1) {
foundChar = true;
break;
}
}

if (!foundChar)
return this;

var result = "";
for (var i = 0; i < this.length; ++i) {
if (chars.indexOf(this.charAt(i)) !== -1)
result += "\\";
result += this.charAt(i);
}

return result;
}

String.prototype.escapeForRegExp = function()
{
return this.escapeCharacters("^[]{}()\\.$*+?|");
}

String.prototype.escapeHTML = function()
{
return this.replace(/&/g, "&amp;").replace(/</g, "&lt;").replace(/>/g, "&gt;").replace(/"/g, "&quot;");
}

String.prototype.collapseWhitespace = function()
{
return this.replace(/[\s\xA0]+/g, " ");
}

String.prototype.trimMiddle = function(maxLength)
{
if (this.length <= maxLength)
return this;
var leftHalf = maxLength >> 1;
var rightHalf = maxLength - leftHalf - 1;
return this.substr(0, leftHalf) + "\u2026" + this.substr(this.length - rightHalf, rightHalf);
}

String.prototype.trimURL = function(baseURLDomain)
{
var result = this.replace(/^(https|http|file):\/\//i, "");
if (baseURLDomain)
result = result.replace(new RegExp("^" + baseURLDomain.escapeForRegExp(), "i"), "");
return result;
}

String.prototype.removeURLFragment = function()
{
var fragmentIndex = this.indexOf("#");
if (fragmentIndex == -1)
fragmentIndex = this.length;
return this.substring(0, fragmentIndex);
}

function isNodeWhitespace()
{
if (!this || this.nodeType !== Node.TEXT_NODE)
return false;
if (!this.nodeValue.length)
return true;
return this.nodeValue.match(/^[\s\xA0]+$/);
}

function nodeDisplayName()
{
if (!this)
return "";

switch (this.nodeType) {
case Node.DOCUMENT_NODE:
return "Document";

case Node.ELEMENT_NODE:
var name = "<" + this.nodeName.toLowerCase();

if (this.hasAttributes()) {
var value = this.getAttribute("id");
if (value)
name += " id=\"" + value + "\"";
value = this.getAttribute("class");
if (value)
name += " class=\"" + value + "\"";
if (this.nodeName.toLowerCase() === "a") {
value = this.getAttribute("name");
if (value)
name += " name=\"" + value + "\"";
value = this.getAttribute("href");
if (value)
name += " href=\"" + value + "\"";
} else if (this.nodeName.toLowerCase() === "img") {
value = this.getAttribute("src");
if (value)
name += " src=\"" + value + "\"";
} else if (this.nodeName.toLowerCase() === "iframe") {
value = this.getAttribute("src");
if (value)
name += " src=\"" + value + "\"";
} else if (this.nodeName.toLowerCase() === "input") {
value = this.getAttribute("name");
if (value)
name += " name=\"" + value + "\"";
value = this.getAttribute("type");
if (value)
name += " type=\"" + value + "\"";
} else if (this.nodeName.toLowerCase() === "form") {
value = this.getAttribute("action");
if (value)
name += " action=\"" + value + "\"";
}
}

return name + ">";

case Node.TEXT_NODE:
if (isNodeWhitespace.call(this))
return "(whitespace)";
return "\"" + this.nodeValue + "\"";

case Node.COMMENT_NODE:
return "<!--" + this.nodeValue + "-->";

case Node.DOCUMENT_TYPE_NODE:
var docType = "<!DOCTYPE " + this.nodeName;
if (this.publicId) {
docType += " PUBLIC \"" + this.publicId + "\"";
if (this.systemId)
docType += " \"" + this.systemId + "\"";
} else if (this.systemId)
docType += " SYSTEM \"" + this.systemId + "\"";
if (this.internalSubset)
docType += " [" + this.internalSubset + "]";
return docType + ">";
}

return this.nodeName.toLowerCase().collapseWhitespace();
}

function isAncestorNode(ancestor, node)
{
if (!node || !ancestor)
return false;

var currentNode = node.parentNode;
while (currentNode) {
if (ancestor === currentNode)
return true;
currentNode = currentNode.parentNode;
}
return false;
}

function isDescendantNode(descendant)
{
return isAncestorNode(descendant, this);
}

function traverseNextNode(stayWithin)
{
if (!this)
return;

var node = this.firstChild;
if (node)
return node;

if (stayWithin && this === stayWithin)
return null;

node = this.nextSibling;
if (node)
return node;

node = this;
while (node && !node.nextSibling && (!stayWithin || !node.parentNode || node.parentNode !== stayWithin))
node = node.parentNode;
if (!node)
return null;

return node.nextSibling;
}

function traversePreviousNode(stayWithin)
{
if (!this)
return;
if (stayWithin && this === stayWithin)
return null;
var node = this.previousSibling;
while (node && node.lastChild)
node = node.lastChild;
if (node)
return node;
return this.parentNode;
}

function getDocumentForNode(node)
{
return node.nodeType == Node.DOCUMENT_NODE ? node : node.ownerDocument;
}

function parentNode(node)
{
return node.parentNode;
}

Number.millisToString = function(ms, higherResolution)
{
return Number.secondsToString(ms / 1000, higherResolution);
}

Number.secondsToString = function(seconds, higherResolution)
{
if (seconds === 0)
return "0";

var ms = seconds * 1000;
if (higherResolution && ms < 1000)
return WebInspector.UIString("%.3fms", ms);
else if (ms < 1000)
return WebInspector.UIString("%.0fms", ms);

if (seconds < 60)
return WebInspector.UIString("%.2fs", seconds);

var minutes = seconds / 60;
if (minutes < 60)
return WebInspector.UIString("%.1fmin", minutes);

var hours = minutes / 60;
if (hours < 24)
return WebInspector.UIString("%.1fhrs", hours);

var days = hours / 24;
return WebInspector.UIString("%.1f days", days);
}

Number.bytesToString = function(bytes, higherResolution)
{
if (typeof higherResolution === "undefined")
higherResolution = true;

if (bytes < 1024)
return WebInspector.UIString("%.0fB", bytes);

var kilobytes = bytes / 1024;
if (higherResolution && kilobytes < 1024)
return WebInspector.UIString("%.2fKB", kilobytes);
else if (kilobytes < 1024)
return WebInspector.UIString("%.0fKB", kilobytes);

var megabytes = kilobytes / 1024;
if (higherResolution)
return WebInspector.UIString("%.2fMB", megabytes);
else
return WebInspector.UIString("%.0fMB", megabytes);
}

Number.constrain = function(num, min, max)
{
if (num < min)
num = min;
else if (num > max)
num = max;
return num;
}

HTMLTextAreaElement.prototype.moveCursorToEnd = function()
{
var length = this.value.length;
this.setSelectionRange(length, length);
}

Object.defineProperty(Array.prototype, "remove", { value: function(value, onlyFirst)
{
if (onlyFirst) {
var index = this.indexOf(value);
if (index !== -1)
this.splice(index, 1);
return;
}

var length = this.length;
for (var i = 0; i < length; ++i) {
if (this[i] === value)
this.splice(i, 1);
}
}});

Object.defineProperty(Array.prototype, "keySet", { value: function()
{
var keys = {};
for (var i = 0; i < this.length; ++i)
keys[this[i]] = true;
return keys;
}});

Object.defineProperty(Array.prototype, "upperBound", { value: function(value)
{
var first = 0;
var count = this.length;
while (count > 0) {
var step = count >> 1;
var middle = first + step;
if (value >= this[middle]) {
first = middle + 1;
count -= step + 1;
} else
count = step;
}
return first;
}});

Array.diff = function(left, right)
{
var o = left;
var n = right;

var ns = {};
var os = {};

for (var i = 0; i < n.length; i++) {
if (ns[n[i]] == null)
ns[n[i]] = { rows: [], o: null };
ns[n[i]].rows.push(i);
}

for (var i = 0; i < o.length; i++) {
if (os[o[i]] == null)
os[o[i]] = { rows: [], n: null };
os[o[i]].rows.push(i);
}

for (var i in ns) {
if (ns[i].rows.length == 1 && typeof(os[i]) != "undefined" && os[i].rows.length == 1) {
n[ns[i].rows[0]] = { text: n[ns[i].rows[0]], row: os[i].rows[0] };
o[os[i].rows[0]] = { text: o[os[i].rows[0]], row: ns[i].rows[0] };
}
}

for (var i = 0; i < n.length - 1; i++) {
if (n[i].text != null && n[i + 1].text == null && n[i].row + 1 < o.length && o[n[i].row + 1].text == null && n[i + 1] == o[n[i].row + 1]) {
n[i + 1] = { text: n[i + 1], row: n[i].row + 1 };
o[n[i].row + 1] = { text: o[n[i].row + 1], row: i + 1 };
}
}

for (var i = n.length - 1; i > 0; i--) {
if (n[i].text != null && n[i - 1].text == null && n[i].row > 0 && o[n[i].row - 1].text == null && 
n[i - 1] == o[n[i].row - 1]) {
n[i - 1] = { text: n[i - 1], row: n[i].row - 1 };
o[n[i].row - 1] = { text: o[n[i].row - 1], row: i - 1 };
}
}

return { left: o, right: n };
}

Array.convert = function(list)
{

return Array.prototype.slice.call(list);
}

String.sprintf = function(format)
{
return String.vsprintf(format, Array.prototype.slice.call(arguments, 1));
}

String.tokenizeFormatString = function(format)
{
var tokens = [];
var substitutionIndex = 0;

function addStringToken(str)
{
tokens.push({ type: "string", value: str });
}

function addSpecifierToken(specifier, precision, substitutionIndex)
{
tokens.push({ type: "specifier", specifier: specifier, precision: precision, substitutionIndex: substitutionIndex });
}

var index = 0;
for (var precentIndex = format.indexOf("%", index); precentIndex !== -1; precentIndex = format.indexOf("%", index)) {
addStringToken(format.substring(index, precentIndex));
index = precentIndex + 1;

if (format[index] === "%") {
addStringToken("%");
++index;
continue;
}

if (!isNaN(format[index])) {

var number = parseInt(format.substring(index));
while (!isNaN(format[index]))
++index;


if (number > 0 && format[index] === "$") {
substitutionIndex = (number - 1);
++index;
}
}

var precision = -1;
if (format[index] === ".") {


++index;
precision = parseInt(format.substring(index));
if (isNaN(precision))
precision = 0;
while (!isNaN(format[index]))
++index;
}

addSpecifierToken(format[index], precision, substitutionIndex);

++substitutionIndex;
++index;
}

addStringToken(format.substring(index));

return tokens;
}

String.standardFormatters = {
d: function(substitution)
{
if (typeof substitution == "object" && WebInspector.RemoteObject.type(substitution) === "number")
substitution = substitution.description;
substitution = parseInt(substitution);
return !isNaN(substitution) ? substitution : 0;
},

f: function(substitution, token)
{
if (typeof substitution == "object" && WebInspector.RemoteObject.type(substitution) === "number")
substitution = substitution.description;
substitution = parseFloat(substitution);
if (substitution && token.precision > -1)
substitution = substitution.toFixed(token.precision);
return !isNaN(substitution) ? substitution : (token.precision > -1 ? Number(0).toFixed(token.precision) : 0);
},

s: function(substitution)
{
if (typeof substitution == "object" && WebInspector.RemoteObject.type(substitution) !== "null")
substitution = substitution.description;
return substitution;
},
};

String.vsprintf = function(format, substitutions)
{
return String.format(format, substitutions, String.standardFormatters, "", function(a, b) { return a + b; }).formattedResult;
}

String.format = function(format, substitutions, formatters, initialValue, append)
{
if (!format || !substitutions || !substitutions.length)
return { formattedResult: append(initialValue, format), unusedSubstitutions: substitutions };

function prettyFunctionName()
{
return "String.format(\"" + format + "\", \"" + substitutions.join("\", \"") + "\")";
}

function warn(msg)
{
console.warn(prettyFunctionName() + ": " + msg);
}

function error(msg)
{
console.error(prettyFunctionName() + ": " + msg);
}

var result = initialValue;
var tokens = String.tokenizeFormatString(format);
var usedSubstitutionIndexes = {};

for (var i = 0; i < tokens.length; ++i) {
var token = tokens[i];

if (token.type === "string") {
result = append(result, token.value);
continue;
}

if (token.type !== "specifier") {
error("Unknown token type \"" + token.type + "\" found.");
continue;
}

if (token.substitutionIndex >= substitutions.length) {


error("not enough substitution arguments. Had " + substitutions.length + " but needed " + (token.substitutionIndex + 1) + ", so substitution was skipped.");
result = append(result, "%" + (token.precision > -1 ? token.precision : "") + token.specifier);
continue;
}

usedSubstitutionIndexes[token.substitutionIndex] = true;

if (!(token.specifier in formatters)) {

warn("unsupported format character \u201C" + token.specifier + "\u201D. Treating as a string.");
result = append(result, substitutions[token.substitutionIndex]);
continue;
}

result = append(result, formatters[token.specifier](substitutions[token.substitutionIndex], token));
}

var unusedSubstitutions = [];
for (var i = 0; i < substitutions.length; ++i) {
if (i in usedSubstitutionIndexes)
continue;
unusedSubstitutions.push(substitutions[i]);
}

return { formattedResult: result, unusedSubstitutions: unusedSubstitutions };
}

function isEnterKey(event) {

return event.keyCode !== 229 && event.keyIdentifier === "Enter";
}

function highlightSearchResult(element, offset, length)
{
var result = highlightSearchResults(element, [{offset: offset, length: length }]);
return result.length ? result[0] : null;
}

function highlightSearchResults(element, resultRanges, changes)
{
changes = changes || [];
var highlightNodes = [];
var lineText = element.textContent;
var textNodeSnapshot = document.evaluate(".//text()", element, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);

var snapshotLength = textNodeSnapshot.snapshotLength;
var snapshotNodeOffset = 0;
var currentSnapshotItem = 0;

for (var i = 0; i < resultRanges.length; ++i) {
var resultLength = resultRanges[i].length;
var startOffset = resultRanges[i].offset;
var endOffset = startOffset + resultLength;
var length = resultLength;
var textNode;
var textNodeOffset;
var found;

while (currentSnapshotItem < snapshotLength) {
textNode = textNodeSnapshot.snapshotItem(currentSnapshotItem++);
var textNodeLength = textNode.nodeValue.length;
if (snapshotNodeOffset + textNodeLength > startOffset) {
textNodeOffset = startOffset - snapshotNodeOffset;
snapshotNodeOffset += textNodeLength;
found = true;
break;
}
snapshotNodeOffset += textNodeLength;
}

if (!found) {
textNode = element;
textNodeOffset = 0;
}

var highlightNode = document.createElement("span");
highlightNode.className = "webkit-search-result";
highlightNode.textContent = lineText.substring(startOffset, endOffset);

var text = textNode.textContent;
if (textNodeOffset + resultLength < text.length) {

textNode.textContent = text.substring(textNodeOffset + resultLength);
changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent });

textNode.parentElement.insertBefore(highlightNode, textNode);
changes.push({ node: highlightNode, type: "added", nextSibling: textNode, parent: textNode.parentElement });

var prefixNode = document.createTextNode(text.substring(0, textNodeOffset));
textNode.parentElement.insertBefore(prefixNode, highlightNode);
changes.push({ node: prefixNode, type: "added", nextSibling: highlightNode, parent: textNode.parentElement });
highlightNodes.push(highlightNode);
continue;
}

var parentElement = textNode.parentElement;
var anchorElement = textNode.nextSibling;

length -= text.length - textNodeOffset;
textNode.textContent = text.substring(0, textNodeOffset);
changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent });

while (currentSnapshotItem < snapshotLength) {
textNode = textNodeSnapshot.snapshotItem(currentSnapshotItem++);
snapshotNodeOffset += textNode.nodeValue.length;
var text = textNode.textContent;
if (length < text.length) {
textNode.textContent = text.substring(length);
changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent });
break;
}

length -= text.length;
textNode.textContent = "";
changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent });
}

parentElement.insertBefore(highlightNode, anchorElement);
changes.push({ node: highlightNode, type: "added", nextSibling: anchorElement, parent: parentElement });
highlightNodes.push(highlightNode);
}

return highlightNodes;
}

function createSearchRegex(query, extraFlags)
{

regexSpecialCharacters = "[](){}+-*.,?\\^$|";
var regex = "";
for (var i = 0; i < query.length; ++i) {
var char = query.charAt(i);
if (regexSpecialCharacters.indexOf(char) != -1)
regex += "\\";
regex += char;
}
return new RegExp(regex, "i" + (extraFlags || ""));
}

function countRegexMatches(regex, content)
{
var text = content;
var result = 0;
var match;
while (text && (match = regex.exec(text))) {
if (match[0].length > 0)
++result;
text = text.substring(match.index + 1);
}
return result;
}





function binarySearch(object, array, comparator)
{
var first = 0;
var last = array.length - 1;

while (first <= last) {
var mid = (first + last) >> 1;
var c = comparator(object, array[mid]);
if (c > 0)
first = mid + 1;
else if (c < 0)
last = mid - 1;
else
return mid;
}


return -(first + 1);
}

Object.defineProperty(Array.prototype, "binaryIndexOf", { value: function(value, comparator)
{
var result = binarySearch(value, this, comparator);
return result >= 0 ? result : -1;
}});

function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunction)
{
var index = binarySearch(anObject, aList, aFunction);
if (index < 0)

return -index - 1;
else {

while (index > 0 && aFunction(anObject, aList[index - 1]) === 0)
index--;
return index;        
}
}





function TreeOutline(listNode)
{
this.children = [];
this.selectedTreeElement = null;
this._childrenListNode = listNode;
this._childrenListNode.removeChildren();
this._knownTreeElements = [];
this._treeElementsExpandedState = [];
this.expandTreeElementsWhenArrowing = false;
this.root = true;
this.hasChildren = false;
this.expanded = true;
this.selected = false;
this.treeOutline = this;

this._childrenListNode.tabIndex = 0;
this._childrenListNode.addEventListener("keydown", this._treeKeyDown.bind(this), true);
}

TreeOutline._knownTreeElementNextIdentifier = 1;

TreeOutline._appendChild = function(child)
{
if (!child)
throw("child can't be undefined or null");

var lastChild = this.children[this.children.length - 1];
if (lastChild) {
lastChild.nextSibling = child;
child.previousSibling = lastChild;
} else {
child.previousSibling = null;
child.nextSibling = null;
}

this.children.push(child);
this.hasChildren = true;
child.parent = this;
child.treeOutline = this.treeOutline;
child.treeOutline._rememberTreeElement(child);

var current = child.children[0];
while (current) {
current.treeOutline = this.treeOutline;
current.treeOutline._rememberTreeElement(current);
current = current.traverseNextTreeElement(false, child, true);
}

if (child.hasChildren && child.treeOutline._treeElementsExpandedState[child.identifier] !== undefined)
child.expanded = child.treeOutline._treeElementsExpandedState[child.identifier];

if (!this._childrenListNode) {
this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
this._childrenListNode.parentTreeElement = this;
this._childrenListNode.addStyleClass("children");
if (this.hidden)
this._childrenListNode.addStyleClass("hidden");
}

child._attach();
}

TreeOutline._insertChild = function(child, index)
{
if (!child)
throw("child can't be undefined or null");

var previousChild = (index > 0 ? this.children[index - 1] : null);
if (previousChild) {
previousChild.nextSibling = child;
child.previousSibling = previousChild;
} else {
child.previousSibling = null;
}

var nextChild = this.children[index];
if (nextChild) {
nextChild.previousSibling = child;
child.nextSibling = nextChild;
} else {
child.nextSibling = null;
}

this.children.splice(index, 0, child);
this.hasChildren = true;
child.parent = this;
child.treeOutline = this.treeOutline;
child.treeOutline._rememberTreeElement(child);

var current = child.children[0];
while (current) {
current.treeOutline = this.treeOutline;
current.treeOutline._rememberTreeElement(current);
current = current.traverseNextTreeElement(false, child, true);
}

if (child.hasChildren && child.treeOutline._treeElementsExpandedState[child.identifier] !== undefined)
child.expanded = child.treeOutline._treeElementsExpandedState[child.identifier];

if (!this._childrenListNode) {
this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
this._childrenListNode.parentTreeElement = this;
this._childrenListNode.addStyleClass("children");
if (this.hidden)
this._childrenListNode.addStyleClass("hidden");
}

child._attach();
}

TreeOutline._removeChildAtIndex = function(childIndex)
{
if (childIndex < 0 || childIndex >= this.children.length)
throw("childIndex out of range");

var child = this.children[childIndex];
this.children.splice(childIndex, 1);

var parent = child.parent;
if (child.deselect()) {
if (child.previousSibling)
child.previousSibling.select();
else if (child.nextSibling)
child.nextSibling.select();
else
parent.select();
}

if (child.previousSibling)
child.previousSibling.nextSibling = child.nextSibling;
if (child.nextSibling)
child.nextSibling.previousSibling = child.previousSibling;

if (child.treeOutline) {
child.treeOutline._forgetTreeElement(child);
child.treeOutline._forgetChildrenRecursive(child);
}

child._detach();
child.treeOutline = null;
child.parent = null;
child.nextSibling = null;
child.previousSibling = null;
}

TreeOutline._removeChild = function(child)
{
if (!child)
throw("child can't be undefined or null");

var childIndex = this.children.indexOf(child);
if (childIndex === -1)
throw("child not found in this node's children");

TreeOutline._removeChildAtIndex.call(this, childIndex);
}

TreeOutline._removeChildren = function()
{
for (var i = 0; i < this.children.length; ++i) {
var child = this.children[i];
child.deselect();

if (child.treeOutline) {
child.treeOutline._forgetTreeElement(child);
child.treeOutline._forgetChildrenRecursive(child);
}

child._detach();
child.treeOutline = null;
child.parent = null;
child.nextSibling = null;
child.previousSibling = null;
}

this.children = [];
}

TreeOutline._removeChildrenRecursive = function()
{
var childrenToRemove = this.children;

var child = this.children[0];
while (child) {
if (child.children.length)
childrenToRemove = childrenToRemove.concat(child.children);
child = child.traverseNextTreeElement(false, this, true);
}

for (var i = 0; i < childrenToRemove.length; ++i) {
var child = childrenToRemove[i];
child.deselect();
if (child.treeOutline)
child.treeOutline._forgetTreeElement(child);
child._detach();
child.children = [];
child.treeOutline = null;
child.parent = null;
child.nextSibling = null;
child.previousSibling = null;
}

this.children = [];
}

TreeOutline.prototype._rememberTreeElement = function(element)
{
if (!this._knownTreeElements[element.identifier])
this._knownTreeElements[element.identifier] = [];


var elements = this._knownTreeElements[element.identifier];
if (elements.indexOf(element) !== -1)
return;


elements.push(element);
}

TreeOutline.prototype._forgetTreeElement = function(element)
{
if (this._knownTreeElements[element.identifier])
this._knownTreeElements[element.identifier].remove(element, true);
}

TreeOutline.prototype._forgetChildrenRecursive = function(parentElement)
{
var child = parentElement.children[0];
while (child) {
this._forgetTreeElement(child);
child = child.traverseNextTreeElement(false, this, true);
}
}

TreeOutline.prototype.getCachedTreeElement = function(representedObject)
{
if (!representedObject)
return null;

if ("__treeElementIdentifier" in representedObject) {


var elements = this._knownTreeElements[representedObject.__treeElementIdentifier];
if (elements) {
for (var i = 0; i < elements.length; ++i)
if (elements[i].representedObject === representedObject)
return elements[i];
}
}
return null;
}

TreeOutline.prototype.findTreeElement = function(representedObject, isAncestor, getParent)
{
if (!representedObject)
return null;

var cachedElement = this.getCachedTreeElement(representedObject);
if (cachedElement)
return cachedElement;



var item;
var found = false;
for (var i = 0; i < this.children.length; ++i) {
item = this.children[i];
if (item.representedObject === representedObject || isAncestor(item.representedObject, representedObject)) {
found = true;
break;
}
}

if (!found)
return null;



var ancestors = [];
var currentObject = representedObject;
while (currentObject) {
ancestors.unshift(currentObject);
if (currentObject === item.representedObject)
break;
currentObject = getParent(currentObject);
}


for (var i = 0; i < ancestors.length; ++i) {


if (ancestors[i] === representedObject)
continue;


item = this.findTreeElement(ancestors[i], isAncestor, getParent);
if (item && item.onpopulate)
item.onpopulate(item);
}

return this.getCachedTreeElement(representedObject);
}

TreeOutline.prototype.treeElementFromPoint = function(x, y)
{
var node = this._childrenListNode.ownerDocument.elementFromPoint(x, y);
var listNode = node.enclosingNodeOrSelfWithNodeNameInArray(["ol", "li"]);
if (listNode)
return listNode.parentTreeElement || listNode.treeElement;
return null;
}

TreeOutline.prototype._treeKeyDown = function(event)
{
if (event.target !== this._childrenListNode)
return;

if (!this.selectedTreeElement || event.shiftKey || event.metaKey || event.ctrlKey)
return;

var handled = false;
var nextSelectedElement;
if (event.keyIdentifier === "Up" && !event.altKey) {
nextSelectedElement = this.selectedTreeElement.traversePreviousTreeElement(true);
while (nextSelectedElement && !nextSelectedElement.selectable)
nextSelectedElement = nextSelectedElement.traversePreviousTreeElement(!this.expandTreeElementsWhenArrowing);
handled = nextSelectedElement ? true : false;
} else if (event.keyIdentifier === "Down" && !event.altKey) {
nextSelectedElement = this.selectedTreeElement.traverseNextTreeElement(true);
while (nextSelectedElement && !nextSelectedElement.selectable)
nextSelectedElement = nextSelectedElement.traverseNextTreeElement(!this.expandTreeElementsWhenArrowing);
handled = nextSelectedElement ? true : false;
} else if (event.keyIdentifier === "Left") {
if (this.selectedTreeElement.expanded) {
if (event.altKey)
this.selectedTreeElement.collapseRecursively();
else
this.selectedTreeElement.collapse();
handled = true;
} else if (this.selectedTreeElement.parent && !this.selectedTreeElement.parent.root) {
handled = true;
if (this.selectedTreeElement.parent.selectable) {
nextSelectedElement = this.selectedTreeElement.parent;
handled = nextSelectedElement ? true : false;
} else if (this.selectedTreeElement.parent)
this.selectedTreeElement.parent.collapse();
}
} else if (event.keyIdentifier === "Right") {
if (!this.selectedTreeElement.revealed()) {
this.selectedTreeElement.reveal();
handled = true;
} else if (this.selectedTreeElement.hasChildren) {
handled = true;
if (this.selectedTreeElement.expanded) {
nextSelectedElement = this.selectedTreeElement.children[0];
handled = nextSelectedElement ? true : false;
} else {
if (event.altKey)
this.selectedTreeElement.expandRecursively();
else
this.selectedTreeElement.expand();
}
}
} else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Backspace.code || event.keyCode === WebInspector.KeyboardShortcut.Keys.Delete.code) {
if (this.selectedTreeElement.ondelete)
handled = this.selectedTreeElement.ondelete();
} else if (isEnterKey(event)) {
if (this.selectedTreeElement.onenter)
handled = this.selectedTreeElement.onenter();
}

if (nextSelectedElement) {
nextSelectedElement.reveal();
nextSelectedElement.select(false, true);
}

if (handled) {
event.preventDefault();
event.stopPropagation();
}
}

TreeOutline.prototype.expand = function()
{

}

TreeOutline.prototype.collapse = function()
{

}

TreeOutline.prototype.revealed = function()
{
return true;
}

TreeOutline.prototype.reveal = function()
{

}

TreeOutline.prototype.select = function()
{

}

TreeOutline.prototype.appendChild = TreeOutline._appendChild;
TreeOutline.prototype.insertChild = TreeOutline._insertChild;
TreeOutline.prototype.removeChild = TreeOutline._removeChild;
TreeOutline.prototype.removeChildAtIndex = TreeOutline._removeChildAtIndex;
TreeOutline.prototype.removeChildren = TreeOutline._removeChildren;
TreeOutline.prototype.removeChildrenRecursive = TreeOutline._removeChildrenRecursive;

function TreeElement(title, representedObject, hasChildren)
{
this._title = title;
this.representedObject = (representedObject || {});

if (this.representedObject.__treeElementIdentifier)
this.identifier = this.representedObject.__treeElementIdentifier;
else {
this.identifier = TreeOutline._knownTreeElementNextIdentifier++;
this.representedObject.__treeElementIdentifier = this.identifier;
}

this._hidden = false;
this.expanded = false;
this.selected = false;
this.hasChildren = hasChildren;
this.children = [];
this.treeOutline = null;
this.parent = null;
this.previousSibling = null;
this.nextSibling = null;
this._listItemNode = null;
}

TreeElement.prototype = {
selectable: true,
arrowToggleWidth: 10,

get listItemElement() {
return this._listItemNode;
},

get childrenListElement() {
return this._childrenListNode;
},

get title() {
return this._title;
},

set title(x) {
this._title = x;
this._setListItemNodeContent();
},

get titleHTML() {
return this._titleHTML;
},

set titleHTML(x) {
this._titleHTML = x;
this._setListItemNodeContent();
},

get tooltip() {
return this._tooltip;
},

set tooltip(x) {
this._tooltip = x;
if (this._listItemNode)
this._listItemNode.title = x ? x : "";
},

get hasChildren() {
return this._hasChildren;
},

set hasChildren(x) {
if (this._hasChildren === x)
return;

this._hasChildren = x;

if (!this._listItemNode)
return;

if (x)
this._listItemNode.addStyleClass("parent");
else {
this._listItemNode.removeStyleClass("parent");
this.collapse();
}
},

get hidden() {
return this._hidden;
},

set hidden(x) {
if (this._hidden === x)
return;

this._hidden = x;

if (x) {
if (this._listItemNode)
this._listItemNode.addStyleClass("hidden");
if (this._childrenListNode)
this._childrenListNode.addStyleClass("hidden");
} else {
if (this._listItemNode)
this._listItemNode.removeStyleClass("hidden");
if (this._childrenListNode)
this._childrenListNode.removeStyleClass("hidden");
}
},

get shouldRefreshChildren() {
return this._shouldRefreshChildren;
},

set shouldRefreshChildren(x) {
this._shouldRefreshChildren = x;
if (x && this.expanded)
this.expand();
},

_setListItemNodeContent: function()
{
if (!this._listItemNode)
return;

if (!this._titleHTML && !this._title)
this._listItemNode.removeChildren();
else if (typeof this._titleHTML === "string")
this._listItemNode.innerHTML = this._titleHTML;
else if (typeof this._title === "string")
this._listItemNode.textContent = this._title;
else {
this._listItemNode.removeChildren();
if (this._title.parentNode)
this._title.parentNode.removeChild(this._title);
this._listItemNode.appendChild(this._title);
}
}
}

TreeElement.prototype.appendChild = TreeOutline._appendChild;
TreeElement.prototype.insertChild = TreeOutline._insertChild;
TreeElement.prototype.removeChild = TreeOutline._removeChild;
TreeElement.prototype.removeChildAtIndex = TreeOutline._removeChildAtIndex;
TreeElement.prototype.removeChildren = TreeOutline._removeChildren;
TreeElement.prototype.removeChildrenRecursive = TreeOutline._removeChildrenRecursive;

TreeElement.prototype._attach = function()
{
if (!this._listItemNode || this.parent._shouldRefreshChildren) {
if (this._listItemNode && this._listItemNode.parentNode)
this._listItemNode.parentNode.removeChild(this._listItemNode);

this._listItemNode = this.treeOutline._childrenListNode.ownerDocument.createElement("li");
this._listItemNode.treeElement = this;
this._setListItemNodeContent();
this._listItemNode.title = this._tooltip ? this._tooltip : "";

if (this.hidden)
this._listItemNode.addStyleClass("hidden");
if (this.hasChildren)
this._listItemNode.addStyleClass("parent");
if (this.expanded)
this._listItemNode.addStyleClass("expanded");
if (this.selected)
this._listItemNode.addStyleClass("selected");

this._listItemNode.addEventListener("mousedown", TreeElement.treeElementMouseDown, false);
this._listItemNode.addEventListener("click", TreeElement.treeElementToggled, false);
this._listItemNode.addEventListener("dblclick", TreeElement.treeElementDoubleClicked, false);

if (this.onattach)
this.onattach(this);
}

var nextSibling = null;
if (this.nextSibling && this.nextSibling._listItemNode && this.nextSibling._listItemNode.parentNode === this.parent._childrenListNode)
nextSibling = this.nextSibling._listItemNode;
this.parent._childrenListNode.insertBefore(this._listItemNode, nextSibling);
if (this._childrenListNode)
this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
if (this.selected)
this.select();
if (this.expanded)
this.expand();
}

TreeElement.prototype._detach = function()
{
if (this._listItemNode && this._listItemNode.parentNode)
this._listItemNode.parentNode.removeChild(this._listItemNode);
if (this._childrenListNode && this._childrenListNode.parentNode)
this._childrenListNode.parentNode.removeChild(this._childrenListNode);
}

TreeElement.treeElementMouseDown = function(event)
{
var element = event.currentTarget;
if (!element || !element.treeElement || !element.treeElement.selectable)
return;

if (element.treeElement.isEventWithinDisclosureTriangle(event))
return;

element.treeElement.selectOnMouseDown(event);
}

TreeElement.treeElementToggled = function(event)
{
var element = event.currentTarget;
if (!element || !element.treeElement)
return;

if (!element.treeElement.isEventWithinDisclosureTriangle(event))
return;

if (element.treeElement.expanded) {
if (event.altKey)
element.treeElement.collapseRecursively();
else
element.treeElement.collapse();
} else {
if (event.altKey)
element.treeElement.expandRecursively();
else
element.treeElement.expand();
}
event.stopPropagation();
}

TreeElement.treeElementDoubleClicked = function(event)
{
var element = event.currentTarget;
if (!element || !element.treeElement)
return;

if (element.treeElement.ondblclick)
element.treeElement.ondblclick.call(element.treeElement, event);
else if (element.treeElement.hasChildren && !element.treeElement.expanded)
element.treeElement.expand();
}

TreeElement.prototype.collapse = function()
{
if (this._listItemNode)
this._listItemNode.removeStyleClass("expanded");
if (this._childrenListNode)
this._childrenListNode.removeStyleClass("expanded");

this.expanded = false;
if (this.treeOutline)
this.treeOutline._treeElementsExpandedState[this.identifier] = true;

if (this.oncollapse)
this.oncollapse(this);
}

TreeElement.prototype.collapseRecursively = function()
{
var item = this;
while (item) {
if (item.expanded)
item.collapse();
item = item.traverseNextTreeElement(false, this, true);
}
}

TreeElement.prototype.expand = function()
{
if (!this.hasChildren || (this.expanded && !this._shouldRefreshChildren && this._childrenListNode))
return;

if (this.treeOutline && (!this._childrenListNode || this._shouldRefreshChildren)) {
if (this._childrenListNode && this._childrenListNode.parentNode)
this._childrenListNode.parentNode.removeChild(this._childrenListNode);

this._childrenListNode = this.treeOutline._childrenListNode.ownerDocument.createElement("ol");
this._childrenListNode.parentTreeElement = this;
this._childrenListNode.addStyleClass("children");

if (this.hidden)
this._childrenListNode.addStyleClass("hidden");

if (this.onpopulate)
this.onpopulate(this);

for (var i = 0; i < this.children.length; ++i)
this.children[i]._attach();

delete this._shouldRefreshChildren;
}

if (this._listItemNode) {
this._listItemNode.addStyleClass("expanded");
if (this._childrenListNode && this._childrenListNode.parentNode != this._listItemNode.parentNode)
this.parent._childrenListNode.insertBefore(this._childrenListNode, this._listItemNode.nextSibling);
}

if (this._childrenListNode)
this._childrenListNode.addStyleClass("expanded");

this.expanded = true;
if (this.treeOutline)
this.treeOutline._treeElementsExpandedState[this.identifier] = true;

if (this.onexpand)
this.onexpand(this);
}

TreeElement.prototype.expandRecursively = function(maxDepth)
{
var item = this;
var info = {};
var depth = 0;




if (typeof maxDepth === "undefined" || typeof maxDepth === "null")
maxDepth = 3;

while (item) {
if (depth < maxDepth)
item.expand();
item = item.traverseNextTreeElement(false, this, (depth >= maxDepth), info);
depth += info.depthChange;
}
}

TreeElement.prototype.hasAncestor = function(ancestor) {
if (!ancestor)
return false;

var currentNode = this.parent;
while (currentNode) {
if (ancestor === currentNode)
return true;
currentNode = currentNode.parent;
}

return false;
}

TreeElement.prototype.reveal = function()
{
var currentAncestor = this.parent;
while (currentAncestor && !currentAncestor.root) {
if (!currentAncestor.expanded)
currentAncestor.expand();
currentAncestor = currentAncestor.parent;
}

if (this.onreveal)
this.onreveal(this);
}

TreeElement.prototype.revealed = function()
{
var currentAncestor = this.parent;
while (currentAncestor && !currentAncestor.root) {
if (!currentAncestor.expanded)
return false;
currentAncestor = currentAncestor.parent;
}

return true;
}

TreeElement.prototype.selectOnMouseDown = function(event)
{
this.select(false, true);
}

TreeElement.prototype.select = function(supressOnSelect, selectedByUser)
{
if (!this.treeOutline || !this.selectable || this.selected)
return;

if (this.treeOutline.selectedTreeElement)
this.treeOutline.selectedTreeElement.deselect();

this.selected = true;
this.treeOutline._childrenListNode.focus();


if (!this.treeOutline)
return;
this.treeOutline.selectedTreeElement = this;
if (this._listItemNode)
this._listItemNode.addStyleClass("selected");

if (this.onselect && !supressOnSelect)
this.onselect(this, selectedByUser);
}

TreeElement.prototype.deselect = function(supressOnDeselect)
{
if (!this.treeOutline || this.treeOutline.selectedTreeElement !== this || !this.selected)
return false;

this.selected = false;
this.treeOutline.selectedTreeElement = null;
if (this._listItemNode)
this._listItemNode.removeStyleClass("selected");

if (this.ondeselect && !supressOnDeselect)
this.ondeselect(this);
return true;
}

TreeElement.prototype.traverseNextTreeElement = function(skipHidden, stayWithin, dontPopulate, info)
{
if (!dontPopulate && this.hasChildren && this.onpopulate)
this.onpopulate(this);

if (info)
info.depthChange = 0;

var element = skipHidden ? (this.revealed() ? this.children[0] : null) : this.children[0];
if (element && (!skipHidden || (skipHidden && this.expanded))) {
if (info)
info.depthChange = 1;
return element;
}

if (this === stayWithin)
return null;

element = skipHidden ? (this.revealed() ? this.nextSibling : null) : this.nextSibling;
if (element)
return element;

element = this;
while (element && !element.root && !(skipHidden ? (element.revealed() ? element.nextSibling : null) : element.nextSibling) && element.parent !== stayWithin) {
if (info)
info.depthChange -= 1;
element = element.parent;
}

if (!element)
return null;

return (skipHidden ? (element.revealed() ? element.nextSibling : null) : element.nextSibling);
}

TreeElement.prototype.traversePreviousTreeElement = function(skipHidden, dontPopulate)
{
var element = skipHidden ? (this.revealed() ? this.previousSibling : null) : this.previousSibling;
if (!dontPopulate && element && element.hasChildren && element.onpopulate)
element.onpopulate(element);

while (element && (skipHidden ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1])) {
if (!dontPopulate && element.hasChildren && element.onpopulate)
element.onpopulate(element);
element = (skipHidden ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1]);
}

if (element)
return element;

if (!this.parent || this.parent.root)
return null;

return this.parent;
}

TreeElement.prototype.isEventWithinDisclosureTriangle = function(event)
{
var left = this._listItemNode.totalOffsetLeft;
return event.pageX >= left && event.pageX <= left + this.arrowToggleWidth && this.hasChildren;
}





var WebInspector = {
resources: {},
missingLocalizedStrings: {},
pendingDispatches: 0,

get platform()
{
if (!("_platform" in this))
this._platform = InspectorFrontendHost.platform();

return this._platform;
},

get platformFlavor()
{
if (!("_platformFlavor" in this))
this._platformFlavor = this._detectPlatformFlavor();

return this._platformFlavor;
},

_detectPlatformFlavor: function()
{
const userAgent = navigator.userAgent;

if (this.platform === "windows") {
var match = userAgent.match(/Windows NT (\d+)\.(?:\d+)/);
if (match && match[1] >= 6)
return WebInspector.PlatformFlavor.WindowsVista;
return null;
} else if (this.platform === "mac") {
var match = userAgent.match(/Mac OS X\s*(?:(\d+)_(\d+))?/);
if (!match || match[1] != 10)
return WebInspector.PlatformFlavor.MacSnowLeopard;
switch (Number(match[2])) {
case 4:
return WebInspector.PlatformFlavor.MacTiger;
case 5:
return WebInspector.PlatformFlavor.MacLeopard;
case 6:
default:
return WebInspector.PlatformFlavor.MacSnowLeopard;
}
}

return null;
},

get port()
{
if (!("_port" in this))
this._port = InspectorFrontendHost.port();

return this._port;
},

get previousFocusElement()
{
return this._previousFocusElement;
},

get currentFocusElement()
{
return this._currentFocusElement;
},

set currentFocusElement(x)
{
if (this._currentFocusElement !== x)
this._previousFocusElement = this._currentFocusElement;
this._currentFocusElement = x;

if (this._currentFocusElement) {
this._currentFocusElement.focus();



var selection = window.getSelection();
if (selection.isCollapsed && !this._currentFocusElement.isInsertionCaretInside()) {
var selectionRange = this._currentFocusElement.ownerDocument.createRange();
selectionRange.setStart(this._currentFocusElement, 0);
selectionRange.setEnd(this._currentFocusElement, 0);

selection.removeAllRanges();
selection.addRange(selectionRange);
}
} else if (this._previousFocusElement)
this._previousFocusElement.blur();
},

resetFocusElement: function()
{
this.currentFocusElement = null;
this._previousFocusElement = null;
},

get currentPanel()
{
return this._currentPanel;
},

set currentPanel(x)
{
if (this._currentPanel === x)
return;

if (this._currentPanel)
this._currentPanel.hide();

this._currentPanel = x;

if (x) {
x.show();
WebInspector.searchController.activePanelChanged();
}
for (var panelName in WebInspector.panels) {
if (WebInspector.panels[panelName] === x) {
WebInspector.settings.lastActivePanel = panelName;
this._panelHistory.setPanel(panelName);
}
}
},

_createPanels: function()
{
if (WebInspector.WorkerManager.isWorkerFrontend()) {
this.panels.scripts = new WebInspector.ScriptsPanel();
this.panels.console = new WebInspector.ConsolePanel();
return;
}
var hiddenPanels = (InspectorFrontendHost.hiddenPanels() || "").split(',');
if (hiddenPanels.indexOf("elements") === -1)
this.panels.elements = new WebInspector.ElementsPanel();
if (hiddenPanels.indexOf("resources") === -1)
this.panels.resources = new WebInspector.ResourcesPanel();
if (hiddenPanels.indexOf("network") === -1)
this.panels.network = new WebInspector.NetworkPanel();
if (hiddenPanels.indexOf("scripts") === -1)
this.panels.scripts = new WebInspector.ScriptsPanel();
if (hiddenPanels.indexOf("timeline") === -1)
this.panels.timeline = new WebInspector.TimelinePanel();
if (hiddenPanels.indexOf("profiles") === -1)
this.panels.profiles = new WebInspector.ProfilesPanel();
if (hiddenPanels.indexOf("audits") === -1)
this.panels.audits = new WebInspector.AuditsPanel();
if (hiddenPanels.indexOf("console") === -1)
this.panels.console = new WebInspector.ConsolePanel();
},

get attached()
{
return this._attached;
},

set attached(x)
{
if (this._attached === x)
return;

this._attached = x;

var dockToggleButton = document.getElementById("dock-status-bar-item");
var body = document.body;

if (x) {
body.removeStyleClass("detached");
body.addStyleClass("attached");
dockToggleButton.title = WebInspector.UIString("Undock into separate window.");
} else {
body.removeStyleClass("attached");
body.addStyleClass("detached");
dockToggleButton.title = WebInspector.UIString("Dock to main window.");
}



if (WebInspector.toolbar)
WebInspector.toolbar.attached = x;

if (WebInspector.searchController)
WebInspector.searchController.updateSearchLabel();
},

get errors()
{
return this._errors || 0;
},

set errors(x)
{
x = Math.max(x, 0);

if (this._errors === x)
return;
this._errors = x;
this._updateErrorAndWarningCounts();
},

get warnings()
{
return this._warnings || 0;
},

set warnings(x)
{
x = Math.max(x, 0);

if (this._warnings === x)
return;
this._warnings = x;
this._updateErrorAndWarningCounts();
},

_updateErrorAndWarningCounts: function()
{
var errorWarningElement = document.getElementById("error-warning-count");
if (!errorWarningElement)
return;

if (!this.errors && !this.warnings) {
errorWarningElement.addStyleClass("hidden");
return;
}

errorWarningElement.removeStyleClass("hidden");

errorWarningElement.removeChildren();

if (this.errors) {
var errorElement = document.createElement("span");
errorElement.id = "error-count";
errorElement.textContent = this.errors;
errorWarningElement.appendChild(errorElement);
}

if (this.warnings) {
var warningsElement = document.createElement("span");
warningsElement.id = "warning-count";
warningsElement.textContent = this.warnings;
errorWarningElement.appendChild(warningsElement);
}

if (this.errors) {
if (this.warnings) {
if (this.errors == 1) {
if (this.warnings == 1)
errorWarningElement.title = WebInspector.UIString("%d error, %d warning", this.errors, this.warnings);
else
errorWarningElement.title = WebInspector.UIString("%d error, %d warnings", this.errors, this.warnings);
} else if (this.warnings == 1)
errorWarningElement.title = WebInspector.UIString("%d errors, %d warning", this.errors, this.warnings);
else
errorWarningElement.title = WebInspector.UIString("%d errors, %d warnings", this.errors, this.warnings);
} else if (this.errors == 1)
errorWarningElement.title = WebInspector.UIString("%d error", this.errors);
else
errorWarningElement.title = WebInspector.UIString("%d errors", this.errors);
} else if (this.warnings == 1)
errorWarningElement.title = WebInspector.UIString("%d warning", this.warnings);
else if (this.warnings)
errorWarningElement.title = WebInspector.UIString("%d warnings", this.warnings);
else
errorWarningElement.title = null;
},

highlightDOMNode: function(nodeId, mode)
{
if ("_hideDOMNodeHighlightTimeout" in this) {
clearTimeout(this._hideDOMNodeHighlightTimeout);
delete this._hideDOMNodeHighlightTimeout;
}

if (this._highlightedDOMNodeId === nodeId)
return;

this._highlightedDOMNodeId = nodeId;
if (nodeId)
DOMAgent.highlightNode(nodeId, mode || "all");
else
DOMAgent.hideNodeHighlight();
},

highlightDOMNodeForTwoSeconds: function(nodeId)
{
this.highlightDOMNode(nodeId);
this._hideDOMNodeHighlightTimeout = setTimeout(this.highlightDOMNode.bind(this, 0), 2000);
},

wireElementWithDOMNode: function(element, nodeId)
{
element.addEventListener("click", this._updateFocusedNode.bind(this, nodeId), false);
element.addEventListener("mouseover", this.highlightDOMNode.bind(this, nodeId), false);
element.addEventListener("mouseout", this.highlightDOMNode.bind(this, 0), false);
},

_updateFocusedNode: function(nodeId)
{
this.currentPanel = this.panels.elements;
this.panels.elements.updateFocusedNode(nodeId);
},

get networkResources()
{
return this.panels.network.resources;
},

networkResourceById: function(id)
{
return this.panels.network.resourceById(id);
},

forAllResources: function(callback)
{
WebInspector.resourceTreeModel.forAllResources(callback);
},

resourceForURL: function(url)
{
return this.resourceTreeModel.resourceForURL(url);
},

openLinkExternallyLabel: function()
{
return WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open link in new tab" : "Open Link in New Tab");
}
}

WebInspector.PlatformFlavor = {
WindowsVista: "windows-vista",
MacTiger: "mac-tiger",
MacLeopard: "mac-leopard",
MacSnowLeopard: "mac-snowleopard"
};

(function parseQueryParameters()
{
WebInspector.queryParamsObject = {};
var queryParams = window.location.search;
if (!queryParams)
return;
var params = queryParams.substring(1).split("&");
for (var i = 0; i < params.length; ++i) {
var pair = params[i].split("=");
WebInspector.queryParamsObject[pair[0]] = pair[1];
}
})();

WebInspector.loaded = function()
{
if ("page" in WebInspector.queryParamsObject) {
var page = WebInspector.queryParamsObject.page;
var host = "host" in WebInspector.queryParamsObject ? WebInspector.queryParamsObject.host : window.location.host;
WebInspector.socket = new WebSocket("ws://" + host + "/devtools/page/" + page);
WebInspector.socket.onmessage = function(message) { InspectorBackend.dispatch(message.data); }
WebInspector.socket.onerror = function(error) { console.error(error); }
WebInspector.socket.onopen = function() {
InspectorFrontendHost.sendMessageToBackend = WebInspector.socket.send.bind(WebInspector.socket);
InspectorFrontendHost.loaded = WebInspector.socket.send.bind(WebInspector.socket, "loaded");
WebInspector.doLoadedDone();
}
return;
}
WebInspector.WorkerManager.loaded();
WebInspector.doLoadedDone();
}

WebInspector.doLoadedDone = function()
{
InspectorFrontendHost.loaded();

var platform = WebInspector.platform;
document.body.addStyleClass("platform-" + platform);
var flavor = WebInspector.platformFlavor;
if (flavor)
document.body.addStyleClass("platform-" + flavor);
var port = WebInspector.port;
document.body.addStyleClass("port-" + port);
if (WebInspector.socket)
document.body.addStyleClass("remote");

WebInspector.settings = new WebInspector.Settings();

this._registerShortcuts();


WebInspector.shortcutsHelp.section(WebInspector.UIString("Console"));
WebInspector.shortcutsHelp.section(WebInspector.UIString("Elements Panel"));

this.drawer = new WebInspector.Drawer();
this.console = new WebInspector.ConsoleView(this.drawer);
this.drawer.visibleView = this.console;
this.networkManager = new WebInspector.NetworkManager();
this.resourceTreeModel = new WebInspector.ResourceTreeModel();
this.domAgent = new WebInspector.DOMAgent();

InspectorBackend.registerDomainDispatcher("Inspector", this);

this.resourceCategories = {
documents: new WebInspector.ResourceCategory("documents", WebInspector.UIString("Documents"), "rgb(47,102,236)"),
stylesheets: new WebInspector.ResourceCategory("stylesheets", WebInspector.UIString("Stylesheets"), "rgb(157,231,119)"),
images: new WebInspector.ResourceCategory("images", WebInspector.UIString("Images"), "rgb(164,60,255)"),
scripts: new WebInspector.ResourceCategory("scripts", WebInspector.UIString("Scripts"), "rgb(255,121,0)"),
xhr: new WebInspector.ResourceCategory("xhr", WebInspector.UIString("XHR"), "rgb(231,231,10)"),
fonts: new WebInspector.ResourceCategory("fonts", WebInspector.UIString("Fonts"), "rgb(255,82,62)"),
websockets: new WebInspector.ResourceCategory("websockets", WebInspector.UIString("WebSockets"), "rgb(186,186,186)"), 
other: new WebInspector.ResourceCategory("other", WebInspector.UIString("Other"), "rgb(186,186,186)")
};

this.cssModel = new WebInspector.CSSStyleModel();
this.debuggerModel = new WebInspector.DebuggerModel();

this.searchController = new WebInspector.SearchController();
this.domBreakpointsSidebarPane = new WebInspector.DOMBreakpointsSidebarPane();

this.panels = {};
this._createPanels();
this._panelHistory = new WebInspector.PanelHistory();
this.toolbar = new WebInspector.Toolbar();
this.toolbar.attached = WebInspector.attached;

this.panelOrder = [];
for (var panelName in this.panels)
this.addPanel(this.panels[panelName]);

this.Tips = {
ResourceNotCompressed: {id: 0, message: WebInspector.UIString("You could save bandwidth by having your web server compress this transfer with gzip or zlib.")}
};

this.Warnings = {
IncorrectMIMEType: {id: 0, message: WebInspector.UIString("Resource interpreted as %s but transferred with MIME type %s.")}
};

this.addMainEventListeners(document);

window.addEventListener("resize", this.windowResize.bind(this), true);

document.addEventListener("focus", this.focusChanged.bind(this), true);
document.addEventListener("keydown", this.documentKeyDown.bind(this), false);
document.addEventListener("beforecopy", this.documentCanCopy.bind(this), true);
document.addEventListener("copy", this.documentCopy.bind(this), true);
document.addEventListener("contextmenu", this.contextMenuEventFired.bind(this), true);

var dockToggleButton = document.getElementById("dock-status-bar-item");
dockToggleButton.addEventListener("click", this.toggleAttach.bind(this), false);

if (this.attached)
dockToggleButton.title = WebInspector.UIString("Undock into separate window.");
else
dockToggleButton.title = WebInspector.UIString("Dock to main window.");

var errorWarningCount = document.getElementById("error-warning-count");
errorWarningCount.addEventListener("click", this.showConsole.bind(this), false);
this._updateErrorAndWarningCounts();

this.extensionServer.initExtensions();

if (WebInspector.settings.monitoringXHREnabled)
ConsoleAgent.setMonitoringXHREnabled(true);
ConsoleAgent.enable(this.console.setConsoleMessageExpiredCount.bind(this.console));

DatabaseAgent.enable();
DOMStorageAgent.enable();

WebInspector.showPanel(WebInspector.settings.lastActivePanel);

function propertyNamesCallback(error, names)
{
if (!error)
WebInspector.cssNameCompletions = new WebInspector.CSSCompletions(names);
}

CSSAgent.getSupportedCSSProperties(propertyNamesCallback);
}

WebInspector.addPanel = function(panel)
{
this.panelOrder.push(panel);
this.toolbar.addPanel(panel);
}

var windowLoaded = function()
{
var localizedStringsURL = InspectorFrontendHost.localizedStringsURL();
if (localizedStringsURL) {
var localizedStringsScriptElement = document.createElement("script");
localizedStringsScriptElement.addEventListener("load", WebInspector.loaded.bind(WebInspector), false);
localizedStringsScriptElement.type = "text/javascript";
localizedStringsScriptElement.src = localizedStringsURL;
document.head.appendChild(localizedStringsScriptElement);
} else
WebInspector.loaded();

window.removeEventListener("DOMContentLoaded", windowLoaded, false);
delete windowLoaded;
};

window.addEventListener("DOMContentLoaded", windowLoaded, false);







var messagesToDispatch = [];

WebInspector.dispatch = function(message) {
messagesToDispatch.push(message);
setTimeout(function() {
InspectorBackend.dispatch(messagesToDispatch.shift());
}, 0);
}

WebInspector.dispatchMessageFromBackend = function(messageObject)
{
WebInspector.dispatch(messageObject);
}

WebInspector.windowResize = function(event)
{
if (this.currentPanel)
this.currentPanel.resize();
this.drawer.resize();
this.toolbar.resize();
}

WebInspector.windowFocused = function(event)
{



if (event.target.document.nodeType === Node.DOCUMENT_NODE)
document.body.removeStyleClass("inactive");
}

WebInspector.windowBlurred = function(event)
{



if (event.target.document.nodeType === Node.DOCUMENT_NODE)
document.body.addStyleClass("inactive");
}

WebInspector.focusChanged = function(event)
{
this.currentFocusElement = event.target;
}

WebInspector.setAttachedWindow = function(attached)
{
this.attached = attached;
}

WebInspector.close = function(event)
{
if (this._isClosing)
return;
this._isClosing = true;
InspectorFrontendHost.closeWindow();
}

WebInspector.disconnectFromBackend = function()
{
InspectorFrontendHost.disconnectFromBackend();
}

WebInspector.documentClick = function(event)
{
var anchor = event.target.enclosingNodeOrSelfWithNodeName("a");
if (!anchor || anchor.target === "_blank")
return;


event.preventDefault();
event.stopPropagation();

function followLink()
{
if (WebInspector._showAnchorLocation(anchor))
return;

const profileMatch = WebInspector.ProfileType.URLRegExp.exec(anchor.href);
if (profileMatch) {
WebInspector.showProfileForURL(anchor.href);
return;
}

var parsedURL = anchor.href.asParsedURL();
if (parsedURL && parsedURL.scheme === "webkit-link-action") {
if (parsedURL.host === "show-panel") {
var panel = parsedURL.path.substring(1);
if (WebInspector.panels[panel])
WebInspector.showPanel(panel);
}
return;
}

WebInspector.showPanel("resources");
}

if (WebInspector.followLinkTimeout)
clearTimeout(WebInspector.followLinkTimeout);

if (anchor.preventFollowOnDoubleClick) {


if (event.detail === 1)
WebInspector.followLinkTimeout = setTimeout(followLink, 333);
return;
}

followLink();
}

WebInspector.openResource = function(resourceURL, inResourcesPanel)
{
var resource = WebInspector.resourceForURL(resourceURL);
if (inResourcesPanel && resource) {
WebInspector.panels.resources.showResource(resource);
WebInspector.showPanel("resources");
} else
PageAgent.open(resourceURL, true);
}

WebInspector._registerShortcuts = function()
{
var shortcut = WebInspector.KeyboardShortcut;
var section = WebInspector.shortcutsHelp.section(WebInspector.UIString("All Panels"));
var keys = [
shortcut.shortcutToString("]", shortcut.Modifiers.CtrlOrMeta),
shortcut.shortcutToString("[", shortcut.Modifiers.CtrlOrMeta)
];
section.addRelatedKeys(keys, WebInspector.UIString("Next/previous panel"));
section.addKey(shortcut.shortcutToString(shortcut.Keys.Esc), WebInspector.UIString("Toggle console"));
section.addKey(shortcut.shortcutToString("f", shortcut.Modifiers.CtrlOrMeta), WebInspector.UIString("Search"));
if (WebInspector.isMac()) {
keys = [
shortcut.shortcutToString("g", shortcut.Modifiers.Meta),
shortcut.shortcutToString("g", shortcut.Modifiers.Meta | shortcut.Modifiers.Shift)
];
section.addRelatedKeys(keys, WebInspector.UIString("Find next/previous"));
}

var goToShortcut = WebInspector.GoToLineDialog.createShortcut();
section.addKey(goToShortcut.name, WebInspector.UIString("Go to Line"));
}

WebInspector.documentKeyDown = function(event)
{
var isInputElement = event.target.nodeName === "INPUT";
var isInEditMode = event.target.enclosingNodeOrSelfWithClass("text-prompt") || WebInspector.isEditingAnyField();
const helpKey = WebInspector.isMac() ? "U+003F" : "U+00BF"; 

if (event.keyIdentifier === "F1" ||
(event.keyIdentifier === helpKey && event.shiftKey && (!isInEditMode && !isInputElement || event.metaKey))) {
WebInspector.shortcutsHelp.show();
event.stopPropagation();
event.preventDefault();
return;
}

if (this.currentFocusElement && this.currentFocusElement.handleKeyEvent) {
this.currentFocusElement.handleKeyEvent(event);
if (event.handled) {
event.preventDefault();
return;
}
}

if (this.currentPanel) {
this.currentPanel.handleShortcut(event);
if (event.handled) {
event.preventDefault();
return;
}
}

WebInspector.searchController.handleShortcut(event);
if (event.handled) {
event.preventDefault();
return;
}

if (WebInspector.isEditingAnyField())
return;

var isMac = WebInspector.isMac();
switch (event.keyIdentifier) {
case "Left":
var isBackKey = !isInEditMode && (isMac ? event.metaKey : event.ctrlKey);
if (isBackKey && this._panelHistory.canGoBack()) {
this._panelHistory.goBack();
event.preventDefault();
}
break;

case "Right":
var isForwardKey = !isInEditMode && (isMac ? event.metaKey : event.ctrlKey);
if (isForwardKey && this._panelHistory.canGoForward()) {
this._panelHistory.goForward();
event.preventDefault();
}
break;

case "U+001B": 
event.preventDefault();
if (this.drawer.fullPanel)
return;

this.drawer.visible = !this.drawer.visible;
break;


case "U+005B":
case "U+00DB": 
if (isMac)
var isRotateLeft = event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey;
else
var isRotateLeft = event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey;

if (isRotateLeft) {
var index = this.panelOrder.indexOf(this.currentPanel);
index = (index === 0) ? this.panelOrder.length - 1 : index - 1;
this.panelOrder[index].toolbarItem.click();
event.preventDefault();
}

break;


case "U+005D":
case "U+00DD":  
if (isMac)
var isRotateRight = event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey;
else
var isRotateRight = event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey;

if (isRotateRight) {
var index = this.panelOrder.indexOf(this.currentPanel);
index = (index + 1) % this.panelOrder.length;
this.panelOrder[index].toolbarItem.click();
event.preventDefault();
}

break;

case "U+0052": 
if ((event.metaKey && isMac) || (event.ctrlKey && !isMac)) {
PageAgent.reload(event.shiftKey);
event.preventDefault();
}
break;
case "F5":
if (!isMac)
PageAgent.reload(event.ctrlKey || event.shiftKey);
break;
}
}

WebInspector.documentCanCopy = function(event)
{
if (this.currentPanel && this.currentPanel.handleCopyEvent)
event.preventDefault();
}

WebInspector.documentCopy = function(event)
{
if (this.currentPanel && this.currentPanel.handleCopyEvent)
this.currentPanel.handleCopyEvent(event);
}

WebInspector.contextMenuEventFired = function(event)
{
if (event.handled || event.target.hasStyleClass("popup-glasspane"))
event.preventDefault();
}

WebInspector.animateStyle = function(animations, duration, callback)
{
var interval;
var complete = 0;
var hasCompleted = false;

const intervalDuration = (1000 / 30); 
const animationsLength = animations.length;
const propertyUnit = {opacity: ""};
const defaultUnit = "px";

function cubicInOut(t, b, c, d)
{
if ((t/=d/2) < 1) return c/2*t*t*t + b;
return c/2*((t-=2)*t*t + 2) + b;
}


for (var i = 0; i < animationsLength; ++i) {
var animation = animations[i];
var element = null, start = null, end = null, key = null;
for (key in animation) {
if (key === "element")
element = animation[key];
else if (key === "start")
start = animation[key];
else if (key === "end")
end = animation[key];
}

if (!element || !end)
continue;

if (!start) {
var computedStyle = element.ownerDocument.defaultView.getComputedStyle(element);
start = {};
for (key in end)
start[key] = parseInt(computedStyle.getPropertyValue(key));
animation.start = start;
} else
for (key in start)
element.style.setProperty(key, start[key] + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
}

function animateLoop()
{

complete += intervalDuration;
var next = complete + intervalDuration;


for (var i = 0; i < animationsLength; ++i) {
var animation = animations[i];
var element = animation.element;
var start = animation.start;
var end = animation.end;
if (!element || !end)
continue;

var style = element.style;
for (key in end) {
var endValue = end[key];
if (next < duration) {
var startValue = start[key];
var newValue = cubicInOut(complete, startValue, endValue - startValue, duration);
style.setProperty(key, newValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
} else
style.setProperty(key, endValue + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
}
}


if (complete >= duration) {
hasCompleted = true;
clearInterval(interval);
if (callback)
callback();
}
}

function forceComplete()
{
if (!hasCompleted) {
complete = duration;
animateLoop();
}
}

function cancel()
{
hasCompleted = true;
clearInterval(interval);
}

interval = setInterval(animateLoop, intervalDuration);
return {
cancel: cancel,
forceComplete: forceComplete
};
}

WebInspector.toggleAttach = function()
{
if (!this.attached)
InspectorFrontendHost.requestAttachWindow();
else
InspectorFrontendHost.requestDetachWindow();
}

WebInspector.elementDragStart = function(element, dividerDrag, elementDragEnd, event, cursor)
{
if (this._elementDraggingEventListener || this._elementEndDraggingEventListener)
this.elementDragEnd(event);

this._elementDraggingEventListener = dividerDrag;
this._elementEndDraggingEventListener = elementDragEnd;

document.addEventListener("mousemove", dividerDrag, true);
document.addEventListener("mouseup", elementDragEnd, true);

document.body.style.cursor = cursor;

event.preventDefault();
}

WebInspector.elementDragEnd = function(event)
{
document.removeEventListener("mousemove", this._elementDraggingEventListener, true);
document.removeEventListener("mouseup", this._elementEndDraggingEventListener, true);

document.body.style.removeProperty("cursor");

delete this._elementDraggingEventListener;
delete this._elementEndDraggingEventListener;

event.preventDefault();
}

WebInspector.toggleSearchingForNode = function()
{
if (this.panels.elements) {
this.showPanel("elements");
this.panels.elements.toggleSearchingForNode();
}
}

WebInspector.showConsole = function()
{
this.drawer.showView(this.console);
}

WebInspector.showPanel = function(panel)
{
if (!(panel in this.panels))
panel = "elements";
this.currentPanel = this.panels[panel];
}

WebInspector.startUserInitiatedDebugging = function()
{
this.currentPanel = this.panels.scripts;
WebInspector.debuggerModel.enableDebugger();
}

WebInspector.reset = function()
{
this.debuggerModel.reset();
for (var panelName in this.panels) {
var panel = this.panels[panelName];
if ("reset" in panel)
panel.reset();
}

this.resources = {};
this.highlightDOMNode(0);

this.console.clearMessages();
this.extensionServer.notifyInspectorReset();
}

WebInspector.bringToFront = function()
{
InspectorFrontendHost.bringToFront();
}

WebInspector.didCreateWorker = function()
{
var workersPane = WebInspector.panels.scripts.sidebarPanes.workers;
workersPane.addWorker.apply(workersPane, arguments);
}

WebInspector.didDestroyWorker = function()
{
var workersPane = WebInspector.panels.scripts.sidebarPanes.workers;
workersPane.removeWorker.apply(workersPane, arguments);
}

WebInspector.log = function(message, messageLevel)
{

var self = this;


function isLogAvailable()
{
return WebInspector.ConsoleMessage && WebInspector.RemoteObject && self.console;
}


function flushQueue()
{
var queued = WebInspector.log.queued;
if (!queued)
return;

for (var i = 0; i < queued.length; ++i)
logMessage(queued[i]);

delete WebInspector.log.queued;
}



function flushQueueIfAvailable()
{
if (!isLogAvailable())
return;

clearInterval(WebInspector.log.interval);
delete WebInspector.log.interval;

flushQueue();
}


function logMessage(message)
{
var repeatCount = 1;
if (message == WebInspector.log.lastMessage)
repeatCount = WebInspector.log.repeatCount + 1;

WebInspector.log.lastMessage = message;
WebInspector.log.repeatCount = repeatCount;


message = new WebInspector.RemoteObject.fromPrimitiveValue(message);


var msg = new WebInspector.ConsoleMessage(
WebInspector.ConsoleMessage.MessageSource.Other,
WebInspector.ConsoleMessage.MessageType.Log,
messageLevel || WebInspector.ConsoleMessage.MessageLevel.Debug,
-1,
null,
repeatCount,
null,
[message],
null);

self.console.addMessage(msg);
}


if (!isLogAvailable()) {
if (!WebInspector.log.queued)
WebInspector.log.queued = [];

WebInspector.log.queued.push(message);

if (!WebInspector.log.interval)
WebInspector.log.interval = setInterval(flushQueueIfAvailable, 1000);

return;
}


flushQueue();


logMessage(message);
}

WebInspector.drawLoadingPieChart = function(canvas, percent) {
var g = canvas.getContext("2d");
var darkColor = "rgb(122, 168, 218)";
var lightColor = "rgb(228, 241, 251)";
var cx = 8;
var cy = 8;
var r = 7;

g.beginPath();
g.arc(cx, cy, r, 0, Math.PI * 2, false);
g.closePath();

g.lineWidth = 1;
g.strokeStyle = darkColor;
g.fillStyle = lightColor;
g.fill();
g.stroke();

var startangle = -Math.PI / 2;
var endangle = startangle + (percent * Math.PI * 2);

g.beginPath();
g.moveTo(cx, cy);
g.arc(cx, cy, r, startangle, endangle, false);
g.closePath();

g.fillStyle = darkColor;
g.fill();
}

WebInspector.inspect = function(payload, hints)
{
var object = WebInspector.RemoteObject.fromPayload(payload);
if (object.type === "node") {

object.pushNodeToFrontend(WebInspector.updateFocusedNode.bind(WebInspector), object.release.bind(object));
return;
}

if (hints.databaseId) {
WebInspector.currentPanel = WebInspector.panels.resources;
WebInspector.panels.resources.selectDatabase(hints.databaseId);
} else if (hints.domStorageId) {
WebInspector.currentPanel = WebInspector.panels.resources;
WebInspector.panels.resources.selectDOMStorage(hints.domStorageId);
}

object.release();
}

WebInspector.updateFocusedNode = function(nodeId)
{
this._updateFocusedNode(nodeId);
this.highlightDOMNodeForTwoSeconds(nodeId);
}

WebInspector.displayNameForURL = function(url)
{
if (!url)
return "";

var resource = this.resourceForURL(url);
if (resource)
return resource.displayName;

if (!WebInspector.mainResource)
return url.trimURL("");

var lastPathComponent = WebInspector.mainResource.lastPathComponent;
var index = WebInspector.mainResource.url.indexOf(lastPathComponent);
if (index !== -1 && index + lastPathComponent.length === WebInspector.mainResource.url.length) {
var baseURL = WebInspector.mainResource.url.substring(0, index);
if (url.indexOf(baseURL) === 0)
return url.substring(index);
}

return url.trimURL(WebInspector.mainResource.domain);
}

WebInspector._showAnchorLocation = function(anchor)
{
var preferedPanel = this.panels[anchor.getAttribute("preferred_panel") || "scripts"];
if (WebInspector._showAnchorLocationInPanel(anchor, preferedPanel))
return true;
if (preferedPanel !== this.panels.resources && WebInspector._showAnchorLocationInPanel(anchor, this.panels.resources))
return true;
return false;
}

WebInspector._showAnchorLocationInPanel = function(anchor, panel)
{
if (!panel.canShowAnchorLocation(anchor))
return false;


if (anchor.hasStyleClass("webkit-html-external-link")) {
anchor.removeStyleClass("webkit-html-external-link");
anchor.addStyleClass("webkit-html-resource-link");
}

this.currentPanel = panel;
if (this.drawer)
this.drawer.immediatelyFinishAnimation();
this.currentPanel.showAnchorLocation(anchor);
return true;
}

WebInspector.linkifyStringAsFragment = function(string)
{
var container = document.createDocumentFragment();
var linkStringRegEx = /(?:[a-zA-Z][a-zA-Z0-9+.-]{2,}:\/\/|www\.)[\w$\-_+*'=\|\/\\(){}[\]%@&#~,:;.!?]{2,}[\w$\-_+*=\|\/\\({%@&#~]/;
    var lineColumnRegEx = /:(\d+)(:(\d+))?$/;

    while (string) {
        var linkString = linkStringRegEx.exec(string);
        if (!linkString)
            break;

        linkString = linkString[0];
        var title = linkString;
        var linkIndex = string.indexOf(linkString);
        var nonLink = string.substring(0, linkIndex);
        container.appendChild(document.createTextNode(nonLink));

        var profileStringMatches = WebInspector.ProfileType.URLRegExp.exec(title);
        if (profileStringMatches)
            title = WebInspector.panels.profiles.displayTitleForProfileLink(profileStringMatches[2], profileStringMatches[1]);

        var realURL = (linkString.indexOf("www.") === 0 ? "http://" + linkString : linkString);
        var lineColumnMatch = lineColumnRegEx.exec(realURL);
        if (lineColumnMatch)
            realURL = realURL.substring(0, realURL.length - lineColumnMatch[0].length);

        var hasResourceWithURL = !!WebInspector.resourceForURL(realURL);
        var urlNode = WebInspector.linkifyURLAsNode(realURL, title, null, hasResourceWithURL);
        container.appendChild(urlNode);
        if (lineColumnMatch) {
            urlNode.setAttribute("line_number", lineColumnMatch[1]);
            urlNode.setAttribute("preferred_panel", "scripts");
        }
        string = string.substring(linkIndex + linkString.length, string.length);
    }

    if (string)
        container.appendChild(document.createTextNode(string));

    return container;
}

WebInspector.showProfileForURL = function(url)
{
    WebInspector.showPanel("profiles");
    WebInspector.panels.profiles.showProfileForURL(url);
}

WebInspector.linkifyURLAsNode = function(url, linkText, classes, isExternal, tooltipText)
{
    if (!linkText)
        linkText = url;
    classes = (classes ? classes + " " : "");
    classes += isExternal ? "webkit-html-external-link" : "webkit-html-resource-link";

    var a = document.createElement("a");
    a.href = url;
    a.className = classes;
    if (typeof tooltipText === "undefined")
        a.title = url;
    else if (typeof tooltipText !== "string" || tooltipText.length)
        a.title = tooltipText;
    a.textContent = linkText;
    a.style.maxWidth = "100%";
    if (isExternal)
        a.setAttribute("target", "_blank");

    return a;
}

WebInspector.linkifyURL = function(url, linkText, classes, isExternal, tooltipText)
{
    // Use the DOM version of this function so as to avoid needing to escape attributes.
    // FIXME:  Get rid of linkifyURL entirely.
    return WebInspector.linkifyURLAsNode(url, linkText, classes, isExternal, tooltipText).outerHTML;
}

WebInspector.linkifyResourceAsNode = function(url, preferredPanel, lineNumber, classes, tooltipText)
{
    var linkText = WebInspector.displayNameForURL(url);
    if (lineNumber)
        linkText += ":" + lineNumber;
    var node = WebInspector.linkifyURLAsNode(url, linkText, classes, false, tooltipText);
    node.setAttribute("line_number", lineNumber);
    node.setAttribute("preferred_panel", preferredPanel);
    return node;
}

WebInspector.resourceURLForRelatedNode = function(node, url)
{
    if (!url || url.indexOf("://") > 0)
        return url;

    for (var frameOwnerCandidate = node; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) {
        if (frameOwnerCandidate.documentURL) {
            var result = WebInspector.completeURL(frameOwnerCandidate.documentURL, url);
            if (result)
                return result;
            break;
        }
    }

    // documentURL not found or has bad value
    var resourceURL = url;
    function callback(resource)
    {
        if (resource.path === url) {
            resourceURL = resource.url;
            return true;
        }
    }
    WebInspector.forAllResources(callback);
    return resourceURL;
}

WebInspector.completeURL = function(baseURL, href)
{
    if (href) {
        // Return absolute URLs as-is.
        var parsedHref = href.asParsedURL();
        if (parsedHref && parsedHref.scheme)
            return href;
    }

    var parsedURL = baseURL.asParsedURL();
    if (parsedURL) {
        var path = href;
        if (path.charAt(0) !== "/") {
            var basePath = parsedURL.path;
            // A href of "?foo=bar" implies "basePath?foo=bar".
            // With "basePath?a=b" and "?foo=bar" we should get "basePath?foo=bar".
            var prefix;
            if (path.charAt(0) === "?") {
                var basePathCutIndex = basePath.indexOf("?");
                if (basePathCutIndex !== -1)
                    prefix = basePath.substring(0, basePathCutIndex);
                else
                    prefix = basePath;
            } else
                prefix = basePath.substring(0, basePath.lastIndexOf("/")) + "/";

            path = prefix + path;
        } else if (path.length > 1 && path.charAt(1) === "/") {
            // href starts with "//" which is a full URL with the protocol dropped (use the baseURL protocol).
            return parsedURL.scheme + ":" + path;
        }
        return parsedURL.scheme + "://" + parsedURL.host + (parsedURL.port ? (":" + parsedURL.port) : "") + path;
    }
    return null;
}

WebInspector.addMainEventListeners = function(doc)
{
    doc.defaultView.addEventListener("focus", this.windowFocused.bind(this), false);
    doc.defaultView.addEventListener("blur", this.windowBlurred.bind(this), false);
    doc.addEventListener("click", this.documentClick.bind(this), true);
}

WebInspector.frontendReused = function()
{
    this.resourceTreeModel.frontendReused();
    this.reset();
}

WebInspector.UIString = function(string)
{
    if (window.localizedStrings && string in window.localizedStrings)
        string = window.localizedStrings[string];
    else {
        if (!(string in WebInspector.missingLocalizedStrings)) {
            if (!WebInspector.InspectorBackendStub)
                console.warn("Localized string \"" + string + "\" not found.");
            WebInspector.missingLocalizedStrings[string] = true;
        }

        if (Preferences.showMissingLocalizedStrings)
            string += " (not localized)";
    }

    return String.vsprintf(string, Array.prototype.slice.call(arguments, 1));
}

WebInspector.formatLocalized = function(format, substitutions, formatters, initialValue, append)
{
    return String.format(WebInspector.UIString(format), substitutions, formatters, initialValue, append);
}

WebInspector.isMac = function()
{
    if (!("_isMac" in this))
        this._isMac = WebInspector.platform === "mac";

    return this._isMac;
}

WebInspector.useLowerCaseMenuTitles = function()
{
    return WebInspector.platform === "windows" && Preferences.useLowerCaseMenuTitlesOnWindows;
}

WebInspector.isBeingEdited = function(element)
{
    return element.__editing;
}

WebInspector.markBeingEdited = function(element, value)
{
    if (value) {
        if (element.__editing)
            return false;
        element.__editing = true;
        WebInspector.__editingCount = (WebInspector.__editingCount || 0) + 1;
    } else {
        if (!element.__editing)
            return false;
        delete element.__editing;
        --WebInspector.__editingCount;
    }
    return true;
}

WebInspector.isEditingAnyField = function()
{
    return !!WebInspector.__editingCount;
}

// Available config fields (all optional):
// context: Object - an arbitrary context object to be passed to the commit and cancel handlers
// commitHandler: Function - handles editing "commit" outcome
// cancelHandler: Function - handles editing "cancel" outcome
// customFinishHandler: Function - custom finish handler for the editing session (invoked on keydown)
// pasteHandler: Function - handles the "paste" event, return values are the same as those for customFinishHandler
// multiline: Boolean - whether the edited element is multiline
WebInspector.startEditing = function(element, config)
{
    if (!WebInspector.markBeingEdited(element, true))
        return;

    config = config || {};
    var committedCallback = config.commitHandler;
    var cancelledCallback = config.cancelHandler;
    var pasteCallback = config.pasteHandler;
    var context = config.context;
    var oldText = getContent(element);
    var moveDirection = "";

    element.addStyleClass("editing");

    var oldTabIndex = element.tabIndex;
    if (element.tabIndex < 0)
        element.tabIndex = 0;

    function blurEventListener() {
        editingCommitted.call(element);
    }

    function getContent(element) {
        if (element.tagName === "INPUT" && element.type === "text")
            return element.value;
        else
            return element.textContent;
    }

    function cleanUpAfterEditing() {
        WebInspector.markBeingEdited(element, false);

        this.removeStyleClass("editing");
        this.tabIndex = oldTabIndex;
        this.scrollTop = 0;
        this.scrollLeft = 0;

        element.removeEventListener("blur", blurEventListener, false);
        element.removeEventListener("keydown", keyDownEventListener, true);
        if (pasteCallback)
            element.removeEventListener("paste", pasteEventListener, true);

        if (element === WebInspector.currentFocusElement || element.isAncestor(WebInspector.currentFocusElement))
            WebInspector.currentFocusElement = WebInspector.previousFocusElement;
    }

    function editingCancelled() {
        if (this.tagName === "INPUT" && this.type === "text")
            this.value = oldText;
        else
            this.textContent = oldText;

        cleanUpAfterEditing.call(this);

        if (cancelledCallback)
            cancelledCallback(this, context);
    }

    function editingCommitted() {
        cleanUpAfterEditing.call(this);

        if (committedCallback)
            committedCallback(this, getContent(this), oldText, context, moveDirection);
    }

    function defaultFinishHandler(event)
    {
        var isMetaOrCtrl = WebInspector.isMac() ?
            event.metaKey && !event.shiftKey && !event.ctrlKey && !event.altKey :
            event.ctrlKey && !event.shiftKey && !event.metaKey && !event.altKey;
        if (isEnterKey(event) && (event.isMetaOrCtrlForTest || !config.multiline || isMetaOrCtrl))
            return "commit";
        else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code || event.keyIdentifier === "U+001B")
            return "cancel";
        else if (event.keyIdentifier === "U+0009") // Tab key
            return "move-" + (event.shiftKey ? "backward" : "forward");
    }

    function handleEditingResult(result, event)
    {
        if (result === "commit") {
            editingCommitted.call(element);
            event.preventDefault();
            event.stopPropagation();
        } else if (result === "cancel") {
            editingCancelled.call(element);
            event.preventDefault();
            event.stopPropagation();
        } else if (result && result.indexOf("move-") === 0) {
            moveDirection = result.substring(5);
            if (event.keyIdentifier !== "U+0009")
                blurEventListener();
        }
    }

    function pasteEventListener(event)
    {
        var result = pasteCallback(event);
        handleEditingResult(result, event);
    }

    function keyDownEventListener(event)
    {
        var handler = config.customFinishHandler || defaultFinishHandler;
        var result = handler(event);
        handleEditingResult(result, event);
    }

    element.addEventListener("blur", blurEventListener, false);
    element.addEventListener("keydown", keyDownEventListener, true);
    if (pasteCallback)
        element.addEventListener("paste", pasteEventListener, true);

    WebInspector.currentFocusElement = element;
    return {
        cancel: editingCancelled.bind(element),
        commit: editingCommitted.bind(element)
    };
}

WebInspector._toolbarItemClicked = function(event)
{
    var toolbarItem = event.currentTarget;
    this.currentPanel = toolbarItem.panel;
}

// This table maps MIME types to the Resource.Types which are valid for them.
// The following line:
//    "text/html":                {0: 1},
// means that text/html is a valid MIME type for resources that have type
// WebInspector.Resource.Type.Document (which has a value of 0).
WebInspector.MIMETypes = {
    "text/html":                   {0: true},
    "text/xml":                    {0: true},
    "text/plain":                  {0: true},
    "application/xhtml+xml":       {0: true},
    "text/css":                    {1: true},
    "text/xsl":                    {1: true},
    "image/jpeg":                  {2: true},
    "image/png":                   {2: true},
    "image/gif":                   {2: true},
    "image/bmp":                   {2: true},
    "image/vnd.microsoft.icon":    {2: true},
    "image/x-icon":                {2: true},
    "image/x-xbitmap":             {2: true},
    "font/ttf":                    {3: true},
    "font/opentype":               {3: true},
    "application/x-font-type1":    {3: true},
    "application/x-font-ttf":      {3: true},
    "application/x-font-woff":     {3: true},
    "application/x-truetype-font": {3: true},
    "text/javascript":             {4: true},
    "text/ecmascript":             {4: true},
    "application/javascript":      {4: true},
    "application/ecmascript":      {4: true},
    "application/x-javascript":    {4: true},
    "text/javascript1.1":          {4: true},
    "text/javascript1.2":          {4: true},
    "text/javascript1.3":          {4: true},
    "text/jscript":                {4: true},
    "text/livescript":             {4: true},
}

WebInspector.PanelHistory = function()
{
    this._history = [];
    this._historyIterator = -1;
}

WebInspector.PanelHistory.prototype = {
    canGoBack: function()
    {
        return this._historyIterator > 0;
    },

    goBack: function()
    {
        this._inHistory = true;
        WebInspector.currentPanel = WebInspector.panels[this._history[--this._historyIterator]];
        delete this._inHistory;
    },

    canGoForward: function()
    {
        return this._historyIterator < this._history.length - 1;
    },

    goForward: function()
    {
        this._inHistory = true;
        WebInspector.currentPanel = WebInspector.panels[this._history[++this._historyIterator]];
        delete this._inHistory;
    },

    setPanel: function(panelName)
    {
        if (this._inHistory)
            return;

        this._history.splice(this._historyIterator + 1, this._history.length - this._historyIterator - 1);
        if (!this._history.length || this._history[this._history.length - 1] !== panelName)
            this._history.push(panelName);
        this._historyIterator = this._history.length - 1;
    }
}

/* InspectorBackendStub.js */

// Copyright (c) 2010 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.


InspectorBackendStub = function()
{
    this._lastCallbackId = 1;
    this._pendingResponsesCount = 0;
    this._callbacks = {};
    this._domainDispatchers = {};
    this._eventArgs = {};
    this._registerDelegate('{"method": "Page.addScriptToEvaluateOnLoad", "params": {"scriptSource": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "Page.removeAllScriptsToEvaluateOnLoad", "id": 0}');
    this._registerDelegate('{"method": "Page.reload", "params": {"ignoreCache": {"optional": true , "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "Page.open", "params": {"url": {"optional": false, "type": "string"},"newWindow": {"optional": true , "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "Page.getCookies", "id": 0}');
    this._registerDelegate('{"method": "Page.deleteCookie", "params": {"cookieName": {"optional": false, "type": "string"},"domain": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "Page.getResourceTree", "id": 0}');
    this._registerDelegate('{"method": "Page.getResourceContent", "params": {"frameId": {"optional": false, "type": "string"},"url": {"optional": false, "type": "string"},"base64Encode": {"optional": true , "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "Page.searchInResources", "params": {"text": {"optional": false, "type": "string"},"caseSensitive": {"optional": true , "type": "boolean"},"isRegex": {"optional": true , "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "Runtime.evaluate", "params": {"expression": {"optional": false, "type": "string"},"objectGroup": {"optional": true , "type": "string"},"includeCommandLineAPI": {"optional": true , "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "Runtime.evaluateOn", "params": {"objectId": {"optional": false, "type": "string"},"expression": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "Runtime.getProperties", "params": {"objectId": {"optional": false, "type": "string"},"ignoreHasOwnProperty": {"optional": false, "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "Runtime.setPropertyValue", "params": {"objectId": {"optional": false, "type": "string"},"propertyName": {"optional": false, "type": "string"},"expression": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "Runtime.releaseObject", "params": {"objectId": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "Runtime.releaseObjectGroup", "params": {"objectGroup": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "Console.enable", "id": 0}');
    this._registerDelegate('{"method": "Console.disable", "id": 0}');
    this._registerDelegate('{"method": "Console.clearConsoleMessages", "id": 0}');
    this._registerDelegate('{"method": "Console.setMonitoringXHREnabled", "params": {"enabled": {"optional": false, "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "Console.addInspectedNode", "params": {"nodeId": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "Network.enable", "id": 0}');
    this._registerDelegate('{"method": "Network.disable", "id": 0}');
    this._registerDelegate('{"method": "Network.setUserAgentOverride", "params": {"userAgent": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "Network.setExtraHeaders", "params": {"headers": {"optional": false, "type": "object"}}, "id": 0}');
    this._registerDelegate('{"method": "Network.setBackgroundEventsCollectionEnabled", "params": {"enabled": {"optional": false, "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "Network.isBackgroundEventsCollectionEnabled", "id": 0}');
    this._registerDelegate('{"method": "Database.enable", "id": 0}');
    this._registerDelegate('{"method": "Database.disable", "id": 0}');
    this._registerDelegate('{"method": "Database.getDatabaseTableNames", "params": {"databaseId": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "Database.executeSQL", "params": {"databaseId": {"optional": false, "type": "number"},"query": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOMStorage.enable", "id": 0}');
    this._registerDelegate('{"method": "DOMStorage.disable", "id": 0}');
    this._registerDelegate('{"method": "DOMStorage.getDOMStorageEntries", "params": {"storageId": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "DOMStorage.setDOMStorageItem", "params": {"storageId": {"optional": false, "type": "number"},"key": {"optional": false, "type": "string"},"value": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOMStorage.removeDOMStorageItem", "params": {"storageId": {"optional": false, "type": "number"},"key": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "ApplicationCache.getApplicationCaches", "id": 0}');
    this._registerDelegate('{"method": "DOM.getDocument", "id": 0}');
    this._registerDelegate('{"method": "DOM.getChildNodes", "params": {"nodeId": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.querySelector", "params": {"nodeId": {"optional": false, "type": "number"},"selectors": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.querySelectorAll", "params": {"nodeId": {"optional": false, "type": "number"},"selectors": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.setNodeName", "params": {"nodeId": {"optional": false, "type": "number"},"name": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.setNodeValue", "params": {"nodeId": {"optional": false, "type": "number"},"value": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.removeNode", "params": {"nodeId": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.setAttribute", "params": {"nodeId": {"optional": false, "type": "number"},"name": {"optional": false, "type": "string"},"value": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.removeAttribute", "params": {"nodeId": {"optional": false, "type": "number"},"name": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.getEventListenersForNode", "params": {"nodeId": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.copyNode", "params": {"nodeId": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.getOuterHTML", "params": {"nodeId": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.setOuterHTML", "params": {"nodeId": {"optional": false, "type": "number"},"outerHTML": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.performSearch", "params": {"query": {"optional": false, "type": "string"},"runSynchronously": {"optional": true , "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.cancelSearch", "id": 0}');
    this._registerDelegate('{"method": "DOM.pushNodeToFrontend", "params": {"objectId": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.setInspectModeEnabled", "params": {"enabled": {"optional": false, "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.highlightNode", "params": {"nodeId": {"optional": false, "type": "number"},"mode": {"optional": true , "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.hideNodeHighlight", "id": 0}');
    this._registerDelegate('{"method": "DOM.highlightFrame", "params": {"frameId": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.hideFrameHighlight", "id": 0}');
    this._registerDelegate('{"method": "DOM.pushNodeByPathToFrontend", "params": {"path": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOM.resolveNode", "params": {"nodeId": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "CSS.getStylesForNode", "params": {"nodeId": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "CSS.getComputedStyleForNode", "params": {"nodeId": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "CSS.getInlineStyleForNode", "params": {"nodeId": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "CSS.getAllStyleSheets", "id": 0}');
    this._registerDelegate('{"method": "CSS.getStyleSheet", "params": {"styleSheetId": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "CSS.getStyleSheetText", "params": {"styleSheetId": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "CSS.setStyleSheetText", "params": {"styleSheetId": {"optional": false, "type": "string"},"text": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "CSS.setPropertyText", "params": {"styleId": {"optional": false, "type": "object"},"propertyIndex": {"optional": false, "type": "number"},"text": {"optional": false, "type": "string"},"overwrite": {"optional": false, "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "CSS.toggleProperty", "params": {"styleId": {"optional": false, "type": "object"},"propertyIndex": {"optional": false, "type": "number"},"disable": {"optional": false, "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "CSS.setRuleSelector", "params": {"ruleId": {"optional": false, "type": "object"},"selector": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "CSS.addRule", "params": {"contextNodeId": {"optional": false, "type": "number"},"selector": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "CSS.getSupportedCSSProperties", "id": 0}');
    this._registerDelegate('{"method": "Timeline.start", "id": 0}');
    this._registerDelegate('{"method": "Timeline.stop", "id": 0}');
    this._registerDelegate('{"method": "Debugger.enable", "id": 0}');
    this._registerDelegate('{"method": "Debugger.disable", "id": 0}');
    this._registerDelegate('{"method": "Debugger.setBreakpointsActive", "params": {"active": {"optional": false, "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "Debugger.setBreakpointByUrl", "params": {"url": {"optional": false, "type": "string"},"lineNumber": {"optional": false, "type": "number"},"columnNumber": {"optional": true , "type": "number"},"condition": {"optional": true , "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "Debugger.setBreakpoint", "params": {"location": {"optional": false, "type": "object"},"condition": {"optional": true , "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "Debugger.removeBreakpoint", "params": {"breakpointId": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "Debugger.continueToLocation", "params": {"location": {"optional": false, "type": "object"}}, "id": 0}');
    this._registerDelegate('{"method": "Debugger.stepOver", "id": 0}');
    this._registerDelegate('{"method": "Debugger.stepInto", "id": 0}');
    this._registerDelegate('{"method": "Debugger.stepOut", "id": 0}');
    this._registerDelegate('{"method": "Debugger.pause", "id": 0}');
    this._registerDelegate('{"method": "Debugger.resume", "id": 0}');
    this._registerDelegate('{"method": "Debugger.editScriptSource", "params": {"sourceId": {"optional": false, "type": "string"},"scriptSource": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "Debugger.getScriptSource", "params": {"sourceId": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "Debugger.setPauseOnExceptions", "params": {"state": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "Debugger.evaluateOnCallFrame", "params": {"callFrameId": {"optional": false, "type": "string"},"expression": {"optional": false, "type": "string"},"objectGroup": {"optional": true , "type": "string"},"includeCommandLineAPI": {"optional": true , "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "DOMDebugger.setDOMBreakpoint", "params": {"nodeId": {"optional": false, "type": "number"},"type": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "DOMDebugger.removeDOMBreakpoint", "params": {"nodeId": {"optional": false, "type": "number"},"type": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "DOMDebugger.setEventListenerBreakpoint", "params": {"eventName": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOMDebugger.removeEventListenerBreakpoint", "params": {"eventName": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOMDebugger.setXHRBreakpoint", "params": {"url": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "DOMDebugger.removeXHRBreakpoint", "params": {"url": {"optional": false, "type": "string"}}, "id": 0}');
    this._registerDelegate('{"method": "Profiler.enable", "id": 0}');
    this._registerDelegate('{"method": "Profiler.disable", "id": 0}');
    this._registerDelegate('{"method": "Profiler.isEnabled", "id": 0}');
    this._registerDelegate('{"method": "Profiler.start", "id": 0}');
    this._registerDelegate('{"method": "Profiler.stop", "id": 0}');
    this._registerDelegate('{"method": "Profiler.getProfileHeaders", "id": 0}');
    this._registerDelegate('{"method": "Profiler.getProfile", "params": {"type": {"optional": false, "type": "string"},"uid": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "Profiler.removeProfile", "params": {"type": {"optional": false, "type": "string"},"uid": {"optional": false, "type": "number"}}, "id": 0}');
    this._registerDelegate('{"method": "Profiler.clearProfiles", "id": 0}');
    this._registerDelegate('{"method": "Profiler.takeHeapSnapshot", "params": {"detailed": {"optional": false, "type": "boolean"}}, "id": 0}');
    this._registerDelegate('{"method": "Profiler.collectGarbage", "id": 0}');
    this._registerDelegate('{"method": "Worker.sendMessageToWorker", "params": {"workerId": {"optional": false, "type": "number"},"message": {"optional": false, "type": "object"}}, "id": 0}');
    this._eventArgs["Inspector.frontendReused"] = [];
    this._eventArgs["Inspector.bringToFront"] = [];
    this._eventArgs["Inspector.disconnectFromBackend"] = [];
    this._eventArgs["Inspector.reset"] = [];
    this._eventArgs["Inspector.showPanel"] = ["panel"];
    this._eventArgs["Inspector.startUserInitiatedDebugging"] = [];
    this._eventArgs["Inspector.evaluateForTestInFrontend"] = ["testCallId","script"];
    this._eventArgs["Inspector.inspect"] = ["object","hints"];
    this._eventArgs["Inspector.didCreateWorker"] = ["id","url","isShared"];
    this._eventArgs["Inspector.didDestroyWorker"] = ["id"];
    this._eventArgs["Page.domContentEventFired"] = ["timestamp"];
    this._eventArgs["Page.loadEventFired"] = ["timestamp"];
    this._eventArgs["Page.frameNavigated"] = ["frame","loaderId"];
    this._eventArgs["Page.frameDetached"] = ["frameId"];
    this._eventArgs["Console.messageAdded"] = ["messageObj"];
    this._eventArgs["Console.messageRepeatCountUpdated"] = ["count"];
    this._eventArgs["Console.messagesCleared"] = [];
    this._eventArgs["Network.requestWillBeSent"] = ["identifier","frameId","loaderId","documentURL","request","timestamp","stackTrace","redirectResponse"];
    this._eventArgs["Network.resourceMarkedAsCached"] = ["identifier"];
    this._eventArgs["Network.responseReceived"] = ["identifier","timestamp","type","response"];
    this._eventArgs["Network.dataReceived"] = ["identifier","timestamp","dataLength","encodedDataLength"];
    this._eventArgs["Network.loadingFinished"] = ["identifier","timestamp"];
    this._eventArgs["Network.loadingFailed"] = ["identifier","timestamp","errorText","canceled"];
    this._eventArgs["Network.resourceLoadedFromMemoryCache"] = ["frameId","loaderId","documentURL","timestamp","resource"];
    this._eventArgs["Network.initialContentSet"] = ["identifier","content","type"];
    this._eventArgs["Network.webSocketWillSendHandshakeRequest"] = ["identifier","timestamp","request"];
    this._eventArgs["Network.webSocketHandshakeResponseReceived"] = ["identifier","timestamp","response"];
    this._eventArgs["Network.webSocketCreated"] = ["identifier","url"];
    this._eventArgs["Network.webSocketClosed"] = ["identifier","timestamp"];
    this._eventArgs["Database.addDatabase"] = ["database"];
    this._eventArgs["Database.sqlTransactionSucceeded"] = ["transactionId","columnNames","values"];
    this._eventArgs["Database.sqlTransactionFailed"] = ["transactionId","sqlError"];
    this._eventArgs["DOMStorage.addDOMStorage"] = ["storage"];
    this._eventArgs["DOMStorage.updateDOMStorage"] = ["storageId"];
    this._eventArgs["ApplicationCache.updateApplicationCacheStatus"] = ["status"];
    this._eventArgs["ApplicationCache.updateNetworkState"] = ["isNowOnline"];
    this._eventArgs["DOM.documentUpdated"] = [];
    this._eventArgs["DOM.setChildNodes"] = ["parentId","nodes"];
    this._eventArgs["DOM.attributesUpdated"] = ["id","attributes"];
    this._eventArgs["DOM.characterDataModified"] = ["id","newValue"];
    this._eventArgs["DOM.childNodeCountUpdated"] = ["id","newValue"];
    this._eventArgs["DOM.childNodeInserted"] = ["parentId","prevId","node"];
    this._eventArgs["DOM.childNodeRemoved"] = ["parentId","id"];
    this._eventArgs["DOM.searchResults"] = ["nodeIds"];
    this._eventArgs["Timeline.started"] = [];
    this._eventArgs["Timeline.stopped"] = [];
    this._eventArgs["Timeline.eventRecorded"] = ["record"];
    this._eventArgs["Debugger.debuggerWasEnabled"] = [];
    this._eventArgs["Debugger.debuggerWasDisabled"] = [];
    this._eventArgs["Debugger.scriptParsed"] = ["sourceId","url","startLine","startColumn","endLine","endColumn","isContentScript"];
    this._eventArgs["Debugger.scriptFailedToParse"] = ["url","data","firstLine","errorLine","errorMessage"];
    this._eventArgs["Debugger.breakpointResolved"] = ["breakpointId","location"];
    this._eventArgs["Debugger.paused"] = ["details"];
    this._eventArgs["Debugger.resumed"] = [];
    this._eventArgs["Profiler.profilerWasEnabled"] = [];
    this._eventArgs["Profiler.profilerWasDisabled"] = [];
    this._eventArgs["Profiler.addProfileHeader"] = ["header"];
    this._eventArgs["Profiler.addHeapSnapshotChunk"] = ["uid","chunk"];
    this._eventArgs["Profiler.finishHeapSnapshot"] = ["uid"];
    this._eventArgs["Profiler.setRecordingProfile"] = ["isProfiling"];
    this._eventArgs["Profiler.resetProfiles"] = [];
    this._eventArgs["Profiler.reportHeapSnapshotProgress"] = ["done","total"];
    this._eventArgs["Worker.workerCreated"] = ["workerId"];
    this._eventArgs["Worker.dispatchMessageFromWorker"] = ["workerId","message"];
}

InspectorBackendStub.prototype = {
    _wrap: function(callback)
    {
        var callbackId = this._lastCallbackId++;
        this._callbacks[callbackId] = callback || function() {};
        return callbackId;
    },

    _registerDelegate: function(requestString)
    {
        var domainAndFunction = JSON.parse(requestString).method.split(".");
        var agentName = domainAndFunction[0] + "Agent";
        if (!window[agentName])
            window[agentName] = {};
        window[agentName][domainAndFunction[1]] = this.sendMessageToBackend.bind(this, requestString);
    },

    sendMessageToBackend: function()
    {
        var args = Array.prototype.slice.call(arguments);
        var request = JSON.parse(args.shift());
        var callback = (args.length && typeof args[args.length - 1] === "function") ? args.pop() : 0;
        var domainAndMethod = request.method.split(".");
        var agentMethod = domainAndMethod[0] + "Agent." + domainAndMethod[1];

        if (request.params) {
            for (var key in request.params) {
                var typeName = request.params[key].type;
                var optionalFlag = request.params[key].optional;

                if (args.length === 0 && !optionalFlag) {
                    console.error("Protocol Error: Invalid number of arguments for method '" + agentMethod + "' call. It should have the next arguments '" + JSON.stringify(request.params) + "'.");
                    return;
                }

                var value = args.shift();
                if (optionalFlag && typeof value === "undefined") {
                    delete request.params[key];
                    continue;
                }

                if (typeof value !== typeName) {
                    console.error("Protocol Error: Invalid type of argument '" + key + "' for method '" + agentMethod + "' call. It should be '" + typeName + "' but it is '" + typeof value + "'.");
                    return;
                }

                request.params[key] = value;
            }
        }

        if (args.length === 1 && !callback) {
            if (typeof args[0] !== "undefined") {
                console.error("Protocol Error: Optional callback argument for method '" + agentMethod + "' call should be a function but its type is '" + typeof args[0] + "'.");
                return;
            }
        }
        request.id = this._wrap(callback || function() {});

        if (window.dumpInspectorProtocolMessages)
            console.log("frontend: " + JSON.stringify(request));

        ++this._pendingResponsesCount;
        this.sendMessageObjectToBackend(request);
    },

    sendMessageObjectToBackend: function(messageObject)
    {
        var message = JSON.stringify(messageObject);
        InspectorFrontendHost.sendMessageToBackend(message);
    },

    registerDomainDispatcher: function(domain, dispatcher)
    {
        this._domainDispatchers[domain] = dispatcher;
    },

    dispatch: function(message)
    {
        if (window.dumpInspectorProtocolMessages)
            console.log("backend: " + ((typeof message === "string") ? message : JSON.stringify(message)));

        var messageObject = (typeof message === "string") ? JSON.parse(message) : message;

        if ("id" in messageObject) { // just a response for some request
            if (messageObject.error && messageObject.error.code !== -32000)
                this.reportProtocolError(messageObject);

            var arguments = [];
            if (messageObject.result) {
                for (var key in messageObject.result)
                    arguments.push(messageObject.result[key]);
            }

            var callback = this._callbacks[messageObject.id];
            if (callback) {
                arguments.unshift(messageObject.error);
                callback.apply(null, arguments);
                --this._pendingResponsesCount;
                delete this._callbacks[messageObject.id];
            }

            if (this._scripts && !this._pendingResponsesCount)
                this.runAfterPendingDispatches();

            return;
        } else {
            var method = messageObject.method.split(".");
            var domainName = method[0];
            var functionName = method[1];
            if (!(domainName in this._domainDispatchers)) {
                console.error("Protocol Error: the message is for non-existing domain '" + domainName + "'");
                return;
            }
            var dispatcher = this._domainDispatchers[domainName];
            if (!(functionName in dispatcher)) {
                console.error("Protocol Error: Attempted to dispatch an unimplemented method '" + messageObject.method + "'");
                return;
            }

            if (!this._eventArgs[messageObject.method]) {
                console.error("Protocol Error: Attempted to dispatch an unspecified method '" + messageObject.method + "'");
                return;
            }

            var params = [];
            if (messageObject.params) {
                var paramNames = this._eventArgs[messageObject.method];
                for (var i = 0; i < paramNames.length; ++i)
                    params.push(messageObject.params[paramNames[i]]);
            }

            dispatcher[functionName].apply(dispatcher, params);
        }
    },

    reportProtocolError: function(messageObject)
    {
        var error = messageObject.error;
        console.error(error.message + "(" + error.code + "): request with id = " + messageObject.id + " failed.");
        for (var i = 0; i < error.data.length; ++i)
            console.error("    " + error.data[i]);
    },

    runAfterPendingDispatches: function(script)
    {
        if (!this._scripts)
            this._scripts = [];

        if (script)
            this._scripts.push(script);

        if (!this._pendingResponsesCount) {
            var scripts = this._scripts;
            this._scripts = []
            for (var id = 0; id < scripts.length; ++id)
                 scripts[id].call(this);
        }
    }
}

InspectorBackend = new InspectorBackendStub();
/* InspectorFrontendHostStub.js */

/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

if (!window.InspectorFrontendHost) {

WebInspector.InspectorFrontendHostStub = function()
{
    this._attachedWindowHeight = 0;
}

WebInspector._platformFlavor = WebInspector.PlatformFlavor.MacLeopard;

WebInspector.InspectorFrontendHostStub.prototype = {
    platform: function()
    {
        var match = navigator.userAgent.match(/Windows NT/);
        if (match)
            return "windows";
        match = navigator.userAgent.match(/Mac OS X/);
        if (match)
            return "mac";
        return "linux";
    },

    port: function()
    {
        return "unknown";
    },

    bringToFront: function()
    {
        this._windowVisible = true;
    },

    closeWindow: function()
    {
        this._windowVisible = false;
    },

    disconnectFromBackend: function()
    {
        this._windowVisible = false;
    },

    attach: function()
    {
    },

    detach: function()
    {
    },

    search: function(sourceRow, query)
    {
    },

    setAttachedWindowHeight: function(height)
    {
    },

    moveWindowBy: function(x, y)
    {
    },

    setExtensionAPI: function(script)
    {
    },

    loaded: function()
    {
    },

    localizedStringsURL: function()
    {
        return undefined;
    },

    hiddenPanels: function()
    {
        return "";
    },

    inspectedURLChanged: function(url)
    {
    },

    copyText: function()
    {
    },

    saveAs: function(fileName, content)
    {
        var builder = new WebKitBlobBuilder();
        builder.append(content);
        var blob = builder.getBlob("application/octet-stream");
    
        var fr = new FileReader();
        fr.onload = function(e) {
            // Force download
            window.location = this.result;
        }
        fr.readAsDataURL(blob);
    },

    canAttachWindow: function()
    {
        return false;
    },

    sendMessageToBackend: function(message)
    {
    },

    saveSessionSetting: function(key, value)
    {
    },

    loadSessionSetting: function(key)
    {
    }
}

InspectorFrontendHost = new WebInspector.InspectorFrontendHostStub();

}

/* ExtensionRegistryStub.js */

/*
 * Copyright (C) 2010 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

if (!window.InspectorExtensionRegistry) {

WebInspector.InspectorExtensionRegistryStub = function()
{
}

WebInspector.InspectorExtensionRegistryStub.prototype = {
    getExtensionsAsync: function()
    {
    }
};

InspectorExtensionRegistry = new WebInspector.InspectorExtensionRegistryStub();

}

/* Object.js */

/*
 * Copyright (C) 2008 Apple Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

WebInspector.Object = function() {
}

WebInspector.Object.prototype = {
    addEventListener: function(eventType, listener, thisObject)
    {
        if (!("_listeners" in this))
            this._listeners = {};
        if (!(eventType in this._listeners))
            this._listeners[eventType] = [];
        this._listeners[eventType].push({ thisObject: thisObject, listener: listener });
    },

    removeEventListener: function(eventType, listener, thisObject)
    {
        if (!("_listeners" in this) || !(eventType in this._listeners))
            return;
        var listeners = this._listeners[eventType];
        for (var i = 0; i < listeners.length; ++i) {
            if (listener && listeners[i].listener === listener && listeners[i].thisObject === thisObject)
                listeners.splice(i, 1);
            else if (!listener && thisObject && listeners[i].thisObject === thisObject)
                listeners.splice(i, 1);
        }

        if (!listeners.length)
            delete this._listeners[eventType];
    },

    removeAllListeners: function()
    {
        delete this._listeners;
    },

    hasEventListeners: function(eventType)
    {
        if (!("_listeners" in this) || !(eventType in this._listeners))
            return false;
        return true;
    },

    dispatchEventToListeners: function(eventType, eventData)
    {
        if (!("_listeners" in this) || !(eventType in this._listeners))
            return;

        var stoppedPropagation = false;

        function stopPropagation()
        {
            stoppedPropagation = true;
        }

        function preventDefault()
        {
            this.defaultPrevented = true;
        }

        var event = {target: this, type: eventType, data: eventData, defaultPrevented: false};
        event.stopPropagation = stopPropagation;
        event.preventDefault = preventDefault;

        var listeners = this._listeners[eventType].slice(0);
        for (var i = 0; i < listeners.length; ++i) {
            listeners[i].listener.call(listeners[i].thisObject, event);
            if (stoppedPropagation)
                break;
        }

        return event.defaultPrevented;
    }
}

/* Settings.js */

/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */


var Preferences = {
    canEditScriptSource: false,
    maxInlineTextChildLength: 80,
    minConsoleHeight: 75,
    minSidebarWidth: 100,
    minElementsSidebarWidth: 200,
    minScriptsSidebarWidth: 200,
    styleRulesExpandedState: {},
    showMissingLocalizedStrings: false,
    samplingCPUProfiler: false,
    showColorNicknames: true,
    debuggerAlwaysEnabled: false,
    profilerAlwaysEnabled: false,
    onlineDetectionEnabled: true,
    nativeInstrumentationEnabled: false,
    useDataURLForResourceImageIcons: true,
    showTimingTab: false,
    showCookiesTab: false,
    debugMode: false,
    heapProfilerPresent: false,
    detailedHeapProfiles: false,
    saveAsAvailable: false,
    useLowerCaseMenuTitlesOnWindows: false
}

WebInspector.Settings = function()
{
    this.installApplicationSetting("colorFormat", "hex");
    this.installApplicationSetting("consoleHistory", []);
    this.installApplicationSetting("debuggerEnabled", false);
    this.installApplicationSetting("domWordWrap", true);
    this.installApplicationSetting("profilerEnabled", false);
    this.installApplicationSetting("eventListenersFilter", "all");
    this.installApplicationSetting("lastActivePanel", "elements");
    this.installApplicationSetting("lastViewedScriptFile", "application");
    this.installApplicationSetting("monitoringXHREnabled", false);
    this.installApplicationSetting("pauseOnExceptionStateString", WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions);
    this.installApplicationSetting("resourcesLargeRows", true);
    this.installApplicationSetting("resourcesSortOptions", {timeOption: "responseTime", sizeOption: "transferSize"});
    this.installApplicationSetting("resourceViewTab", "content");
    this.installApplicationSetting("showInheritedComputedStyleProperties", false);
    this.installApplicationSetting("showUserAgentStyles", true);
    this.installApplicationSetting("watchExpressions", []);
    this.installApplicationSetting("breakpoints", []);
    this.installApplicationSetting("eventListenerBreakpoints", []);
    this.installApplicationSetting("domBreakpoints", []);
    this.installApplicationSetting("xhrBreakpoints", []);
}

WebInspector.Settings.prototype = {
    installApplicationSetting: function(key, defaultValue)
    {
        if (key in this)
            return;

        this.__defineGetter__(key, this._get.bind(this, key, defaultValue));
        this.__defineSetter__(key, this._set.bind(this, key));
    },

    _get: function(key, defaultValue)
    {
        if (window.localStorage != null && key in window.localStorage) {
            try {
                return JSON.parse(window.localStorage[key]);
            } catch(e) {
                window.localStorage.removeItem(key);
            }
        }
        return defaultValue;
    },

    _set: function(key, value)
    {
        if (window.localStorage != null)
            window.localStorage[key] = JSON.stringify(value);
    }
}

WebInspector.Settings.prototype.__proto__ = WebInspector.Object.prototype;

/* Checkbox.js */

/*
 * Copyright (C) 2010 Google Inc. All Rights Reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 *
 * THIS SOFTWARE IS PROVIDED BY APPLE INC. ``AS IS'' AND ANY
 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
 * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL APPLE INC. OR
 * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
 * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
 * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
 * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

WebInspector.Checkbox = function(label, className, tooltip)
{
    this.element = document.createElement('label');
    this._inputElement = document.createElement('input');
    this._inputElement.type = "checkbox";

    this.element.className = className;
    this.element.appendChild(this._inputElement);
    this.element.appendChild(document.createTextNode(label));
    if (tooltip)
        this.element.title = tooltip;
}

WebInspector.Checkbox.prototype = {
    set checked(checked)
    {
        this._inputElement.checked = checked;
    },

    get checked()
    {
        return this._inputElement.checked;
    },

    addEventListener: function(listener)
    {
        function listenerWrapper(event)
        {
            if (listener)
                listener(event);
            event.stopPropagation();
            return true;
        }

        this._inputElement.addEventListener("click", listenerWrapper, false);
        this.element.addEventListener("click", listenerWrapper, false);
    }
}

/* ContextMenu.js */

/*
 * Copyright (C) 2009 Google Inc. All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions are
 * met:
 *
 *     * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 *     * Redistributions in binary form must reproduce the above
 * copyright notice, this list of conditions and the following disclaimer
 * in the documentation and/or other materials provided with the
 * distribution.
 *     * Neither the name of Google Inc. nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 */

WebInspector.ContextMenu = function() {
    this._items = [];
    this._handlers = {};
}

WebInspector.ContextMenu.prototype = {
    show: function(event)
    {
        // Remove trailing separator.
        while (this._items.length > 0 && !("id" in this._items[this._items.length - 1]))
            this._items.splice(this._items.length - 1, 1);

        if (this._items.length) {
            WebInspector._contextMenu = this;
            InspectorFrontendHost.showContextMenu(event, this._items);
        }
        event.stopPropagation();
    },

    appendItem: function(label, handler, disabled)
    {
        var id = this._items.length;
        this._items.push({type: "item", id: id, label: label, enabled: !disabled});
        this._handlers[id] = handler;
    },

    appendCheckboxItem: function(label, handler, checked, disabled)
    {
        var id = this._items.length;
        this._items.push({type: "checkbox", id: id, label: label, checked: !!checked, enabled: !disabled});
        this._handlers[id] = handler;
    },

    appendSeparator: function()
    {
        // No separator dupes allowed.
        if (this._items.length === 0)
            return;
        if (!("id" in this._items[this._items.length - 1]))
            return;
        this._items.push({type: "separator"});
    },

    _itemSelected: function(id)
    {
        if (this._handlers[id])
            this._handlers[id].call(this);
    }
}

WebInspector.contextMenuItemSelected = function(id)
{
    if (WebInspector._contextMenu)
        WebInspector._contextMenu._itemSelected(id);
}

WebInspector.contextMenuCleared = function()
{
    // FIXME: Unfortunately, contextMenuCleared is invoked between show and item selected
    // so we can't delete last menu object from WebInspector. Fix the contract.
}





WebInspector.KeyboardShortcut = function()
{
};


WebInspector.KeyboardShortcut.Modifiers = {
None: 0,   
Shift: 1,
Ctrl: 2,
Alt: 4,
Meta: 8,   
get CtrlOrMeta()
{

return WebInspector.isMac() ? this.Meta : this.Ctrl;
}
};

WebInspector.KeyboardShortcut.Keys = {
Backspace: { code: 8, name: "\u21a4" },
Tab: { code: 9, name: { mac: "\u21e5", other: "<Tab>" } },
Enter: { code: 13, name: { mac: "\u21a9", other: "<Enter>" } },
Esc: { code: 27, name: { mac: "\u238b", other: "<Esc>" } },
Space: { code: 32, name: "<Space>" },
PageUp: { code: 33,  name: { mac: "\u21de", other: "<PageUp>" } },      
PageDown: { code: 34, name: { mac: "\u21df", other: "<PageDown>" } },   
End: { code: 35, name: { mac: "\u2197", other: "<End>" } },             
Home: { code: 36, name: { mac: "\u2196", other: "<Home>" } },           
Left: { code: 37, name: "\u2190" },           
Up: { code: 38, name: "\u2191" },             
Right: { code: 39, name: "\u2192" },          
Down: { code: 40, name: "\u2193" },           
Delete: { code: 46, name: "<Del>" },
Zero: { code: 48, name: "0" },
F1: { code: 112, name: "F1" },
F2: { code: 113, name: "F2" },
F3: { code: 114, name: "F3" },
F4: { code: 115, name: "F4" },
F5: { code: 116, name: "F5" },
F6: { code: 117, name: "F6" },
F7: { code: 118, name: "F7" },
F8: { code: 119, name: "F8" },
F9: { code: 120, name: "F9" },
F10: { code: 121, name: "F10" },
F11: { code: 122, name: "F11" },
F12: { code: 123, name: "F12" },
Semicolon: { code: 186, name: ";" },
Plus: { code: 187, name: "+" },
Comma: { code: 188, name: "," },
Minus: { code: 189, name: "-" },
Period: { code: 190, name: "." },
Slash: { code: 191, name: "/" },
Apostrophe: { code: 192, name: "`" },
SingleQuote: { code: 222, name: "\'" }
};


WebInspector.KeyboardShortcut.makeKey = function(keyCode, optModifiers)
{
if (typeof keyCode === "string")
keyCode = keyCode.charCodeAt(0) - 32;
var modifiers = WebInspector.KeyboardShortcut.Modifiers.None;
for (var i = 1; i < arguments.length; i++)
modifiers |= arguments[i];
return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyCode, modifiers);
};

WebInspector.KeyboardShortcut.makeKeyFromEvent = function(keyboardEvent)
{
var modifiers = WebInspector.KeyboardShortcut.Modifiers.None;
if (keyboardEvent.shiftKey)
modifiers |= WebInspector.KeyboardShortcut.Modifiers.Shift;
if (keyboardEvent.ctrlKey)
modifiers |= WebInspector.KeyboardShortcut.Modifiers.Ctrl;
if (keyboardEvent.altKey)
modifiers |= WebInspector.KeyboardShortcut.Modifiers.Alt;
if (keyboardEvent.metaKey)
modifiers |= WebInspector.KeyboardShortcut.Modifiers.Meta;
return WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers(keyboardEvent.keyCode, modifiers);
};

WebInspector.KeyboardShortcut.makeDescriptor = function(key, optModifiers)
{
var modifiers = 0;
for (var i = 1; i < arguments.length; i++)
modifiers |= arguments[i];

return {
key: WebInspector.KeyboardShortcut.makeKey(typeof key === "string" ? key : key.code, modifiers),
name: WebInspector.KeyboardShortcut.shortcutToString(key, modifiers)
};
}

WebInspector.KeyboardShortcut.shortcutToString = function(key, modifiers)
{
return WebInspector.KeyboardShortcut._modifiersToString(modifiers) + WebInspector.KeyboardShortcut._keyName(key);
}

WebInspector.KeyboardShortcut._keyName = function(key)
{
if (typeof key === "string")
return key.toUpperCase();
if (typeof key.name === "string")
return key.name;
return key.name[WebInspector.platform] || key.name.other;
}

WebInspector.KeyboardShortcut._makeKeyFromCodeAndModifiers = function(keyCode, modifiers)
{
return (keyCode & 255) | (modifiers << 8);
};

WebInspector.KeyboardShortcut._modifiersToString = function(modifiers)
{
const cmdKey = "\u2318";
const optKey = "\u2325";
const shiftKey = "\u21e7";
const ctrlKey = "\u2303";

var isMac = WebInspector.isMac();
var res = "";
if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Ctrl)
res += isMac ? ctrlKey : "<Ctrl> + ";
if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Alt)
res += isMac ? optKey : "<Alt> + ";
if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Shift)
res += isMac ? shiftKey : "<Shift> + ";
if (modifiers & WebInspector.KeyboardShortcut.Modifiers.Meta)
res += isMac ? cmdKey : "<Win> + ";

return res;
};





WebInspector.TextPrompt = function(element, completions, stopCharacters, omitHistory)
{
this.element = element;
this.element.addStyleClass("text-prompt");
this.completions = completions;
this.completionStopCharacters = stopCharacters;
if (!omitHistory) {
this.history = [];
this.historyOffset = 0;
}
this._boundOnKeyDown = this._onKeyDown.bind(this);
this.element.addEventListener("keydown", this._boundOnKeyDown, true);
}

WebInspector.TextPrompt.prototype = {
get text()
{
return this.element.textContent;
},

set text(x)
{
if (!x) {

this.element.removeChildren();
this.element.appendChild(document.createElement("br"));
} else
this.element.textContent = x;

this.moveCaretToEndOfPrompt();
},

removeFromElement: function()
{
this.clearAutoComplete(true);
this.element.removeEventListener("keydown", this._boundOnKeyDown, true);
},

_onKeyDown: function(event)
{
function defaultAction()
{
this.clearAutoComplete();
this.autoCompleteSoon();
}

if (event.handled)
return;

var handled = false;

switch (event.keyIdentifier) {
case "Up":
this.upKeyPressed(event);
break;
case "Down":
this.downKeyPressed(event);
break;
case "U+0009": 
this.tabKeyPressed(event);
break;
case "Right":
case "End":
if (!this.acceptAutoComplete())
this.autoCompleteSoon();
break;
case "Alt":
case "Meta":
case "Shift":
case "Control":
break;
case "U+0050": 
if (this.history && WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
handled = true;
this._moveBackInHistory();
break;
}
defaultAction.call(this);
break;
case "U+004E": 
if (this.history && WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
handled = true;
this._moveForwardInHistory();
break;
}
defaultAction.call(this);
break;
default:
defaultAction.call(this);
break;
}

handled |= event.handled;
if (handled) {
event.handled = true;
event.preventDefault();
event.stopPropagation();
}
},

acceptAutoComplete: function()
{
if (!this.autoCompleteElement || !this.autoCompleteElement.parentNode)
return false;

var text = this.autoCompleteElement.textContent;
var textNode = document.createTextNode(text);
this.autoCompleteElement.parentNode.replaceChild(textNode, this.autoCompleteElement);
delete this.autoCompleteElement;

var finalSelectionRange = document.createRange();
finalSelectionRange.setStart(textNode, text.length);
finalSelectionRange.setEnd(textNode, text.length);

var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(finalSelectionRange);

return true;
},

clearAutoComplete: function(includeTimeout)
{
if (includeTimeout && "_completeTimeout" in this) {
clearTimeout(this._completeTimeout);
delete this._completeTimeout;
}

if (!this.autoCompleteElement)
return;

if (this.autoCompleteElement.parentNode)
this.autoCompleteElement.parentNode.removeChild(this.autoCompleteElement);
delete this.autoCompleteElement;

if (!this._userEnteredRange || !this._userEnteredText)
return;

this._userEnteredRange.deleteContents();
this.element.pruneEmptyTextNodes();

var userTextNode = document.createTextNode(this._userEnteredText);
this._userEnteredRange.insertNode(userTextNode);

var selectionRange = document.createRange();
selectionRange.setStart(userTextNode, this._userEnteredText.length);
selectionRange.setEnd(userTextNode, this._userEnteredText.length);

var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(selectionRange);

delete this._userEnteredRange;
delete this._userEnteredText;
},

autoCompleteSoon: function()
{
if (!("_completeTimeout" in this))
this._completeTimeout = setTimeout(this.complete.bind(this, true), 250);
},

complete: function(auto, reverse)
{
this.clearAutoComplete(true);
var selection = window.getSelection();
if (!selection.rangeCount)
return;

var selectionRange = selection.getRangeAt(0);
var isEmptyInput = selectionRange.commonAncestorContainer === this.element; 


if (auto && isEmptyInput)
return;
if (!auto && !isEmptyInput && !selectionRange.commonAncestorContainer.isDescendant(this.element))
return;
if (auto && !this.isCaretAtEndOfPrompt())
return;
var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, this.completionStopCharacters, this.element, "backward");
this.completions(wordPrefixRange, auto, this._completionsReady.bind(this, selection, auto, wordPrefixRange, reverse));
},

_completionsReady: function(selection, auto, originalWordPrefixRange, reverse, completions)
{
if (!completions || !completions.length)
return;

var selectionRange = selection.getRangeAt(0);

var fullWordRange = document.createRange();
fullWordRange.setStart(originalWordPrefixRange.startContainer, originalWordPrefixRange.startOffset);
fullWordRange.setEnd(selectionRange.endContainer, selectionRange.endOffset);

if (originalWordPrefixRange.toString() + selectionRange.toString() != fullWordRange.toString())
return;

var wordPrefixLength = originalWordPrefixRange.toString().length;

if (auto)
var completionText = completions[0];
else {
if (completions.length === 1) {
var completionText = completions[0];
wordPrefixLength = completionText.length;
} else {
var commonPrefix = completions[0];
for (var i = 0; i < completions.length; ++i) {
var completion = completions[i];
var lastIndex = Math.min(commonPrefix.length, completion.length);
for (var j = wordPrefixLength; j < lastIndex; ++j) {
if (commonPrefix[j] !== completion[j]) {
commonPrefix = commonPrefix.substr(0, j);
break;
}
}
}
wordPrefixLength = commonPrefix.length;

if (selection.isCollapsed)
var completionText = completions[0];
else {
var currentText = fullWordRange.toString();

var foundIndex = null;
for (var i = 0; i < completions.length; ++i) {
if (completions[i] === currentText)
foundIndex = i;
}

var nextIndex = foundIndex + (reverse ? -1 : 1);
if (foundIndex === null || nextIndex >= completions.length)
var completionText = completions[0];
else if (nextIndex < 0)
var completionText = completions[completions.length - 1];
else
var completionText = completions[nextIndex];
}
}
}

this._userEnteredRange = fullWordRange;
this._userEnteredText = fullWordRange.toString();

fullWordRange.deleteContents();
this.element.pruneEmptyTextNodes();

var finalSelectionRange = document.createRange();

if (auto) {
var prefixText = completionText.substring(0, wordPrefixLength);
var suffixText = completionText.substring(wordPrefixLength);

var prefixTextNode = document.createTextNode(prefixText);
fullWordRange.insertNode(prefixTextNode);

this.autoCompleteElement = document.createElement("span");
this.autoCompleteElement.className = "auto-complete-text";
this.autoCompleteElement.textContent = suffixText;

prefixTextNode.parentNode.insertBefore(this.autoCompleteElement, prefixTextNode.nextSibling);

finalSelectionRange.setStart(prefixTextNode, wordPrefixLength);
finalSelectionRange.setEnd(prefixTextNode, wordPrefixLength);
} else {
var completionTextNode = document.createTextNode(completionText);
fullWordRange.insertNode(completionTextNode);

if (completions.length > 1)
finalSelectionRange.setStart(completionTextNode, wordPrefixLength);
else
finalSelectionRange.setStart(completionTextNode, completionText.length);

finalSelectionRange.setEnd(completionTextNode, completionText.length);
}

selection.removeAllRanges();
selection.addRange(finalSelectionRange);
},

isCaretInsidePrompt: function()
{
return this.element.isInsertionCaretInside();
},

isCaretAtEndOfPrompt: function()
{
var selection = window.getSelection();
if (!selection.rangeCount || !selection.isCollapsed)
return false;

var selectionRange = selection.getRangeAt(0);
var node = selectionRange.startContainer;
if (node !== this.element && !node.isDescendant(this.element))
return false;

if (node.nodeType === Node.TEXT_NODE && selectionRange.startOffset < node.nodeValue.length)
return false;

var foundNextText = false;
while (node) {
if (node.nodeType === Node.TEXT_NODE && node.nodeValue.length) {
if (foundNextText)
return false;
foundNextText = true;
}

node = node.traverseNextNode(this.element);
}

return true;
},

isCaretOnFirstLine: function()
{
var selection = window.getSelection();
var focusNode = selection.focusNode;
if (!focusNode || focusNode.nodeType !== Node.TEXT_NODE || focusNode.parentNode !== this.element)
return true;

if (focusNode.textContent.substring(0, selection.focusOffset).indexOf("\n") !== -1)
return false;
focusNode = focusNode.previousSibling;

while (focusNode) {
if (focusNode.nodeType !== Node.TEXT_NODE)
return true;
if (focusNode.textContent.indexOf("\n") !== -1)
return false;
focusNode = focusNode.previousSibling;
}

return true;
},

isCaretOnLastLine: function()
{
var selection = window.getSelection();
var focusNode = selection.focusNode;
if (!focusNode || focusNode.nodeType !== Node.TEXT_NODE || focusNode.parentNode !== this.element)
return true;

if (focusNode.textContent.substring(selection.focusOffset).indexOf("\n") !== -1)
return false;
focusNode = focusNode.nextSibling;

while (focusNode) {
if (focusNode.nodeType !== Node.TEXT_NODE)
return true;
if (focusNode.textContent.indexOf("\n") !== -1)
return false;
focusNode = focusNode.nextSibling;
}

return true;
},

moveCaretToEndOfPrompt: function()
{
var selection = window.getSelection();
var selectionRange = document.createRange();

var offset = this.element.childNodes.length;
selectionRange.setStart(this.element, offset);
selectionRange.setEnd(this.element, offset);

selection.removeAllRanges();
selection.addRange(selectionRange);
},

tabKeyPressed: function(event)
{
event.handled = true;
this.complete(false, event.shiftKey);
},

upKeyPressed: function(event)
{
if (!this.isCaretOnFirstLine())
return;

event.handled = true;
this._moveBackInHistory();
},

downKeyPressed: function(event)
{
if (!this.isCaretOnLastLine())
return;

event.handled = true;
this._moveForwardInHistory();
},

_moveBackInHistory: function()
{
if (!this.history || this.historyOffset == this.history.length)
return;

this.clearAutoComplete(true);

if (this.historyOffset === 0)
this.tempSavedCommand = this.text;

++this.historyOffset;
this.text = this.history[this.history.length - this.historyOffset];

this.element.scrollIntoView(true);
var firstNewlineIndex = this.text.indexOf("\n");
if (firstNewlineIndex === -1)
this.moveCaretToEndOfPrompt();
else {
var selection = window.getSelection();
var selectionRange = document.createRange();

selectionRange.setStart(this.element.firstChild, firstNewlineIndex);
selectionRange.setEnd(this.element.firstChild, firstNewlineIndex);

selection.removeAllRanges();
selection.addRange(selectionRange);
}
},

_moveForwardInHistory: function()
{
if (!this.history || this.historyOffset === 0)
return;

this.clearAutoComplete(true);

--this.historyOffset;

if (this.historyOffset === 0) {
this.text = this.tempSavedCommand;
delete this.tempSavedCommand;
return;
}

this.text = this.history[this.history.length - this.historyOffset];
this.element.scrollIntoView();
}
}





WebInspector.Popover = function(contentElement)
{
this.element = document.createElement("div");
this.element.className = "popover";

this._popupArrowElement = document.createElement("div");
this._popupArrowElement.className = "arrow";
this.element.appendChild(this._popupArrowElement);

this.contentElement = contentElement;
this._contentDiv = document.createElement("div");
this._contentDiv.className = "content";
this._visible = false;
}

WebInspector.Popover.prototype = {
show: function(anchor, preferredWidth, preferredHeight)
{

if (WebInspector.Popover._popoverElement)
document.body.removeChild(WebInspector.Popover._popoverElement);
WebInspector.Popover._popoverElement = this.element;


this.contentElement.positionAt(0, 0);
document.body.appendChild(this.contentElement);
var preferredWidth = preferredWidth || this.contentElement.offsetWidth;
var preferredHeight = preferredHeight || this.contentElement.offsetHeight;

this._contentDiv.appendChild(this.contentElement);
this.element.appendChild(this._contentDiv);
document.body.appendChild(this.element);
this._positionElement(anchor, preferredWidth, preferredHeight);
this._visible = true;
},

hide: function()
{
if (WebInspector.Popover._popoverElement) {
delete WebInspector.Popover._popoverElement;
document.body.removeChild(this.element);
}
this._visible = false;
},

get visible()
{
return this._visible;
},

_positionElement: function(anchorElement, preferredWidth, preferredHeight)
{
const borderWidth = 25;
const scrollerWidth = 11;
const arrowHeight = 15;
const arrowOffset = 10;
const borderRadius = 10;


preferredWidth = Math.max(preferredWidth, 50);
const totalWidth = window.innerWidth;
const totalHeight = window.innerHeight;

var anchorBox = {x: anchorElement.totalOffsetLeft, y: anchorElement.totalOffsetTop, width: anchorElement.offsetWidth, height: anchorElement.offsetHeight};
while (anchorElement !== document.body) {
if (anchorElement.scrollLeft)
anchorBox.x -= anchorElement.scrollLeft;
if (anchorElement.scrollTop)
anchorBox.y -= anchorElement.scrollTop;
anchorElement = anchorElement.parentElement;
}

var newElementPosition = { x: 0, y: 0, width: preferredWidth + scrollerWidth, height: preferredHeight };

var verticalAlignment;
var roomAbove = anchorBox.y;
var roomBelow = totalHeight - anchorBox.y - anchorBox.height;

if (roomAbove > roomBelow) {

if (anchorBox.y > newElementPosition.height + arrowHeight + borderRadius)
newElementPosition.y = anchorBox.y - newElementPosition.height - arrowHeight;
else {
newElementPosition.y = borderRadius * 2;
newElementPosition.height = anchorBox.y - borderRadius * 2 - arrowHeight;
}
verticalAlignment = "bottom";
} else {

newElementPosition.y = anchorBox.y + anchorBox.height + arrowHeight;
if (newElementPosition.y + newElementPosition.height + arrowHeight - borderWidth >= totalHeight)
newElementPosition.height = totalHeight - anchorBox.y - anchorBox.height - borderRadius * 2 - arrowHeight;

verticalAlignment = "top";
}

var horizontalAlignment;
if (anchorBox.x + newElementPosition.width < totalWidth) {
newElementPosition.x = Math.max(borderRadius, anchorBox.x - borderRadius - arrowOffset);
horizontalAlignment = "left";
} else if (newElementPosition.width + borderRadius * 2 < totalWidth) {
newElementPosition.x = totalWidth - newElementPosition.width - borderRadius;
horizontalAlignment = "right";

var arrowRightPosition = Math.max(0, totalWidth - anchorBox.x - anchorBox.width - borderRadius - arrowOffset);
arrowRightPosition += anchorBox.width / 2;
this._popupArrowElement.style.right = arrowRightPosition + "px";
} else {
newElementPosition.x = borderRadius;
newElementPosition.width = totalWidth - borderRadius * 2;
newElementPosition.height += scrollerWidth;
horizontalAlignment = "left";
if (verticalAlignment === "bottom")
newElementPosition.y -= scrollerWidth;

this._popupArrowElement.style.left = Math.max(0, anchorBox.x - borderRadius * 2 - arrowOffset) + "px";
this._popupArrowElement.style.left += anchorBox.width / 2;
}

this.element.className = "popover " + verticalAlignment + "-" + horizontalAlignment + "-arrow";
this.element.positionAt(newElementPosition.x - borderWidth, newElementPosition.y - borderWidth);
this.element.style.width = newElementPosition.width + borderWidth * 2 + "px";
this.element.style.height = newElementPosition.height + borderWidth * 2 + "px";
}
}

WebInspector.PopoverHelper = function(panelElement, getAnchor, showPopup, showOnClick, onHide)
{
this._panelElement = panelElement;
this._getAnchor = getAnchor;
this._showPopup = showPopup;
this._showOnClick = showOnClick;
this._onHide = onHide;
panelElement.addEventListener("mousedown", this._mouseDown.bind(this), false);
panelElement.addEventListener("mousemove", this._mouseMove.bind(this), false);
this.setTimeout(1000);
}

WebInspector.PopoverHelper.prototype = {
setTimeout: function(timeout)
{
this._timeout = timeout;
},

_mouseDown: function(event)
{
this._killHidePopupTimer();
this._handleMouseAction(event, true);
},

_mouseMove: function(event)
{

if (this._hoverElement === event.target || (this._hoverElement && this._hoverElement.isAncestor(event.target)))
return;


if (this._popup && !this._hidePopupTimer) {
var self = this;
function doHide()
{
self._hidePopup();
delete self._hidePopupTimer;
}
this._hidePopupTimer = setTimeout(doHide, this._timeout / 2);
}

this._handleMouseAction(event);
},

_handleMouseAction: function(event, isMouseDown)
{
this._resetHoverTimer();

this._hoverElement = this._getAnchor(event.target);
if (!this._hoverElement)
return;

const toolTipDelay = isMouseDown ? 0 : (this._popup ? this._timeout * 0.6 : this._timeout);
this._hoverTimer = setTimeout(this._mouseHover.bind(this, this._hoverElement), toolTipDelay);
},

_resetHoverTimer: function()
{
if (this._hoverTimer) {
clearTimeout(this._hoverTimer);
delete this._hoverTimer;
}
},

hidePopup: function()
{
this._resetHoverTimer();
this._hidePopup();
},

_hidePopup: function()
{
if (!this._popup)
return;

if (this._onHide)
this._onHide();

this._popup.hide();
delete this._popup;
},

_mouseHover: function(element)
{
delete this._hoverTimer;

this._popup = this._showPopup(element);
if (this._popup)
this._popup.contentElement.addEventListener("mousemove", this._killHidePopupTimer.bind(this), true);
},

_killHidePopupTimer: function()
{
if (this._hidePopupTimer) {
clearTimeout(this._hidePopupTimer);
delete this._hidePopupTimer;



this._resetHoverTimer();
}
}
}





WebInspector.TabbedPane = function(element)
{
this.element = element || document.createElement("div");
this.element.addStyleClass("tabbed-pane");
this._tabsElement = this.element.createChild("div", "tabbed-pane-header");
this._contentElement = this.element.createChild("div", "tabbed-pane-content");
this._tabs = {};
}

WebInspector.TabbedPane.prototype = {
appendTab: function(id, tabTitle, view)
{
var tabElement = document.createElement("li");
tabElement.textContent = tabTitle;
tabElement.addEventListener("click", this.selectTab.bind(this, id, true), false);

this._tabsElement.appendChild(tabElement);
this._contentElement.appendChild(view.element);

this._tabs[id] = { tabElement: tabElement, view: view };
},

selectTab: function(id, userGesture)
{
if (!(id in this._tabs))
return false;

if (this._currentTab) {
this._hideTab(this._currentTab)
delete this._currentTab;
}

var tab = this._tabs[id];
this._showTab(tab);
this._currentTab = tab;
var event = {tabId: id, view: tab.view, isUserGesture: userGesture};
this.dispatchEventToListeners("tab-selected", event);
return true;
},

_showTab: function(tab)
{
tab.tabElement.addStyleClass("selected");
tab.view.show(this._contentElement);
},

_hideTab: function(tab)
{
tab.tabElement.removeStyleClass("selected");
tab.view.visible = false;
}
}

WebInspector.TabbedPane.prototype.__proto__ = WebInspector.Object.prototype;





WebInspector.Placard = function(title, subtitle)
{
this.element = document.createElement("div");
this.element.className = "placard";
this.element.placard = this;

this.titleElement = document.createElement("div");
this.titleElement.className = "title";

this.subtitleElement = document.createElement("div");
this.subtitleElement.className = "subtitle";

this.element.appendChild(this.subtitleElement);
this.element.appendChild(this.titleElement);

this.title = title;
this.subtitle = subtitle;
this.selected = false;
}

WebInspector.Placard.prototype = {
get title()
{
return this._title;
},

set title(x)
{
if (this._title === x)
return;
this._title = x;
this.titleElement.textContent = x;
},

get subtitle()
{
return this._subtitle;
},

set subtitle(x)
{
if (this._subtitle === x)
return;
this._subtitle = x;
this.subtitleElement.textContent = x;
},

get selected()
{
return this._selected;
},

set selected(x)
{
if (x)
this.select();
else
this.deselect();
},

select: function()
{
if (this._selected)
return;
this._selected = true;
this.element.addStyleClass("selected");
},

deselect: function()
{
if (!this._selected)
return;
this._selected = false;
this.element.removeStyleClass("selected");
},

toggleSelected: function()
{
this.selected = !this.selected;
}
}





WebInspector.PleaseWaitMessage = function()
{
this.element = document.createElement("div");
this.element.className = "please-wait-msg";
this.element.textContent = WebInspector.UIString("Please wait\u2026");

this.cancelButton = document.createElement("button");
this.cancelButton.textContent = WebInspector.UIString("Cancel");
this.cancelButton.addEventListener("click", this._cancelClicked.bind(this), false);
}

WebInspector.PleaseWaitMessage.prototype = {
_cancelClicked: function()
{
if (this._cancelCallback) {
var cancelCallback = this._cancelCallback;
delete this._cancelCallback;
cancelCallback();
}
},

hide: function()
{
var instance = WebInspector.PleaseWaitMessage.prototype.instance;
var message = instance.element;
if (message.parentNode)
message.parentNode.removeChild(message);
},

get instance()
{
if (!("_instance" in WebInspector.PleaseWaitMessage.prototype))
WebInspector.PleaseWaitMessage.prototype._instance = new WebInspector.PleaseWaitMessage();
return WebInspector.PleaseWaitMessage.prototype._instance;
},

show: function(element, cancelCallback)
{
var instance = WebInspector.PleaseWaitMessage.prototype.instance;
var message = instance.element;
if (message.parentNode === element)
return;
else if (message.parentNode)
message.parentNode.removeChild(message);
if (message.childNodes.length > 1)
message.removeChild(instance.cancelButton);
if (cancelCallback) {
message.appendChild(instance.cancelButton);
instance._cancelCallback = cancelCallback;
}
element.appendChild(message);
},

showAndWaitFor: function(element, listenObject, listenEvent, action)
{
var instance = WebInspector.PleaseWaitMessage.prototype.instance;
var message = instance.element;
if (message.parentNode !== element) {

listenObject.addEventListener(listenEvent, instance.unlistenAndHide.bind(instance, listenObject, listenEvent), instance);
WebInspector.PleaseWaitMessage.prototype.show(element);
}
if (action)
setTimeout(action, 0);
},

unlistenAndHide: function(listenObject, listenEvent)
{
var instance = WebInspector.PleaseWaitMessage.prototype.instance;
listenObject.removeEventListener(listenEvent, instance.unlistenAndHide, instance);
WebInspector.PleaseWaitMessage.prototype.hide();
}
};






WebInspector.View = function(element)
{
this.element = element || document.createElement("div");
this._visible = false;
}

WebInspector.View.prototype = {
get visible()
{
return this._visible;
},

set visible(x)
{
if (this._visible === x)
return;

if (x)
this.show();
else
this.hide();
},

show: function(parentElement)
{
this._visible = true;
if (parentElement && parentElement !== this.element.parentNode) {
this.detach();
parentElement.appendChild(this.element);
}
if (!this.element.parentNode && this.attach)
this.attach();
this.element.addStyleClass("visible");
},

hide: function()
{
this.element.removeStyleClass("visible");
this._visible = false;
},

detach: function()
{
if (this.element.parentNode)
this.element.parentNode.removeChild(this.element);
}
}

WebInspector.View.prototype.__proto__ = WebInspector.Object.prototype;





WebInspector.Drawer = function()
{
WebInspector.View.call(this, document.getElementById("drawer"));

this._savedHeight = 200; 
this.state = WebInspector.Drawer.State.Hidden;
this.fullPanel = false;

this._mainElement = document.getElementById("main");
this._toolbarElement = document.getElementById("toolbar");
this._mainStatusBar = document.getElementById("main-status-bar");
this._mainStatusBar.addEventListener("mousedown", this._startStatusBarDragging.bind(this), true);
this._viewStatusBar = document.getElementById("other-drawer-status-bar-items");
this._counters = document.getElementById("counters");
this._drawerStatusBar = document.getElementById("drawer-status-bar");
}

WebInspector.Drawer.prototype = {
get visibleView()
{
return this._visibleView;
},

set visibleView(x)
{
if (this._visibleView === x) {
if (this.visible && this.fullPanel)
return;
this.visible = !this.visible;
return;
}

var firstTime = !this._visibleView;
if (this._visibleView)
this._visibleView.hide();

this._visibleView = x;

if (x && !firstTime) {
this._safelyRemoveChildren();
this._viewStatusBar.removeChildren(); 
x.attach(this.element, this._viewStatusBar);
x.show();
this.visible = true;
}
},

get savedHeight()
{
var height = this._savedHeight || this.element.offsetHeight;
return Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - this._mainElement.totalOffsetTop - Preferences.minConsoleHeight);
},

showView: function(view)
{
if (!this.visible || this.visibleView !== view)
this.visibleView = view;
},

show: function()
{
if (this._animating || this.visible)
return;

if (this.visibleView)
this.visibleView.show();

WebInspector.View.prototype.show.call(this);

this._animating = true;

document.body.addStyleClass("drawer-visible");

var anchoredItems = document.getElementById("anchored-status-bar-items");
var height = (this.fullPanel ? window.innerHeight - this._toolbarElement.offsetHeight : this.savedHeight);
var animations = [
{element: this.element, end: {height: height}},
{element: this._mainElement, end: {bottom: height}},
{element: this._mainStatusBar, start: {"padding-left": anchoredItems.offsetWidth - 1}, end: {"padding-left": 0}},
{element: this._viewStatusBar, start: {opacity: 0}, end: {opacity: 1}}
];

this._drawerStatusBar.insertBefore(anchoredItems, this._drawerStatusBar.firstChild);

if (this._currentPanelCounters) {
var oldRight = this._drawerStatusBar.clientWidth - (this._counters.offsetLeft + this._currentPanelCounters.offsetWidth);
var newRight = WebInspector.Panel.counterRightMargin;
var rightPadding = (oldRight - newRight);
animations.push({element: this._currentPanelCounters, start: {"padding-right": rightPadding}, end: {"padding-right": 0}});
this._currentPanelCounters.parentNode.removeChild(this._currentPanelCounters);
this._mainStatusBar.appendChild(this._currentPanelCounters);
}

function animationFinished()
{
if ("updateStatusBarItems" in WebInspector.currentPanel)
WebInspector.currentPanel.updateStatusBarItems();
if (this.visibleView.afterShow)
this.visibleView.afterShow();
delete this._animating;
delete this._currentAnimation;
this.state = (this.fullPanel ? WebInspector.Drawer.State.Full : WebInspector.Drawer.State.Variable);
if (this._currentPanelCounters)
this._currentPanelCounters.removeAttribute("style");
}

this._currentAnimation = WebInspector.animateStyle(animations, this._animationDuration(), animationFinished.bind(this));
},

hide: function()
{
if (this._animating || !this.visible)
return;

WebInspector.View.prototype.hide.call(this);

if (this.visibleView)
this.visibleView.hide();

this._animating = true;

if (!this.fullPanel)
this._savedHeight = this.element.offsetHeight;

if (this.element === WebInspector.currentFocusElement || this.element.isAncestor(WebInspector.currentFocusElement))
WebInspector.currentFocusElement = WebInspector.previousFocusElement;

var anchoredItems = document.getElementById("anchored-status-bar-items");



this._mainStatusBar.style.setProperty("padding-left", (anchoredItems.offsetWidth - 1) + "px");
document.body.removeStyleClass("drawer-visible");
if ("updateStatusBarItems" in WebInspector.currentPanel)
WebInspector.currentPanel.updateStatusBarItems();
document.body.addStyleClass("drawer-visible");

var animations = [
{element: this._mainElement, end: {bottom: 0}},
{element: this._mainStatusBar, start: {"padding-left": 0}, end: {"padding-left": anchoredItems.offsetWidth - 1}},
{element: this._viewStatusBar, start: {opacity: 1}, end: {opacity: 0}}
];

if (this._currentPanelCounters) {
var newRight = this._drawerStatusBar.clientWidth - this._counters.offsetLeft;
var oldRight = this._mainStatusBar.clientWidth - (this._currentPanelCounters.offsetLeft + this._currentPanelCounters.offsetWidth);
var rightPadding = (newRight - oldRight);
animations.push({element: this._currentPanelCounters, start: {"padding-right": 0}, end: {"padding-right": rightPadding}});
}

function animationFinished()
{
WebInspector.currentPanel.resize();
this._mainStatusBar.insertBefore(anchoredItems, this._mainStatusBar.firstChild);
this._mainStatusBar.style.removeProperty("padding-left");

if (this._currentPanelCounters) {
this._currentPanelCounters.setAttribute("style", null);
this._currentPanelCounters.parentNode.removeChild(this._currentPanelCounters);
this._counters.insertBefore(this._currentPanelCounters, this._counters.firstChild);
}

document.body.removeStyleClass("drawer-visible");
delete this._animating;
delete this._currentAnimation;
this.state = WebInspector.Drawer.State.Hidden;
}

this._currentAnimation = WebInspector.animateStyle(animations, this._animationDuration(), animationFinished.bind(this));
},

resize: function()
{
if (this.state === WebInspector.Drawer.State.Hidden)
return;

var height;
if (this.state === WebInspector.Drawer.State.Variable) {
height = parseInt(this.element.style.height);
height = Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - this._mainElement.totalOffsetTop - Preferences.minConsoleHeight);
} else
height = window.innerHeight - this._toolbarElement.offsetHeight;

this._mainElement.style.bottom = height + "px";
this.element.style.height = height + "px";
},

enterPanelMode: function()
{
this._cancelAnimationIfNeeded();
this.fullPanel = true;

if (this.visible) {
this._savedHeight = this.element.offsetHeight;
var height = window.innerHeight - this._toolbarElement.offsetHeight;
this._animateDrawerHeight(height, WebInspector.Drawer.State.Full);
}
},

exitPanelMode: function()
{
this._cancelAnimationIfNeeded();
this.fullPanel = false;

if (this.visible) {


this.state = WebInspector.Drawer.State.Variable;
var height = this.savedHeight;
this._animateDrawerHeight(height, WebInspector.Drawer.State.Variable);
}
},

immediatelyExitPanelMode: function()
{
this.visible = false;
this.fullPanel = false;
},

immediatelyFinishAnimation: function()
{
if (this._currentAnimation)
this._currentAnimation.forceComplete();
},

set currentPanelCounters(x)
{
if (!x) {
if (this._currentPanelCounters)
this._currentPanelCounters.parentElement.removeChild(this._currentPanelCounters);
delete this._currentPanelCounters;
return;
}

this._currentPanelCounters = x;
if (this.visible)
this._mainStatusBar.appendChild(x);
else
this._counters.insertBefore(x, this._counters.firstChild);
},

_cancelAnimationIfNeeded: function()
{
if (this._animating) {
if (this._currentAnimation)
this._currentAnimation.cancel();
delete this._animating;
delete this._currentAnimation;
}
},

_animateDrawerHeight: function(height, finalState)
{
this._animating = true;
var animations = [
{element: this.element, end: {height: height}},
{element: this._mainElement, end: {bottom: height}}
];

function animationFinished()
{
delete this._animating;
delete this._currentAnimation;
this.state = finalState;
}

this._currentAnimation = WebInspector.animateStyle(animations, this._animationDuration(), animationFinished.bind(this));
},

_animationDuration: function()
{

if (this.fullPanel && (this.state === WebInspector.Drawer.State.Hidden || this.state === WebInspector.Drawer.State.Full))
return 0;

return (window.event && window.event.shiftKey ? 2000 : 250);
},

_safelyRemoveChildren: function()
{
var child = this.element.firstChild;
while (child) {
if (child.id !== "drawer-status-bar") {
var moveTo = child.nextSibling;
this.element.removeChild(child);
child = moveTo;
} else
child = child.nextSibling;
}
},

_startStatusBarDragging: function(event)
{
if (!this.visible || event.target !== this._mainStatusBar)
return;

WebInspector.elementDragStart(this._mainStatusBar, this._statusBarDragging.bind(this), this._endStatusBarDragging.bind(this), event, "row-resize");

this._statusBarDragOffset = event.pageY - this.element.totalOffsetTop;

event.stopPropagation();
},

_statusBarDragging: function(event)
{
var height = window.innerHeight - event.pageY + this._statusBarDragOffset;
height = Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - this._mainElement.totalOffsetTop - Preferences.minConsoleHeight);

this._mainElement.style.bottom = height + "px";
this.element.style.height = height + "px";

event.preventDefault();
event.stopPropagation();
},

_endStatusBarDragging: function(event)
{
WebInspector.elementDragEnd(event);

this._savedHeight = this.element.offsetHeight;
delete this._statusBarDragOffset;

event.stopPropagation();
}
}

WebInspector.Drawer.prototype.__proto__ = WebInspector.View.prototype;

WebInspector.Drawer.State = {
Hidden: 0,
Variable: 1,
Full: 2
};





const ExpressionStopCharacters = " =:[({;,!+-*/&|^<>";

WebInspector.ConsoleView = function(drawer)
{
WebInspector.View.call(this, document.getElementById("console-view"));

this.messages = [];
this.drawer = drawer;

this.clearButton = document.getElementById("clear-console-status-bar-item");
this.clearButton.title = WebInspector.UIString("Clear console log.");
this.clearButton.addEventListener("click", this._clearButtonClicked.bind(this), false);

this.messagesElement = document.getElementById("console-messages");
this.messagesElement.addEventListener("selectstart", this._messagesSelectStart.bind(this), false);
this.messagesElement.addEventListener("click", this._messagesClicked.bind(this), true);

this.promptElement = document.getElementById("console-prompt");
this.promptElement.className = "source-code";
this.promptElement.addEventListener("keydown", this._promptKeyDown.bind(this), true);
this.prompt = new WebInspector.TextPrompt(this.promptElement, this.completions.bind(this), ExpressionStopCharacters + ".");
this.prompt.history = WebInspector.settings.consoleHistory;

this.topGroup = new WebInspector.ConsoleGroup(null);
this.messagesElement.insertBefore(this.topGroup.element, this.promptElement);
this.currentGroup = this.topGroup;

this.toggleConsoleButton = document.getElementById("console-status-bar-item");
this.toggleConsoleButton.title = WebInspector.UIString("Show console.");
this.toggleConsoleButton.addEventListener("click", this._toggleConsoleButtonClicked.bind(this), false);


this.filterBarElement = document.getElementById("console-filter");

function createDividerElement() {
var dividerElement = document.createElement("div");
dividerElement.addStyleClass("scope-bar-divider");
this.filterBarElement.appendChild(dividerElement);
}

var updateFilterHandler = this._updateFilter.bind(this);
function createFilterElement(category, label) {
var categoryElement = document.createElement("li");
categoryElement.category = category;
categoryElement.className = category;
categoryElement.addEventListener("click", updateFilterHandler, false);
categoryElement.textContent = label;

this.filterBarElement.appendChild(categoryElement);

return categoryElement;
}

this.allElement = createFilterElement.call(this, "all", WebInspector.UIString("All"));
createDividerElement.call(this);
this.errorElement = createFilterElement.call(this, "errors", WebInspector.UIString("Errors"));
this.warningElement = createFilterElement.call(this, "warnings", WebInspector.UIString("Warnings"));
this.logElement = createFilterElement.call(this, "logs", WebInspector.UIString("Logs"));

this.filter(this.allElement, false);
this._registerShortcuts();

this.messagesElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), false);

this._customFormatters = {
"object": this._formatobject,
"array":  this._formatarray,
"node":   this._formatnode,
"string": this._formatstring
};

this._registerConsoleDomainDispatcher();
}

WebInspector.ConsoleView.Events = {
ConsoleCleared: "console-cleared",
EntryAdded: "console-entry-added",
MessageAdded: "console-message-added"
}

WebInspector.ConsoleView.prototype = {
_registerConsoleDomainDispatcher: function() {
var console = this;
var dispatcher = {
messageAdded: function(payload)
{
var consoleMessage = new WebInspector.ConsoleMessage(
payload.source,
payload.type,
payload.level,
payload.line,
payload.url,
payload.repeatCount,
payload.text,
payload.parameters,
payload.stackTrace,
payload.networkIdentifier);
console.addMessage(consoleMessage);
},

messageRepeatCountUpdated: function(count)
{
var msg = console.previousMessage;
var prevRepeatCount = msg.totalRepeatCount;

if (!console.commandSincePreviousMessage) {
msg.repeatDelta = count - prevRepeatCount;
msg.repeatCount = msg.repeatCount + msg.repeatDelta;
msg.totalRepeatCount = count;
msg._updateRepeatCount();
console._incrementErrorWarningCount(msg);
} else {
var msgCopy = new WebInspector.ConsoleMessage(msg.source, msg.type, msg.level, msg.line, msg.url, count - prevRepeatCount, msg._messageText, msg._parameters, msg._stackTrace, msg._requestId);
msgCopy.totalRepeatCount = count;
msgCopy._formatMessage();
console.addMessage(msgCopy);
}
},

messagesCleared: function()
{
console.clearMessages();
},
}
InspectorBackend.registerDomainDispatcher("Console", dispatcher);
},

setConsoleMessageExpiredCount: function(count)
{
if (count) {
var message = String.sprintf(WebInspector.UIString("%d console messages are not shown."), count);
this.addMessage(WebInspector.ConsoleMessage.createTextMessage(message, WebInspector.ConsoleMessage.MessageLevel.Warning));
}
},

_updateFilter: function(e)
{
var isMac = WebInspector.isMac();
var selectMultiple = false;
if (isMac && e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey)
selectMultiple = true;
if (!isMac && e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey)
selectMultiple = true;

this.filter(e.target, selectMultiple);
},

filter: function(target, selectMultiple)
{
function unselectAll()
{
this.allElement.removeStyleClass("selected");
this.errorElement.removeStyleClass("selected");
this.warningElement.removeStyleClass("selected");
this.logElement.removeStyleClass("selected");

this.messagesElement.removeStyleClass("filter-all");
this.messagesElement.removeStyleClass("filter-errors");
this.messagesElement.removeStyleClass("filter-warnings");
this.messagesElement.removeStyleClass("filter-logs");
}

var targetFilterClass = "filter-" + target.category;

if (target.category === "all") {
if (target.hasStyleClass("selected")) {

return;
}

unselectAll.call(this);
} else {

if (this.allElement.hasStyleClass("selected")) {
this.allElement.removeStyleClass("selected");
this.messagesElement.removeStyleClass("filter-all");
}
}

if (!selectMultiple) {


unselectAll.call(this);

target.addStyleClass("selected");
this.messagesElement.addStyleClass(targetFilterClass);

return;
}

if (target.hasStyleClass("selected")) {


target.removeStyleClass("selected");
this.messagesElement.removeStyleClass(targetFilterClass);
} else {


target.addStyleClass("selected");
this.messagesElement.addStyleClass(targetFilterClass);
}
},

_toggleConsoleButtonClicked: function()
{
this.drawer.visibleView = this;
},

attach: function(mainElement, statusBarElement)
{
mainElement.appendChild(this.element);
statusBarElement.appendChild(this.clearButton);
statusBarElement.appendChild(this.filterBarElement);
},

show: function()
{
this.toggleConsoleButton.addStyleClass("toggled-on");
this.toggleConsoleButton.title = WebInspector.UIString("Hide console.");
if (!this.prompt.isCaretInsidePrompt())
this.prompt.moveCaretToEndOfPrompt();
},

afterShow: function()
{
WebInspector.currentFocusElement = this.promptElement;
},

hide: function()
{
this.toggleConsoleButton.removeStyleClass("toggled-on");
this.toggleConsoleButton.title = WebInspector.UIString("Show console.");
},

_scheduleScrollIntoView: function()
{
if (this._scrollIntoViewTimer)
return;

function scrollIntoView()
{
this.promptElement.scrollIntoView(true);
delete this._scrollIntoViewTimer;
}
this._scrollIntoViewTimer = setTimeout(scrollIntoView.bind(this), 20);
},

addMessage: function(msg)
{
var shouldScrollToLastMessage = this.messagesElement.isScrolledToBottom();

if (msg instanceof WebInspector.ConsoleMessage && !(msg instanceof WebInspector.ConsoleCommandResult)) {
this._incrementErrorWarningCount(msg);
this.dispatchEventToListeners(WebInspector.ConsoleView.Events.MessageAdded, msg);
this.commandSincePreviousMessage = false;
this.previousMessage = msg;
} else if (msg instanceof WebInspector.ConsoleCommand) {
if (this.previousMessage) {
this.commandSincePreviousMessage = true;
}
}

this.messages.push(msg);

if (msg.type === WebInspector.ConsoleMessage.MessageType.EndGroup) {
var parentGroup = this.currentGroup.parentGroup
if (parentGroup)
this.currentGroup = parentGroup;
} else {
if (msg.type === WebInspector.ConsoleMessage.MessageType.StartGroup || msg.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed) {
var group = new WebInspector.ConsoleGroup(this.currentGroup);
this.currentGroup.messagesElement.appendChild(group.element);
this.currentGroup = group;
}

this.currentGroup.addMessage(msg);
}


if (shouldScrollToLastMessage || (msg instanceof WebInspector.ConsoleCommandResult))
this._scheduleScrollIntoView();

this.dispatchEventToListeners(WebInspector.ConsoleView.Events.EntryAdded, msg);
},

_incrementErrorWarningCount: function(msg)
{
switch (msg.level) {
case WebInspector.ConsoleMessage.MessageLevel.Warning:
WebInspector.warnings += msg.repeatDelta;
break;
case WebInspector.ConsoleMessage.MessageLevel.Error:
WebInspector.errors += msg.repeatDelta;
break;
}
},

requestClearMessages: function()
{
ConsoleAgent.clearConsoleMessages();
},

clearMessages: function()
{
this.dispatchEventToListeners(WebInspector.ConsoleView.Events.ConsoleCleared);

this.messages = [];

this.currentGroup = this.topGroup;
this.topGroup.messagesElement.removeChildren();

WebInspector.errors = 0;
WebInspector.warnings = 0;

delete this.commandSincePreviousMessage;
delete this.previousMessage;
},

completions: function(wordRange, bestMatchOnly, completionsReadyCallback)
{

var expressionRange = wordRange.startContainer.rangeOfWord(wordRange.startOffset, ExpressionStopCharacters, this.promptElement, "backward");
var expressionString = expressionRange.toString();
var prefix = wordRange.toString();
this._completions(expressionString, prefix, bestMatchOnly, completionsReadyCallback);
},

_completions: function(expressionString, prefix, bestMatchOnly, completionsReadyCallback)
{
var lastIndex = expressionString.length - 1;

var dotNotation = (expressionString[lastIndex] === ".");
var bracketNotation = (expressionString[lastIndex] === "[");

if (dotNotation || bracketNotation)
expressionString = expressionString.substr(0, lastIndex);

if (!expressionString && !prefix)
return;

if (!expressionString && WebInspector.panels.scripts.paused)
WebInspector.panels.scripts.getSelectedCallFrameVariables(reportCompletions.bind(this));
else
this.evalInInspectedWindow(expressionString, "completion", true, evaluated.bind(this));

function evaluated(result, wasThrown)
{
if (wasThrown)
return;
result.getAllProperties(evaluatedProperties.bind(this));
}

function evaluatedProperties(properties)
{
RuntimeAgent.releaseObjectGroup("completion");
var propertyNames = {};
for (var i = 0; properties && i < properties.length; ++i)
propertyNames[properties[i].name] = true;
reportCompletions.call(this, propertyNames);
}

function reportCompletions(propertyNames)
{
var includeCommandLineAPI = (!dotNotation && !bracketNotation);
if (includeCommandLineAPI) {
const commandLineAPI = ["dir", "dirxml", "keys", "values", "profile", "profileEnd", "monitorEvents", "unmonitorEvents", "inspect", "copy", "clear"];
for (var i = 0; i < commandLineAPI.length; ++i)
propertyNames[commandLineAPI[i]] = true;
}

this._reportCompletions(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, Object.keys(propertyNames));
}
},

_reportCompletions: function(bestMatchOnly, completionsReadyCallback, dotNotation, bracketNotation, prefix, properties) {
if (bracketNotation) {
if (prefix.length && prefix[0] === "'")
var quoteUsed = "'";
else
var quoteUsed = "\"";
}

var results = [];
properties.sort();

for (var i = 0; i < properties.length; ++i) {
var property = properties[i];

if (dotNotation && !/^[a-zA-Z_$][a-zA-Z0-9_$]*$/.test(property))
continue;

if (bracketNotation) {
if (!/^[0-9]+$/.test(property))
property = quoteUsed + property.escapeCharacters(quoteUsed + "\\") + quoteUsed;
property += "]";
}

if (property.length < prefix.length)
continue;
if (property.indexOf(prefix) !== 0)
continue;

results.push(property);
if (bestMatchOnly)
break;
}
completionsReadyCallback(results);
},

_clearButtonClicked: function()
{
this.requestClearMessages();
},

_handleContextMenuEvent: function(event)
{
if (!window.getSelection().isCollapsed) {


return;
}

var itemAction = function () {
WebInspector.settings.monitoringXHREnabled = !WebInspector.settings.monitoringXHREnabled;
ConsoleAgent.setMonitoringXHREnabled(WebInspector.settings.monitoringXHREnabled);
}.bind(this);
var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendCheckboxItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "XMLHttpRequest logging" : "XMLHttpRequest Logging"), itemAction, WebInspector.settings.monitoringXHREnabled)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Clear console" : "Clear Console"), this.requestClearMessages.bind(this));
contextMenu.show(event);
},

_messagesSelectStart: function(event)
{
if (this._selectionTimeout)
clearTimeout(this._selectionTimeout);

this.prompt.clearAutoComplete();

function moveBackIfOutside()
{
delete this._selectionTimeout;
if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
this.prompt.moveCaretToEndOfPrompt();
this.prompt.autoCompleteSoon();
}

this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
},

_messagesClicked: function(event)
{
var link = event.target.enclosingNodeOrSelfWithNodeName("a");
if (!link || !link.representedNode)
return;

WebInspector.updateFocusedNode(link.representedNode.id);
event.stopPropagation();
event.preventDefault();
},

_registerShortcuts: function()
{
this._shortcuts = {};

var shortcut = WebInspector.KeyboardShortcut;
var shortcutK = shortcut.makeDescriptor("k", WebInspector.KeyboardShortcut.Modifiers.Meta);

this._shortcuts[shortcutK.key] = this.requestClearMessages.bind(this);
this._shortcuts[shortcutK.key].isMacOnly = true;

var clearConsoleHandler = this.requestClearMessages.bind(this);
var shortcutL = shortcut.makeDescriptor("l", WebInspector.KeyboardShortcut.Modifiers.Ctrl);
this._shortcuts[shortcutL.key] = clearConsoleHandler;

var section = WebInspector.shortcutsHelp.section(WebInspector.UIString("Console"));
var keys = WebInspector.isMac() ? [ shortcutK.name, shortcutL.name ] : [ shortcutL.name ];
section.addAlternateKeys(keys, WebInspector.UIString("Clear Console"));

keys = [
shortcut.shortcutToString(shortcut.Keys.Tab),
shortcut.shortcutToString(shortcut.Keys.Tab, shortcut.Modifiers.Shift)
];
section.addRelatedKeys(keys, WebInspector.UIString("Next/previous suggestion"));
section.addKey(shortcut.shortcutToString(shortcut.Keys.Right), WebInspector.UIString("Accept suggestion"));
keys = [
shortcut.shortcutToString(shortcut.Keys.Down),
shortcut.shortcutToString(shortcut.Keys.Up)
];
section.addRelatedKeys(keys, WebInspector.UIString("Next/previous line"));
keys = [
shortcut.shortcutToString("N", shortcut.Modifiers.Alt),
shortcut.shortcutToString("P", shortcut.Modifiers.Alt)
];
if (WebInspector.isMac())
section.addRelatedKeys(keys, WebInspector.UIString("Next/previous command"));
section.addKey(shortcut.shortcutToString(shortcut.Keys.Enter), WebInspector.UIString("Execute command"));
},

_promptKeyDown: function(event)
{
if (isEnterKey(event)) {
this._enterKeyPressed(event);
return;
}

var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
var handler = this._shortcuts[shortcut];
if (handler) {
if (!this._shortcuts[shortcut].isMacOnly || WebInspector.isMac()) {
handler();
event.preventDefault();
return;
}
}
},

evalInInspectedWindow: function(expression, objectGroup, includeCommandLineAPI, callback)
{
if (WebInspector.panels.scripts && WebInspector.panels.scripts.paused) {
WebInspector.panels.scripts.evaluateInSelectedCallFrame(expression, objectGroup, includeCommandLineAPI, callback);
return;
}

if (!expression) {

expression = "this";
}

function evalCallback(error, result, wasThrown)
{
if (!error)
callback(WebInspector.RemoteObject.fromPayload(result), wasThrown);
}
RuntimeAgent.evaluate(expression, objectGroup, includeCommandLineAPI, evalCallback);
},

_enterKeyPressed: function(event)
{
if (event.altKey || event.ctrlKey || event.shiftKey)
return;

event.preventDefault();
event.stopPropagation();

this.prompt.clearAutoComplete(true);

var str = this.prompt.text;
if (!str.length)
return;

var commandMessage = new WebInspector.ConsoleCommand(str);
this.addMessage(commandMessage);

var self = this;
function printResult(result, wasThrown)
{
self.prompt.history.push(str);
self.prompt.historyOffset = 0;
self.prompt.text = "";

WebInspector.settings.consoleHistory = self.prompt.history.slice(-30);

self.addMessage(new WebInspector.ConsoleCommandResult(result, wasThrown, commandMessage));
}
this.evalInInspectedWindow(str, "console", true, printResult);
},

_format: function(output, forceObjectFormat)
{
var isProxy = (output != null && typeof output === "object");
var type = (forceObjectFormat ? "object" : WebInspector.RemoteObject.type(output));

var formatter = this._customFormatters[type];
if (!formatter || !isProxy) {
formatter = this._formatvalue;
output = output.description;
}

var span = document.createElement("span");
span.className = "console-formatted-" + type + " source-code";
formatter.call(this, output, span);
return span;
},

_formatvalue: function(val, elem)
{
elem.appendChild(document.createTextNode(val));
},

_formatobject: function(obj, elem)
{
elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, obj.description).element);
},

_formatnode: function(object, elem)
{
function printNode(nodeId)
{
if (!nodeId) {


this._formatobject(object, elem);
return;
}
var treeOutline = new WebInspector.ElementsTreeOutline();
treeOutline.showInElementsPanelEnabled = true;
treeOutline.rootDOMNode = WebInspector.domAgent.nodeForId(nodeId);
treeOutline.element.addStyleClass("outline-disclosure");
if (!treeOutline.children[0].hasChildren)
treeOutline.element.addStyleClass("single-node");
elem.appendChild(treeOutline.element);
}
object.pushNodeToFrontend(printNode.bind(this));
},

_formatarray: function(arr, elem)
{
arr.getOwnProperties(this._printArray.bind(this, elem));
},

_formatstring: function(output, elem)
{
var span = document.createElement("span");
span.className = "console-formatted-string source-code";
span.appendChild(WebInspector.linkifyStringAsFragment(output.description));


elem.removeStyleClass("console-formatted-string");
elem.appendChild(document.createTextNode("\""));
elem.appendChild(span);
elem.appendChild(document.createTextNode("\""));
},

_printArray: function(elem, properties)
{
if (!properties)
return;

var elements = [];
for (var i = 0; i < properties.length; ++i) {
var name = properties[i].name;
if (name == parseInt(name))
elements[name] = this._formatAsArrayEntry(properties[i].value);
}

elem.appendChild(document.createTextNode("["));
for (var i = 0; i < elements.length; ++i) {
var element = elements[i];
if (element)
elem.appendChild(element);
else
elem.appendChild(document.createTextNode("undefined"))
if (i < elements.length - 1)
elem.appendChild(document.createTextNode(", "));
}
elem.appendChild(document.createTextNode("]"));
},

_formatAsArrayEntry: function(output)
{

return this._format(output, WebInspector.RemoteObject.type(output) === "array");
}
}

WebInspector.ConsoleView.prototype.__proto__ = WebInspector.View.prototype;

WebInspector.ConsoleMessage = function(source, type, level, line, url, repeatCount, message, parameters, stackTrace, requestId)
{
this.source = source;
this.type = type;
this.level = level;
this.line = line;
this.url = url;
this.repeatCount = repeatCount;
this.repeatDelta = repeatCount;
this.totalRepeatCount = repeatCount;
this._messageText = message;
this._parameters = parameters;
this._stackTrace = stackTrace;
this._requestId = requestId;

if (stackTrace && stackTrace.length) {
var topCallFrame = stackTrace[0];
if (!this.url)
this.url = topCallFrame.url;
if (!this.line)
this.line = topCallFrame.lineNumber;
}

this._formatMessage();
}

WebInspector.ConsoleMessage.createTextMessage = function(text, level)
{
level = level || WebInspector.ConsoleMessage.MessageLevel.Log;
return new WebInspector.ConsoleMessage(WebInspector.ConsoleMessage.MessageSource.JS, WebInspector.ConsoleMessage.MessageType.Log, level, 0, null, 1, null, [text], null);
}

WebInspector.ConsoleMessage.prototype = {
_formatMessage: function()
{
var stackTrace = this._stackTrace;
var messageText;
switch (this.type) {
case WebInspector.ConsoleMessage.MessageType.Trace:
messageText = document.createTextNode("console.trace()");
break;
case WebInspector.ConsoleMessage.MessageType.UncaughtException:
messageText = document.createTextNode(this._messageText);
break;
case WebInspector.ConsoleMessage.MessageType.NetworkError:
var resource = this._requestId && WebInspector.networkResourceById(this._requestId);
if (resource) {
stackTrace = resource.stackTrace;

messageText = document.createElement("span");
messageText.appendChild(document.createTextNode(resource.requestMethod + " "));
messageText.appendChild(WebInspector.linkifyURLAsNode(resource.url));
if (resource.failed)
messageText.appendChild(document.createTextNode(" " + resource.localizedFailDescription));
else
messageText.appendChild(document.createTextNode(" " + resource.statusCode + " (" + resource.statusText + ")"));
} else
messageText = this._format([this._messageText]);
break;
case WebInspector.ConsoleMessage.MessageType.Assert:
var args = [WebInspector.UIString("Assertion failed:")];
if (this._parameters)
args = args.concat(this._parameters);
messageText = this._format(args);
break;
case WebInspector.ConsoleMessage.MessageType.Object:
var obj = this._parameters ? this._parameters[0] : undefined;
var args = ["%O", obj];
messageText = this._format(args);
break;
default:
var args = this._parameters || [this._messageText];
messageText = this._format(args);
break;
}

this._formattedMessage = document.createElement("span");
this._formattedMessage.className = "console-message-text source-code";

if (this.url && this.url !== "undefined") {
var urlElement = WebInspector.linkifyResourceAsNode(this.url, "scripts", this.line, "console-message-url");
this._formattedMessage.appendChild(urlElement);
}

this._formattedMessage.appendChild(messageText);

if (this._stackTrace) {
switch (this.type) {
case WebInspector.ConsoleMessage.MessageType.Trace:
case WebInspector.ConsoleMessage.MessageType.UncaughtException:
case WebInspector.ConsoleMessage.MessageType.NetworkError:
case WebInspector.ConsoleMessage.MessageType.Assert: {
var ol = document.createElement("ol");
ol.className = "outline-disclosure";
var treeOutline = new TreeOutline(ol);

var content = this._formattedMessage;
var root = new TreeElement(content, null, true);
content.treeElementForTest = root;
treeOutline.appendChild(root);
if (this.type === WebInspector.ConsoleMessage.MessageType.Trace)
root.expand();

this._populateStackTraceTreeElement(root);
this._formattedMessage = ol;
}
}
}


this.message = this._formattedMessage.textContent;
},

isErrorOrWarning: function()
{
return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning || this.level === WebInspector.ConsoleMessage.MessageLevel.Error);
},

_format: function(parameters)
{

var formattedResult = document.createElement("span");
if (!parameters.length)
return formattedResult;



for (var i = 0; i < parameters.length; ++i) {
if (typeof parameters[i] === "object")
parameters[i] = WebInspector.RemoteObject.fromPayload(parameters[i]);
else
parameters[i] = WebInspector.RemoteObject.fromPrimitiveValue(parameters[i]);
}


var shouldFormatMessage = WebInspector.RemoteObject.type(parameters[0]) === "string" && this.type !== WebInspector.ConsoleMessage.MessageType.Result;


if (shouldFormatMessage) {

var result = this._formatWithSubstitutionString(parameters, formattedResult);
parameters = result.unusedSubstitutions;
if (parameters.length)
formattedResult.appendChild(document.createTextNode(" "));
}


for (var i = 0; i < parameters.length; ++i) {

if (shouldFormatMessage && parameters[i].type === "string")
formattedResult.appendChild(document.createTextNode(parameters[i].description));
else
formattedResult.appendChild(WebInspector.console._format(parameters[i]));
if (i < parameters.length - 1)
formattedResult.appendChild(document.createTextNode(" "));
}
return formattedResult;
},

_formatWithSubstitutionString: function(parameters, formattedResult)
{
var formatters = {}
for (var i in String.standardFormatters)
formatters[i] = String.standardFormatters[i];

function consoleFormatWrapper(force)
{
return function(obj) {
return WebInspector.console._format(obj, force);
};
}


formatters.o = consoleFormatWrapper();

formatters.i = formatters.d;

formatters.O = consoleFormatWrapper(true);

function append(a, b)
{
if (!(b instanceof Node))
a.appendChild(WebInspector.linkifyStringAsFragment(b.toString()));
else
a.appendChild(b);
return a;
}


return String.format(parameters[0].description, parameters.slice(1), formatters, formattedResult, append);
},

clearHighlight: function()
{
var highlightedMessage = this._formattedMessage;
delete this._formattedMessage;
this._formatMessage();
this._element.replaceChild(this._formattedMessage, highlightedMessage);
},

highlightSearchResults: function(regexObject)
{
regexObject.lastIndex = 0;
var text = this.message;
var match = regexObject.exec(text);
var offset = 0;
var matchRanges = [];
while (match) {
matchRanges.push({ offset: match.index, length: match[0].length });
match = regexObject.exec(text);
}
highlightSearchResults(this._formattedMessage, matchRanges);
this._element.scrollIntoViewIfNeeded();
},

matchesRegex: function(regexObject)
{
return regexObject.test(this.message);
},

toMessageElement: function()
{
if (this._element)
return this._element;

var element = document.createElement("div");
element.message = this;
element.className = "console-message";

this._element = element;

switch (this.level) {
case WebInspector.ConsoleMessage.MessageLevel.Tip:
element.addStyleClass("console-tip-level");
break;
case WebInspector.ConsoleMessage.MessageLevel.Log:
element.addStyleClass("console-log-level");
break;
case WebInspector.ConsoleMessage.MessageLevel.Debug:
element.addStyleClass("console-debug-level");
break;
case WebInspector.ConsoleMessage.MessageLevel.Warning:
element.addStyleClass("console-warning-level");
break;
case WebInspector.ConsoleMessage.MessageLevel.Error:
element.addStyleClass("console-error-level");
break;
}

if (this.type === WebInspector.ConsoleMessage.MessageType.StartGroup || this.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed)
element.addStyleClass("console-group-title");

element.appendChild(this._formattedMessage);

if (this.repeatCount > 1)
this._updateRepeatCount();

return element;
},

_populateStackTraceTreeElement: function(parentTreeElement)
{
for (var i = 0; i < this._stackTrace.length; i++) {
var frame = this._stackTrace[i];

var content = document.createElement("div");
var messageTextElement = document.createElement("span");
messageTextElement.className = "console-message-text source-code";
var functionName = frame.functionName || WebInspector.UIString("(anonymous function)");
messageTextElement.appendChild(document.createTextNode(functionName));
content.appendChild(messageTextElement);

var urlElement = WebInspector.linkifyResourceAsNode(frame.url, "scripts", frame.lineNumber, "console-message-url");
content.appendChild(urlElement);

var treeElement = new TreeElement(content);
parentTreeElement.appendChild(treeElement);
}
},

_updateRepeatCount: function() {
if (!this.repeatCountElement) {
this.repeatCountElement = document.createElement("span");
this.repeatCountElement.className = "bubble";

this._element.insertBefore(this.repeatCountElement, this._element.firstChild);
this._element.addStyleClass("repeated-message");
}
this.repeatCountElement.textContent = this.repeatCount;
},

toString: function()
{
var sourceString;
switch (this.source) {
case WebInspector.ConsoleMessage.MessageSource.HTML:
sourceString = "HTML";
break;
case WebInspector.ConsoleMessage.MessageSource.XML:
sourceString = "XML";
break;
case WebInspector.ConsoleMessage.MessageSource.JS:
sourceString = "JS";
break;
case WebInspector.ConsoleMessage.MessageSource.CSS:
sourceString = "CSS";
break;
case WebInspector.ConsoleMessage.MessageSource.Other:
sourceString = "Other";
break;
}

var typeString;
switch (this.type) {
case WebInspector.ConsoleMessage.MessageType.Log:
case WebInspector.ConsoleMessage.MessageType.UncaughtException:
case WebInspector.ConsoleMessage.MessageType.NetworkError:
typeString = "Log";
break;
case WebInspector.ConsoleMessage.MessageType.Object:
typeString = "Object";
break;
case WebInspector.ConsoleMessage.MessageType.Trace:
typeString = "Trace";
break;
case WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed:
case WebInspector.ConsoleMessage.MessageType.StartGroup:
typeString = "Start Group";
break;
case WebInspector.ConsoleMessage.MessageType.EndGroup:
typeString = "End Group";
break;
case WebInspector.ConsoleMessage.MessageType.Assert:
typeString = "Assert";
break;
case WebInspector.ConsoleMessage.MessageType.Result:
typeString = "Result";
break;
}

var levelString;
switch (this.level) {
case WebInspector.ConsoleMessage.MessageLevel.Tip:
levelString = "Tip";
break;
case WebInspector.ConsoleMessage.MessageLevel.Log:
levelString = "Log";
break;
case WebInspector.ConsoleMessage.MessageLevel.Warning:
levelString = "Warning";
break;
case WebInspector.ConsoleMessage.MessageLevel.Debug:
levelString = "Debug";
break;
case WebInspector.ConsoleMessage.MessageLevel.Error:
levelString = "Error";
break;
}

return sourceString + " " + typeString + " " + levelString + ": " + this._formattedMessage.textContent + "\n" + this.url + " line " + this.line;
},

isEqual: function(msg)
{
if (!msg)
return false;

if (this._stackTrace) {
if (!msg._stackTrace)
return false;
var l = this._stackTrace;
var r = msg._stackTrace;
for (var i = 0; i < l.length; i++) {
if (l[i].url !== r[i].url ||
l[i].functionName !== r[i].functionName ||
l[i].lineNumber !== r[i].lineNumber ||
l[i].columnNumber !== r[i].columnNumber)
return false;
}
}

return (this.source === msg.source)
&& (this.type === msg.type)
&& (this.level === msg.level)
&& (this.line === msg.line)
&& (this.url === msg.url)
&& (this.message === msg.message)
&& (this._requestId === msg._requestId);
}
}


WebInspector.ConsoleMessage.MessageSource = {
HTML: "html",
XML: "xml",
JS: "javascript",
CSS: "css",
Other: "other"
}

WebInspector.ConsoleMessage.MessageType = {
Log: "log",
Object: "other",
Trace: "trace",
StartGroup: "startGroup",
StartGroupCollapsed: "startGroupCollapsed",
EndGroup: "endGroup",
Assert: "assert",
UncaughtException: "uncaughtException",
NetworkError: "networkError",
Result: "result"
}

WebInspector.ConsoleMessage.MessageLevel = {
Tip: "tip",
Log: "log",
Warning: "warning",
Error: "error",
Debug: "debug"
}

WebInspector.ConsoleCommand = function(command)
{
this.command = command;
}

WebInspector.ConsoleCommand.prototype = {
clearHighlight: function()
{
var highlightedMessage = this._formattedCommand;
delete this._formattedCommand;
this._formatCommand();
this._element.replaceChild(this._formattedCommand, highlightedMessage);
},

highlightSearchResults: function(regexObject)
{
regexObject.lastIndex = 0;
var text = this.command;
var match = regexObject.exec(text);
var offset = 0;
var matchRanges = [];
while (match) {
matchRanges.push({ offset: match.index, length: match[0].length });
match = regexObject.exec(text);
}
highlightSearchResults(this._formattedCommand, matchRanges);
this._element.scrollIntoViewIfNeeded();
},

matchesRegex: function(regexObject)
{
return regexObject.test(this.command);
},

toMessageElement: function()
{
if (!this._element) {
this._element = document.createElement("div");
this._element.command = this;
this._element.className = "console-user-command";

this._formatCommand();
this._element.appendChild(this._formattedCommand);
}
return this._element;
},

_formatCommand: function()
{
this._formattedCommand = document.createElement("span");
this._formattedCommand.className = "console-message-text source-code";
this._formattedCommand.textContent = this.command;
},
}

WebInspector.ConsoleCommandResult = function(result, wasThrown, originatingCommand)
{
var level = (wasThrown ? WebInspector.ConsoleMessage.MessageLevel.Error : WebInspector.ConsoleMessage.MessageLevel.Log);
this.originatingCommand = originatingCommand;
WebInspector.ConsoleMessage.call(this, WebInspector.ConsoleMessage.MessageSource.JS, WebInspector.ConsoleMessage.MessageType.Result, level, -1, null, 1, null, [result]);
}

WebInspector.ConsoleCommandResult.prototype = {
toMessageElement: function()
{
var element = WebInspector.ConsoleMessage.prototype.toMessageElement.call(this);
element.addStyleClass("console-user-command-result");
return element;
}
}

WebInspector.ConsoleCommandResult.prototype.__proto__ = WebInspector.ConsoleMessage.prototype;

WebInspector.ConsoleGroup = function(parentGroup)
{
this.parentGroup = parentGroup;

var element = document.createElement("div");
element.className = "console-group";
element.group = this;
this.element = element;

var messagesElement = document.createElement("div");
messagesElement.className = "console-group-messages";
element.appendChild(messagesElement);
this.messagesElement = messagesElement;
}

WebInspector.ConsoleGroup.prototype = {
addMessage: function(msg)
{
var element = msg.toMessageElement();

if (msg.type === WebInspector.ConsoleMessage.MessageType.StartGroup || msg.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed) {
this.messagesElement.parentNode.insertBefore(element, this.messagesElement);
element.addEventListener("click", this._titleClicked.bind(this), false);
var groupElement = element.enclosingNodeOrSelfWithClass("console-group");
if (groupElement && msg.type === WebInspector.ConsoleMessage.MessageType.StartGroupCollapsed)
groupElement.addStyleClass("collapsed");
} else
this.messagesElement.appendChild(element);

if (element.previousSibling && msg.originatingCommand && element.previousSibling.command === msg.originatingCommand)
element.previousSibling.addStyleClass("console-adjacent-user-command-result");
},

_titleClicked: function(event)
{
var groupTitleElement = event.target.enclosingNodeOrSelfWithClass("console-group-title");
if (groupTitleElement) {
var groupElement = groupTitleElement.enclosingNodeOrSelfWithClass("console-group");
if (groupElement)
if (groupElement.hasStyleClass("collapsed"))
groupElement.removeStyleClass("collapsed");
else
groupElement.addStyleClass("collapsed");
groupTitleElement.scrollIntoViewIfNeeded(true);
}

event.stopPropagation();
event.preventDefault();
}
}






WebInspector.Panel = function(name)
{
WebInspector.View.call(this);

this.element.addStyleClass("panel");
this.element.addStyleClass(name);
this._panelName = name;

this._shortcuts = {};

WebInspector.settings.installApplicationSetting(this._sidebarWidthSettingName(), undefined);
}


WebInspector.Panel.counterRightMargin = 25;

WebInspector.Panel.prototype = {
get toolbarItem()
{
if (this._toolbarItem)
return this._toolbarItem;

this._toolbarItem = WebInspector.Toolbar.createPanelToolbarItem(this);
return this._toolbarItem;
},

get name()
{
return this._panelName;
},

show: function()
{
WebInspector.View.prototype.show.call(this);

var statusBarItems = this.statusBarItems;
if (statusBarItems) {
this._statusBarItemContainer = document.createElement("div");
for (var i = 0; i < statusBarItems.length; ++i)
this._statusBarItemContainer.appendChild(statusBarItems[i]);
document.getElementById("main-status-bar").appendChild(this._statusBarItemContainer);
}

if ("_toolbarItem" in this)
this._toolbarItem.addStyleClass("toggled-on");

WebInspector.currentFocusElement = this.defaultFocusedElement;

this.restoreSidebarWidth();
this._restoreScrollPositions();
WebInspector.extensionServer.notifyPanelShown(this.name);
},

hide: function()
{
this._storeScrollPositions();
WebInspector.View.prototype.hide.call(this);

if (this._statusBarItemContainer && this._statusBarItemContainer.parentNode)
this._statusBarItemContainer.parentNode.removeChild(this._statusBarItemContainer);
delete this._statusBarItemContainer;
if ("_toolbarItem" in this)
this._toolbarItem.removeStyleClass("toggled-on");
WebInspector.extensionServer.notifyPanelHidden(this.name);
},

reset: function()
{
this.searchCanceled();
WebInspector.resetFocusElement();
},

get defaultFocusedElement()
{
return this.sidebarTreeElement || this.element;
},

attach: function()
{
if (!this.element.parentNode)
document.getElementById("main-panels").appendChild(this.element);
},

searchCanceled: function()
{
if (this._searchResults) {
for (var i = 0; i < this._searchResults.length; ++i) {
var view = this._searchResults[i];
if (view.searchCanceled)
view.searchCanceled();
delete view.currentQuery;
}
}

WebInspector.searchController.updateSearchMatchesCount(0, this);

if (this._currentSearchChunkIntervalIdentifier) {
clearInterval(this._currentSearchChunkIntervalIdentifier);
delete this._currentSearchChunkIntervalIdentifier;
}

this._totalSearchMatches = 0;
this._currentSearchResultIndex = 0;
this._searchResults = [];
},

performSearch: function(query)
{

this.searchCanceled(true);

var searchableViews = this.searchableViews;
if (!searchableViews || !searchableViews.length)
return;

var parentElement = this.viewsContainerElement;
var visibleView = this.visibleView;
var sortFuction = this.searchResultsSortFunction;

var matchesCountUpdateTimeout = null;

function updateMatchesCount()
{
WebInspector.searchController.updateSearchMatchesCount(this._totalSearchMatches, this);
matchesCountUpdateTimeout = null;
}

function updateMatchesCountSoon()
{
if (matchesCountUpdateTimeout)
return;

matchesCountUpdateTimeout = setTimeout(updateMatchesCount.bind(this), 500);
}

function finishedCallback(view, searchMatches)
{
if (!searchMatches)
return;

this._totalSearchMatches += searchMatches;
this._searchResults.push(view);

if (sortFuction)
this._searchResults.sort(sortFuction);

if (this.searchMatchFound)
this.searchMatchFound(view, searchMatches);

updateMatchesCountSoon.call(this);

if (view === visibleView)
view.jumpToFirstSearchResult();
}

var i = 0;
var panel = this;
var boundFinishedCallback = finishedCallback.bind(this);
var chunkIntervalIdentifier = null;




function processChunk()
{
var view = searchableViews[i];

if (++i >= searchableViews.length) {
if (panel._currentSearchChunkIntervalIdentifier === chunkIntervalIdentifier)
delete panel._currentSearchChunkIntervalIdentifier;
clearInterval(chunkIntervalIdentifier);
}

if (!view)
return;

if (view.element.parentNode !== parentElement && view.element.parentNode && parentElement)
view.detach();

view.currentQuery = query;
view.performSearch(query, boundFinishedCallback);
}

processChunk();

chunkIntervalIdentifier = setInterval(processChunk, 25);
this._currentSearchChunkIntervalIdentifier = chunkIntervalIdentifier;
},

jumpToNextSearchResult: function()
{
if (!this.showView || !this._searchResults || !this._searchResults.length)
return;

var showFirstResult = false;

this._currentSearchResultIndex = this._searchResults.indexOf(this.visibleView);
if (this._currentSearchResultIndex === -1) {
this._currentSearchResultIndex = 0;
showFirstResult = true;
}

var currentView = this._searchResults[this._currentSearchResultIndex];

if (currentView.showingLastSearchResult()) {
if (++this._currentSearchResultIndex >= this._searchResults.length)
this._currentSearchResultIndex = 0;
currentView = this._searchResults[this._currentSearchResultIndex];
showFirstResult = true;
}

if (currentView !== this.visibleView) {
this.showView(currentView);
WebInspector.searchController.focusSearchField();
}

if (showFirstResult)
currentView.jumpToFirstSearchResult();
else
currentView.jumpToNextSearchResult();
},

jumpToPreviousSearchResult: function()
{
if (!this.showView || !this._searchResults || !this._searchResults.length)
return;

var showLastResult = false;

this._currentSearchResultIndex = this._searchResults.indexOf(this.visibleView);
if (this._currentSearchResultIndex === -1) {
this._currentSearchResultIndex = 0;
showLastResult = true;
}

var currentView = this._searchResults[this._currentSearchResultIndex];

if (currentView.showingFirstSearchResult()) {
if (--this._currentSearchResultIndex < 0)
this._currentSearchResultIndex = (this._searchResults.length - 1);
currentView = this._searchResults[this._currentSearchResultIndex];
showLastResult = true;
}

if (currentView !== this.visibleView) {
this.showView(currentView);
WebInspector.searchController.focusSearchField();
}

if (showLastResult)
currentView.jumpToLastSearchResult();
else
currentView.jumpToPreviousSearchResult();
},

createSidebar: function(parentElement, resizerParentElement)
{
if (this.sidebarElement)
return;

if (!parentElement)
parentElement = this.element;

if (!resizerParentElement)
resizerParentElement = parentElement;

this.sidebarElement = document.createElement("div");
this.sidebarElement.className = "sidebar";
parentElement.appendChild(this.sidebarElement);

this.sidebarResizeElement = document.createElement("div");
this.sidebarResizeElement.className = "sidebar-resizer-vertical";
this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarDragging.bind(this), false);
resizerParentElement.appendChild(this.sidebarResizeElement);

this.sidebarTreeElement = document.createElement("ol");
this.sidebarTreeElement.className = "sidebar-tree";
this.sidebarElement.appendChild(this.sidebarTreeElement);

this.sidebarTree = new TreeOutline(this.sidebarTreeElement);
this.sidebarTree.panel = this;
},

_sidebarWidthSettingName: function()
{
return this._panelName + "SidebarWidth";
},

_startSidebarDragging: function(event)
{
WebInspector.elementDragStart(this.sidebarResizeElement, this._sidebarDragging.bind(this), this._endSidebarDragging.bind(this), event, "col-resize");
},

_sidebarDragging: function(event)
{
this.updateSidebarWidth(event.pageX);

event.preventDefault();
},

_endSidebarDragging: function(event)
{
WebInspector.elementDragEnd(event);
this.saveSidebarWidth();
},

updateSidebarWidth: function(width)
{
if (!this.sidebarElement)
return;

if (this.sidebarElement.offsetWidth <= 0) {


return;
}

if (!("_currentSidebarWidth" in this))
this._currentSidebarWidth = this.sidebarElement.offsetWidth;

if (typeof width === "undefined")
width = this._currentSidebarWidth;

width = Number.constrain(width, Preferences.minSidebarWidth, window.innerWidth / 2);

this._currentSidebarWidth = width;
this.setSidebarWidth(width);

this.updateMainViewWidth(width);
},

setSidebarWidth: function(width)
{
this.sidebarElement.style.width = width + "px";
this.sidebarResizeElement.style.left = (width - 3) + "px";
},

restoreSidebarWidth: function()
{
var sidebarWidth = WebInspector.settings[this._sidebarWidthSettingName()];
this.updateSidebarWidth(sidebarWidth);
},

saveSidebarWidth: function()
{
if (!this.sidebarElement)
return;
WebInspector.settings[this._sidebarWidthSettingName()] = this.sidebarElement.offsetWidth;
},

updateMainViewWidth: function(width)
{

},

resize: function()
{
var visibleView = this.visibleView;
if (visibleView && "resize" in visibleView)
visibleView.resize();
},

canShowAnchorLocation: function(anchor)
{
return false;
},

showAnchorLocation: function(anchor)
{
return false;
},

elementsToRestoreScrollPositionsFor: function()
{
return [];
},

_storeScrollPositions: function()
{
var elements = this.elementsToRestoreScrollPositionsFor();
for (var i = 0; i < elements.length; ++i) {
var container = elements[i];
container._scrollTop = container.scrollTop;
}
},

_restoreScrollPositions: function()
{
var elements = this.elementsToRestoreScrollPositionsFor();
for (var i = 0; i < elements.length; ++i) {
var container = elements[i];
if (container._scrollTop)
container.scrollTop = container._scrollTop;
}
},

handleShortcut: function(event)
{
var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
var handler = this._shortcuts[shortcutKey];
if (handler) {
handler(event);
event.handled = true;
}
},

registerShortcuts: function(shortcuts)
{
this._shortcuts = shortcuts || {};
var goToLineShortcut = WebInspector.GoToLineDialog.createShortcut();
this._shortcuts[goToLineShortcut.key] = this._showGoToLineDialog.bind(this);
},

registerShortcut: function(key, handler)
{
this._shortcuts[key] = handler;
},

_showGoToLineDialog: function(e)
{
var view = this.visibleView;
WebInspector.GoToLineDialog.show(view);
if (view)
WebInspector.GoToLineDialog.show(view);
}
}

WebInspector.Panel.prototype.__proto__ = WebInspector.View.prototype;





WebInspector.TimelineGrid = function()
{
this.element = document.createElement("div");

this._itemsGraphsElement = document.createElement("div");
this._itemsGraphsElement.id = "resources-graphs";
this.element.appendChild(this._itemsGraphsElement);

this._dividersElement = document.createElement("div");
this._dividersElement.className = "resources-dividers";
this.element.appendChild(this._dividersElement);

this._eventDividersElement = document.createElement("div");
this._eventDividersElement.className = "resources-event-dividers";
this.element.appendChild(this._eventDividersElement);

this._dividersLabelBarElement = document.createElement("div");
this._dividersLabelBarElement.className = "resources-dividers-label-bar";
this.element.appendChild(this._dividersLabelBarElement);
}

WebInspector.TimelineGrid.prototype = {
get itemsGraphsElement()
{
return this._itemsGraphsElement;
},


updateDividers: function(force, calculator, paddingLeft)
{
var dividerCount = Math.round(this._dividersElement.offsetWidth / 64);
var slice = calculator.boundarySpan / dividerCount;
if (!force && this._currentDividerSlice === slice)
return false;

if (typeof paddingLeft !== "number")
paddingLeft = 0;
this._currentDividerSlice = slice;


var divider = this._dividersElement.firstChild;
var dividerLabelBar = this._dividersLabelBarElement.firstChild;

var dividersLabelBarElementClientWidth = this._dividersLabelBarElement.clientWidth;
var clientWidth = dividersLabelBarElementClientWidth - paddingLeft;
for (var i = paddingLeft ? 0 : 1; i <= dividerCount; ++i) {
if (!divider) {
divider = document.createElement("div");
divider.className = "resources-divider";
this._dividersElement.appendChild(divider);

dividerLabelBar = document.createElement("div");
dividerLabelBar.className = "resources-divider";
var label = document.createElement("div");
label.className = "resources-divider-label";
dividerLabelBar._labelElement = label;
dividerLabelBar.appendChild(label);
this._dividersLabelBarElement.appendChild(dividerLabelBar);
dividersLabelBarElementClientWidth = this._dividersLabelBarElement.clientWidth;
}

if (i === (paddingLeft ? 0 : 1)) {
divider.addStyleClass("first");
dividerLabelBar.addStyleClass("first");
} else {
divider.removeStyleClass("first");
dividerLabelBar.removeStyleClass("first");
}

if (i === dividerCount) {
divider.addStyleClass("last");
dividerLabelBar.addStyleClass("last");
} else {
divider.removeStyleClass("last");
dividerLabelBar.removeStyleClass("last");
}

var left = paddingLeft + clientWidth * (i / dividerCount);
var percentLeft = 100 * left / dividersLabelBarElementClientWidth;
this._setDividerAndBarLeft(divider, dividerLabelBar, percentLeft);

if (!isNaN(slice))
dividerLabelBar._labelElement.textContent = calculator.formatValue(slice * i);
else
dividerLabelBar._labelElement.textContent = "";

divider = divider.nextSibling;
dividerLabelBar = dividerLabelBar.nextSibling;
}


while (divider) {
var nextDivider = divider.nextSibling;
this._dividersElement.removeChild(divider);
divider = nextDivider;
}
while (dividerLabelBar) {
var nextDivider = dividerLabelBar.nextSibling;
this._dividersLabelBarElement.removeChild(dividerLabelBar);
dividerLabelBar = nextDivider;
}
return true;
},

_setDividerAndBarLeft: function(divider, dividerLabelBar, percentLeft)
{
var percentStyleLeft = parseFloat(divider.style.left);
if (!isNaN(percentStyleLeft) && Math.abs(percentStyleLeft - percentLeft) < 0.1)
return;
divider.style.left = percentLeft + "%";
dividerLabelBar.style.left = percentLeft + "%";
},

addEventDivider: function(divider)
{
this._eventDividersElement.appendChild(divider);
},

addEventDividers: function(dividers)
{
this.element.removeChild(this._eventDividersElement);
for (var i = 0; i < dividers.length; ++i)
if (dividers[i])
this._eventDividersElement.appendChild(dividers[i]);
this.element.appendChild(this._eventDividersElement);
},

removeEventDividers: function()
{
this._eventDividersElement.removeChildren();
},

hideEventDividers: function()
{
this._eventDividersElement.addStyleClass("hidden");
},

showEventDividers: function()
{
this._eventDividersElement.removeStyleClass("hidden");
},

setScrollAndDividerTop: function(scrollTop, dividersTop)
{
this._dividersElement.style.top = scrollTop + "px";
this._eventDividersElement.style.top = scrollTop + "px";
this._dividersLabelBarElement.style.top = dividersTop + "px";
}
}




WebInspector.Resource = function(identifier, url, loaderId)
{
this.identifier = identifier;
this.url = url;
this.loaderId = loaderId;
this._startTime = -1;
this._endTime = -1;
this._category = WebInspector.resourceCategories.other;
this._pendingContentCallbacks = [];
this.history = [];
}


WebInspector.Resource.Type = {
Document:   0,
Stylesheet: 1,
Image:      2,
Font:       3,
Script:     4,
XHR:        5,
WebSocket:  7,
Other:      8,

isTextType: function(type)
{
return (type === this.Document) || (type === this.Stylesheet) || (type === this.Script) || (type === this.XHR);
},

toUIString: function(type)
{
switch (type) {
case this.Document:
return WebInspector.UIString("Document");
case this.Stylesheet:
return WebInspector.UIString("Stylesheet");
case this.Image:
return WebInspector.UIString("Image");
case this.Font:
return WebInspector.UIString("Font");
case this.Script:
return WebInspector.UIString("Script");
case this.XHR:
return WebInspector.UIString("XHR");
case this.WebSocket:
return WebInspector.UIString("WebSocket");
case this.Other:
default:
return WebInspector.UIString("Other");
}
},



toString: function(type)
{
switch (type) {
case this.Document:
return "document";
case this.Stylesheet:
return "stylesheet";
case this.Image:
return "image";
case this.Font:
return "font";
case this.Script:
return "script";
case this.XHR:
return "xhr";
case this.WebSocket:
return "websocket";
case this.Other:
default:
return "other";
}
}
}

WebInspector.Resource._domainModelBindings = [];

WebInspector.Resource.registerDomainModelBinding = function(type, binding)
{
WebInspector.Resource._domainModelBindings[type] = binding;
}


WebInspector.Resource._resourceRevisionRegistry = function()
{
if (!WebInspector.Resource._resourceRevisionRegistryObject) {
if (window.localStorage) {
var resourceHistory = window.localStorage["resource-history"];
try {
WebInspector.Resource._resourceRevisionRegistryObject = resourceHistory ? JSON.parse(resourceHistory) : {};
} catch (e) {
WebInspector.Resource._resourceRevisionRegistryObject = {};
}
} else
WebInspector.Resource._resourceRevisionRegistryObject = {};
}
return WebInspector.Resource._resourceRevisionRegistryObject;
}

WebInspector.Resource.restoreRevisions = function()
{
var registry = WebInspector.Resource._resourceRevisionRegistry();
var filteredRegistry = {};
for (var url in registry) {
var historyItems = registry[url];
var resource = WebInspector.resourceForURL(url);

var filteredHistoryItems = [];
for (var i = 0; historyItems && i < historyItems.length; ++i) {
var historyItem = historyItems[i];
if (resource && historyItem.loaderId === resource.loaderId) {
resource.addRevision(window.localStorage[historyItem.key], new Date(historyItem.timestamp), true);
filteredHistoryItems.push(historyItem);
filteredRegistry[url] = filteredHistoryItems;
} else
delete window.localStorage[historyItem.key];
}
}
WebInspector.Resource._resourceRevisionRegistryObject = filteredRegistry;

function persist()
{
window.localStorage["resource-history"] = JSON.stringify(filteredRegistry);
}


setTimeout(persist, 0);}

WebInspector.Resource.persistRevision = function(resource)
{
if (!window.localStorage)
return;

var url = resource.url;
var loaderId = resource.loaderId;
var timestamp = resource._contentTimestamp.getTime();
var key = "resource-history|" + url + "|" + loaderId + "|" + timestamp;
var content = resource._content;

var registry = WebInspector.Resource._resourceRevisionRegistry();

var historyItems = registry[resource.url];
if (!historyItems) {
historyItems = [];
registry[resource.url] = historyItems;
}
historyItems.push({url: url, loaderId: loaderId, timestamp: timestamp, key: key});

function persist()
{
window.localStorage[key] = content;
window.localStorage["resource-history"] = JSON.stringify(registry);
}


setTimeout(persist, 0);
}

WebInspector.Resource.Events = {
RevisionAdded: 0
}

WebInspector.Resource.prototype = {
get url()
{
return this._url;
},

set url(x)
{
if (this._url === x)
return;

this._url = x;
delete this._parsedQueryParameters;

var parsedURL = x.asParsedURL();
this.domain = parsedURL ? parsedURL.host : "";
this.path = parsedURL ? parsedURL.path : "";
this.lastPathComponent = "";
if (parsedURL && parsedURL.path) {

var path = parsedURL.path;
var indexOfQuery = path.indexOf("?");
if (indexOfQuery !== -1)
path = path.substring(0, indexOfQuery);


var lastSlashIndex = path.lastIndexOf("/");
if (lastSlashIndex !== -1)
this.lastPathComponent = path.substring(lastSlashIndex + 1);
}
this.lastPathComponentLowerCase = this.lastPathComponent.toLowerCase();
},

get documentURL()
{
return this._documentURL;
},

set documentURL(x)
{
this._documentURL = x;
},

get displayName()
{
if (this._displayName)
return this._displayName;
this._displayName = this.lastPathComponent;
if (!this._displayName)
this._displayName = this.displayDomain;
if (!this._displayName && this.url)
this._displayName = this.url.trimURL(WebInspector.mainResource ? WebInspector.mainResource.domain : "");
if (this._displayName === "/")
this._displayName = this.url;
return this._displayName;
},

get displayDomain()
{

if (this.domain && (!WebInspector.mainResource || (WebInspector.mainResource && this.domain !== WebInspector.mainResource.domain)))
return this.domain;
return "";
},

get startTime()
{
return this._startTime || -1;
},

set startTime(x)
{
this._startTime = x;
},

get responseReceivedTime()
{
return this._responseReceivedTime || -1;
},

set responseReceivedTime(x)
{
this._responseReceivedTime = x;
},

get endTime()
{
return this._endTime || -1;
},

set endTime(x)
{
if (this.timing && this.timing.requestTime) {

this._endTime = Math.max(x, this.responseReceivedTime);
} else {

this._endTime = x;
if (this._responseReceivedTime > x)
this._responseReceivedTime = x;
}
},

get duration()
{
if (this._endTime === -1 || this._startTime === -1)
return -1;
return this._endTime - this._startTime;
},

get latency()
{
if (this._responseReceivedTime === -1 || this._startTime === -1)
return -1;
return this._responseReceivedTime - this._startTime;
},

get receiveDuration()
{
if (this._endTime === -1 || this._responseReceivedTime === -1)
return -1;
return this._endTime - this._responseReceivedTime;
},

get resourceSize()
{
return this._resourceSize || 0;
},

set resourceSize(x)
{
this._resourceSize = x;
},

get transferSize()
{
if (this.cached)
return 0;
if (this.statusCode === 304) 
return this.responseHeadersSize;
if (this._transferSize !== undefined)
return this._transferSize;










var bodySize = Number(this.responseHeaders["Content-Length"] || this.resourceSize);
return this.responseHeadersSize + bodySize;
},

increaseTransferSize: function(x)
{
this._transferSize = (this._transferSize || 0) + x;
},

get finished()
{
return this._finished;
},

set finished(x)
{
if (this._finished === x)
return;

this._finished = x;

if (x) {
this._checkWarnings();
this.dispatchEventToListeners("finished");
if (this._pendingContentCallbacks.length)
this._innerRequestContent();
}
},

get failed()
{
return this._failed;
},

set failed(x)
{
this._failed = x;
},

get canceled()
{
return this._canceled;
},

set canceled(x)
{
this._canceled = x;
},

get category()
{
return this._category;
},

set category(x)
{
this._category = x;
},

get cached()
{
return this._cached;
},

set cached(x)
{
this._cached = x;
if (x)
delete this._timing;
},

get timing()
{
return this._timing;
},

set timing(x)
{
if (x && !this._cached) {


this._startTime = x.requestTime;
this._responseReceivedTime = x.requestTime + x.receiveHeadersEnd / 1000.0;

this._timing = x;
this.dispatchEventToListeners("timing changed");
}
},

get mimeType()
{
return this._mimeType;
},

set mimeType(x)
{
this._mimeType = x;
},

get type()
{
return this._type;
},

set type(x)
{
if (this._type === x)
return;

this._type = x;

switch (x) {
case WebInspector.Resource.Type.Document:
this.category = WebInspector.resourceCategories.documents;
break;
case WebInspector.Resource.Type.Stylesheet:
this.category = WebInspector.resourceCategories.stylesheets;
break;
case WebInspector.Resource.Type.Script:
this.category = WebInspector.resourceCategories.scripts;
break;
case WebInspector.Resource.Type.Image:
this.category = WebInspector.resourceCategories.images;
break;
case WebInspector.Resource.Type.Font:
this.category = WebInspector.resourceCategories.fonts;
break;
case WebInspector.Resource.Type.XHR:
this.category = WebInspector.resourceCategories.xhr;
break;
case WebInspector.Resource.Type.WebSocket:
this.category = WebInspector.resourceCategories.websockets;
break;
case WebInspector.Resource.Type.Other:
default:
this.category = WebInspector.resourceCategories.other;
break;
}
},

get requestHeaders()
{
return this._requestHeaders || {};
},

set requestHeaders(x)
{
this._requestHeaders = x;
delete this._sortedRequestHeaders;
delete this._requestCookies;
delete this._responseHeadersSize;

this.dispatchEventToListeners("requestHeaders changed");
},

get requestHeadersText()
{
if (this._requestHeadersText !== undefined)
return this._requestHeadersText;

this._requestHeadersText = "";
for (var key in this.requestHeaders)
this._requestHeadersText += key + ": " + this.requestHeaders[key] + "\n"; 
return this._requestHeadersText;
},

set requestHeadersText(x)
{
this._requestHeadersText = x;
delete this._responseHeadersSize;

this.dispatchEventToListeners("requestHeaders changed");
},

get requestHeadersSize()
{
if (typeof(this._requestHeadersSize) === "undefined") {
if (this._requestHeadersText)
this._requestHeadersSize = this._requestHeadersText.length;
else 
this._requestHeadersSize = this._headersSize(this._requestHeaders)
}
return this._requestHeadersSize;
},

get sortedRequestHeaders()
{
if (this._sortedRequestHeaders !== undefined)
return this._sortedRequestHeaders;

this._sortedRequestHeaders = [];
for (var key in this.requestHeaders)
this._sortedRequestHeaders.push({header: key, value: this.requestHeaders[key]});
this._sortedRequestHeaders.sort(function(a,b) { return a.header.localeCompare(b.header) });

return this._sortedRequestHeaders;
},

requestHeaderValue: function(headerName)
{
return this._headerValue(this.requestHeaders, headerName);
},

get requestCookies()
{
if (!this._requestCookies)
this._requestCookies = WebInspector.CookieParser.parseCookie(this.requestHeaderValue("Cookie"));
return this._requestCookies;
},

get requestFormData()
{
return this._requestFormData;
},

set requestFormData(x)
{
this._requestFormData = x;
delete this._parsedFormParameters;
},

get responseHeaders()
{
return this._responseHeaders || {};
},

set responseHeaders(x)
{
this._responseHeaders = x;
delete this._responseHeadersSize;
delete this._sortedResponseHeaders;
delete this._responseCookies;

this.dispatchEventToListeners("responseHeaders changed");
},

get responseHeadersText()
{
if (this._responseHeadersText !== undefined)
return this._responseHeadersText;

this._responseHeadersText = "";
for (var key in this.responseHeaders)
this._responseHeadersText += key + ": " + this.responseHeaders[key] + "\n"; 
return this._responseHeadersText;
},

set responseHeadersText(x)
{
this._responseHeadersText = x;
delete this._responseHeadersSize;

this.dispatchEventToListeners("responseHeaders changed");
},

get responseHeadersSize()
{
if (typeof(this._responseHeadersSize) === "undefined") {
if (this._responseHeadersText)
this._responseHeadersSize = this._responseHeadersText.length;
else 
this._responseHeadersSize = this._headersSize(this._responseHeaders)
}
return this._responseHeadersSize;
},


get sortedResponseHeaders()
{
if (this._sortedResponseHeaders !== undefined)
return this._sortedResponseHeaders;

this._sortedResponseHeaders = [];
for (var key in this.responseHeaders)
this._sortedResponseHeaders.push({header: key, value: this.responseHeaders[key]});
this._sortedResponseHeaders.sort(function(a,b) { return a.header.localeCompare(b.header) });

return this._sortedResponseHeaders;
},

responseHeaderValue: function(headerName)
{
return this._headerValue(this.responseHeaders, headerName);
},

get responseCookies()
{
if (!this._responseCookies)
this._responseCookies = WebInspector.CookieParser.parseSetCookie(this.responseHeaderValue("Set-Cookie"));
return this._responseCookies;
},

get queryParameters()
{
if (this._parsedQueryParameters)
return this._parsedQueryParameters;
var queryString = this.url.split("?", 2)[1];
if (!queryString)
return;
this._parsedQueryParameters = this._parseParameters(queryString);
return this._parsedQueryParameters;
},

get formParameters()
{
if (this._parsedFormParameters)
return this._parsedFormParameters;
if (!this.requestFormData)
return;
var requestContentType = this.requestContentType();
if (!requestContentType || !requestContentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i))
return;
this._parsedFormParameters = this._parseParameters(this.requestFormData);
return this._parsedFormParameters;
},

_parseParameters: function(queryString)
{
function parseNameValue(pair)
{
var parameter = {};
var splitPair = pair.split("=", 2);

parameter.name = splitPair[0];
if (splitPair.length === 1)
parameter.value = "";
else
parameter.value = splitPair[1];
return parameter;
}
return queryString.split("&").map(parseNameValue);
},

_headerValue: function(headers, headerName)
{
headerName = headerName.toLowerCase();
for (var header in headers) {
if (header.toLowerCase() === headerName)
return headers[header];
}
},

_headersSize: function(headers)
{


var size = 0;
for (var header in headers)
size += header.length + headers[header].length + 4; 
return size;
},

get messages()
{
return this._messages || [];
},

addMessage: function(msg)
{
if (!msg.isErrorOrWarning() || !msg.message) 
return;

if (!this._messages)
this._messages = [];
this._messages.push(msg);
this.dispatchEventToListeners("errors-warnings-message-added", msg);
},

get errors()
{
return this._errors || 0;
},

set errors(x)
{
this._errors = x;
},

get warnings()
{
return this._warnings || 0;
},

set warnings(x)
{
this._warnings = x;
},

clearErrorsAndWarnings: function()
{
this._messages = [];
this._warnings = 0;
this._errors = 0;
this.dispatchEventToListeners("errors-warnings-cleared");
},

_mimeTypeIsConsistentWithType: function()
{






if (this.statusCode >= 400 || this.statusCode === 304)
return true;

if (typeof this.type === "undefined"
|| this.type === WebInspector.Resource.Type.Other
|| this.type === WebInspector.Resource.Type.XHR
|| this.type === WebInspector.Resource.Type.WebSocket)
return true;

if (!this.mimeType)
return true; 

if (this.mimeType in WebInspector.MIMETypes)
return this.type in WebInspector.MIMETypes[this.mimeType];

return false;
},

_checkWarnings: function()
{
for (var warning in WebInspector.Warnings)
this._checkWarning(WebInspector.Warnings[warning]);
},

_checkWarning: function(warning)
{
var msg;
switch (warning.id) {
case WebInspector.Warnings.IncorrectMIMEType.id:
if (!this._mimeTypeIsConsistentWithType())
msg = new WebInspector.ConsoleMessage(WebInspector.ConsoleMessage.MessageSource.Other,
WebInspector.ConsoleMessage.MessageType.Log,
WebInspector.ConsoleMessage.MessageLevel.Warning,
-1,
this.url,
1,
String.sprintf(WebInspector.Warnings.IncorrectMIMEType.message, WebInspector.Resource.Type.toUIString(this.type), this.mimeType),
null,
null);
break;
}

if (msg)
WebInspector.console.addMessage(msg);
},

get content()
{
return this._content;
},

get contentTimestamp()
{
return this._contentTimestamp;
},

setInitialContent: function(content)
{
this._content = content;
},

isEditable: function()
{
if (this._actualResource)
return false;
var binding = WebInspector.Resource._domainModelBindings[this.type];
return binding && binding.canSetContent(this);
},

setContent: function(newContent, majorChange, callback)
{
if (!this.isEditable(this)) {
if (callback)
callback("Resource is not editable");
return;
}
var binding = WebInspector.Resource._domainModelBindings[this.type];
binding.setContent(this, newContent, majorChange, callback);
},

addRevision: function(newContent, timestamp, restoringHistory)
{
var revision = new WebInspector.ResourceRevision(this, this._content, this._contentTimestamp);
this.history.push(revision);

this._content = newContent;
this._contentTimestamp = timestamp || new Date();

this.dispatchEventToListeners(WebInspector.Resource.Events.RevisionAdded, revision);

if (!restoringHistory)
this._persistRevision();
},

_persistRevision: function()
{
WebInspector.Resource.persistRevision(this);
},

requestContent: function(callback)
{



if (this.type === WebInspector.Resource.Type.WebSocket) {
callback(null, null);
return;
}
if (typeof this._content !== "undefined") {
callback(this.content, this._contentEncoded);
return;
}
this._pendingContentCallbacks.push(callback);
if (this.finished)
this._innerRequestContent();
},

populateImageSource: function(image)
{
function onResourceContent()
{
image.src = this._contentURL();
}

if (Preferences.useDataURLForResourceImageIcons)
this.requestContent(onResourceContent.bind(this));
else
image.src = this.url;
},

isDataURL: function()
{
return this.url.match(/^data:/i);
},

requestContentType: function()
{
return this.requestHeaderValue("Content-Type");
},

isPingRequest: function()
{
return "text/ping" === this.requestContentType();
},

_contentURL: function()
{
const maxDataUrlSize = 1024 * 1024;

if (this._content == null || this._content.length > maxDataUrlSize)
return this.url;

return "data:" + this.mimeType + (this._contentEncoded ? ";base64," : ",") + this._content;
},

_innerRequestContent: function()
{
if (this._contentRequested)
return;
this._contentRequested = true;
this._contentEncoded = !WebInspector.Resource.Type.isTextType(this.type);

function onResourceContent(data)
{
this._content = data;
this._originalContent = data;
var callbacks = this._pendingContentCallbacks.slice();
for (var i = 0; i < callbacks.length; ++i)
callbacks[i](this._content, this._contentEncoded);
this._pendingContentCallbacks.length = 0;
delete this._contentRequested;
}
WebInspector.networkManager.requestContent(this, this._contentEncoded, onResourceContent.bind(this));
}
}

WebInspector.Resource.prototype.__proto__ = WebInspector.Object.prototype;

WebInspector.ResourceRevision = function(resource, content, timestamp)
{
this._resource = resource;
this._content = content;
this._timestamp = timestamp;
}

WebInspector.ResourceRevision.prototype = {
get resource()
{
return this._resource;
},

get timestamp()
{
return this._timestamp;
},

get content()
{
return this._content;
},

revertToThis: function()
{
function revert(content)
{
this._resource.setContent(content, true);
}
this.requestContent(revert.bind(this));
},

requestContent: function(callback)
{
if (typeof this._content === "string") {
callback(this._content);
return;
}


if (typeof this.resource._originalContent === "string") {
this._content = this._resource._originalContent;
callback(this._content);
return;
}


function mycallback(content)
{
this._content = content;
callback(content);
}
WebInspector.networkManager.requestContent(this._resource, false, mycallback.bind(this));
}
}

WebInspector.ResourceDomainModelBinding = function()
{
}

WebInspector.ResourceDomainModelBinding.prototype = {
canSetContent: function()
{

return true;
},

setContent: function(resource, content, majorChange, callback)
{

}
}





WebInspector.CSSStyleModel = function()
{
new WebInspector.CSSStyleModelResourceBinding(this);
}

WebInspector.CSSStyleModel.parseRuleArrayPayload = function(ruleArray)
{
var result = [];
for (var i = 0; i < ruleArray.length; ++i)
result.push(WebInspector.CSSRule.parsePayload(ruleArray[i]));
return result;
}

WebInspector.CSSStyleModel.Events = {
StyleSheetChanged: 0
}

WebInspector.CSSStyleModel.prototype = {
getStylesAsync: function(nodeId, userCallback)
{
function callback(userCallback, error, payload)
{
if (error) {
if (userCallback)
userCallback(null);
return;
}

var result = {};
if ("inlineStyle" in payload)
result.inlineStyle = WebInspector.CSSStyleDeclaration.parsePayload(payload.inlineStyle);

result.computedStyle = WebInspector.CSSStyleDeclaration.parsePayload(payload.computedStyle);
result.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleArrayPayload(payload.matchedCSSRules);

result.styleAttributes = {};
var payloadStyleAttributes = payload.styleAttributes;
for (var i = 0; i < payloadStyleAttributes.length; ++i) {
var name = payloadStyleAttributes[i].name;
result.styleAttributes[name] = WebInspector.CSSStyleDeclaration.parsePayload(payloadStyleAttributes[i].style);
}

result.pseudoElements = [];
for (var i = 0; i < payload.pseudoElements.length; ++i) {
var entryPayload = payload.pseudoElements[i];
result.pseudoElements.push({ pseudoId: entryPayload.pseudoId, rules: WebInspector.CSSStyleModel.parseRuleArrayPayload(entryPayload.rules) });
}

result.inherited = [];
for (var i = 0; i < payload.inherited.length; ++i) {
var entryPayload = payload.inherited[i];
var entry = {};
if ("inlineStyle" in entryPayload)
entry.inlineStyle = WebInspector.CSSStyleDeclaration.parsePayload(entryPayload.inlineStyle);
if ("matchedCSSRules" in entryPayload)
entry.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleArrayPayload(entryPayload.matchedCSSRules);
result.inherited.push(entry);
}

if (userCallback)
userCallback(result);
}

CSSAgent.getStylesForNode(nodeId, callback.bind(null, userCallback));
},

getComputedStyleAsync: function(nodeId, userCallback)
{
function callback(userCallback, error, stylePayload)
{
if (error)
userCallback(null);
else
userCallback(WebInspector.CSSStyleDeclaration.parsePayload(stylePayload));
}

CSSAgent.getComputedStyleForNode(nodeId, callback.bind(null, userCallback));
},

getInlineStyleAsync: function(nodeId, userCallback)
{
function callback(userCallback, error, stylePayload)
{
if (error)
userCallback(null);
else
userCallback(WebInspector.CSSStyleDeclaration.parsePayload(stylePayload));
}

CSSAgent.getInlineStyleForNode(nodeId, callback.bind(null, userCallback));
},

setRuleSelector: function(ruleId, nodeId, newSelector, successCallback, failureCallback)
{
function checkAffectsCallback(nodeId, successCallback, rulePayload, selectedNodeIds)
{
if (!selectedNodeIds)
return;
var doesAffectSelectedNode = (selectedNodeIds.indexOf(nodeId) >= 0);
var rule = WebInspector.CSSRule.parsePayload(rulePayload);
successCallback(rule, doesAffectSelectedNode);
this._fireStyleSheetChanged(rule.id.styleSheetId, true);
}

function callback(nodeId, successCallback, failureCallback, error, newSelector, rulePayload)
{

if (error)
failureCallback();
else {
var documentElementId = this._documentElementId(nodeId);
if (documentElementId)
WebInspector.domAgent.querySelectorAll(documentElementId, newSelector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
else
failureCallback();
}
}

CSSAgent.setRuleSelector(ruleId, newSelector, callback.bind(this, nodeId, successCallback, failureCallback, newSelector));
},

addRule: function(nodeId, selector, successCallback, failureCallback)
{
function checkAffectsCallback(nodeId, successCallback, rulePayload, selectedNodeIds)
{
if (!selectedNodeIds)
return;

var doesAffectSelectedNode = (selectedNodeIds.indexOf(nodeId) >= 0);
var rule = WebInspector.CSSRule.parsePayload(rulePayload);
successCallback(rule, doesAffectSelectedNode);
this._fireStyleSheetChanged(rule.id.styleSheetId, true);
}

function callback(successCallback, failureCallback, selector, error, rulePayload)
{
if (error) {

failureCallback();
} else {
var documentElementId = this._documentElementId(nodeId);
if (documentElementId)
WebInspector.domAgent.querySelectorAll(documentElementId, selector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
else
failureCallback();
}
}

CSSAgent.addRule(nodeId, selector, callback.bind(this, successCallback, failureCallback, selector));
},

_documentElementId: function(nodeId)
{
var node = WebInspector.domAgent.nodeForId(nodeId);
if (!node)
return null;
return node.ownerDocumentElement().id;
},

_fireStyleSheetChanged: function(styleSheetId, majorChange, callback)
{
callback = callback || function() {};

if (!majorChange || !styleSheetId || !this.hasEventListeners(WebInspector.CSSStyleModel.Events.StyleSheetChanged)) {
callback();
return;
}

function mycallback(error, content)
{
if (!error)
this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.StyleSheetChanged, { styleSheetId: styleSheetId, content: content, majorChange: majorChange });
callback();
}

CSSAgent.getStyleSheetText(styleSheetId, mycallback.bind(this));
},

setStyleSheetText: function(styleSheetId, newText, majorChange, userCallback)
{
function callback(error)
{
if (!error)
this._fireStyleSheetChanged(styleSheetId, majorChange, userCallback ? userCallback.bind(this, error) : null);
}
CSSAgent.setStyleSheetText(styleSheetId, newText, callback.bind(this));
}
}

WebInspector.CSSStyleModel.prototype.__proto__ = WebInspector.Object.prototype;

WebInspector.CSSStyleDeclaration = function(payload)
{
this.id = payload.styleId;
this.width = payload.width;
this.height = payload.height;
this.range = payload.range;
this._shorthandValues = WebInspector.CSSStyleDeclaration.buildShorthandValueMap(payload.shorthandEntries);
this._livePropertyMap = {}; 
this._allProperties = []; 
this._longhandProperties = {}; 
this.__disabledProperties = {}; 
var payloadPropertyCount = payload.cssProperties.length;

var propertyIndex = 0;
for (var i = 0; i < payloadPropertyCount; ++i) {
var property = new WebInspector.CSSProperty.parsePayload(this, i, payload.cssProperties[i]);
this._allProperties.push(property);
if (property.disabled)
this.__disabledProperties[i] = property;
if (!property.active && !property.styleBased)
continue;
var name = property.name;
this[propertyIndex] = name;
this._livePropertyMap[name] = property;


if (property.shorthand) { 
var longhands = this._longhandProperties[property.shorthand];
if (!longhands) {
longhands = [];
this._longhandProperties[property.shorthand] = longhands;
}
longhands.push(property);
}
++propertyIndex;
}
this.length = propertyIndex;
if ("cssText" in payload)
this.cssText = payload.cssText;
}

WebInspector.CSSStyleDeclaration.buildShorthandValueMap = function(shorthandEntries)
{
var result = {};
for (var i = 0; i < shorthandEntries.length; ++i)
result[shorthandEntries[i].name] = shorthandEntries[i].value;
return result;
}

WebInspector.CSSStyleDeclaration.parsePayload = function(payload)
{
return new WebInspector.CSSStyleDeclaration(payload);
}

WebInspector.CSSStyleDeclaration.prototype = {
get allProperties()
{
return this._allProperties;
},

getLiveProperty: function(name)
{
return this._livePropertyMap[name];
},

getPropertyValue: function(name)
{
var property = this._livePropertyMap[name];
return property ? property.value : "";
},

getPropertyPriority: function(name)
{
var property = this._livePropertyMap[name];
return property ? property.priority : "";
},

getPropertyShorthand: function(name)
{
var property = this._livePropertyMap[name];
return property ? property.shorthand : "";
},

isPropertyImplicit: function(name)
{
var property = this._livePropertyMap[name];
return property ? property.implicit : "";
},

styleTextWithShorthands: function()
{
var cssText = "";
var foundProperties = {};
for (var i = 0; i < this.length; ++i) {
var individualProperty = this[i];
var shorthandProperty = this.getPropertyShorthand(individualProperty);
var propertyName = (shorthandProperty || individualProperty);

if (propertyName in foundProperties)
continue;

if (shorthandProperty) {
var value = this.getShorthandValue(shorthandProperty);
var priority = this.getShorthandPriority(shorthandProperty);
} else {
var value = this.getPropertyValue(individualProperty);
var priority = this.getPropertyPriority(individualProperty);
}

foundProperties[propertyName] = true;

cssText += propertyName + ": " + value;
if (priority)
cssText += " !" + priority;
cssText += "; ";
}

return cssText;
},

getLonghandProperties: function(name)
{
return this._longhandProperties[name] || [];
},

getShorthandValue: function(shorthandProperty)
{
var property = this.getLiveProperty(shorthandProperty);
return property ? property.value : this._shorthandValues[shorthandProperty];
},

getShorthandPriority: function(shorthandProperty)
{
var priority = this.getPropertyPriority(shorthandProperty);
if (priority)
return priority;

var longhands = this._longhandProperties[shorthandProperty];
return longhands ? this.getPropertyPriority(longhands[0]) : null;
},

propertyAt: function(index)
{
return (index < this.allProperties.length) ? this.allProperties[index] : null;
},

pastLastSourcePropertyIndex: function()
{
for (var i = this.allProperties.length - 1; i >= 0; --i) {
var property = this.allProperties[i];
if (property.active || property.disabled)
return i + 1;
}
return 0;
},

newBlankProperty: function()
{
return new WebInspector.CSSProperty(this, this.pastLastSourcePropertyIndex(), "", "", "", "active", true, false, false, "");
},

insertPropertyAt: function(index, name, value, userCallback)
{
function callback(userCallback, error, payload)
{
if (!userCallback)
return;

if (error) {
console.error(JSON.stringify(error));
userCallback(null);
} else {
userCallback(WebInspector.CSSStyleDeclaration.parsePayload(payload));
WebInspector.cssModel._fireStyleSheetChanged(this.id.styleSheetId, true);
}
}

CSSAgent.setPropertyText(this.id, index, name + ": " + value + ";", false, callback.bind(null, userCallback));
},

appendProperty: function(name, value, userCallback)
{
this.insertPropertyAt(this.allProperties.length, name, value, userCallback);
}
}

WebInspector.CSSRule = function(payload)
{
this.id = payload.ruleId;
this.selectorText = payload.selectorText;
this.sourceLine = payload.sourceLine;
this.sourceURL = payload.sourceURL;
this.origin = payload.origin;
this.style = WebInspector.CSSStyleDeclaration.parsePayload(payload.style);
this.style.parentRule = this;
this.selectorRange = payload.selectorRange;
}

WebInspector.CSSRule.parsePayload = function(payload)
{
return new WebInspector.CSSRule(payload);
}

WebInspector.CSSRule.prototype = {
get isUserAgent()
{
return this.origin === "user-agent";
},

get isUser()
{
return this.origin === "user";
},

get isViaInspector()
{
return this.origin === "inspector";
},

get isRegular()
{
return this.origin === "";
}
}

WebInspector.CSSProperty = function(ownerStyle, index, name, value, priority, status, parsedOk, implicit, shorthand, text)
{
this.ownerStyle = ownerStyle;
this.index = index;
this.name = name;
this.value = value;
this.priority = priority;
this.status = status;
this.parsedOk = parsedOk;
this.implicit = implicit;
this.shorthand = shorthand;
this.text = text;
}

WebInspector.CSSProperty.parsePayload = function(ownerStyle, index, payload)
{






var result = new WebInspector.CSSProperty(
ownerStyle, index, payload.name, payload.value, payload.priority || "", payload.status || "style", ("parsedOk" in payload) ? payload.parsedOk : true, !!payload.implicit, payload.shorthandName || "", payload.text);
return result;
}

WebInspector.CSSProperty.prototype = {
get propertyText()
{
if (this.text !== undefined)
return this.text;

if (this.name === "")
return "";
return this.name + ": " + this.value + (this.priority ? " !" + this.priority : "") + ";";
},

get isLive()
{
return this.active || this.styleBased;
},

get active()
{
return this.status === "active";
},

get styleBased()
{
return this.status === "style";
},

get inactive()
{
return this.status === "inactive";
},

get disabled()
{
return this.status === "disabled";
},


setText: function(propertyText, majorChange, userCallback)
{
function enabledCallback(style)
{
if (style)
WebInspector.cssModel._fireStyleSheetChanged(style.id.styleSheetId, majorChange);
if (userCallback)
userCallback(style);
}

function callback(error, stylePayload)
{
if (!error) {
this.text = propertyText;
var style = WebInspector.CSSStyleDeclaration.parsePayload(stylePayload);
var newProperty = style.allProperties[this.index];

if (newProperty && this.disabled && !propertyText.match(/^\s*$/)) {
newProperty.setDisabled(false, enabledCallback);
return;
}

WebInspector.cssModel._fireStyleSheetChanged(style.id.styleSheetId, majorChange, userCallback ? userCallback.bind(this, style) : null);
} else {
if (userCallback)
userCallback(null);
}
}

if (!this.ownerStyle)
throw "No ownerStyle for property";


CSSAgent.setPropertyText(this.ownerStyle.id, this.index, propertyText, this.index < this.ownerStyle.pastLastSourcePropertyIndex(), callback.bind(this));
},

setValue: function(newValue, majorChange, userCallback)
{
var text = this.name + ": " + newValue + (this.priority ? " !" + this.priority : "") + ";"
this.setText(text, majorChange, userCallback);
},

setDisabled: function(disabled, userCallback)
{
if (!this.ownerStyle && userCallback)
userCallback(null);
if (disabled === this.disabled && userCallback)
userCallback(this.ownerStyle);

function callback(error, stylePayload)
{
if (error) {
if (userCallback)
userCallback(null);
return;
}
if (userCallback) {
var style = WebInspector.CSSStyleDeclaration.parsePayload(stylePayload);
userCallback(style);
}
WebInspector.cssModel._fireStyleSheetChanged(this.ownerStyle.id.styleSheetId, false);
}

CSSAgent.toggleProperty(this.ownerStyle.id, this.index, disabled, callback.bind(this));
}
}

WebInspector.CSSStyleSheet = function(payload)
{
this.id = payload.styleSheetId;
this.rules = [];
this.styles = {};
for (var i = 0; i < payload.rules.length; ++i) {
var rule = WebInspector.CSSRule.parsePayload(payload.rules[i]);
this.rules.push(rule);
if (rule.style)
this.styles[rule.style.id] = rule.style;
}
if ("text" in payload)
this._text = payload.text;
}

WebInspector.CSSStyleSheet.createForId = function(styleSheetId, userCallback)
{
function callback(error, styleSheetPayload)
{
if (error)
userCallback(null);
else
userCallback(new WebInspector.CSSStyleSheet(styleSheetPayload));
}
CSSAgent.getStyleSheet(styleSheetId, callback.bind(this));
}

WebInspector.CSSStyleSheet.prototype = {
getText: function()
{
return this._text;
},

setText: function(newText, majorChange, userCallback)
{
function callback(error)
{
if (userCallback)
userCallback(error);
if (!error)
WebInspector.cssModel._fireStyleSheetChanged(this.id, majorChange);
}

CSSAgent.setStyleSheetText(this.id, newText, callback.bind(this));
}
}

WebInspector.CSSStyleModelResourceBinding = function(cssModel)
{
this._cssModel = cssModel;
this._urlToStyleSheetId = {};
this._styleSheetIdToURL = {};
this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetChanged, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, this._inspectedURLChanged, this);
WebInspector.Resource.registerDomainModelBinding(WebInspector.Resource.Type.Stylesheet, this);
}

WebInspector.CSSStyleModelResourceBinding.prototype = {
setContent: function(resource, content, majorChange, userCallback)
{
if (this._urlToStyleSheetId[resource.url]) {
this._innerSetContent(resource.url, content, majorChange, userCallback);
return;
}
this._loadStyleSheetHeaders(this._innerSetContent.bind(this, resource.url, content, majorChange, userCallback));
},

_inspectedURLChanged: function(event)
{

this._urlToStyleSheetId = {};
this._styleSheetIdToURL = {};
},

_innerSetContent: function(url, content, majorChange, userCallback, error)
{
if (error) {
userCallback(error);
return;
}

var styleSheetId = this._urlToStyleSheetId[url];
if (!styleSheetId) {
if (userCallback)
userCallback("No stylesheet found: " + url);
return;
}
this._cssModel.setStyleSheetText(styleSheetId, content, majorChange, userCallback);
},

_loadStyleSheetHeaders: function(callback)
{
function didGetAllStyleSheets(error, infos)
{
if (error) {
callback(error);
return;
}

for (var i = 0; i < infos.length; ++i) {
var info = infos[i];
this._urlToStyleSheetId[info.sourceURL] = info.styleSheetId;
this._styleSheetIdToURL[info.styleSheetId] = info.sourceURL;
}
callback();
}
CSSAgent.getAllStyleSheets(didGetAllStyleSheets.bind(this));
},

_styleSheetChanged: function(event)
{
var styleSheetId = event.data.styleSheetId;
function setContent()
{
var url = this._styleSheetIdToURL[styleSheetId];
if (!url)
return;

var resource = WebInspector.resourceForURL(url);
if (!resource)
return;

var majorChange = event.data.majorChange;
if (majorChange)
resource.addRevision(event.data.content);
}

if (!this._styleSheetIdToURL[styleSheetId]) {
this._loadStyleSheetHeaders(setContent.bind(this));
return;
}
setContent.call(this);
}
}

WebInspector.CSSStyleModelResourceBinding.prototype.__proto__ = WebInspector.ResourceDomainModelBinding.prototype;





WebInspector.NetworkManager = function()
{
WebInspector.Object.call(this);
this._dispatcher = new WebInspector.NetworkDispatcher(this);
NetworkAgent.enable();
}

WebInspector.NetworkManager.EventTypes = {
ResourceStarted: "ResourceStarted",
ResourceUpdated: "ResourceUpdated",
ResourceFinished: "ResourceFinished"
}

WebInspector.NetworkManager.prototype = {
requestContent: function(resource, base64Encode, callback)
{
function callbackWrapper(error, content)
{
callback(!error ? content : null);
}
PageAgent.getResourceContent(resource.frameId, resource.url, base64Encode, callbackWrapper);
},

inflightResourceForURL: function(url)
{
return this._dispatcher._inflightResourcesByURL[url];
}
}

WebInspector.NetworkManager.prototype.__proto__ = WebInspector.Object.prototype;

WebInspector.NetworkDispatcher = function(manager)
{
this._manager = manager;
this._inflightResourcesById = {};
this._inflightResourcesByURL = {};
this._lastIdentifierForCachedResource = 0;
InspectorBackend.registerDomainDispatcher("Network", this);
}

WebInspector.NetworkDispatcher.prototype = {
_updateResourceWithRequest: function(resource, request)
{
resource.requestMethod = request.method;
resource.requestHeaders = request.headers;
resource.requestFormData = request.postData;
},

_updateResourceWithResponse: function(resource, response)
{
if (!response)
return;

resource.mimeType = response.mimeType;
resource.statusCode = response.status;
resource.statusText = response.statusText;
resource.responseHeaders = response.headers;
if (response.headersText)
resource.responseHeadersText = response.headersText;
if (response.requestHeaders)
resource.requestHeaders = response.requestHeaders;
if (response.requestHeadersText)
resource.requestHeadersText = response.requestHeadersText;

resource.connectionReused = response.connectionReused;
resource.connectionId = response.connectionId;

if (response.fromDiskCache)
resource.cached = true;
else
resource.timing = response.timing;
},

_updateResourceWithCachedResource: function(resource, cachedResource)
{
resource.type = WebInspector.Resource.Type[cachedResource.type];
resource.resourceSize = cachedResource.bodySize;
this._updateResourceWithResponse(resource, cachedResource.response);
},

_isNull: function(response)
{
return response && !response.status && !response.mimeType && !Object.keys(response.headers).length;
},

requestWillBeSent: function(identifier, frameId, loaderId, documentURL, request, time, stackTrace, redirectResponse)
{
var resource = this._inflightResourcesById[identifier];
if (resource) {

if (this._isNull(redirectResponse))
return;
this.responseReceived(identifier, time, "Other", redirectResponse);
resource = this._appendRedirect(identifier, time, request.url);
} else
resource = this._createResource(identifier, frameId, loaderId, request.url, documentURL, stackTrace);
this._updateResourceWithRequest(resource, request);
resource.startTime = time;

this._startResource(resource);
},

resourceMarkedAsCached: function(identifier)
{
var resource = this._inflightResourcesById[identifier];
if (!resource)
return;

resource.cached = true;
this._updateResource(resource);
},

responseReceived: function(identifier, time, resourceType, response)
{

if (this._isNull(response))
return;

var resource = this._inflightResourcesById[identifier];
if (!resource)
return;

resource.responseReceivedTime = time;
resource.type = WebInspector.Resource.Type[resourceType];

this._updateResourceWithResponse(resource, response);

this._updateResource(resource);
},

dataReceived: function(identifier, time, dataLength, encodedDataLength)
{
var resource = this._inflightResourcesById[identifier];
if (!resource)
return;

resource.resourceSize += dataLength;
if (encodedDataLength != -1)
resource.increaseTransferSize(encodedDataLength);
resource.endTime = time;

this._updateResource(resource);
},

loadingFinished: function(identifier, finishTime)
{
var resource = this._inflightResourcesById[identifier];
if (!resource)
return;

this._finishResource(resource, finishTime);
},

loadingFailed: function(identifier, time, localizedDescription, canceled)
{
var resource = this._inflightResourcesById[identifier];
if (!resource)
return;

resource.failed = true;
resource.canceled = canceled;
resource.localizedFailDescription = localizedDescription;
this._finishResource(resource, time);
},

resourceLoadedFromMemoryCache: function(frameId, loaderId, documentURL, time, cachedResource)
{
var resource = this._createResource("cached:" + ++this._lastIdentifierForCachedResource, frameId, loaderId, cachedResource.url, documentURL);
this._updateResourceWithCachedResource(resource, cachedResource);
resource.cached = true;
resource.requestMethod = "GET";
this._startResource(resource);
resource.startTime = resource.responseReceivedTime = time;
this._finishResource(resource, time);
},

initialContentSet: function(identifier, sourceString, type)
{
var resource = WebInspector.networkResourceById(identifier);
if (!resource)
return;

resource.type = WebInspector.Resource.Type[type];
resource.setInitialContent(sourceString);
this._updateResource(resource);
},

webSocketCreated: function(identifier, requestURL)
{
var resource = this._createResource(identifier, null, null, requestURL);
resource.type = WebInspector.Resource.Type.WebSocket;
this._startResource(resource);
},

webSocketWillSendHandshakeRequest: function(identifier, time, request)
{
var resource = this._inflightResourcesById[identifier];
if (!resource)
return;

resource.requestMethod = "GET";
resource.requestHeaders = request.headers;
resource.webSocketRequestKey3 = request.requestKey3;
resource.startTime = time;

this._updateResource(resource);
},

webSocketHandshakeResponseReceived: function(identifier, time, response)
{
var resource = this._inflightResourcesById[identifier];
if (!resource)
return;

resource.statusCode = response.status;
resource.statusText = response.statusText;
resource.responseHeaders = response.headers;
resource.webSocketChallengeResponse = response.challengeResponse;
resource.responseReceivedTime = time;

this._updateResource(resource);
},

webSocketClosed: function(identifier, time)
{
var resource = this._inflightResourcesById[identifier];
if (!resource)
return;
this._finishResource(resource, time);
},

_appendRedirect: function(identifier, time, redirectURL)
{
var originalResource = this._inflightResourcesById[identifier];
var previousRedirects = originalResource.redirects || [];
originalResource.identifier = "redirected:" + identifier + "." + previousRedirects.length;
delete originalResource.redirects;
this._finishResource(originalResource, time);
var newResource = this._createResource(identifier, originalResource.frameId, originalResource.loaderId,
redirectURL, originalResource.documentURL, originalResource.stackTrace);
newResource.redirects = previousRedirects.concat(originalResource);
return newResource;
},

_startResource: function(resource)
{
this._inflightResourcesById[resource.identifier] = resource;
this._inflightResourcesByURL[resource.url] = resource;
this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceStarted, resource);
},

_updateResource: function(resource)
{
this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceUpdated, resource);
},

_finishResource: function(resource, finishTime)
{
resource.endTime = finishTime;
resource.finished = true;
this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceFinished, resource);
delete this._inflightResourcesById[resource.identifier];
delete this._inflightResourcesByURL[resource.url];
},

_dispatchEventToListeners: function(eventType, resource)
{
this._manager.dispatchEventToListeners(eventType, resource);
},

_createResource: function(identifier, frameId, loaderId, url, documentURL, stackTrace)
{
var resource = new WebInspector.Resource(identifier, url, loaderId);
resource.documentURL = documentURL;
resource.frameId = frameId;
resource.stackTrace = stackTrace;
return resource;
}
}






WebInspector.ResourceTreeModel = function(networkManager)
{
WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceStarted, this._onResourceStarted, this);
WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceUpdated, this._onResourceUpdated, this);
WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._onResourceUpdated, this);

WebInspector.console.addEventListener(WebInspector.ConsoleView.Events.MessageAdded, this._consoleMessageAdded, this);
WebInspector.console.addEventListener(WebInspector.ConsoleView.Events.ConsoleCleared, this._consoleCleared, this);

this.frontendReused();
InspectorBackend.registerDomainDispatcher("Page", new WebInspector.PageDispatcher(this));
}

WebInspector.ResourceTreeModel.EventTypes = {
FrameAdded: "FrameAdded",
FrameNavigated: "FrameNavigated",
FrameDetached: "FrameDetached",
ResourceAdded: "ResourceAdded",
WillLoadCachedResources: "WillLoadCachedResources",
CachedResourcesLoaded: "CachedResourcesLoaded",
DOMContentLoaded: "DOMContentLoaded",
OnLoad: "OnLoad",
InspectedURLChanged: "InspectedURLChanged"
}

WebInspector.ResourceTreeModel.prototype = {
frontendReused: function()
{
this._resourcesByURL = {};
this._resourcesByFrameId = {};
this._subframes = {};
this._frameIds = {};
delete this._cachedResourcesProcessed;
PageAgent.getResourceTree(this._processCachedResources.bind(this));
},

_processCachedResources: function(error, mainFramePayload)
{
if (error) {
console.error(JSON.stringify(error));
return;
}

this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.WillLoadCachedResources);
this._addFramesRecursively(mainFramePayload);
this._dispatchInspectedURLChanged(WebInspector.mainResource.url);
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded);
WebInspector.Resource.restoreRevisions();

this._cachedResourcesProcessed = true;
},

_dispatchInspectedURLChanged: function(url)
{
InspectorFrontendHost.inspectedURLChanged(url);
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, url);
},

_addFrame: function(frame)
{
frame.parentId = frame.parentId || "";
this._frameIds[frame.id] = frame;
var subframes = this._subframes[frame.parentId];
if (!subframes) {
subframes = [];
this._subframes[frame.parentId] = subframes;
}

subframes.push(frame);
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, frame);
},

subframes: function(parentFrameId)
{
return this._subframes[parentFrameId] || [];
},

resources: function(frameId)
{
var result = [];
var resources = this._resourcesByFrameId[frameId] || {};
for (var url in resources)
result.push(resources[url]);
return result;
},

_frameNavigated: function(frame, loaderId)
{
var isMainFrame = !frame.parentId;

if (isMainFrame) {
this._cleanupFramesAfterNavigation(frame);
if (this.resourceForURL(frame.url))
WebInspector.mainResource = this.resourceForURL(frame.url);
}

if (!this._cachedResourcesProcessed)
return;


if (!this._frameIds[frame.id])
this._addFrame(frame);
else {
this._clearChildFramesAndResources(frame.id, loaderId);
frame.parentId = frame.parentId || "";
this._frameIds[frame.id] = frame;
}

this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, { frame: frame, loaderId: loaderId, isMainFrame: isMainFrame });


var resourcesForFrame = this._resourcesByFrameId[frame.id];
if (resourcesForFrame) {
for (var url in resourcesForFrame)
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resourcesForFrame[url]);
}

if (isMainFrame)
this._dispatchInspectedURLChanged(frame.url);
},

_cleanupFramesAfterNavigation: function(newMainFrame)
{
for (var frameId in this._frameIds) {
if (frameId !== newMainFrame.id)
this._frameDetached(frameId);
}
},

_frameDetached: function(frameId)
{

if (!this._cachedResourcesProcessed)
return;

this._clearChildFramesAndResources(frameId, "");
var frame = this._frameIds[frameId];

if (frame) {
var siblings = this._subframes[frame.parentId];
if (siblings)
siblings.remove(frame);
delete this._frameIds[frameId];
}

this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, frameId);
},

_onResourceStarted: function(event)
{
if (!this._cachedResourcesProcessed)
return;
this._bindResourceURL(event.data);
},

_onResourceUpdated: function(event)
{
if (!this._cachedResourcesProcessed)
return;

var resource = event.data;
if (resource.failed) {
this._unbindResourceURL(resource);
return;
}

if (resource.finished)
this._addResourceToFrame(resource);
},

_addResourceToFrame: function(resource)
{
var frameId = resource.frameId;
var resourcesForFrame = this._resourcesByFrameId[frameId];
if (!resourcesForFrame) {
resourcesForFrame = {};
this._resourcesByFrameId[frameId] = resourcesForFrame;
}
if (resourcesForFrame[resource.url] === resource) {

return;
}

resourcesForFrame[resource.url] = resource;
this._bindResourceURL(resource);
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resource);
},

forAllResources: function(callback)
{
return this._callForFrameResources("", callback);
},

_consoleMessageAdded: function(event)
{
var msg = event.data;
var resource = this.resourceForURL(msg.url);
if (!resource)
return;

switch (msg.level) {
case WebInspector.ConsoleMessage.MessageLevel.Warning:
resource.warnings += msg.repeatDelta;
break;
case WebInspector.ConsoleMessage.MessageLevel.Error:
resource.errors += msg.repeatDelta;
break;
}
resource.addMessage(msg);
},

_consoleCleared: function()
{
function callback(resource)
{
resource.clearErrorsAndWarnings();
}
this.forAllResources(callback);
},

resourceForURL: function(url)
{
return this._resourcesByURL[url];
},

_bindResourceURL: function(resource)
{
this._resourcesByURL[resource.url] = resource;
},

_clearChildFramesAndResources: function(frameId, loaderToPreserveId)
{
this._clearResources(frameId, loaderToPreserveId);
var subframes = this._subframes[frameId];
for (var i = 0; subframes && i < subframes.length; ++ i) {
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, subframes[i].id);
this._clearChildFramesAndResources(subframes[i].id, loaderToPreserveId);
}
delete this._subframes[frameId];
},

_clearResources: function(frameId, loaderToPreserveId)
{
var resourcesForFrame = this._resourcesByFrameId[frameId];
if (!resourcesForFrame)
return;

var preservedResourcesForFrame = [];
for (var url in resourcesForFrame) {
var resource = resourcesForFrame[url];
if (resource.loaderId === loaderToPreserveId) {
preservedResourcesForFrame[url] = resource;
continue;
}
this._unbindResourceURL(resource);
}

delete this._resourcesByFrameId[frameId];
if (preservedResourcesForFrame.length) {
this._resourcesByFrameId[frameId] = preservedResourcesForFrame;
}
},

_callForFrameResources: function(frameId, callback)
{
var resources = this._resourcesByFrameId[frameId];

for (var url in resources) {
if (callback(resources[url]))
return true;
}

var frames = this._subframes[frameId];
for (var i = 0; frames && i < frames.length; ++i) {
if (this._callForFrameResources(frames[i].id, callback))
return true;
}
return false;
},

_unbindResourceURL: function(resource)
{
delete this._resourcesByURL[resource.url];
},

_addFramesRecursively: function(frameTreePayload)
{
var framePayload = frameTreePayload.frame;


var frameResource = this._createResource(framePayload, framePayload.url);
frameResource.type = WebInspector.Resource.Type.Document;
frameResource.finished = true;

if (!framePayload.parentId)
WebInspector.mainResource = frameResource;
this._addFrame(framePayload);
this._addResourceToFrame(frameResource);

for (var i = 0; frameTreePayload.childFrames && i < frameTreePayload.childFrames.length; ++i)
this._addFramesRecursively(frameTreePayload.childFrames[i]);

if (!frameTreePayload.resources)
return;


for (var i = 0; i < frameTreePayload.resources.length; ++i) {
var subresource = frameTreePayload.resources[i];
var resource = this._createResource(framePayload, subresource.url);
resource.type = WebInspector.Resource.Type[subresource.type];
resource.finished = true;
this._addResourceToFrame(resource);
}
},

_createResource: function(frame, url)
{
var resource = new WebInspector.Resource(null, url, frame.loaderId);
resource.frameId = frame.id;
resource.documentURL = frame.url;
return resource;
}
}

WebInspector.ResourceTreeModel.prototype.__proto__ = WebInspector.Object.prototype;

WebInspector.PageDispatcher = function(resourceTreeModel)
{
this._resourceTreeModel = resourceTreeModel;
}

WebInspector.PageDispatcher.prototype = {
domContentEventFired: function(time)
{
this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, time);


WebInspector.mainResourceDOMContentTime = time;
},

loadEventFired: function(time)
{
this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.OnLoad, time);


WebInspector.mainResourceLoadTime = time;
},

frameNavigated: function(frame, loaderId)
{
this._resourceTreeModel._frameNavigated(frame, loaderId);
},

frameDetached: function(frameId)
{
this._resourceTreeModel._frameDetached(frameId);
}
}





WebInspector.ResourceCategory = function(name, title, color)
{
this.name = name;
this.title = title;
this.color = color;
}

WebInspector.ResourceCategory.prototype = {
toString: function()
{
return this.title;
}
}





WebInspector.TimelineManager = function()
{
WebInspector.Object.call(this);
this._dispatcher = new WebInspector.TimelineDispatcher(this);
this._enablementCount = 0;
}

WebInspector.TimelineManager.EventTypes = {
TimelineStarted: "TimelineStarted",
TimelineStopped: "TimelineStopped",
TimelineEventRecorded: "TimelineEventRecorded"
}

WebInspector.TimelineManager.prototype = {
start: function()
{
this._enablementCount++;
if (this._enablementCount === 1)
TimelineAgent.start();
},

stop: function()
{
if (!this._enablementCount) {
console.error("WebInspector.TimelineManager start/stop calls are unbalanced");
return;
}
this._enablementCount--;
if (!this._enablementCount)
TimelineAgent.stop();
}
}

WebInspector.TimelineManager.prototype.__proto__ = WebInspector.Object.prototype;

WebInspector.TimelineDispatcher = function(manager)
{
this._manager = manager;
InspectorBackend.registerDomainDispatcher("Timeline", this);
}

WebInspector.TimelineDispatcher.prototype = {
started: function()
{
this._manager.dispatchEventToListeners(WebInspector.TimelineManager.EventTypes.TimelineStarted);
},

stopped: function()
{
this._manager.dispatchEventToListeners(WebInspector.TimelineManager.EventTypes.TimelineStopped);
},

eventRecorded: function(record)
{
this._manager.dispatchEventToListeners(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded, record);
}
}

WebInspector.timelineManager = new WebInspector.TimelineManager();





WebInspector.Database = function(id, domain, name, version)
{
this._id = id;
this._domain = domain;
this._name = name;
this._version = version;
}

WebInspector.Database.prototype = {
get id()
{
return this._id;
},

get name()
{
return this._name;
},

set name(x)
{
this._name = x;
},

get version()
{
return this._version;
},

set version(x)
{
this._version = x;
},

get domain()
{
return this._domain;
},

set domain(x)
{
this._domain = x;
},

get displayDomain()
{
return WebInspector.Resource.prototype.__lookupGetter__("displayDomain").call(this);
},

getTableNames: function(callback)
{
function sortingCallback(error, names)
{
if (!error)
callback(names.sort());
}
DatabaseAgent.getDatabaseTableNames(this._id, sortingCallback);
},

executeSql: function(query, onSuccess, onError)
{
function callback(error, success, transactionId)
{
if (error) {
onError(error);
return;
}
if (!success) {
onError(WebInspector.UIString("Database not found."));
return;
}
WebInspector.DatabaseDispatcher._callbacks[transactionId] = {"onSuccess": onSuccess, "onError": onError};
}
DatabaseAgent.executeSQL(this._id, query, callback);
}
}

WebInspector.DatabaseDispatcher = function()
{
}

WebInspector.DatabaseDispatcher._callbacks = {};

WebInspector.DatabaseDispatcher.prototype = {
addDatabase: function(payload)
{
var database = new WebInspector.Database(
payload.id,
payload.domain,
payload.name,
payload.version);
WebInspector.panels.resources.addDatabase(database);
},

sqlTransactionSucceeded: function(transactionId, columnNames, values)
{
if (!WebInspector.DatabaseDispatcher._callbacks[transactionId])
return;

var callback = WebInspector.DatabaseDispatcher._callbacks[transactionId].onSuccess;
delete WebInspector.DatabaseDispatcher._callbacks[transactionId];
if (callback)
callback(columnNames, values);
},

sqlTransactionFailed: function(transactionId, errorObj)
{
if (!WebInspector.DatabaseDispatcher._callbacks[transactionId])
return;

var callback = WebInspector.DatabaseDispatcher._callbacks[transactionId].onError;
delete WebInspector.DatabaseDispatcher._callbacks[transactionId];
if (callback)
callback(errorObj);
}
}

InspectorBackend.registerDomainDispatcher("Database", new WebInspector.DatabaseDispatcher());





WebInspector.DOMStorage = function(id, domain, isLocalStorage)
{
this._id = id;
this._domain = domain;
this._isLocalStorage = isLocalStorage;
}

WebInspector.DOMStorage.prototype = {
get id()
{
return this._id;
},

get domain()
{
return this._domain;
},

get isLocalStorage()
{
return this._isLocalStorage;
},

getEntries: function(callback)
{
DOMStorageAgent.getDOMStorageEntries(this._id, callback);
},

setItem: function(key, value, callback)
{
DOMStorageAgent.setDOMStorageItem(this._id, key, value, callback);
},

removeItem: function(key, callback)
{
DOMStorageAgent.removeDOMStorageItem(this._id, key, callback);
}
}


WebInspector.DOMStorageDispatcher = function()
{
}

WebInspector.DOMStorageDispatcher.prototype = {
addDOMStorage: function(payload)
{
var domStorage = new WebInspector.DOMStorage(
payload.id,
payload.host,
payload.isLocalStorage);
WebInspector.panels.resources.addDOMStorage(domStorage);
},

updateDOMStorage: function(storageId)
{
WebInspector.panels.resources.updateDOMStorage(storageId);
}
}

InspectorBackend.registerDomainDispatcher("DOMStorage", new WebInspector.DOMStorageDispatcher());





WebInspector.DOMStorageItemsView = function(domStorage)
{
WebInspector.View.call(this);

this.domStorage = domStorage;

this.element.addStyleClass("storage-view");
this.element.addStyleClass("table");

this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item");
this.deleteButton.visible = false;
this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);

this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
}

WebInspector.DOMStorageItemsView.prototype = {
get statusBarItems()
{
return [this.refreshButton.element, this.deleteButton.element];
},

show: function(parentElement)
{
WebInspector.View.prototype.show.call(this, parentElement);
this.update();
},

hide: function()
{
WebInspector.View.prototype.hide.call(this);
this.deleteButton.visible = false;
},

update: function()
{
this.element.removeChildren();
this.domStorage.getEntries(this._showDOMStorageEntries.bind(this));
},

_showDOMStorageEntries: function(error, entries)
{
if (error)
return;

this._dataGrid = this._dataGridForDOMStorageEntries(entries);
this.element.appendChild(this._dataGrid.element);
this._dataGrid.autoSizeColumns(10);
this.deleteButton.visible = true;
},

resize: function()
{
if (this._dataGrid)
this._dataGrid.updateWidths();
},

_dataGridForDOMStorageEntries: function(entries)
{
var columns = {};
columns[0] = {};
columns[1] = {};
columns[0].title = WebInspector.UIString("Key");
columns[1].title = WebInspector.UIString("Value");

var nodes = [];

var keys = [];
var length = entries.length;
for (var i = 0; i < entries.length; i++) {
var data = {};

var key = entries[i][0];
data[0] = key;
var value = entries[i][1];
data[1] = value;
var node = new WebInspector.DataGridNode(data, false);
node.selectable = true;
nodes.push(node);
keys.push(key);
}

var dataGrid = new WebInspector.DataGrid(columns, this._editingCallback.bind(this), this._deleteCallback.bind(this));
var length = nodes.length;
for (var i = 0; i < length; ++i)
dataGrid.appendChild(nodes[i]);
dataGrid.addCreationNode(false);
if (length > 0)
nodes[0].selected = true;
return dataGrid;
},

_deleteButtonClicked: function(event)
{
if (!this._dataGrid || !this._dataGrid.selectedNode)
return;

this._deleteCallback(this._dataGrid.selectedNode);
},

_refreshButtonClicked: function(event)
{
this.update();
},

_editingCallback: function(editingNode, columnIdentifier, oldText, newText)
{
var domStorage = this.domStorage;
if (columnIdentifier === 0) {
if (oldText)
domStorage.removeItem(oldText);

domStorage.setItem(newText, editingNode.data[1]);
} else {
domStorage.setItem(editingNode.data[0], newText);
}

this.update();
},

_deleteCallback: function(node)
{
if (!node || node.isCreationNode)
return;

if (this.domStorage)
this.domStorage.removeItem(node.data[0]);

this.update();
}
}

WebInspector.DOMStorageItemsView.prototype.__proto__ = WebInspector.View.prototype;





WebInspector.DataGrid = function(columns, editCallback, deleteCallback)
{
this.element = document.createElement("div");
this.element.className = "data-grid";
this.element.tabIndex = 0;
this.element.addEventListener("keydown", this._keyDown.bind(this), false);

this._headerTable = document.createElement("table");
this._headerTable.className = "header";
this._headerTableHeaders = {};

this._dataTable = document.createElement("table");
this._dataTable.className = "data";

this._dataTable.addEventListener("mousedown", this._mouseDownInDataTable.bind(this), true);
this._dataTable.addEventListener("click", this._clickInDataTable.bind(this), true);

this._dataTable.addEventListener("contextmenu", this._contextMenuInDataTable.bind(this), true);



if (editCallback) {
this._dataTable.addEventListener("dblclick", this._ondblclick.bind(this), false);
this._editCallback = editCallback;
}
if (deleteCallback)
this._deleteCallback = deleteCallback;

this.aligned = {};

this._scrollContainer = document.createElement("div");
this._scrollContainer.className = "data-container";
this._scrollContainer.appendChild(this._dataTable);

this.element.appendChild(this._headerTable);
this.element.appendChild(this._scrollContainer);

var headerRow = document.createElement("tr");
var columnGroup = document.createElement("colgroup");
this._columnCount = 0;

for (var columnIdentifier in columns) {
var column = columns[columnIdentifier];
if (column.disclosure)
this.disclosureColumnIdentifier = columnIdentifier;

var col = document.createElement("col");
if (column.width)
col.style.width = column.width;
column.element = col;
columnGroup.appendChild(col);

var cell = document.createElement("th");
cell.className = columnIdentifier + "-column";
cell.columnIdentifier = columnIdentifier;
this._headerTableHeaders[columnIdentifier] = cell;

var div = document.createElement("div");
if (column.titleDOMFragment)
div.appendChild(column.titleDOMFragment);
else
div.textContent = column.title;
cell.appendChild(div);

if (column.sort) {
cell.addStyleClass("sort-" + column.sort);
this._sortColumnCell = cell;
}

if (column.sortable) {
cell.addEventListener("click", this._clickInHeaderCell.bind(this), false);
cell.addStyleClass("sortable");
}

if (column.aligned)
this.aligned[columnIdentifier] = column.aligned;

headerRow.appendChild(cell);

++this._columnCount;
}

columnGroup.span = this._columnCount;

var cell = document.createElement("th");
cell.className = "corner";
headerRow.appendChild(cell);

this._headerTableColumnGroup = columnGroup;
this._headerTable.appendChild(this._headerTableColumnGroup);
this.headerTableBody.appendChild(headerRow);

var fillerRow = document.createElement("tr");
fillerRow.className = "filler";

for (var columnIdentifier in columns) {
var column = columns[columnIdentifier];
var cell = document.createElement("td");
cell.className = columnIdentifier + "-column";
fillerRow.appendChild(cell);
}

this._dataTableColumnGroup = columnGroup.cloneNode(true);
this._dataTable.appendChild(this._dataTableColumnGroup);
this.dataTableBody.appendChild(fillerRow);

this.columns = columns || {};
this._columnsArray = [];
for (var columnIdentifier in columns) {
columns[columnIdentifier].ordinal = this._columnsArray.length;
columns[columnIdentifier].identifier = columnIdentifier;
this._columnsArray.push(columns[columnIdentifier]);
}

for (var i = 0; i < this._columnsArray.length; ++i)
this._columnsArray[i].bodyElement = this._dataTableColumnGroup.children[i];

this.children = [];
this.selectedNode = null;
this.expandNodesWhenArrowing = false;
this.root = true;
this.hasChildren = false;
this.expanded = true;
this.revealed = true;
this.selected = false;
this.dataGrid = this;
this.indentWidth = 15;
this.resizers = [];
this._columnWidthsInitialized = false;
}

WebInspector.DataGrid.prototype = {
_ondblclick: function(event)
{
if (this._editing || this._editingNode)
return;

this._startEditing(event.target);
},

_startEditingColumnOfDataGridNode: function(node, column)
{
this._editing = true;
this._editingNode = node;
this._editingNode.select();

var element = this._editingNode._element.children[column];
WebInspector.startEditing(element, {
context: element.textContent,
commitHandler: this._editingCommitted.bind(this),
cancelHandler: this._editingCancelled.bind(this)
});
window.getSelection().setBaseAndExtent(element, 0, element, 1);
},

_startEditing: function(target)
{
var element = target.enclosingNodeOrSelfWithNodeName("td");
if (!element)
return;

this._editingNode = this.dataGridNodeFromNode(target);
if (!this._editingNode) {
if (!this.creationNode)
return;
this._editingNode = this.creationNode;
}


if (this._editingNode.isCreationNode)
return this._startEditingColumnOfDataGridNode(this._editingNode, 0);

this._editing = true;
WebInspector.startEditing(element, {
context: element.textContent,
commitHandler: this._editingCommitted.bind(this),
cancelHandler: this._editingCancelled.bind(this)
});
window.getSelection().setBaseAndExtent(element, 0, element, 1);
},

_editingCommitted: function(element, newText, oldText, context, moveDirection)
{




var columnIdentifier = parseInt(element.className.match(/\b(\d+)-column\b/)[1]);

var textBeforeEditing = this._editingNode.data[columnIdentifier];
var currentEditingNode = this._editingNode;

function moveToNextIfNeeded(wasChange) {
if (!moveDirection)
return;

if (moveDirection === "forward") {
if (currentEditingNode.isCreationNode && columnIdentifier === 0 && !wasChange)
return;

if (columnIdentifier === 0)
return this._startEditingColumnOfDataGridNode(currentEditingNode, 1);

var nextDataGridNode = currentEditingNode.traverseNextNode(true, null, true);
if (nextDataGridNode)
return this._startEditingColumnOfDataGridNode(nextDataGridNode, 0);
if (currentEditingNode.isCreationNode && wasChange) {
addCreationNode(false);
return this._startEditingColumnOfDataGridNode(this.creationNode, 0);
}
return;
}

if (moveDirection === "backward") {
if (columnIdentifier === 1)
return this._startEditingColumnOfDataGridNode(currentEditingNode, 0);
var nextDataGridNode = currentEditingNode.traversePreviousNode(true, null, true);

if (nextDataGridNode)
return this._startEditingColumnOfDataGridNode(nextDataGridNode, 1);
return;
}
}

if (textBeforeEditing == newText) {
this._editingCancelled(element);
moveToNextIfNeeded.call(this, false);
return;
}


this._editingNode.data[columnIdentifier] = newText;



this._editCallback(this._editingNode, columnIdentifier, textBeforeEditing, newText);

if (this._editingNode.isCreationNode)
this.addCreationNode(false);

this._editingCancelled(element);
moveToNextIfNeeded.call(this, true);
},

_editingCancelled: function(element, context)
{
delete this._editing;
this._editingNode = null;
},

get sortColumnIdentifier()
{
if (!this._sortColumnCell)
return null;
return this._sortColumnCell.columnIdentifier;
},

get sortOrder()
{
if (!this._sortColumnCell || this._sortColumnCell.hasStyleClass("sort-ascending"))
return "ascending";
if (this._sortColumnCell.hasStyleClass("sort-descending"))
return "descending";
return null;
},

get headerTableBody()
{
if ("_headerTableBody" in this)
return this._headerTableBody;

this._headerTableBody = this._headerTable.getElementsByTagName("tbody")[0];
if (!this._headerTableBody) {
this._headerTableBody = this.element.ownerDocument.createElement("tbody");
this._headerTable.insertBefore(this._headerTableBody, this._headerTable.tFoot);
}

return this._headerTableBody;
},

get dataTableBody()
{
if ("_dataTableBody" in this)
return this._dataTableBody;

this._dataTableBody = this._dataTable.getElementsByTagName("tbody")[0];
if (!this._dataTableBody) {
this._dataTableBody = this.element.ownerDocument.createElement("tbody");
this._dataTable.insertBefore(this._dataTableBody, this._dataTable.tFoot);
}

return this._dataTableBody;
},

autoSizeColumns: function(minPercent, maxPercent, maxDescentLevel)
{
if (minPercent)
minPercent = Math.min(minPercent, Math.floor(100 / this._columnCount));
var widths = {};
var columns = this.columns;
for (var columnIdentifier in columns)
widths[columnIdentifier] = (columns[columnIdentifier].title || "").length;

var children = maxDescentLevel ? this._enumerateChildren(this, [], maxDescentLevel + 1) : this.children;
for (var i = 0; i < children.length; ++i) {
var node = children[i];
for (var columnIdentifier in columns) {
var text = node.data[columnIdentifier] || "";
if (text.length > widths[columnIdentifier])
widths[columnIdentifier] = text.length;
}
}

var totalColumnWidths = 0;
for (var columnIdentifier in columns)
totalColumnWidths += widths[columnIdentifier];

var recoupPercent = 0;
for (var columnIdentifier in columns) {
var width = Math.round(100 * widths[columnIdentifier] / totalColumnWidths);
if (minPercent && width < minPercent) {
recoupPercent += (minPercent - width);
width = minPercent;
} else if (maxPercent && width > maxPercent) {
recoupPercent -= (width - maxPercent);
width = maxPercent;
}
widths[columnIdentifier] = width;
}

while (minPercent && recoupPercent > 0) {
for (var columnIdentifier in columns) {
if (widths[columnIdentifier] > minPercent) {
--widths[columnIdentifier];
--recoupPercent;
if (!recoupPercent)
break;
}
}
}

while (maxPercent && recoupPercent < 0) {
for (var columnIdentifier in columns) {
if (widths[columnIdentifier] < maxPercent) {
++widths[columnIdentifier];
++recoupPercent;
if (!recoupPercent)
break;
}
}
}

for (var columnIdentifier in columns)
columns[columnIdentifier].element.style.width = widths[columnIdentifier] + "%";
this._columnWidthsInitialized = false;
this.updateWidths();
},

_enumerateChildren: function(rootNode, result, maxLevel)
{
if (!rootNode.root)
result.push(rootNode);
if (!maxLevel)
return;
for (var i = 0; i < rootNode.children.length; ++i)
this._enumerateChildren(rootNode.children[i], result, maxLevel - 1);
return result;
},











updateWidths: function()
{
var headerTableColumns = this._headerTableColumnGroup.children;

var tableWidth = this._dataTable.offsetWidth;
var numColumns = headerTableColumns.length;


if (!this._columnWidthsInitialized && this.element.offsetWidth) {




for (var i = 0; i < numColumns; i++) {
var columnWidth = this.headerTableBody.rows[0].cells[i].offsetWidth;
var percentWidth = ((columnWidth / tableWidth) * 100) + "%";
this._headerTableColumnGroup.children[i].style.width = percentWidth;
this._dataTableColumnGroup.children[i].style.width = percentWidth;
}
this._columnWidthsInitialized = true;
}
this._positionResizers();
this.dispatchEventToListeners("width changed");
},

columnWidthsMap: function()
{
var result = {};
for (var i = 0; i < this._columnsArray.length; ++i) {
var width = this._headerTableColumnGroup.children[i].style.width;
result[this._columnsArray[i].columnIdentifier] = parseFloat(width);
}
return result;
},

applyColumnWidthsMap: function(columnWidthsMap)
{
for (var columnIdentifier in this.columns) {
var column = this.columns[columnIdentifier];
var width = (columnWidthsMap[columnIdentifier] || 0) + "%";
this._headerTableColumnGroup.children[column.ordinal].style.width = width;
this._dataTableColumnGroup.children[column.ordinal].style.width = width;
}


delete this._columnWidthsInitialized;
this.updateWidths();
},

isColumnVisible: function(columnIdentifier)
{
var column = this.columns[columnIdentifier];
var columnElement = column.element;
return !columnElement.hidden;
},

showColumn: function(columnIdentifier)
{
var column = this.columns[columnIdentifier];
var columnElement = column.element;
if (!columnElement.hidden)
return;

columnElement.hidden = false;
columnElement.removeStyleClass("hidden");

var columnBodyElement = column.bodyElement;
columnBodyElement.hidden = false;
columnBodyElement.removeStyleClass("hidden");
},

hideColumn: function(columnIdentifier)
{
var column = this.columns[columnIdentifier];
var columnElement = column.element;
if (columnElement.hidden)
return;

var oldWidth = parseFloat(columnElement.style.width);

columnElement.hidden = true;
columnElement.addStyleClass("hidden");
columnElement.style.width = 0;

var columnBodyElement = column.bodyElement;
columnBodyElement.hidden = true;
columnBodyElement.addStyleClass("hidden");
columnBodyElement.style.width = 0;

this._columnWidthsInitialized = false;
},

get scrollContainer()
{
return this._scrollContainer;        
},

isScrolledToLastRow: function()
{
return this._scrollContainer.isScrolledToBottom();
},

scrollToLastRow: function()
{
this._scrollContainer.scrollTop = this._scrollContainer.scrollHeight - this._scrollContainer.offsetHeight;
},

_positionResizers: function()
{
var headerTableColumns = this._headerTableColumnGroup.children;
var numColumns = headerTableColumns.length;
var left = 0;
var previousResizer = null;


for (var i = 0; i < numColumns - 1; i++) {
var resizer = this.resizers[i];

if (!resizer) {


resizer = document.createElement("div");
resizer.addStyleClass("data-grid-resizer");

resizer.addEventListener("mousedown", this._startResizerDragging.bind(this), false);
this.element.appendChild(resizer);
this.resizers[i] = resizer;
}




left += this.headerTableBody.rows[0].cells[i].offsetWidth;

var columnIsVisible = !this._headerTableColumnGroup.children[i].hidden;
if (columnIsVisible) {
resizer.style.removeProperty("display");
resizer.style.left = left + "px";
resizer.leftNeighboringColumnID = i;
if (previousResizer)
previousResizer.rightNeighboringColumnID = i;
previousResizer = resizer;
} else {
resizer.style.setProperty("display", "none");
resizer.leftNeighboringColumnID = 0;
resizer.rightNeighboringColumnID = 0;
}
}
if (previousResizer)
previousResizer.rightNeighboringColumnID = numColumns - 1;
},

addCreationNode: function(hasChildren)
{
if (this.creationNode)
this.creationNode.makeNormal();

var emptyData = {};
for (var column in this.columns)
emptyData[column] = '';
this.creationNode = new WebInspector.CreationDataGridNode(emptyData, hasChildren);
this.appendChild(this.creationNode);
},

appendChild: function(child)
{
this.insertChild(child, this.children.length);
},

insertChild: function(child, index)
{
if (!child)
throw("insertChild: Node can't be undefined or null.");
if (child.parent === this)
throw("insertChild: Node is already a child of this node.");

if (child.parent)
child.parent.removeChild(child);

this.children.splice(index, 0, child);
this.hasChildren = true;

child.parent = this;
child.dataGrid = this.dataGrid;
child._recalculateSiblings(index);

delete child._depth;
delete child._revealed;
delete child._attached;
child._shouldRefreshChildren = true;

var current = child.children[0];
while (current) {
current.dataGrid = this.dataGrid;
delete current._depth;
delete current._revealed;
delete current._attached;
current._shouldRefreshChildren = true;
current = current.traverseNextNode(false, child, true);
}

if (this.expanded)
child._attach();
},

removeChild: function(child)
{
if (!child)
throw("removeChild: Node can't be undefined or null.");
if (child.parent !== this)
throw("removeChild: Node is not a child of this node.");

child.deselect();
child._detach();

this.children.remove(child, true);

if (child.previousSibling)
child.previousSibling.nextSibling = child.nextSibling;
if (child.nextSibling)
child.nextSibling.previousSibling = child.previousSibling;

child.dataGrid = null;
child.parent = null;
child.nextSibling = null;
child.previousSibling = null;

if (this.children.length <= 0)
this.hasChildren = false;
},

removeChildren: function()
{
for (var i = 0; i < this.children.length; ++i) {
var child = this.children[i];
child.deselect();
child._detach();

child.dataGrid = null;
child.parent = null;
child.nextSibling = null;
child.previousSibling = null;
}

this.children = [];
this.hasChildren = false;
},

removeChildrenRecursive: function()
{
var childrenToRemove = this.children;

var child = this.children[0];
while (child) {
if (child.children.length)
childrenToRemove = childrenToRemove.concat(child.children);
child = child.traverseNextNode(false, this, true);
}

for (var i = 0; i < childrenToRemove.length; ++i) {
var child = childrenToRemove[i];
child.deselect();
child._detach();

child.children = [];
child.dataGrid = null;
child.parent = null;
child.nextSibling = null;
child.previousSibling = null;
}

this.children = [];
},

sortNodes: function(comparator, reverseMode)
{
function comparatorWrapper(a, b)
{
if (a._dataGridNode._data.summaryRow)
return 1;
if (b._dataGridNode._data.summaryRow)
return -1;

var aDataGirdNode = a._dataGridNode;
var bDataGirdNode = b._dataGridNode;
return reverseMode ? comparator(bDataGirdNode, aDataGirdNode) : comparator(aDataGirdNode, bDataGirdNode);
}

var tbody = this.dataTableBody;
var tbodyParent = tbody.parentElement;
tbodyParent.removeChild(tbody);

var childNodes = tbody.childNodes;
var fillerRow = childNodes[childNodes.length - 1];

var sortedRows = Array.prototype.slice.call(childNodes, 0, childNodes.length - 1);
sortedRows.sort(comparatorWrapper);
var sortedRowsLength = sortedRows.length;

tbody.removeChildren();
var previousSiblingNode = null;
for (var i = 0; i < sortedRowsLength; ++i) {
var row = sortedRows[i];
var node = row._dataGridNode;
node.previousSibling = previousSiblingNode;
if (previousSiblingNode)
previousSiblingNode.nextSibling = node;
tbody.appendChild(row);
previousSiblingNode = node;
}
if (previousSiblingNode)
previousSiblingNode.nextSibling = null;

tbody.appendChild(fillerRow);
tbodyParent.appendChild(tbody);
},

_keyDown: function(event)
{
if (!this.selectedNode || event.shiftKey || event.metaKey || event.ctrlKey || this._editing)
return;

var handled = false;
var nextSelectedNode;
if (event.keyIdentifier === "Up" && !event.altKey) {
nextSelectedNode = this.selectedNode.traversePreviousNode(true);
while (nextSelectedNode && !nextSelectedNode.selectable)
nextSelectedNode = nextSelectedNode.traversePreviousNode(!this.expandTreeNodesWhenArrowing);
handled = nextSelectedNode ? true : false;
} else if (event.keyIdentifier === "Down" && !event.altKey) {
nextSelectedNode = this.selectedNode.traverseNextNode(true);
while (nextSelectedNode && !nextSelectedNode.selectable)
nextSelectedNode = nextSelectedNode.traverseNextNode(!this.expandTreeNodesWhenArrowing);
handled = nextSelectedNode ? true : false;
} else if (event.keyIdentifier === "Left") {
if (this.selectedNode.expanded) {
if (event.altKey)
this.selectedNode.collapseRecursively();
else
this.selectedNode.collapse();
handled = true;
} else if (this.selectedNode.parent && !this.selectedNode.parent.root) {
handled = true;
if (this.selectedNode.parent.selectable) {
nextSelectedNode = this.selectedNode.parent;
handled = nextSelectedNode ? true : false;
} else if (this.selectedNode.parent)
this.selectedNode.parent.collapse();
}
} else if (event.keyIdentifier === "Right") {
if (!this.selectedNode.revealed) {
this.selectedNode.reveal();
handled = true;
} else if (this.selectedNode.hasChildren) {
handled = true;
if (this.selectedNode.expanded) {
nextSelectedNode = this.selectedNode.children[0];
handled = nextSelectedNode ? true : false;
} else {
if (event.altKey)
this.selectedNode.expandRecursively();
else
this.selectedNode.expand();
}
}
} else if (event.keyCode === 8 || event.keyCode === 46) {
if (this._deleteCallback) {
handled = true;
this._deleteCallback(this.selectedNode);
}
} else if (isEnterKey(event)) {
if (this._editCallback) {
handled = true;


this._startEditing(this.selectedNode._element.children[0]);
}
}

if (nextSelectedNode) {
nextSelectedNode.reveal();
nextSelectedNode.select();
}

if (handled) {
event.preventDefault();
event.stopPropagation();
}
},

expand: function()
{

},

collapse: function()
{

},

reveal: function()
{

},

dataGridNodeFromNode: function(target)
{
var rowElement = target.enclosingNodeOrSelfWithNodeName("tr");
return rowElement && rowElement._dataGridNode;
},

dataGridNodeFromPoint: function(x, y)
{
var node = this._dataTable.ownerDocument.elementFromPoint(x, y);
var rowElement = node.enclosingNodeOrSelfWithNodeName("tr");
return rowElement && rowElement._dataGridNode;
},

_clickInHeaderCell: function(event)
{
var cell = event.target.enclosingNodeOrSelfWithNodeName("th");
if (!cell || !cell.columnIdentifier || !cell.hasStyleClass("sortable"))
return;

var sortOrder = this.sortOrder;

if (this._sortColumnCell)
this._sortColumnCell.removeMatchingStyleClasses("sort-\\w+");

if (cell == this._sortColumnCell) {
if (sortOrder === "ascending")
sortOrder = "descending";
else
sortOrder = "ascending";
}

this._sortColumnCell = cell;

cell.addStyleClass("sort-" + sortOrder);

this.dispatchEventToListeners("sorting changed");
},

markColumnAsSortedBy: function(columnIdentifier, sortOrder)
{
if (this._sortColumnCell)
this._sortColumnCell.removeMatchingStyleClasses("sort-\\w+");
this._sortColumnCell = this._headerTableHeaders[columnIdentifier];
this._sortColumnCell.addStyleClass("sort-" + sortOrder);
},

headerTableHeader: function(columnIdentifier)
{
return this._headerTableHeaders[columnIdentifier];
},

_mouseDownInDataTable: function(event)
{
var gridNode = this.dataGridNodeFromNode(event.target);
if (!gridNode || !gridNode.selectable)
return;

if (gridNode.isEventWithinDisclosureTriangle(event))
return;

if (event.metaKey) {
if (gridNode.selected)
gridNode.deselect();
else
gridNode.select();
} else
gridNode.select();
},

_contextMenuInDataTable: function(event)
{
var gridNode = this.dataGridNodeFromNode(event.target);
if (!gridNode || !gridNode.selectable)
return;

if (gridNode.isEventWithinDisclosureTriangle(event))
return;

var contextMenu = new WebInspector.ContextMenu();


if (this.dataGrid._editCallback) {
if (gridNode === this.creationNode)
contextMenu.appendItem(WebInspector.UIString("Add New"), this._startEditing.bind(this, event.target));
else
contextMenu.appendItem(WebInspector.UIString("Edit"), this._startEditing.bind(this, event.target));
}
if (this.dataGrid._deleteCallback && gridNode !== this.creationNode)
contextMenu.appendItem(WebInspector.UIString("Delete"), this._deleteCallback.bind(this, gridNode));

contextMenu.show(event);
},

_clickInDataTable: function(event)
{
var gridNode = this.dataGridNodeFromNode(event.target);
if (!gridNode || !gridNode.hasChildren)
return;

if (!gridNode.isEventWithinDisclosureTriangle(event))
return;

if (gridNode.expanded) {
if (event.altKey)
gridNode.collapseRecursively();
else
gridNode.collapse();
} else {
if (event.altKey)
gridNode.expandRecursively();
else
gridNode.expand();
}
},

get resizeMethod()
{
if (typeof this._resizeMethod === "undefined")
return WebInspector.DataGrid.ResizeMethod.Nearest;
return this._resizeMethod;
},

set resizeMethod(method)
{
this._resizeMethod = method;
},

_startResizerDragging: function(event)
{
this.currentResizer = event.target;
if (!this.currentResizer.rightNeighboringColumnID)
return;
WebInspector.elementDragStart(this.lastResizer, this._resizerDragging.bind(this),
this._endResizerDragging.bind(this), event, "col-resize");
},

_resizerDragging: function(event)
{
var resizer = this.currentResizer;
if (!resizer)
return;



var dragPoint = event.clientX - this.element.totalOffsetLeft;


var leftCellIndex = resizer.leftNeighboringColumnID;
var rightCellIndex = resizer.rightNeighboringColumnID;
var firstRowCells = this.headerTableBody.rows[0].cells;
var leftEdgeOfPreviousColumn = 0;
for (var i = 0; i < leftCellIndex; i++)
leftEdgeOfPreviousColumn += firstRowCells[i].offsetWidth;


if (this.resizeMethod == WebInspector.DataGrid.ResizeMethod.Last) {
rightCellIndex = this.resizers.length;
} else if (this.resizeMethod == WebInspector.DataGrid.ResizeMethod.First) {
leftEdgeOfPreviousColumn += firstRowCells[leftCellIndex].offsetWidth - firstRowCells[0].offsetWidth;
leftCellIndex = 0;
}

var rightEdgeOfNextColumn = leftEdgeOfPreviousColumn + firstRowCells[leftCellIndex].offsetWidth + firstRowCells[rightCellIndex].offsetWidth;


var leftMinimum = leftEdgeOfPreviousColumn + this.ColumnResizePadding;
var rightMaximum = rightEdgeOfNextColumn - this.ColumnResizePadding;

dragPoint = Number.constrain(dragPoint, leftMinimum, rightMaximum);

resizer.style.left = (dragPoint - this.CenterResizerOverBorderAdjustment) + "px";

var percentLeftColumn = (((dragPoint - leftEdgeOfPreviousColumn) / this._dataTable.offsetWidth) * 100) + "%";
this._headerTableColumnGroup.children[leftCellIndex].style.width = percentLeftColumn;
this._dataTableColumnGroup.children[leftCellIndex].style.width = percentLeftColumn;

var percentRightColumn = (((rightEdgeOfNextColumn - dragPoint) / this._dataTable.offsetWidth) * 100) + "%";
this._headerTableColumnGroup.children[rightCellIndex].style.width =  percentRightColumn;
this._dataTableColumnGroup.children[rightCellIndex].style.width = percentRightColumn;

this._positionResizers();
event.preventDefault();
this.dispatchEventToListeners("width changed");
},

_endResizerDragging: function(event)
{
WebInspector.elementDragEnd(event);
this.currentResizer = null;
this.dispatchEventToListeners("width changed");
},

ColumnResizePadding: 10,

CenterResizerOverBorderAdjustment: 3,
}

WebInspector.DataGrid.ResizeMethod = {
Nearest: "nearest",
First: "first",
Last: "last"
}

WebInspector.DataGrid.prototype.__proto__ = WebInspector.Object.prototype;

WebInspector.DataGridNode = function(data, hasChildren)
{
this._expanded = false;
this._selected = false;
this._shouldRefreshChildren = true;
this._data = data || {};
this.hasChildren = hasChildren || false;
this.children = [];
this.dataGrid = null;
this.parent = null;
this.previousSibling = null;
this.nextSibling = null;
this.disclosureToggleWidth = 10;
}

WebInspector.DataGridNode.prototype = {
selectable: true,

get element()
{
if (this._element)
return this._element;

if (!this.dataGrid)
return null;

this._element = document.createElement("tr");
this._element._dataGridNode = this;

if (this.hasChildren)
this._element.addStyleClass("parent");
if (this.expanded)
this._element.addStyleClass("expanded");
if (this.selected)
this._element.addStyleClass("selected");
if (this.revealed)
this._element.addStyleClass("revealed");

this.createCells();
return this._element;
},

createCells: function()
{
for (var columnIdentifier in this.dataGrid.columns) {
var cell = this.createCell(columnIdentifier);
this._element.appendChild(cell);
}
},

get data()
{
return this._data;
},

set data(x)
{
this._data = x || {};
this.refresh();
},

get revealed()
{
if ("_revealed" in this)
return this._revealed;

var currentAncestor = this.parent;
while (currentAncestor && !currentAncestor.root) {
if (!currentAncestor.expanded) {
this._revealed = false;
return false;
}

currentAncestor = currentAncestor.parent;
}

this._revealed = true;
return true;
},

set hasChildren(x)
{
if (this._hasChildren === x)
return;

this._hasChildren = x;

if (!this._element)
return;

if (this._hasChildren)
{
this._element.addStyleClass("parent");
if (this.expanded)
this._element.addStyleClass("expanded");
}
else
{
this._element.removeStyleClass("parent");
this._element.removeStyleClass("expanded");
}
},

get hasChildren()
{
return this._hasChildren;
},

set revealed(x)
{
if (this._revealed === x)
return;

this._revealed = x;

if (this._element) {
if (this._revealed)
this._element.addStyleClass("revealed");
else
this._element.removeStyleClass("revealed");
}

for (var i = 0; i < this.children.length; ++i)
this.children[i].revealed = x && this.expanded;
},

get depth()
{
if ("_depth" in this)
return this._depth;
if (this.parent && !this.parent.root)
this._depth = this.parent.depth + 1;
else
this._depth = 0;
return this._depth;
},

get shouldRefreshChildren()
{
return this._shouldRefreshChildren;
},

set shouldRefreshChildren(x)
{
this._shouldRefreshChildren = x;
if (x && this.expanded)
this.expand();
},

get selected()
{
return this._selected;
},

set selected(x)
{
if (x)
this.select();
else
this.deselect();
},

get expanded()
{
return this._expanded;
},

set expanded(x)
{
if (x)
this.expand();
else
this.collapse();
},

refresh: function()
{
if (!this._element || !this.dataGrid)
return;

this._element.removeChildren();
this.createCells();
},

createCell: function(columnIdentifier)
{
var cell = document.createElement("td");
cell.className = columnIdentifier + "-column";

var alignment = this.dataGrid.aligned[columnIdentifier];
if (alignment)
cell.addStyleClass(alignment);

var div = document.createElement("div");
div.textContent = this.data[columnIdentifier];
cell.appendChild(div);

if (columnIdentifier === this.dataGrid.disclosureColumnIdentifier) {
cell.addStyleClass("disclosure");
if (this.depth)
cell.style.setProperty("padding-left", (this.depth * this.dataGrid.indentWidth) + "px");
}

return cell;
},


appendChild: WebInspector.DataGrid.prototype.appendChild,
insertChild: WebInspector.DataGrid.prototype.insertChild,
removeChild: WebInspector.DataGrid.prototype.removeChild,
removeChildren: WebInspector.DataGrid.prototype.removeChildren,
removeChildrenRecursive: WebInspector.DataGrid.prototype.removeChildrenRecursive,

_recalculateSiblings: function(myIndex)
{
if (!this.parent)
return;

var previousChild = (myIndex > 0 ? this.parent.children[myIndex - 1] : null);

if (previousChild) {
previousChild.nextSibling = this;
this.previousSibling = previousChild;
} else
this.previousSibling = null;

var nextChild = this.parent.children[myIndex + 1];

if (nextChild) {
nextChild.previousSibling = this;
this.nextSibling = nextChild;
} else
this.nextSibling = null;
},

collapse: function()
{
if (this._element)
this._element.removeStyleClass("expanded");

this._expanded = false;

for (var i = 0; i < this.children.length; ++i)
this.children[i].revealed = false;

this.dispatchEventToListeners("collapsed");
},

collapseRecursively: function()
{
var item = this;
while (item) {
if (item.expanded)
item.collapse();
item = item.traverseNextNode(false, this, true);
}
},

expand: function()
{
if (!this.hasChildren || this.expanded)
return;

if (this.revealed && !this._shouldRefreshChildren)
for (var i = 0; i < this.children.length; ++i)
this.children[i].revealed = true;

if (this._shouldRefreshChildren) {
for (var i = 0; i < this.children.length; ++i)
this.children[i]._detach();

this.dispatchEventToListeners("populate");

if (this._attached) {
for (var i = 0; i < this.children.length; ++i) {
var child = this.children[i];
if (this.revealed)
child.revealed = true;
child._attach();
}
}

delete this._shouldRefreshChildren;
}

if (this._element)
this._element.addStyleClass("expanded");

this._expanded = true;

this.dispatchEventToListeners("expanded");
},

expandRecursively: function()
{
var item = this;
while (item) {
item.expand();
item = item.traverseNextNode(false, this);
}
},

reveal: function()
{
var currentAncestor = this.parent;
while (currentAncestor && !currentAncestor.root) {
if (!currentAncestor.expanded)
currentAncestor.expand();
currentAncestor = currentAncestor.parent;
}

this.element.scrollIntoViewIfNeeded(false);

this.dispatchEventToListeners("revealed");
},

select: function(supressSelectedEvent)
{
if (!this.dataGrid || !this.selectable || this.selected)
return;

if (this.dataGrid.selectedNode)
this.dataGrid.selectedNode.deselect();

this._selected = true;
this.dataGrid.selectedNode = this;

if (this._element)
this._element.addStyleClass("selected");

if (!supressSelectedEvent)
this.dispatchEventToListeners("selected");
},

deselect: function(supressDeselectedEvent)
{
if (!this.dataGrid || this.dataGrid.selectedNode !== this || !this.selected)
return;

this._selected = false;
this.dataGrid.selectedNode = null;

if (this._element)
this._element.removeStyleClass("selected");

if (!supressDeselectedEvent)
this.dispatchEventToListeners("deselected");
},

traverseNextNode: function(skipHidden, stayWithin, dontPopulate, info)
{
if (!dontPopulate && this.hasChildren)
this.dispatchEventToListeners("populate");

if (info)
info.depthChange = 0;

var node = (!skipHidden || this.revealed) ? this.children[0] : null;
if (node && (!skipHidden || this.expanded)) {
if (info)
info.depthChange = 1;
return node;
}

if (this === stayWithin)
return null;

node = (!skipHidden || this.revealed) ? this.nextSibling : null;
if (node)
return node;

node = this;
while (node && !node.root && !((!skipHidden || node.revealed) ? node.nextSibling : null) && node.parent !== stayWithin) {
if (info)
info.depthChange -= 1;
node = node.parent;
}

if (!node)
return null;

return (!skipHidden || node.revealed) ? node.nextSibling : null;
},

traversePreviousNode: function(skipHidden, dontPopulate)
{
var node = (!skipHidden || this.revealed) ? this.previousSibling : null;
if (!dontPopulate && node && node.hasChildren)
node.dispatchEventToListeners("populate");

while (node && ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null)) {
if (!dontPopulate && node.hasChildren)
node.dispatchEventToListeners("populate");
node = ((!skipHidden || (node.revealed && node.expanded)) ? node.children[node.children.length - 1] : null);
}

if (node)
return node;

if (!this.parent || this.parent.root)
return null;

return this.parent;
},

isEventWithinDisclosureTriangle: function(event)
{
if (!this.hasChildren)
return false;
var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
if (!cell.hasStyleClass("disclosure"))
return false;
var computedLeftPadding = window.getComputedStyle(cell).getPropertyCSSValue("padding-left").getFloatValue(CSSPrimitiveValue.CSS_PX);
var left = cell.totalOffsetLeft + computedLeftPadding;
return event.pageX >= left && event.pageX <= left + this.disclosureToggleWidth;
},

_attach: function()
{
if (!this.dataGrid || this._attached)
return;

this._attached = true;

var nextNode = null;
var previousNode = this.traversePreviousNode(true, true);
if (previousNode && previousNode.element.parentNode && previousNode.element.nextSibling)
var nextNode = previousNode.element.nextSibling;
if (!nextNode)
nextNode = this.dataGrid.dataTableBody.lastChild;
this.dataGrid.dataTableBody.insertBefore(this.element, nextNode);

if (this.expanded)
for (var i = 0; i < this.children.length; ++i)
this.children[i]._attach();
},

_detach: function()
{
if (!this._attached)
return;

this._attached = false;

if (this._element && this._element.parentNode)
this._element.parentNode.removeChild(this._element);

for (var i = 0; i < this.children.length; ++i)
this.children[i]._detach();
},

savePosition: function()
{
if (this._savedPosition)
return;

if (!this.parent)
throw("savePosition: Node must have a parent.");
this._savedPosition = {
parent: this.parent,
index: this.parent.children.indexOf(this)
};
},

restorePosition: function()
{
if (!this._savedPosition)
return;

if (this.parent !== this._savedPosition.parent)
this._savedPosition.parent.insertChild(this, this._savedPosition.index);

delete this._savedPosition;
}
}

WebInspector.DataGridNode.prototype.__proto__ = WebInspector.Object.prototype;

WebInspector.CreationDataGridNode = function(data, hasChildren)
{
WebInspector.DataGridNode.call(this, data, hasChildren);
this.isCreationNode = true;
}

WebInspector.CreationDataGridNode.prototype = {
makeNormal: function()
{
delete this.isCreationNode;
delete this.makeNormal;
}
}

WebInspector.CreationDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;





WebInspector.ShowMoreDataGridNode = function(callback, nextCount, allCount)
{
function populate(count)
{
var index = this.parent.children.indexOf(this);
this.parent.removeChild(this);
callback(count, index);
}

this.showNext = document.createElement("button");
this.showNext.setAttribute("type", "button");
this.showNext.textContent = WebInspector.UIString("Show next %d", nextCount);
this.showNext.addEventListener("click", populate.bind(this, nextCount), false);

if (allCount) {
this.showAll = document.createElement("button");
this.showAll.setAttribute("type", "button");
this.showAll.textContent = WebInspector.UIString("Show all %d", allCount);
this.showAll.addEventListener("click", populate.bind(this, allCount), false);
}

WebInspector.DataGridNode.call(this, {summaryRow:true}, false);
this.selectable = false;
}

WebInspector.ShowMoreDataGridNode.prototype = {
createCells: function()
{
var cell = document.createElement("td");
if (this.depth)
cell.style.setProperty("padding-left", (this.depth * this.dataGrid.indentWidth) + "px");
cell.appendChild(this.showNext);
if (this.showAll)
cell.appendChild(this.showAll);
this._element.appendChild(cell);

var columns = this.dataGrid.columns;
var count = 0;
for (var c in columns)
++count;
while (--count > 0) {
cell = document.createElement("td");
this._element.appendChild(cell);
}
}
};

WebInspector.ShowMoreDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;





WebInspector.CookiesTable = function(cookieDomain, expandable, deleteCallback)
{
this._cookieDomain = cookieDomain;

var columns = { 0: {}, 1: {}, 2: {}, 3: {}, 4: {}, 5: {}, 6: {}, 7: {} };
columns[0].title = WebInspector.UIString("Name");
columns[0].sortable = true;
columns[0].disclosure = expandable;
columns[0].width = "24%";
columns[1].title = WebInspector.UIString("Value");
columns[1].sortable = true;
columns[1].width = "34%";
columns[2].title = WebInspector.UIString("Domain");
columns[2].sortable = true;
columns[2].width = "7%";
columns[3].title = WebInspector.UIString("Path");
columns[3].sortable = true;
columns[3].width = "7%";
columns[4].title = WebInspector.UIString("Expires");
columns[4].sortable = true;
columns[4].width = "7%";
columns[5].title = WebInspector.UIString("Size");
columns[5].aligned = "right";
columns[5].sortable = true;
columns[5].width = "7%";
columns[6].title = WebInspector.UIString("HTTP");
columns[6].aligned = "centered";
columns[6].sortable = true;
columns[6].width = "7%";
columns[7].title = WebInspector.UIString("Secure");
columns[7].aligned = "centered";
columns[7].sortable = true;
columns[7].width = "7%";

this._dataGrid = new WebInspector.DataGrid(columns, null, deleteCallback ? this._onDeleteFromGrid.bind(this) : null);
this._dataGrid.addEventListener("sorting changed", this._rebuildTable, this);

this.element = this._dataGrid.element;
this._data = [];
this._deleteCallback = deleteCallback;
}

WebInspector.CookiesTable.prototype = {
updateWidths: function()
{
if (this._dataGrid)
this._dataGrid.updateWidths();
},

setCookies: function(cookies)
{
this._data = [{cookies: cookies}];
this._rebuildTable();
},

addCookiesFolder: function(folderName, cookies)
{
this._data.push({cookies: cookies, folderName: folderName});
this._rebuildTable();
},

get selectedCookie()
{
var node = this._dataGrid.selectedNode;
return node ? node.cookie : null;
},

_rebuildTable: function()
{
this._dataGrid.removeChildren();
for (var i = 0; i < this._data.length; ++i) {
var item = this._data[i];
if (item.folderName) {
var groupData = [ item.folderName, "", "", "", "", this._totalSize(item.cookies), "", "" ];
var groupNode = new WebInspector.DataGridNode(groupData);
groupNode.selectable = true;
this._dataGrid.appendChild(groupNode);
groupNode.element.addStyleClass("row-group");
this._populateNode(groupNode, item.cookies);
groupNode.expand();
} else
this._populateNode(this._dataGrid, item.cookies);
}
},

_populateNode: function(parentNode, cookies)
{
var selectedCookie = this.selectedCookie;
parentNode.removeChildren();
if (!cookies)
return;

this._sortCookies(cookies);
for (var i = 0; i < cookies.length; ++i) {
var cookieNode = this._createGridNode(cookies[i]);
parentNode.appendChild(cookieNode);
if (selectedCookie === cookies[i])
cookieNode.selected = true;
}
},

_totalSize: function(cookies)
{
var totalSize = 0;
for (var i = 0; cookies && i < cookies.length; ++i)
totalSize += cookies[i].size;
return totalSize;
},

_sortCookies: function(cookies)
{
var sortDirection = this._dataGrid.sortOrder === "ascending" ? 1 : -1;

function localeCompare(field, cookie1, cookie2)
{
return sortDirection * (cookie1[field] + "").localeCompare(cookie2[field] + "")
}

function numberCompare(field, cookie1, cookie2)
{
return sortDirection * (cookie1[field] - cookie2[field]);
}

function expiresCompare(cookie1, cookie2)
{
if (cookie1.session !== cookie2.session)
return sortDirection * (cookie1.session ? 1 : -1);

if (cookie1.session)
return 0;

return sortDirection * (cookie1.expires - cookie2.expires);
}

var comparator;
switch (parseInt(this._dataGrid.sortColumnIdentifier)) {
case 0: comparator = localeCompare.bind(this, "name"); break;
case 1: comparator = localeCompare.bind(this, "value"); break;
case 2: comparator = localeCompare.bind(this, "domain"); break;
case 3: comparator = localeCompare.bind(this, "path"); break;
case 4: comparator = expiresCompare; break;
case 5: comparator = numberCompare.bind(this, "size"); break;
case 6: comparator = localeCompare.bind(this, "httpOnly"); break;
case 7: comparator = localeCompare.bind(this, "secure"); break;
default: localeCompare.bind(this, "name");
}

cookies.sort(comparator);
},

_createGridNode: function(cookie)
{
var data = {};
data[0] = cookie.name;
data[1] = cookie.value;
data[2] = cookie.domain || "";
data[3] = cookie.path || "";
data[4] = cookie.type === WebInspector.Cookie.Type.Request ? "" :
(cookie.session ? WebInspector.UIString("Session") : new Date(cookie.expires).toGMTString());
data[5] = cookie.size;
const checkmark = "\u2713";
data[6] = (cookie.httpOnly ? checkmark : "");
data[7] = (cookie.secure ? checkmark : "");

var node = new WebInspector.DataGridNode(data);
node.cookie = cookie;
node.selectable = true;
return node;
},

_onDeleteFromGrid: function(node)
{
this._deleteCallback(node.cookie);
}
}





WebInspector.CookieItemsView = function(treeElement, cookieDomain)
{
WebInspector.View.call(this);

this.element.addStyleClass("storage-view");

this._deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item");
this._deleteButton.visible = false;
this._deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);

this._refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
this._refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);

this._treeElement = treeElement;
this._cookieDomain = cookieDomain;

this._emptyMsgElement = document.createElement("div");
this._emptyMsgElement.className = "storage-empty-view";
this._emptyMsgElement.textContent = WebInspector.UIString("This site has no cookies.");
this.element.appendChild(this._emptyMsgElement);
}

WebInspector.CookieItemsView.prototype = {
get statusBarItems()
{
return [this._refreshButton.element, this._deleteButton.element];
},

show: function(parentElement)
{
WebInspector.View.prototype.show.call(this, parentElement);
this._update();
},

hide: function()
{
WebInspector.View.prototype.hide.call(this);
this._deleteButton.visible = false;
},

resize: function()
{
if (this._cookiesTable)
this._cookiesTable.updateWidths();
},

_update: function()
{
WebInspector.Cookies.getCookiesAsync(this._updateWithCookies.bind(this));
},

_updateWithCookies: function(allCookies, isAdvanced)
{
this._cookies = isAdvanced ? this._filterCookiesForDomain(allCookies) : allCookies;

if (!this._cookies.length) {

this._emptyMsgElement.removeStyleClass("hidden");
this._deleteButton.visible = false;
if (this._cookiesTable)
this._cookiesTable.element.addStyleClass("hidden");
return;
}

if (!this._cookiesTable) {
this._cookiesTable = isAdvanced ? new WebInspector.CookiesTable(this._cookieDomain, false, this._deleteCookie.bind(this)) : new WebInspector.SimpleCookiesTable();
this.element.appendChild(this._cookiesTable.element);
}

this._cookiesTable.setCookies(this._cookies);
this._cookiesTable.element.removeStyleClass("hidden");
this._emptyMsgElement.addStyleClass("hidden");
if (isAdvanced) {
this._treeElement.subtitle = String.sprintf(WebInspector.UIString("%d cookies (%s)"), this._cookies.length,
Number.bytesToString(this._totalSize));
this._deleteButton.visible = true;
}
this._cookiesTable.updateWidths();
},

_filterCookiesForDomain: function(allCookies)
{
var cookies = [];
var resourceURLsForDocumentURL = [];
this._totalSize = 0;

function populateResourcesForDocuments(resource)
{
var url = resource.documentURL.asParsedURL();
if (url && url.host == this._cookieDomain)
resourceURLsForDocumentURL.push(resource.url);
}
WebInspector.forAllResources(populateResourcesForDocuments.bind(this));

for (var i = 0; i < allCookies.length; ++i) {
var pushed = false;
var size = allCookies[i].size;
for (var j = 0; j < resourceURLsForDocumentURL.length; ++j) {
var resourceURL = resourceURLsForDocumentURL[j];
if (WebInspector.Cookies.cookieMatchesResourceURL(allCookies[i], resourceURL)) {
this._totalSize += size;
if (!pushed) {
pushed = true;
cookies.push(allCookies[i]);
}
}
}
}
return cookies;
},

_deleteCookie: function(cookie)
{
PageAgent.deleteCookie(cookie.name, this._cookieDomain);
this._update();
},

_deleteButtonClicked: function()
{
if (this._cookiesTable.selectedCookie)
this._deleteCookie(this._cookiesTable.selectedCookie);
},

_refreshButtonClicked: function(event)
{
this._update();
}
}

WebInspector.CookieItemsView.prototype.__proto__ = WebInspector.View.prototype;

WebInspector.SimpleCookiesTable = function()
{
this.element = document.createElement("div");
var columns = {};
columns[0] = {};
columns[1] = {};
columns[0].title = WebInspector.UIString("Name");
columns[1].title = WebInspector.UIString("Value");

this._dataGrid = new WebInspector.DataGrid(columns);
this._dataGrid.autoSizeColumns(20, 80);
this.element.appendChild(this._dataGrid.element);
this._dataGrid.updateWidths();
}

WebInspector.SimpleCookiesTable.prototype = {
setCookies: function(cookies)
{
this._dataGrid.removeChildren();
var addedCookies = {};
for (var i = 0; i < cookies.length; ++i) {
if (addedCookies[cookies[i].name])
continue;
addedCookies[cookies[i].name] = true;
var data = {};
data[0] = cookies[i].name;
data[1] = cookies[i].value;

var node = new WebInspector.DataGridNode(data, false);
node.selectable = true;
this._dataGrid.appendChild(node);
}
this._dataGrid.children[0].selected = true;
},

resize: function()
{
if (this._dataGrid)
this._dataGrid.updateWidths();
}
}


WebInspector.Cookies = {}

WebInspector.Cookies.getCookiesAsync = function(callback)
{
function mycallback(error, cookies, cookiesString)
{
if (error)
return;
if (cookiesString)
callback(WebInspector.Cookies.buildCookiesFromString(cookiesString), false);
else
callback(cookies, true);
}

PageAgent.getCookies(mycallback);
}

WebInspector.Cookies.buildCookiesFromString = function(rawCookieString)
{
var rawCookies = rawCookieString.split(/;\s*/);
var cookies = [];

if (!(/^\s*$/.test(rawCookieString))) {
for (var i = 0; i < rawCookies.length; ++i) {
var cookie = rawCookies[i];
var delimIndex = cookie.indexOf("=");
var name = cookie.substring(0, delimIndex);
var value = cookie.substring(delimIndex + 1);
var size = name.length + value.length;
cookies.push({ name: name, value: value, size: size });
}
}

return cookies;
}

WebInspector.Cookies.cookieMatchesResourceURL = function(cookie, resourceURL)
{
var url = resourceURL.asParsedURL();
if (!url || !this.cookieDomainMatchesResourceDomain(cookie.domain, url.host))
return false;
return (url.path.indexOf(cookie.path) === 0
&& (!cookie.port || url.port == cookie.port)
&& (!cookie.secure || url.scheme === "https"));
}

WebInspector.Cookies.cookieDomainMatchesResourceDomain = function(cookieDomain, resourceDomain)
{
if (cookieDomain.charAt(0) !== '.')
return resourceDomain === cookieDomain;
return !!resourceDomain.match(new RegExp("^([^\\.]+\\.)?" + cookieDomain.substring(1).escapeForRegExp() + "$"), "i");
}





WebInspector.ApplicationCacheItemsView = function(treeElement, appcacheDomain)
{
WebInspector.View.call(this);

this.element.addStyleClass("storage-view");
this.element.addStyleClass("table");


this.deleteButton = new WebInspector.StatusBarButton(WebInspector.UIString("Delete"), "delete-storage-status-bar-item");
this.deleteButton.visible = false;
this.deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);


this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);

if (Preferences.onlineDetectionEnabled) {
this.connectivityIcon = document.createElement("img");
this.connectivityIcon.className = "storage-application-cache-connectivity-icon";
this.connectivityIcon.src = "";
this.connectivityMessage = document.createElement("span");
this.connectivityMessage.className = "storage-application-cache-connectivity";
this.connectivityMessage.textContent = "";
}

this.divider = document.createElement("span");
this.divider.className = "status-bar-item status-bar-divider";

this.statusIcon = document.createElement("img");
this.statusIcon.className = "storage-application-cache-status-icon";
this.statusIcon.src = "";
this.statusMessage = document.createElement("span");
this.statusMessage.className = "storage-application-cache-status";
this.statusMessage.textContent = "";

this._treeElement = treeElement;
this._appcacheDomain = appcacheDomain;

this._emptyMsgElement = document.createElement("div");
this._emptyMsgElement.className = "storage-empty-view";
this._emptyMsgElement.textContent = WebInspector.UIString("No Application Cache information available.");
this.element.appendChild(this._emptyMsgElement);

this.updateStatus(applicationCache.UNCACHED);





this.deleteButton.element.style.display = "none";
this.refreshButton.element.style.display = "none";
if (Preferences.onlineDetectionEnabled) {
this.connectivityIcon.style.display = "none";
this.connectivityMessage.style.display = "none";
}
this.divider.style.display = "none";
this.statusIcon.style.display = "none";
this.statusMessage.style.display = "none";

}

WebInspector.ApplicationCacheItemsView.prototype = {
get statusBarItems()
{
if (Preferences.onlineDetectionEnabled) {
return [
this.refreshButton.element, this.deleteButton.element,
this.connectivityIcon, this.connectivityMessage, this.divider,
this.statusIcon, this.statusMessage
];
} else {
return [
this.refreshButton.element, this.deleteButton.element, this.divider,
this.statusIcon, this.statusMessage
];
}
},

show: function(parentElement)
{
WebInspector.View.prototype.show.call(this, parentElement);
this.updateNetworkState(navigator.onLine);
this._update();
},

hide: function()
{
WebInspector.View.prototype.hide.call(this);
this.deleteButton.visible = false;
},

updateStatus: function(status)
{
var statusInformation = {};
statusInformation[applicationCache.UNCACHED]    = { src: "Images/warningOrangeDot.png", text: "UNCACHED"    };
statusInformation[applicationCache.IDLE]        = { src: "Images/warningOrangeDot.png", text: "IDLE"        };
statusInformation[applicationCache.CHECKING]    = { src: "Images/successGreenDot.png",  text: "CHECKING"    };
statusInformation[applicationCache.DOWNLOADING] = { src: "Images/successGreenDot.png",  text: "DOWNLOADING" };
statusInformation[applicationCache.UPDATEREADY] = { src: "Images/successGreenDot.png",  text: "UPDATEREADY" };
statusInformation[applicationCache.OBSOLETE]    = { src: "Images/errorRedDot.png",      text: "OBSOLETE"    };

var info = statusInformation[status];
if (!info) {
console.error("Unknown Application Cache Status was Not Handled: %d", status);
return;
}

this.statusIcon.src = info.src;
this.statusMessage.textContent = info.text;
},

updateNetworkState: function(isNowOnline)
{
if (Preferences.onlineDetectionEnabled) {
if (isNowOnline) {
this.connectivityIcon.src = "Images/successGreenDot.png";
this.connectivityMessage.textContent = WebInspector.UIString("Online");
} else {
this.connectivityIcon.src = "Images/errorRedDot.png";
this.connectivityMessage.textContent = WebInspector.UIString("Offline");
}
}
},

_update: function()
{
WebInspector.ApplicationCacheDispatcher.getApplicationCachesAsync(this._updateCallback.bind(this));
},

_updateCallback: function(applicationCaches)
{


this._manifest = applicationCaches.manifest;
this._creationTime = applicationCaches.creationTime;
this._updateTime = applicationCaches.updateTime;
this._size = applicationCaches.size;
this._resources = applicationCaches.resources;
var lastPathComponent = applicationCaches.lastPathComponent;

if (!this._manifest) {
this._emptyMsgElement.removeStyleClass("hidden");
this.deleteButton.visible = false;
if (this._dataGrid)
this._dataGrid.element.addStyleClass("hidden");
return;
}

if (!this._dataGrid)
this._createDataGrid();

this._populateDataGrid();
this._dataGrid.autoSizeColumns(20, 80);
this._dataGrid.element.removeStyleClass("hidden");
this._emptyMsgElement.addStyleClass("hidden");
this.deleteButton.visible = true;

var totalSizeString = Number.bytesToString(this._size);
this._treeElement.subtitle = WebInspector.UIString("%s (%s)", lastPathComponent, totalSizeString);




},

_createDataGrid: function()
{
var columns = { 0: {}, 1: {}, 2: {} };
columns[0].title = WebInspector.UIString("Resource");
columns[0].sort = "ascending";
columns[0].sortable = true;
columns[1].title = WebInspector.UIString("Type");
columns[1].sortable = true;
columns[2].title = WebInspector.UIString("Size");
columns[2].aligned = "right";
columns[2].sortable = true;
this._dataGrid = new WebInspector.DataGrid(columns);
this.element.appendChild(this._dataGrid.element);
this._dataGrid.addEventListener("sorting changed", this._populateDataGrid, this);
this._dataGrid.updateWidths();
},

_populateDataGrid: function()
{
var selectedResource = this._dataGrid.selectedNode ? this._dataGrid.selectedNode.resource : null;
var sortDirection = this._dataGrid.sortOrder === "ascending" ? 1 : -1;

function numberCompare(field, resource1, resource2)
{
return sortDirection * (resource1[field] - resource2[field]);
}
function localeCompare(field, resource1, resource2)
{
return sortDirection * (resource1[field] + "").localeCompare(resource2[field] + "")
}

var comparator;
switch (parseInt(this._dataGrid.sortColumnIdentifier)) {
case 0: comparator = localeCompare.bind(this, "name"); break;
case 1: comparator = localeCompare.bind(this, "type"); break;
case 2: comparator = numberCompare.bind(this, "size"); break;
default: localeCompare.bind(this, "resource"); 
}

this._resources.sort(comparator);
this._dataGrid.removeChildren();

var nodeToSelect;
for (var i = 0; i < this._resources.length; ++i) {
var data = {};
var resource = this._resources[i];
data[0] = resource.name;
data[1] = resource.type;
data[2] = Number.bytesToString(resource.size);
var node = new WebInspector.DataGridNode(data);
node.resource = resource;
node.selectable = true;
this._dataGrid.appendChild(node);
if (resource === selectedResource) {
nodeToSelect = node;
nodeToSelect.selected = true;
}
}

if (!nodeToSelect)
this._dataGrid.children[0].selected = true;
},

resize: function()
{
if (this._dataGrid)
this._dataGrid.updateWidths();
},

_deleteButtonClicked: function(event)
{
if (!this._dataGrid || !this._dataGrid.selectedNode)
return;


this._deleteCallback(this._dataGrid.selectedNode);
},

_deleteCallback: function(node)
{



},

_refreshButtonClicked: function(event)
{


}
}

WebInspector.ApplicationCacheItemsView.prototype.__proto__ = WebInspector.View.prototype;

WebInspector.ApplicationCacheDispatcher = function()
{
}

WebInspector.ApplicationCacheDispatcher.getApplicationCachesAsync = function(callback)
{
function mycallback(error, applicationCaches)
{

if (!error && applicationCaches)
callback(applicationCaches);
}

ApplicationCacheAgent.getApplicationCaches(mycallback);
}

WebInspector.ApplicationCacheDispatcher.prototype = {
updateApplicationCacheStatus: function(status)
{
WebInspector.panels.resources.updateApplicationCacheStatus(status);
},

updateNetworkState: function(isNowOnline)
{
WebInspector.panels.resources.updateNetworkState(isNowOnline);
}
}

InspectorBackend.registerDomainDispatcher("ApplicationCache", new WebInspector.ApplicationCacheDispatcher());





WebInspector.Script = function(sourceId, sourceURL, startLine, startColumn, endLine, endColumn, errorLine, errorMessage, isContentScript)
{
this.sourceId = sourceId;
this.sourceURL = sourceURL;
this.lineOffset = startLine;
this.columnOffset = startColumn;
this.endLine = endLine;
this.endColumn = endColumn;
this.errorLine = errorLine;
this.errorMessage = errorMessage;
this.isContentScript = isContentScript;
}

WebInspector.Script.prototype = {
requestSource: function(callback)
{
if (this._source) {
callback(this._source);
return;
}

function didGetScriptSource(error, source)
{
this._source = source;
callback(this._source);
}
DebuggerAgent.getScriptSource(this.sourceId, didGetScriptSource.bind(this));
},

editSource: function(newSource, callback)
{
function didEditScriptSource(error, callFrames)
{
if (!error)
this._source = newSource;
callback(error, callFrames);
}
DebuggerAgent.editScriptSource(this.sourceId, newSource, didEditScriptSource.bind(this));
}
}





WebInspector.SidebarPane = function(title)
{
this.element = document.createElement("div");
this.element.className = "pane";

this.titleElement = document.createElement("div");
this.titleElement.className = "title";
this.titleElement.tabIndex = 0;
this.titleElement.addEventListener("click", this.toggleExpanded.bind(this), false);
this.titleElement.addEventListener("keydown", this._onTitleKeyDown.bind(this), false);

this.bodyElement = document.createElement("div");
this.bodyElement.className = "body";

this.element.appendChild(this.titleElement);
this.element.appendChild(this.bodyElement);

this.title = title;
this.growbarVisible = false;
this.expanded = false;
}

WebInspector.SidebarPane.prototype = {
get title()
{
return this._title;
},

set title(x)
{
if (this._title === x)
return;
this._title = x;
this.titleElement.textContent = x;
},

get growbarVisible()
{
return this._growbarVisible;
},

set growbarVisible(x)
{
if (this._growbarVisible === x)
return;

this._growbarVisible = x;

if (x && !this._growbarElement) {
this._growbarElement = document.createElement("div");
this._growbarElement.className = "growbar";
this.element.appendChild(this._growbarElement);
} else if (!x && this._growbarElement) {
if (this._growbarElement.parentNode)
this._growbarElement.parentNode(this._growbarElement);
delete this._growbarElement;
}
},

get expanded()
{
return this._expanded;
},

set expanded(x)
{
if (x)
this.expand();
else
this.collapse();
},

expand: function()
{
if (this._expanded)
return;
this._expanded = true;
this.element.addStyleClass("expanded");
if (this.onexpand)
this.onexpand(this);
},

collapse: function()
{
if (!this._expanded)
return;
this._expanded = false;
this.element.removeStyleClass("expanded");
if (this.oncollapse)
this.oncollapse(this);
},

toggleExpanded: function()
{
this.expanded = !this.expanded;
},

_onTitleKeyDown: function(event)
{
if (isEnterKey(event) || event.keyCode === WebInspector.KeyboardShortcut.Keys.Space.code)
this.toggleExpanded();
}
}

WebInspector.SidebarPane.prototype.__proto__ = WebInspector.Object.prototype;





WebInspector.ElementsTreeOutline = function() {
this.element = document.createElement("ol");
this.element.addEventListener("mousedown", this._onmousedown.bind(this), false);
this.element.addEventListener("mousemove", this._onmousemove.bind(this), false);
this.element.addEventListener("mouseout", this._onmouseout.bind(this), false);

TreeOutline.call(this, this.element);

this.includeRootDOMNode = true;
this.selectEnabled = false;
this.showInElementsPanelEnabled = false;
this.rootDOMNode = null;
this.focusedDOMNode = null;
}

WebInspector.ElementsTreeOutline.prototype = {
get rootDOMNode()
{
return this._rootDOMNode;
},

set rootDOMNode(x)
{
if (this._rootDOMNode === x)
return;

this._rootDOMNode = x;

this._isXMLMimeType = x && !!x.xmlVersion;

this.update();
},

get isXMLMimeType()
{
return this._isXMLMimeType;
},

nodeNameToCorrectCase: function(nodeName)
{
return this.isXMLMimeType ? nodeName : nodeName.toLowerCase();
},

get focusedDOMNode()
{
return this._focusedDOMNode;
},

set focusedDOMNode(x)
{
if (this._focusedDOMNode === x) {
this.revealAndSelectNode(x);
return;
}

this._focusedDOMNode = x;

this.revealAndSelectNode(x);





if (this._focusedDOMNode === x)
this.focusedNodeChanged();
},

get editing()
{
return this._editing;
},

update: function()
{
var selectedNode = this.selectedTreeElement ? this.selectedTreeElement.representedObject : null;

this.removeChildren();

if (!this.rootDOMNode)
return;

var treeElement;
if (this.includeRootDOMNode) {
treeElement = new WebInspector.ElementsTreeElement(this.rootDOMNode);
treeElement.selectable = this.selectEnabled;
this.appendChild(treeElement);
} else {

var node = this.rootDOMNode.firstChild;
while (node) {
treeElement = new WebInspector.ElementsTreeElement(node);
treeElement.selectable = this.selectEnabled;
this.appendChild(treeElement);
node = node.nextSibling;
}
}

if (selectedNode)
this.revealAndSelectNode(selectedNode);
},

updateSelection: function()
{
if (!this.selectedTreeElement)
return;
var element = this.treeOutline.selectedTreeElement;
element.updateSelection();
},

focusedNodeChanged: function(forceUpdate) {},

findTreeElement: function(node)
{
var treeElement = TreeOutline.prototype.findTreeElement.call(this, node, isAncestorNode, parentNode);
if (!treeElement && node.nodeType() === Node.TEXT_NODE) {

treeElement = TreeOutline.prototype.findTreeElement.call(this, node.parentNode, isAncestorNode, parentNode);
}

return treeElement;
},

createTreeElementFor: function(node)
{
var treeElement = this.findTreeElement(node);
if (treeElement)
return treeElement;
if (!node.parentNode)
return null;

var treeElement = this.createTreeElementFor(node.parentNode);
if (treeElement && treeElement.showChild(node.index))
return treeElement.children[node.index];

return null;
},

set suppressRevealAndSelect(x)
{
if (this._suppressRevealAndSelect === x)
return;
this._suppressRevealAndSelect = x;
},

revealAndSelectNode: function(node)
{
if (!node || this._suppressRevealAndSelect)
return;

var treeElement = this.createTreeElementFor(node);
if (!treeElement)
return;

treeElement.reveal();
treeElement.select();
},

_treeElementFromEvent: function(event)
{
var scrollContainer = this.element.parentElement;





var x = scrollContainer.totalOffsetLeft + scrollContainer.offsetWidth - 36;

var y = event.pageY;




var elementUnderMouse = this.treeElementFromPoint(x, y);
var elementAboveMouse = this.treeElementFromPoint(x, y - 2);
var element;
if (elementUnderMouse === elementAboveMouse)
element = elementUnderMouse;
else
element = this.treeElementFromPoint(x, y + 2);

return element;
},

_onmousedown: function(event)
{
var element = this._treeElementFromEvent(event);

if (!element || element.isEventWithinDisclosureTriangle(event))
return;

element.select();
},

_onmousemove: function(event)
{
var element = this._treeElementFromEvent(event);
if (element && this._previousHoveredElement === element)
return;

if (this._previousHoveredElement) {
this._previousHoveredElement.hovered = false;
delete this._previousHoveredElement;
}

if (element) {
element.hovered = true;
this._previousHoveredElement = element;


if (element.representedObject && !element.tooltip)
element._createTooltipForNode();
}

WebInspector.highlightDOMNode(element ? element.representedObject.id : 0);
},

_onmouseout: function(event)
{
var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
if (nodeUnderMouse && nodeUnderMouse.isDescendant(this.element))
return;

if (this._previousHoveredElement) {
this._previousHoveredElement.hovered = false;
delete this._previousHoveredElement;
}

WebInspector.highlightDOMNode(0);
},

populateContextMenu: function(contextMenu, event)
{
var listItem = event.target.enclosingNodeOrSelfWithNodeName("LI");
if (!listItem || !listItem.treeElement)
return false;

var populated;
if (this.showInElementsPanelEnabled) {
function focusElement()
{
WebInspector.panels.elements.switchToAndFocus(listItem.treeElement.representedObject);
}
contextMenu.appendItem(WebInspector.UIString("Reveal in Elements Panel"), focusElement.bind(this));
populated = true;
} else {
var href = event.target.enclosingNodeOrSelfWithClass("webkit-html-resource-link") || event.target.enclosingNodeOrSelfWithClass("webkit-html-external-link");
var tag = event.target.enclosingNodeOrSelfWithClass("webkit-html-tag");
var textNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-text-node");
if (href)
populated = WebInspector.panels.elements.populateHrefContextMenu(contextMenu, event, href);
if (tag && listItem.treeElement._populateTagContextMenu) {
if (populated)
contextMenu.appendSeparator();
listItem.treeElement._populateTagContextMenu(contextMenu, event);
populated = true;
} else if (textNode && listItem.treeElement._populateTextContextMenu) {
if (populated)
contextMenu.appendSeparator();
listItem.treeElement._populateTextContextMenu(contextMenu, textNode);
populated = true;
}
}

return populated;
}
}

WebInspector.ElementsTreeOutline.prototype.__proto__ = TreeOutline.prototype;

WebInspector.ElementsTreeElement = function(node, elementCloseTag)
{
this._elementCloseTag = elementCloseTag;
var hasChildrenOverride = !elementCloseTag && node.hasChildNodes() && !this._showInlineText(node);


TreeElement.call(this, "", node, hasChildrenOverride);

if (this.representedObject.nodeType() == Node.ELEMENT_NODE && !elementCloseTag)
this._canAddAttributes = true;
this._searchQuery = null;
this._expandedChildrenLimit = WebInspector.ElementsTreeElement.InitialChildrenLimit;
}

WebInspector.ElementsTreeElement.InitialChildrenLimit = 500;




WebInspector.ElementsTreeElement.ForbiddenClosingTagElements = [
"area", "base", "basefont", "br", "canvas", "col", "command", "embed", "frame",
"hr", "img", "input", "isindex", "keygen", "link", "meta", "param", "source"
].keySet();


WebInspector.ElementsTreeElement.EditTagBlacklist = [
"html", "head", "body"
].keySet();

WebInspector.ElementsTreeElement.prototype = {
highlightSearchResults: function(searchQuery)
{
if (this._searchQuery !== searchQuery) {
this._updateSearchHighlight(false);
delete this._highlightResult; 
}

this._searchQuery = searchQuery;
this._searchHighlightsVisible = true;
this.updateTitle(true);
},

hideSearchHighlights: function()
{
delete this._searchHighlightsVisible;
this._updateSearchHighlight(false);
},

_updateSearchHighlight: function(show)
{
if (!this._highlightResult)
return;

function updateEntryShow(entry)
{
switch (entry.type) {
case "added":
entry.parent.insertBefore(entry.node, entry.nextSibling);
break;
case "changed":
entry.node.textContent = entry.newText;
break;
}
}

function updateEntryHide(entry)
{
switch (entry.type) {
case "added":
if (entry.node.parentElement)
entry.node.parentElement.removeChild(entry.node);
break;
case "changed":
entry.node.textContent = entry.oldText;
break;
}
}

var updater = show ? updateEntryShow : updateEntryHide;

for (var i = 0, size = this._highlightResult.length; i < size; ++i)
updater(this._highlightResult[i]);
},

get hovered()
{
return this._hovered;
},

set hovered(x)
{
if (this._hovered === x)
return;

this._hovered = x;

if (this.listItemElement) {
if (x) {
this.updateSelection();
this.listItemElement.addStyleClass("hovered");
} else {
this.listItemElement.removeStyleClass("hovered");
}
}
},

get expandedChildrenLimit()
{
return this._expandedChildrenLimit;
},

set expandedChildrenLimit(x)
{
if (this._expandedChildrenLimit === x)
return;

this._expandedChildrenLimit = x;
if (this.treeOutline && !this._updateChildrenInProgress)
this._updateChildren(true);
},

get expandedChildCount()
{
var count = this.children.length;
if (count && this.children[count - 1]._elementCloseTag)
count--;
if (count && this.children[count - 1].expandAllButton)
count--;
return count;
},

showChild: function(index)
{
if (this._elementCloseTag)
return;

if (index >= this.expandedChildrenLimit) {
this._expandedChildrenLimit = index + 1;
this._updateChildren(true);
}


return this.expandedChildCount > index;
},

_createTooltipForNode: function()
{
var node = this.representedObject;
if (!node.nodeName() || node.nodeName().toLowerCase() !== "img")
return;

function setTooltip(error, result, wasThrown)
{
if (error || wasThrown || result.type !== "string")
return;

try {
var properties = JSON.parse(result.description);
var offsetWidth = properties[0];
var offsetHeight = properties[1];
var naturalWidth = properties[2];
var naturalHeight = properties[3];
if (offsetHeight === naturalHeight && offsetWidth === naturalWidth)
this.tooltip = WebInspector.UIString("%d \xd7 %d pixels", offsetWidth, offsetHeight);
else
this.tooltip = WebInspector.UIString("%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)", offsetWidth, offsetHeight, naturalWidth, naturalHeight);
} catch (e) {
console.error(e);
}
}

function resolvedNode(object)
{
if (!object)
return;

object.evaluate("return '[' + this.offsetWidth + ',' + this.offsetHeight + ',' + this.naturalWidth + ',' + this.naturalHeight + ']'", setTooltip.bind(this));
object.release();
}
WebInspector.RemoteObject.resolveNode(node, resolvedNode.bind(this));
},

updateSelection: function()
{
var listItemElement = this.listItemElement;
if (!listItemElement)
return;

if (document.body.offsetWidth <= 0) {


return;
}

if (!this.selectionElement) {
this.selectionElement = document.createElement("div");
this.selectionElement.className = "selection selected";
listItemElement.insertBefore(this.selectionElement, listItemElement.firstChild);
}

this.selectionElement.style.height = listItemElement.offsetHeight + "px";
},

onattach: function()
{
if (this._hovered) {
this.updateSelection();
this.listItemElement.addStyleClass("hovered");
}

this.updateTitle();

this._preventFollowingLinksOnDoubleClick();
},

_preventFollowingLinksOnDoubleClick: function()
{
var links = this.listItemElement.querySelectorAll("li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-external-link, li > .webkit-html-tag > .webkit-html-attribute > .webkit-html-resource-link");
if (!links)
return;

for (var i = 0; i < links.length; ++i)
links[i].preventFollowOnDoubleClick = true;
},

onpopulate: function()
{
if (this.children.length || this._showInlineText(this.representedObject) || this._elementCloseTag)
return;

this.updateChildren();
},

updateChildren: function(fullRefresh)
{
if (this._elementCloseTag)
return;
this.representedObject.getChildNodes(this._updateChildren.bind(this, fullRefresh));
},

insertChildElement: function(child, index, closingTag)
{
var newElement = new WebInspector.ElementsTreeElement(child, closingTag);
newElement.selectable = this.treeOutline.selectEnabled;
this.insertChild(newElement, index);
return newElement;
},

moveChild: function(child, targetIndex)
{
var wasSelected = child.selected;
this.removeChild(child);
this.insertChild(child, targetIndex);
if (wasSelected)
child.select();
},

_updateChildren: function(fullRefresh)
{
if (this._updateChildrenInProgress)
return;

this._updateChildrenInProgress = true;
var focusedNode = this.treeOutline.focusedDOMNode;
var originalScrollTop;
if (fullRefresh) {
var treeOutlineContainerElement = this.treeOutline.element.parentNode;
originalScrollTop = treeOutlineContainerElement.scrollTop;
var selectedTreeElement = this.treeOutline.selectedTreeElement;
if (selectedTreeElement && selectedTreeElement.hasAncestor(this))
this.select();
this.removeChildren();
}

var treeElement = this;
var treeChildIndex = 0;
var elementToSelect;

function updateChildrenOfNode(node)
{
var treeOutline = treeElement.treeOutline;
var child = node.firstChild;
while (child) {
var currentTreeElement = treeElement.children[treeChildIndex];
if (!currentTreeElement || currentTreeElement.representedObject !== child) {

var existingTreeElement = null;
for (var i = (treeChildIndex + 1), size = treeElement.expandedChildCount; i < size; ++i) {
if (treeElement.children[i].representedObject === child) {
existingTreeElement = treeElement.children[i];
break;
}
}

if (existingTreeElement && existingTreeElement.parent === treeElement) {

treeElement.moveChild(existingTreeElement, treeChildIndex);
} else {

if (treeChildIndex < treeElement.expandedChildrenLimit) {
var newElement = treeElement.insertChildElement(child, treeChildIndex);
if (child === focusedNode)
elementToSelect = newElement;
if (treeElement.expandedChildCount > treeElement.expandedChildrenLimit)
treeElement.expandedChildrenLimit++;
}
}
}

child = child.nextSibling;
++treeChildIndex;
}
}


for (var i = (this.children.length - 1); i >= 0; --i) {
var currentChild = this.children[i];
var currentNode = currentChild.representedObject;
var currentParentNode = currentNode.parentNode;

if (currentParentNode === this.representedObject)
continue;

var selectedTreeElement = this.treeOutline.selectedTreeElement;
if (selectedTreeElement && (selectedTreeElement === currentChild || selectedTreeElement.hasAncestor(currentChild)))
this.select();

this.removeChildAtIndex(i);
}

updateChildrenOfNode(this.representedObject);
this.adjustCollapsedRange(false);

var lastChild = this.children[this.children.length - 1];
if (this.representedObject.nodeType() == Node.ELEMENT_NODE && (!lastChild || !lastChild._elementCloseTag))
this.insertChildElement(this.representedObject, this.children.length, true);


if (fullRefresh && elementToSelect) {
elementToSelect.select();
if (treeOutlineContainerElement && originalScrollTop <= treeOutlineContainerElement.scrollHeight)
treeOutlineContainerElement.scrollTop = originalScrollTop;
}

delete this._updateChildrenInProgress;
},

adjustCollapsedRange: function()
{


if (this.expandAllButtonElement && this.expandAllButtonElement.__treeElement.parent)
this.removeChild(this.expandAllButtonElement.__treeElement);

const node = this.representedObject;
if (!node.children)
return;
const childNodeCount = node.children.length;


for (var i = this.expandedChildCount, limit = Math.min(this.expandedChildrenLimit, childNodeCount); i < limit; ++i)
this.insertChildElement(node.children[i], i);

const expandedChildCount = this.expandedChildCount;
if (childNodeCount > this.expandedChildCount) {
var targetButtonIndex = expandedChildCount;
if (!this.expandAllButtonElement) {
var item = new TreeElement(null, null, false);
item.titleHTML = "<button class=\"show-all-nodes\" value=\"\" />";
item.selectable = false;
item.expandAllButton = true;
this.insertChild(item, targetButtonIndex);
this.expandAllButtonElement = item.listItemElement.firstChild;
this.expandAllButtonElement.__treeElement = item;
this.expandAllButtonElement.addEventListener("click", this.handleLoadAllChildren.bind(this), false);
} else if (!this.expandAllButtonElement.__treeElement.parent)
this.insertChild(this.expandAllButtonElement.__treeElement, targetButtonIndex);
this.expandAllButtonElement.textContent = WebInspector.UIString("Show All Nodes (%d More)", childNodeCount - expandedChildCount);
} else if (this.expandAllButtonElement)
delete this.expandAllButtonElement;
},

handleLoadAllChildren: function()
{
this.expandedChildrenLimit = Math.max(this.representedObject._childNodeCount, this.expandedChildrenLimit + WebInspector.ElementsTreeElement.InitialChildrenLimit);
},

onexpand: function()
{
if (this._elementCloseTag)
return;

this.updateTitle();
this.treeOutline.updateSelection();
},

oncollapse: function()
{
if (this._elementCloseTag)
return;

this.updateTitle();
this.treeOutline.updateSelection();
},

onreveal: function()
{
if (this.listItemElement) {
var tagSpans = this.listItemElement.getElementsByClassName("webkit-html-tag-name");
if (tagSpans.length)
tagSpans[0].scrollIntoViewIfNeeded(false);
else
this.listItemElement.scrollIntoViewIfNeeded(false);
}
},

onselect: function(treeElement, selectedByUser)
{
this.treeOutline.suppressRevealAndSelect = true;
this.treeOutline.focusedDOMNode = this.representedObject;
if (selectedByUser)
WebInspector.highlightDOMNode(this.representedObject.id);
this.updateSelection();
this.treeOutline.suppressRevealAndSelect = false;
},

ondelete: function()
{
var startTagTreeElement = this.treeOutline.findTreeElement(this.representedObject);
startTagTreeElement ? startTagTreeElement.remove() : this.remove();
return true;
},

onenter: function()
{


if (this.treeOutline.editing)
return false;

this._startEditing();


return true;
},

selectOnMouseDown: function(event)
{
TreeElement.prototype.selectOnMouseDown.call(this, event);

if (this._editing)
return;

if (this.treeOutline.showInElementsPanelEnabled) {
WebInspector.showPanel("elements");
WebInspector.panels.elements.focusedDOMNode = this.representedObject;
}


if (event.detail >= 2)
event.preventDefault();
},

ondblclick: function(event)
{
if (this._editing || this._elementCloseTag)
return;

if (this._startEditingTarget(event.target))
return;

if (this.hasChildren && !this.expanded)
this.expand();
},

_insertInLastAttributePosition: function(tag, node)
{
if (tag.getElementsByClassName("webkit-html-attribute").length > 0)
tag.insertBefore(node, tag.lastChild);
else {
var nodeName = tag.textContent.match(/^<(.*?)>$/)[1];
tag.textContent = '';
tag.appendChild(document.createTextNode('<'+nodeName));
tag.appendChild(node);
tag.appendChild(document.createTextNode('>'));
}

this.updateSelection();
},

_startEditingTarget: function(eventTarget)
{
if (this.treeOutline.focusedDOMNode != this.representedObject)
return;

if (this.representedObject.nodeType() != Node.ELEMENT_NODE && this.representedObject.nodeType() != Node.TEXT_NODE)
return false;

var textNode = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-text-node");
if (textNode)
return this._startEditingTextNode(textNode);

var attribute = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-attribute");
if (attribute)
return this._startEditingAttribute(attribute, eventTarget);

var tagName = eventTarget.enclosingNodeOrSelfWithClass("webkit-html-tag-name");
if (tagName)
return this._startEditingTagName(tagName);

var newAttribute = eventTarget.enclosingNodeOrSelfWithClass("add-attribute");
if (newAttribute)
return this._addNewAttribute();

return false;
},

_populateTagContextMenu: function(contextMenu, event)
{
var attribute = event.target.enclosingNodeOrSelfWithClass("webkit-html-attribute");
var newAttribute = event.target.enclosingNodeOrSelfWithClass("add-attribute");


contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add attribute" : "Add Attribute"), this._addNewAttribute.bind(this));
if (attribute && !newAttribute)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Edit attribute" : "Edit Attribute"), this._startEditingAttribute.bind(this, attribute, event.target));
contextMenu.appendSeparator();


contextMenu.appendItem(WebInspector.UIString("Edit as HTML"), this._editAsHTML.bind(this));
contextMenu.appendItem(WebInspector.UIString("Copy as HTML"), this._copyHTML.bind(this));
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Delete node" : "Delete Node"), this.remove.bind(this));

if (Preferences.nativeInstrumentationEnabled) {

contextMenu.appendSeparator();
var pane = WebInspector.panels.elements.sidebarPanes.domBreakpoints;
pane.populateNodeContextMenu(this.representedObject, contextMenu);
}
},

_populateTextContextMenu: function(contextMenu, textNode)
{
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Edit text" : "Edit Text"), this._startEditingTextNode.bind(this, textNode));
},

_startEditing: function()
{
if (this.treeOutline.focusedDOMNode !== this.representedObject)
return;

var listItem = this._listItemNode;

if (this._canAddAttributes) {
var attribute = listItem.getElementsByClassName("webkit-html-attribute")[0];
if (attribute)
return this._startEditingAttribute(attribute, attribute.getElementsByClassName("webkit-html-attribute-value")[0]);

return this._addNewAttribute();
}

if (this.representedObject.nodeType() === Node.TEXT_NODE) {
var textNode = listItem.getElementsByClassName("webkit-html-text-node")[0];
if (textNode)
return this._startEditingTextNode(textNode);
return;
}
},

_addNewAttribute: function()
{


var container = document.createElement("span");
this._buildAttributeDOM(container, " ", "");
var attr = container.firstChild;
attr.style.marginLeft = "2px"; 
attr.style.marginRight = "2px"; 

var tag = this.listItemElement.getElementsByClassName("webkit-html-tag")[0];
this._insertInLastAttributePosition(tag, attr);
return this._startEditingAttribute(attr, attr);
},

_triggerEditAttribute: function(attributeName)
{
var attributeElements = this.listItemElement.getElementsByClassName("webkit-html-attribute-name");
for (var i = 0, len = attributeElements.length; i < len; ++i) {
if (attributeElements[i].textContent === attributeName) {
for (var elem = attributeElements[i].nextSibling; elem; elem = elem.nextSibling) {
if (elem.nodeType !== Node.ELEMENT_NODE)
continue;

if (elem.hasStyleClass("webkit-html-attribute-value"))
return this._startEditingAttribute(elem.parentNode, elem);
}
}
}
},

_startEditingAttribute: function(attribute, elementForSelection)
{
if (WebInspector.isBeingEdited(attribute))
return true;

var attributeNameElement = attribute.getElementsByClassName("webkit-html-attribute-name")[0];
if (!attributeNameElement)
return false;

var attributeName = attributeNameElement.textContent;

function removeZeroWidthSpaceRecursive(node)
{
if (node.nodeType === Node.TEXT_NODE) {
node.nodeValue = node.nodeValue.replace(/\u200B/g, "");
return;
}

if (node.nodeType !== Node.ELEMENT_NODE)
return;

for (var child = node.firstChild; child; child = child.nextSibling)
removeZeroWidthSpaceRecursive(child);
}


removeZeroWidthSpaceRecursive(attribute);

this._editing = WebInspector.startEditing(attribute, {
context: attributeName,
commitHandler: this._attributeEditingCommitted.bind(this),
cancelHandler: this._editingCancelled.bind(this)
});
window.getSelection().setBaseAndExtent(elementForSelection, 0, elementForSelection, 1);

return true;
},

_startEditingTextNode: function(textNode)
{
if (WebInspector.isBeingEdited(textNode))
return true;

this._editing = WebInspector.startEditing(textNode, {
context: null,
commitHandler: this._textNodeEditingCommitted.bind(this),
cancelHandler: this._editingCancelled.bind(this)
});
window.getSelection().setBaseAndExtent(textNode, 0, textNode, 1);

return true;
},

_startEditingTagName: function(tagNameElement)
{
if (!tagNameElement) {
tagNameElement = this.listItemElement.getElementsByClassName("webkit-html-tag-name")[0];
if (!tagNameElement)
return false;
}

var tagName = tagNameElement.textContent;
if (WebInspector.ElementsTreeElement.EditTagBlacklist[tagName.toLowerCase()])
return false;

if (WebInspector.isBeingEdited(tagNameElement))
return true;

var closingTagElement = this._distinctClosingTagElement();

function keyupListener(event)
{
if (closingTagElement)
closingTagElement.textContent = "</" + tagNameElement.textContent + ">";
}

function editingComitted(element, newTagName)
{
tagNameElement.removeEventListener('keyup', keyupListener, false);
this._tagNameEditingCommitted.apply(this, arguments);
}

function editingCancelled()
{
tagNameElement.removeEventListener('keyup', keyupListener, false);
this._editingCancelled.apply(this, arguments);
}

tagNameElement.addEventListener('keyup', keyupListener, false);

this._editing = WebInspector.startEditing(tagNameElement, {
context: tagName,
commitHandler: editingComitted.bind(this),
cancelHandler: editingCancelled.bind(this)
});
window.getSelection().setBaseAndExtent(tagNameElement, 0, tagNameElement, 1);
return true;
},

_startEditingAsHTML: function(commitCallback, error, initialValue)
{
if (error)
return;
if (this._htmlEditElement && WebInspector.isBeingEdited(this._htmlEditElement))
return;

this._htmlEditElement = document.createElement("div");
this._htmlEditElement.className = "source-code elements-tree-editor";
this._htmlEditElement.textContent = initialValue;


var child = this.listItemElement.firstChild;
while (child) {
child.style.display = "none";
child = child.nextSibling;
}

if (this._childrenListNode)
this._childrenListNode.style.display = "none";

this.listItemElement.appendChild(this._htmlEditElement);

this.updateSelection();

function commit()
{
commitCallback(this._htmlEditElement.textContent);
dispose.call(this);
}

function dispose()
{
delete this._editing;


this.listItemElement.removeChild(this._htmlEditElement);
delete this._htmlEditElement;

if (this._childrenListNode)
this._childrenListNode.style.removeProperty("display");

var child = this.listItemElement.firstChild;
while (child) {
child.style.removeProperty("display");
child = child.nextSibling;
}

this.updateSelection();
}

this._editing = WebInspector.startEditing(this._htmlEditElement, {
context: null,
commitHandler: commit.bind(this),
cancelHandler: dispose.bind(this),
multiline: true
});
},

_attributeEditingCommitted: function(element, newText, oldText, attributeName, moveDirection)
{
delete this._editing;

function moveToNextAttributeIfNeeded(error)
{
if (error)
this._editingCancelled(element, attributeName);

if (!moveDirection)
return;

WebInspector.panels.elements.updateModifiedNodes();


var attributes = this.representedObject.attributes();
for (var i = 0; i < attributes.length; ++i) {
if (attributes[i].name !== attributeName)
continue;

if (moveDirection === "backward") {
if (i === 0)
this._startEditingTagName();
else
this._triggerEditAttribute(attributes[i - 1].name);
} else {
if (i === attributes.length - 1)
this._addNewAttribute();
else
this._triggerEditAttribute(attributes[i + 1].name);
}
return;
}


if (moveDirection === "backward") {
if (newText === " ") {

if (attributes.length > 0)
this._triggerEditAttribute(attributes[attributes.length - 1].name);
} else {

if (attributes.length > 1)
this._triggerEditAttribute(attributes[attributes.length - 2].name);
}
} else if (moveDirection === "forward") {
if (!/^\s*$/.test(newText))
this._addNewAttribute();
else
this._startEditingTagName();
}
}

this.representedObject.setAttribute(attributeName, newText, moveToNextAttributeIfNeeded.bind(this));
},

_tagNameEditingCommitted: function(element, newText, oldText, tagName, moveDirection)
{
delete this._editing;
var self = this;

function cancel()
{
var closingTagElement = self._distinctClosingTagElement();
if (closingTagElement)
closingTagElement.textContent = "</" + tagName + ">";

self._editingCancelled(element, tagName);
moveToNextAttributeIfNeeded.call(self);
}

function moveToNextAttributeIfNeeded()
{
if (moveDirection !== "forward") {
this._addNewAttribute();
return;
}

var attributes = this.representedObject.attributes();
if (attributes.length > 0)
this._triggerEditAttribute(attributes[0].name);
else
this._addNewAttribute();
}

newText = newText.trim();
if (newText === oldText) {
cancel();
return;
}

var treeOutline = this.treeOutline;
var wasExpanded = this.expanded;

function changeTagNameCallback(error, nodeId)
{
if (error || !nodeId) {
cancel();
return;
}


WebInspector.panels.elements.updateModifiedNodes();

WebInspector.updateFocusedNode(nodeId);
var newTreeItem = treeOutline.findTreeElement(WebInspector.domAgent.nodeForId(nodeId));
if (wasExpanded)
newTreeItem.expand();

moveToNextAttributeIfNeeded.call(newTreeItem);
}

this.representedObject.setNodeName(newText, changeTagNameCallback);
},

_textNodeEditingCommitted: function(element, newText)
{
delete this._editing;

var textNode;
if (this.representedObject.nodeType() === Node.ELEMENT_NODE) {


textNode = this.representedObject.firstChild;
} else if (this.representedObject.nodeType() == Node.TEXT_NODE)
textNode = this.representedObject;

textNode.setNodeValue(newText, this.updateTitle.bind(this));
},

_editingCancelled: function(element, context)
{
delete this._editing;


this.updateTitle();
},

_distinctClosingTagElement: function()
{




if (this.expanded) {
var closers = this._childrenListNode.querySelectorAll(".close");
return closers[closers.length-1];
}




var tags = this.listItemElement.getElementsByClassName("webkit-html-tag");
return (tags.length === 1 ? null : tags[tags.length-1]);
},

updateTitle: function(onlySearchQueryChanged)
{


if (this._editing)
return;

if (onlySearchQueryChanged) {
if (this._highlightResult)
this._updateSearchHighlight(false);
} else {
var highlightElement = document.createElement("span");
highlightElement.className = "highlight";
highlightElement.appendChild(this._nodeTitleInfo(WebInspector.linkifyURLAsNode).titleDOM);
this.title = highlightElement;
delete this._highlightResult;
}

delete this.selectionElement;
this.updateSelection();
this._preventFollowingLinksOnDoubleClick();
this._highlightSearchResults();
},

_buildAttributeDOM: function(parentElement, name, value, node, linkify)
{
var hasText = (value.length > 0);
var attrSpanElement = parentElement.createChild("span", "webkit-html-attribute");
var attrNameElement = attrSpanElement.createChild("span", "webkit-html-attribute-name");
attrNameElement.textContent = name.escapeHTML();

if (hasText)
attrSpanElement.appendChild(document.createTextNode("=\u200B\""));

if (linkify && (name === "src" || name === "href")) {
var rewrittenHref = WebInspector.resourceURLForRelatedNode(node, value);
value = value.replace(/([\/;:\)\]\}])/g, "$1\u200B");
attrSpanElement.appendChild(linkify(rewrittenHref, value, "webkit-html-attribute-value", node.nodeName().toLowerCase() === "a"));
} else {
value = value.escapeHTML().replace(/([\/;:\)\]\}])/g, "$1\u200B");
var attrValueElement = attrSpanElement.createChild("span", "webkit-html-attribute-value");
attrValueElement.textContent = value;
}

if (hasText)
attrSpanElement.appendChild(document.createTextNode("\""));
},

_buildTagDOM: function(parentElement, tagName, isClosingTag, isDistinctTreeElement, linkify)
{
var node = this.representedObject;
var classes = [ "webkit-html-tag" ];
if (isClosingTag && isDistinctTreeElement)
classes.push("close");
var tagElement = parentElement.createChild("span", classes.join(" "));
tagElement.appendChild(document.createTextNode("<"));
var tagNameElement = tagElement.createChild("span", isClosingTag ? "" : "webkit-html-tag-name");
tagNameElement.textContent = (isClosingTag ? "/" : "") + tagName;
if (!isClosingTag && node.hasAttributes()) {
var attributes = node.attributes();
for (var i = 0; i < attributes.length; ++i) {
var attr = attributes[i];
tagElement.appendChild(document.createTextNode(" "));
this._buildAttributeDOM(tagElement, attr.name, attr.value, node, linkify);
}
}
tagElement.appendChild(document.createTextNode(">"));
parentElement.appendChild(document.createTextNode("\u200B"));
},

_nodeTitleInfo: function(linkify)
{
var node = this.representedObject;
var info = {titleDOM: document.createDocumentFragment(), hasChildren: this.hasChildren};

switch (node.nodeType()) {
case Node.DOCUMENT_NODE:
info.titleDOM.appendChild(document.createTextNode("Document"));
break;

case Node.DOCUMENT_FRAGMENT_NODE:
info.titleDOM.appendChild(document.createTextNode("Document Fragment"));
break;

case Node.ATTRIBUTE_NODE:
var value = node.value || "\u200B"; 
this._buildAttributeDOM(info.titleDOM, node.name, value);
break;

case Node.ELEMENT_NODE:
var tagName = this.treeOutline.nodeNameToCorrectCase(node.nodeName()).escapeHTML();
if (this._elementCloseTag) {
this._buildTagDOM(info.titleDOM, tagName, true, true);
info.hasChildren = false;
break;
}

this._buildTagDOM(info.titleDOM, tagName, false, false, linkify);

var textChild = this._singleTextChild(node);
var showInlineText = textChild && textChild.nodeValue().length < Preferences.maxInlineTextChildLength;

if (!this.expanded && (!showInlineText && (this.treeOutline.isXMLMimeType || !WebInspector.ElementsTreeElement.ForbiddenClosingTagElements[tagName]))) {
if (this.hasChildren) {
var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node");
textNodeElement.textContent = "\u2026";
info.titleDOM.appendChild(document.createTextNode("\u200B"));
}
this._buildTagDOM(info.titleDOM, tagName, true, false, false);
}




if (showInlineText) {
var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node");
textNodeElement.textContent = textChild.nodeValue().escapeHTML();
info.titleDOM.appendChild(document.createTextNode("\u200B"));
this._buildTagDOM(info.titleDOM, tagName, true, false);
info.hasChildren = false;
}
break;

case Node.TEXT_NODE:
if (isNodeWhitespace.call(node))
info.titleDOM.appendChild(document.createTextNode("(whitespace)"));
else {
if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "script") {
var newNode = info.titleDOM.createChild("span", "webkit-html-text-node webkit-html-js-node");
newNode.textContent = node.nodeValue();

var javascriptSyntaxHighlighter = new WebInspector.DOMSyntaxHighlighter("text/javascript", true);
javascriptSyntaxHighlighter.syntaxHighlightNode(newNode);
} else if (node.parentNode && node.parentNode.nodeName().toLowerCase() === "style") {
var newNode = info.titleDOM.createChild("span", "webkit-html-text-node webkit-html-css-node");
newNode.textContent = node.nodeValue();

var cssSyntaxHighlighter = new WebInspector.DOMSyntaxHighlighter("text/css", true);
cssSyntaxHighlighter.syntaxHighlightNode(newNode);
} else {
info.titleDOM.appendChild(document.createTextNode("\""));
var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node");
textNodeElement.textContent = node.nodeValue().escapeHTML();
info.titleDOM.appendChild(document.createTextNode("\""));
}
}
break;

case Node.COMMENT_NODE:
var commentElement = info.titleDOM.createChild("span", "webkit-html-comment");
commentElement.appendChild(document.createTextNode("<!--" + node.nodeValue().escapeHTML() + "-->"));
break;

case Node.DOCUMENT_TYPE_NODE:
var docTypeElement = info.titleDOM.createChild("span", "webkit-html-doctype");
docTypeElement.appendChild(document.createTextNode("<!DOCTYPE " + node.nodeName()));
if (node.publicId) {
docTypeElement.appendChild(document.createTextNode(" PUBLIC \"" + node.publicId + "\""));
if (node.systemId)
docTypeElement.appendChild(document.createTextNode(" \"" + node.systemId + "\""));
} else if (node.systemId)
docTypeElement.appendChild(document.createTextNode(" SYSTEM \"" + node.systemId + "\""));

if (node.internalSubset)
docTypeElement.appendChild(document.createTextNode(" [" + node.internalSubset + "]"));

docTypeElement.appendChild(document.createTextNode(">"));
break;

case Node.CDATA_SECTION_NODE:
var cdataElement = info.titleDOM.createChild("span", "webkit-html-text-node");
cdataElement.appendChild(document.createTextNode("<![CDATA[" + node.nodeValue().escapeHTML() + "]]>"));
break;
default:
var defaultElement = info.titleDOM.appendChild(document.createTextNode(this.treeOutline.nodeNameToCorrectCase(node.nodeName()).collapseWhitespace().escapeHTML()));
}

return info;
},

_singleTextChild: function(node)
{
if (!node)
return null;

var firstChild = node.firstChild;
if (!firstChild || firstChild.nodeType() !== Node.TEXT_NODE)
return null;

var sibling = firstChild.nextSibling;
return sibling ? null : firstChild;
},

_showInlineText: function(node)
{
if (node.nodeType() === Node.ELEMENT_NODE) {
var textChild = this._singleTextChild(node);
if (textChild && textChild.nodeValue().length < Preferences.maxInlineTextChildLength)
return true;
}
return false;
},

remove: function()
{
var parentElement = this.parent;
if (!parentElement)
return;

var self = this;
function removeNodeCallback(error, removedNodeId)
{
if (error)
return;

parentElement.removeChild(self);
parentElement.adjustCollapsedRange(true);
}

this.representedObject.removeNode(removeNodeCallback);
},

_editAsHTML: function()
{
var treeOutline = this.treeOutline;
var node = this.representedObject;
var wasExpanded = this.expanded;

function selectNode(error, nodeId)
{
if (error || !nodeId)
return;


WebInspector.panels.elements.updateModifiedNodes();

WebInspector.updateFocusedNode(nodeId);
if (wasExpanded) {
var newTreeItem = treeOutline.findTreeElement(WebInspector.domAgent.nodeForId(nodeId));
if (newTreeItem)
newTreeItem.expand();
}
}

function commitChange(value)
{
node.setOuterHTML(value, selectNode);
}

node.getOuterHTML(this._startEditingAsHTML.bind(this, commitChange));
},

_copyHTML: function()
{
this.representedObject.copyNode();
},

_highlightSearchResults: function()
{
if (!this._searchQuery || !this._searchHighlightsVisible)
return;
if (this._highlightResult) {
this._updateSearchHighlight(true);
return;
}

var text = this.listItemElement.textContent;
var regexObject = createSearchRegex(this._searchQuery, "g");

var offset = 0;
var match = regexObject.exec(text);
var matchRanges = [];
while (match) {
matchRanges.push({ offset: match.index, length: match[0].length });
match = regexObject.exec(text);
}


if (!matchRanges.length)
matchRanges.push({ offset: 0, length: text.length });

this._highlightResult = [];
highlightSearchResults(this.listItemElement, matchRanges, this._highlightResult);
}
}

WebInspector.ElementsTreeElement.prototype.__proto__ = TreeElement.prototype;





WebInspector.SidebarSectionTreeElement = function(title, representedObject, hasChildren)
{
TreeElement.call(this, title.escapeHTML(), representedObject || {}, hasChildren);
}

WebInspector.SidebarSectionTreeElement.prototype = {
selectable: false,

get smallChildren()
{
return this._smallChildren;
},

set smallChildren(x)
{
if (this._smallChildren === x)
return;

this._smallChildren = x;

if (this._smallChildren)
this._childrenListNode.addStyleClass("small");
else
this._childrenListNode.removeStyleClass("small");
},

onattach: function()
{
this._listItemNode.addStyleClass("sidebar-tree-section");
},

onreveal: function()
{
if (this.listItemElement)
this.listItemElement.scrollIntoViewIfNeeded(false);
}
}

WebInspector.SidebarSectionTreeElement.prototype.__proto__ = TreeElement.prototype;

WebInspector.SidebarTreeElement = function(className, title, subtitle, representedObject, hasChildren)
{
TreeElement.call(this, "", representedObject || {}, hasChildren);

if (hasChildren) {
this.disclosureButton = document.createElement("button");
this.disclosureButton.className = "disclosure-button";
}

if (!this.iconElement) {
this.iconElement = document.createElement("img");
this.iconElement.className = "icon";
}

this.statusElement = document.createElement("div");
this.statusElement.className = "status";

this.titlesElement = document.createElement("div");
this.titlesElement.className = "titles";

this.titleElement = document.createElement("span");
this.titleElement.className = "title";
this.titlesElement.appendChild(this.titleElement);

this.subtitleElement = document.createElement("span");
this.subtitleElement.className = "subtitle";
this.titlesElement.appendChild(this.subtitleElement);

this.className = className;
this.mainTitle = title;
this.subtitle = subtitle;
}

WebInspector.SidebarTreeElement.prototype = {
get small()
{
return this._small;
},

set small(x)
{
this._small = x;

if (this._listItemNode) {
if (this._small)
this._listItemNode.addStyleClass("small");
else
this._listItemNode.removeStyleClass("small");
}
},

get mainTitle()
{
return this._mainTitle;
},

set mainTitle(x)
{
this._mainTitle = x;
this.refreshTitles();
},

get subtitle()
{
return this._subtitle;
},

set subtitle(x)
{
this._subtitle = x;
this.refreshTitles();
},

get bubbleText()
{
return this._bubbleText;
},

set bubbleText(x)
{
if (!this.bubbleElement) {
this.bubbleElement = document.createElement("div");
this.bubbleElement.className = "bubble";
this.statusElement.appendChild(this.bubbleElement);
}

this._bubbleText = x;
this.bubbleElement.textContent = x;
},

refreshTitles: function()
{
var mainTitle = this.mainTitle;
if (this.titleElement.textContent !== mainTitle)
this.titleElement.textContent = mainTitle;

var subtitle = this.subtitle;
if (subtitle) {
if (this.subtitleElement.textContent !== subtitle)
this.subtitleElement.textContent = subtitle;
this.titlesElement.removeStyleClass("no-subtitle");
} else {
this.subtitleElement.textContent = "";
this.titlesElement.addStyleClass("no-subtitle");
}
},

isEventWithinDisclosureTriangle: function(event)
{
return event.target === this.disclosureButton;
},

onattach: function()
{
this._listItemNode.addStyleClass("sidebar-tree-item");

if (this.className)
this._listItemNode.addStyleClass(this.className);

if (this.small)
this._listItemNode.addStyleClass("small");

if (this.hasChildren && this.disclosureButton)
this._listItemNode.appendChild(this.disclosureButton);

this._listItemNode.appendChild(this.iconElement);
this._listItemNode.appendChild(this.statusElement);
this._listItemNode.appendChild(this.titlesElement);
},

onreveal: function()
{
if (this._listItemNode)
this._listItemNode.scrollIntoViewIfNeeded(false);
}
}

WebInspector.SidebarTreeElement.prototype.__proto__ = TreeElement.prototype;





WebInspector.Section = function(title, subtitle)
{
this.element = document.createElement("div");
this.element.className = "section";
this.element._section = this;

this.headerElement = document.createElement("div");
this.headerElement.className = "header";

this.titleElement = document.createElement("div");
this.titleElement.className = "title";

this.subtitleElement = document.createElement("div");
this.subtitleElement.className = "subtitle";

this.headerElement.appendChild(this.subtitleElement);
this.headerElement.appendChild(this.titleElement);

this.headerElement.addEventListener("click", this.handleClick.bind(this), false);
this.element.appendChild(this.headerElement);

this.title = title;
this.subtitle = subtitle;
this._expanded = false;
}

WebInspector.Section.prototype = {
get title()
{
return this._title;
},

set title(x)
{
if (this._title === x)
return;
this._title = x;

if (x instanceof Node) {
this.titleElement.removeChildren();
this.titleElement.appendChild(x);
} else
this.titleElement.textContent = x;
},

get subtitle()
{
return this._subtitle;
},

set subtitle(x)
{
if (this._subtitle === x)
return;
this._subtitle = x;
this.subtitleElement.textContent = x;
},

get subtitleAsTextForTest()
{
var result = this.subtitleElement.textContent;
var child = this.subtitleElement.querySelector("[data-uncopyable]");
if (child) {
var linkData = child.getAttribute("data-uncopyable");
if (linkData)
result += linkData;
}
return result;
},

get expanded()
{
return this._expanded;
},

set expanded(x)
{
if (x)
this.expand();
else
this.collapse();
},

get populated()
{
return this._populated;
},

set populated(x)
{
this._populated = x;
if (!x && this.onpopulate && this._expanded) {
this.onpopulate(this);
this._populated = true;
}
},

get nextSibling()
{
var curElement = this.element;
do {
curElement = curElement.nextSibling;
} while (curElement && !curElement._section);

return curElement ? curElement._section : null;
},

get previousSibling()
{
var curElement = this.element;
do {
curElement = curElement.previousSibling;
} while (curElement && !curElement._section);

return curElement ? curElement._section : null;
},

expand: function()
{
if (this._expanded)
return;
this._expanded = true;
this.element.addStyleClass("expanded");

if (!this._populated && this.onpopulate) {
this.onpopulate(this);
this._populated = true;
}
},

collapse: function()
{
if (!this._expanded)
return;
this._expanded = false;
this.element.removeStyleClass("expanded");
},

toggleExpanded: function()
{
this.expanded = !this.expanded;
},

handleClick: function(e)
{
this.toggleExpanded();
e.stopPropagation();
}
}





WebInspector.PropertiesSection = function(title, subtitle)
{
WebInspector.Section.call(this, title, subtitle);

this.headerElement.addStyleClass("monospace");
this.propertiesElement = document.createElement("ol");
this.propertiesElement.className = "properties properties-tree monospace";
this.propertiesElement.tabIndex = 0;
this.propertiesTreeOutline = new TreeOutline(this.propertiesElement);
this.propertiesTreeOutline.section = this;

this.element.appendChild(this.propertiesElement);
}

WebInspector.PropertiesSection.prototype.__proto__ = WebInspector.Section.prototype;





WebInspector.RemoteObject = function(objectId, type, description, hasChildren)
{
this._objectId = objectId;
this._type = type;
this._description = description;
this._hasChildren = hasChildren;
}

WebInspector.RemoteObject.fromPrimitiveValue = function(value)
{
return new WebInspector.RemoteObject(null, typeof value, value);
}

WebInspector.RemoteObject.fromLocalObject = function(value)
{
return new WebInspector.LocalJSONObject(value);
}

WebInspector.RemoteObject.resolveNode = function(node, callback)
{
function mycallback(error, object)
{
if (!callback)
return;

if (error || !object)
callback(null);
else
callback(WebInspector.RemoteObject.fromPayload(object));
}
DOMAgent.resolveNode(node.id, mycallback);
}

WebInspector.RemoteObject.fromPayload = function(payload)
{
if (typeof payload === "object")
return new WebInspector.RemoteObject(payload.objectId, payload.type, payload.description, payload.hasChildren);

return payload;
}

WebInspector.RemoteObject.type = function(remoteObject)
{
if (remoteObject === null)
return "null";

var type = typeof remoteObject;
if (type !== "object" && type !== "function")
return type;

return remoteObject.type;
}

WebInspector.RemoteObject.prototype = {
get objectId()
{
return this._objectId;
},

get type()
{
return this._type;
},

get description()
{
return this._description;
},

get hasChildren()
{
return this._hasChildren;
},

isError: function()
{
return this._type === "error";
},

getOwnProperties: function(callback)
{
this._getProperties(false, callback);
},

getAllProperties: function(callback)
{
this._getProperties(true, callback);
},

_getProperties: function(ignoreHasOwnProperty, callback)
{
if (!this._objectId) {
callback([]);
return;
}
function remoteObjectBinder(error, properties)
{
if (error) {
callback(null);
return;
}
for (var i = 0; properties && i < properties.length; ++i)
properties[i].value = WebInspector.RemoteObject.fromPayload(properties[i].value);
callback(properties);
}
RuntimeAgent.getProperties(this._objectId, !!ignoreHasOwnProperty, remoteObjectBinder);
},

setPropertyValue: function(name, value, callback)
{
if (!this._objectId) {
callback("Can't get a property of non-object.");
return;
}
RuntimeAgent.setPropertyValue(this._objectId, name, value, callback);
},

pushNodeToFrontend: function(callback)
{
if (this._objectId)
WebInspector.domAgent.pushNodeToFrontend(this._objectId, callback);
else
callback(0);
},

evaluate: function(expression, callback)
{
RuntimeAgent.evaluateOn(this._objectId, expression, callback);
},

release: function()
{
RuntimeAgent.releaseObject(this._objectId);
}
}

WebInspector.RemoteObjectProperty = function(name, value)
{
this.name = name;
this.value = value;
}







WebInspector.LocalJSONObject = function(value)
{
this._value = value;
}

WebInspector.LocalJSONObject.prototype = {
get description()
{
if (this._cachedDescription)
return this._cachedDescription;

var type = this.type;

switch (type) {
case "array":
function formatArrayItem(property)
{
return property.value.description;
}
this._cachedDescription = this._concatenate("[", "]", formatArrayItem);
break;
case "object":
function formatObjectItem(property)
{
return property.name + ":" + property.value.description;
}
this._cachedDescription = this._concatenate("{", "}", formatObjectItem);
break;
default:
this._cachedDescription = String(this._value);
}
return this._cachedDescription;
},

_concatenate: function(prefix, suffix, formatProperty)
{
const previewChars = 100;

var buffer = prefix;
var children = this._children();
for (var i = 0; i < children.length; ++i) {
var itemDescription = formatProperty(children[i]);
if (buffer.length + itemDescription.length > previewChars) {
buffer += ",\u2026";
break;
}
if (i)
buffer += ", ";
buffer += itemDescription;
}
buffer += suffix;
return buffer;
},

get type()
{
if (this._value === null)
return "null";
if (this._value instanceof Array)
return "array";
return typeof this._value;
},

get hasChildren()
{
return typeof this._value === "object" && this._value !== null && Object.keys(this._value).length;
},

getOwnProperties: function(callback)
{
callback(this._children());
},

getAllProperties: function(callback)
{
callback(this._children());
},

_children: function()
{
function buildProperty(propName)
{
return new WebInspector.RemoteObjectProperty(propName, new WebInspector.LocalJSONObject(this._value[propName]));
}
if (!this._cachedChildren)
this._cachedChildren = Object.keys(this._value).map(buildProperty.bind(this));
return this._cachedChildren;
},

isError: function()
{
return false;
}
}





WebInspector.ObjectPropertiesSection = function(object, title, subtitle, emptyPlaceholder, ignoreHasOwnProperty, extraProperties, treeElementConstructor)
{
this.emptyPlaceholder = (emptyPlaceholder || WebInspector.UIString("No Properties"));
this.object = object;
this.ignoreHasOwnProperty = ignoreHasOwnProperty;
this.extraProperties = extraProperties;
this.treeElementConstructor = treeElementConstructor || WebInspector.ObjectPropertyTreeElement;
this.editable = true;

WebInspector.PropertiesSection.call(this, title, subtitle);
}

WebInspector.ObjectPropertiesSection.prototype = {
onpopulate: function()
{
this.update();
},

update: function()
{
var self = this;
function callback(properties)
{
if (!properties)
return;
self.updateProperties(properties);
}
if (this.ignoreHasOwnProperty)
this.object.getAllProperties(callback);
else
this.object.getOwnProperties(callback);
},

updateProperties: function(properties, rootTreeElementConstructor, rootPropertyComparer)
{
if (!rootTreeElementConstructor)
rootTreeElementConstructor = this.treeElementConstructor;

if (!rootPropertyComparer)
rootPropertyComparer = WebInspector.ObjectPropertiesSection.CompareProperties;

if (this.extraProperties)
for (var i = 0; i < this.extraProperties.length; ++i)
properties.push(this.extraProperties[i]);

properties.sort(rootPropertyComparer);

this.propertiesTreeOutline.removeChildren();

for (var i = 0; i < properties.length; ++i) {
properties[i].parentObject = this.object;
this.propertiesTreeOutline.appendChild(new rootTreeElementConstructor(properties[i]));
}

if (!this.propertiesTreeOutline.children.length) {
var title = "<div class=\"info\">" + this.emptyPlaceholder + "</div>";
var infoElement = new TreeElement(null, null, false);
infoElement.titleHTML = title;
this.propertiesTreeOutline.appendChild(infoElement);
}
this.propertiesForTest = properties;
}
}

WebInspector.ObjectPropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;

WebInspector.ObjectPropertiesSection.CompareProperties = function(propertyA, propertyB) 
{
var a = propertyA.name;
var b = propertyB.name;
if (a === "__proto__")
return 1;
if (b === "__proto__")
return -1;





var diff = 0;
var chunk = /^\d+|^\D+/;
var chunka, chunkb, anum, bnum;
while (diff === 0) {
if (!a && b)
return -1;
if (!b && a)
return 1;
chunka = a.match(chunk)[0];
chunkb = b.match(chunk)[0];
anum = !isNaN(chunka);
bnum = !isNaN(chunkb);
if (anum && !bnum)
return -1;
if (bnum && !anum)
return 1;
if (anum && bnum) {
diff = chunka - chunkb;
if (diff === 0 && chunka.length !== chunkb.length) {
if (!+chunka && !+chunkb) 
return chunka.length - chunkb.length;
else
return chunkb.length - chunka.length;
}
} else if (chunka !== chunkb)
return (chunka < chunkb) ? -1 : 1;
a = a.substring(chunka.length);
b = b.substring(chunkb.length);
}
return diff;
}

WebInspector.ObjectPropertyTreeElement = function(property)
{
this.property = property;


TreeElement.call(this, "", null, false);
}

WebInspector.ObjectPropertyTreeElement.prototype = {
onpopulate: function()
{
if (this.children.length && !this.shouldRefreshChildren)
return;

var callback = function(properties) {
this.removeChildren();
if (!properties)
return;

properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties);
for (var i = 0; i < properties.length; ++i) {
this.appendChild(new this.treeOutline.section.treeElementConstructor(properties[i]));
}
};
this.property.value.getOwnProperties(callback.bind(this));
},

ondblclick: function(event)
{
this.startEditing();
},

onattach: function()
{
this.update();
},

update: function()
{
this.nameElement = document.createElement("span");
this.nameElement.className = "name";
this.nameElement.textContent = this.property.name;

var separatorElement = document.createElement("span");
separatorElement.className = "separator";
separatorElement.textContent = ": ";

this.valueElement = document.createElement("span");
this.valueElement.className = "value";

var description = this.property.value.description;

if (this.property.wasThrown)
this.valueElement.textContent = "[Exception: " + description + "]";
else if (this.property.value.type === "string" && typeof description === "string") {
this.valueElement.textContent = "\"" + description.replace(/\n/g, "\u21B5") + "\"";
this.valueElement._originalTextContent = "\"" + description + "\"";
} else if (this.property.value.type === "function" && typeof description === "string") {
this.valueElement.textContent = /.*/.exec(description)[0].replace(/ +$/g, "");
this.valueElement._originalTextContent = description;
} else
this.valueElement.textContent = description;

if (this.property.isGetter)
this.valueElement.addStyleClass("dimmed");
if (this.property.wasThrown)
this.valueElement.addStyleClass("error");
if (this.property.value.type)
this.valueElement.addStyleClass("console-formatted-" + this.property.value.type);
if (this.property.value.type === "node")
this.valueElement.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), false);

this.listItemElement.removeChildren();

this.listItemElement.appendChild(this.nameElement);
this.listItemElement.appendChild(separatorElement);
this.listItemElement.appendChild(this.valueElement);
this.hasChildren = this.property.value.hasChildren && !this.property.wasThrown;
},

_contextMenuEventFired: function()
{
function selectNode(nodeId)
{
if (nodeId) {
WebInspector.panels.elements.switchToAndFocus(WebInspector.domAgent.nodeForId(nodeId));
}
}

function revealElement()
{
this.property.value.pushNodeToFrontend(selectNode);
}

var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendItem(WebInspector.UIString("Reveal in Elements Panel"), revealElement.bind(this));
contextMenu.show(event);
},

updateSiblings: function()
{
if (this.parent.root)
this.treeOutline.section.update();
else
this.parent.shouldRefreshChildren = true;
},

startEditing: function()
{
if (WebInspector.isBeingEdited(this.valueElement) || !this.treeOutline.section.editable)
return;

var context = { expanded: this.expanded };


this.hasChildren = false;

this.listItemElement.addStyleClass("editing-sub-part");


if (typeof this.valueElement._originalTextContent === "string")
this.valueElement.textContent = this.valueElement._originalTextContent;

WebInspector.startEditing(this.valueElement, {
context: context,
commitHandler: this.editingCommitted.bind(this),
cancelHandler: this.editingCancelled.bind(this)
});
},

editingEnded: function(context)
{
this.listItemElement.scrollLeft = 0;
this.listItemElement.removeStyleClass("editing-sub-part");
if (context.expanded)
this.expand();
},

editingCancelled: function(element, context)
{
this.update();
this.editingEnded(context);
},

editingCommitted: function(element, userInput, previousContent, context)
{
if (userInput === previousContent)
return this.editingCancelled(element, context); 

this.applyExpression(userInput, true);

this.editingEnded(context);
},

applyExpression: function(expression, updateInterface)
{
expression = expression.trim();
var expressionLength = expression.length;
function callback(error)
{
if (!updateInterface)
return;

if (error)
this.update();

if (!expressionLength) {

this.parent.removeChild(this);
} else {

this.updateSiblings();
}
};
this.property.parentObject.setPropertyValue(this.property.name, expression.trim(), callback.bind(this));
}
}

WebInspector.ObjectPropertyTreeElement.prototype.__proto__ = TreeElement.prototype;





WebInspector.JavaScriptBreakpointsSidebarPane = function(model, showSourceLineDelegate)
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints"));

this._model = model;
this._showSourceLineDelegate = showSourceLineDelegate;

this.listElement = document.createElement("ol");
this.listElement.className = "breakpoint-list";

this.emptyElement = document.createElement("div");
this.emptyElement.className = "info";
this.emptyElement.textContent = WebInspector.UIString("No Breakpoints");

this.bodyElement.appendChild(this.emptyElement);

this._items = {};
}

WebInspector.JavaScriptBreakpointsSidebarPane.prototype = {
addBreakpoint: function(breakpoint)
{
var element = document.createElement("li");
element.addStyleClass("cursor-pointer");
element.addEventListener("contextmenu", this._contextMenu.bind(this, breakpoint), true);
element.addEventListener("click", this._breakpointClicked.bind(this, breakpoint), false);

var checkbox = document.createElement("input");
checkbox.className = "checkbox-elem";
checkbox.type = "checkbox";
checkbox.checked = breakpoint.enabled;
checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(this, breakpoint), false);
element.appendChild(checkbox);

var displayName = breakpoint.url ? WebInspector.displayNameForURL(breakpoint.url) : WebInspector.UIString("(program)");
var labelElement = document.createTextNode(displayName + ":" + (breakpoint.lineNumber + 1));
element.appendChild(labelElement);

var snippetElement = document.createElement("div");
snippetElement.className = "source-text monospace";
element.appendChild(snippetElement);
if (breakpoint.loadSnippet) {
function didLoadSnippet(snippet)
{
snippetElement.textContent = snippet;
}
breakpoint.loadSnippet(didLoadSnippet);
}

element._data = breakpoint;
var currentElement = this.listElement.firstChild;
while (currentElement) {
if (currentElement._data && this._compareBreakpoints(currentElement._data, element._data) > 0)
break;
currentElement = currentElement.nextSibling;
}
this._addListElement(element, currentElement);

var breakpointItem = {};
breakpointItem.element = element;
breakpointItem.checkbox = checkbox;
this._items[this._createBreakpointItemId(breakpoint.sourceFileId, breakpoint.lineNumber)] = breakpointItem;

if (!this.expanded)
this.expanded = true;
},

removeBreakpoint: function(sourceFileId, lineNumber)
{
var breakpointItemId = this._createBreakpointItemId(sourceFileId, lineNumber);
var breakpointItem = this._items[breakpointItemId];
if (!breakpointItem)
return;
delete this._items[breakpointItemId];
this._removeListElement(breakpointItem.element);
},

highlightBreakpoint: function(sourceFileId, lineNumber)
{
var breakpointItem = this._items[this._createBreakpointItemId(sourceFileId, lineNumber)];
if (!breakpointItem)
return;
breakpointItem.element.addStyleClass("breakpoint-hit");
this._highlightedBreakpointItem = breakpointItem;
},

clearBreakpointHighlight: function()
{
if (this._highlightedBreakpointItem) {
this._highlightedBreakpointItem.element.removeStyleClass("breakpoint-hit");
delete this._highlightedBreakpointItem;
}
},

_createBreakpointItemId: function(sourceFileId, lineNumber)
{
return sourceFileId + ":" + lineNumber;
},

_breakpointClicked: function(breakpoint, event)
{
this._showSourceLineDelegate(breakpoint.sourceFileId, breakpoint.lineNumber);
},

_breakpointCheckboxClicked: function(breakpoint, event)
{

event.stopPropagation();

this._model.setBreakpointEnabled(breakpoint.sourceFileId, breakpoint.lineNumber, event.target.checked);
},

_contextMenu: function(breakpoint, event)
{
var contextMenu = new WebInspector.ContextMenu();

var removeHandler = this._model.removeBreakpoint.bind(this._model, breakpoint.sourceFileId, breakpoint.lineNumber);
contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), removeHandler);

contextMenu.show(event);
},

_addListElement: function(element, beforeElement)
{
if (beforeElement)
this.listElement.insertBefore(element, beforeElement);
else {
if (!this.listElement.firstChild) {
this.bodyElement.removeChild(this.emptyElement);
this.bodyElement.appendChild(this.listElement);
}
this.listElement.appendChild(element);
}
},

_removeListElement: function(element)
{
this.listElement.removeChild(element);
if (!this.listElement.firstChild) {
this.bodyElement.removeChild(this.listElement);
this.bodyElement.appendChild(this.emptyElement);
}
},

_compare: function(x, y)
{
if (x !== y)
return x < y ? -1 : 1;
return 0;
},

_compareBreakpoints: function(b1, b2)
{
return this._compare(b1.url, b2.url) || this._compare(b1.lineNumber, b2.lineNumber);
},

reset: function()
{
this.listElement.removeChildren();
if (this.listElement.parentElement) {
this.bodyElement.removeChild(this.listElement);
this.bodyElement.appendChild(this.emptyElement);
}
this._items = {};
}
}

WebInspector.JavaScriptBreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;

WebInspector.NativeBreakpointsSidebarPane = function(title)
{
WebInspector.SidebarPane.call(this, title);

this.listElement = document.createElement("ol");
this.listElement.className = "breakpoint-list";

this.emptyElement = document.createElement("div");
this.emptyElement.className = "info";
this.emptyElement.textContent = WebInspector.UIString("No Breakpoints");

this.bodyElement.appendChild(this.emptyElement);
}

WebInspector.NativeBreakpointsSidebarPane.prototype = {
_addListElement: function(element, beforeElement)
{
if (beforeElement)
this.listElement.insertBefore(element, beforeElement);
else {
if (!this.listElement.firstChild) {
this.bodyElement.removeChild(this.emptyElement);
this.bodyElement.appendChild(this.listElement);
}
this.listElement.appendChild(element);
}
},

_removeListElement: function(element)
{
this.listElement.removeChild(element);
if (!this.listElement.firstChild) {
this.bodyElement.removeChild(this.listElement);
this.bodyElement.appendChild(this.emptyElement);
}
},

_reset: function()
{
this.listElement.removeChildren();
if (this.listElement.parentElement) {
this.bodyElement.removeChild(this.listElement);
this.bodyElement.appendChild(this.emptyElement);
}
}
}

WebInspector.NativeBreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;

WebInspector.XHRBreakpointsSidebarPane = function()
{
WebInspector.NativeBreakpointsSidebarPane.call(this, WebInspector.UIString("XHR Breakpoints"));

this._breakpointElements = {};

var addButton = document.createElement("button");
addButton.className = "pane-title-button add";
addButton.addEventListener("click", this._addButtonClicked.bind(this), false);
this.titleElement.appendChild(addButton);

this._restoreBreakpoints();
}

WebInspector.XHRBreakpointsSidebarPane.prototype = {
_addButtonClicked: function(event)
{
event.stopPropagation();

this.expanded = true;

var inputElementContainer = document.createElement("p");
inputElementContainer.className = "breakpoint-condition";
var inputElement = document.createElement("span");
inputElementContainer.textContent = WebInspector.UIString("Break when URL contains:");
inputElement.className = "editing";
inputElement.id = "breakpoint-condition-input";
inputElementContainer.appendChild(inputElement);
this._addListElement(inputElementContainer, this.listElement.firstChild);

function finishEditing(accept, e, text)
{
this._removeListElement(inputElementContainer);
if (accept) {
this._setBreakpoint(text, true);
this._saveBreakpoints();
}
}

WebInspector.startEditing(inputElement, {
commitHandler: finishEditing.bind(this, true),
cancelHandler: finishEditing.bind(this, false)
});
},

_setBreakpoint: function(url, enabled)
{
if (url in this._breakpointElements)
return;

var element = document.createElement("li");
element._url = url;
element.addEventListener("contextmenu", this._contextMenu.bind(this, url), true);

var checkboxElement = document.createElement("input");
checkboxElement.className = "checkbox-elem";
checkboxElement.type = "checkbox";
checkboxElement.checked = enabled;
checkboxElement.addEventListener("click", this._checkboxClicked.bind(this, url), false);
element._checkboxElement = checkboxElement;
element.appendChild(checkboxElement);

var labelElement = document.createElement("span");
if (!url)
labelElement.textContent = WebInspector.UIString("Any XHR");
else
labelElement.textContent = WebInspector.UIString("URL contains \"%s\"", url);
labelElement.addStyleClass("cursor-auto");
labelElement.addEventListener("dblclick", this._labelClicked.bind(this, url), false);
element.appendChild(labelElement);

var currentElement = this.listElement.firstChild;
while (currentElement) {
if (currentElement._url && currentElement._url < element._url)
break;
currentElement = currentElement.nextSibling;
}
this._addListElement(element, currentElement);
this._breakpointElements[url] = element;
if (enabled)
DOMDebuggerAgent.setXHRBreakpoint(url);
},

_removeBreakpoint: function(url)
{
var element = this._breakpointElements[url];
if (!element)
return;

this._removeListElement(element);
delete this._breakpointElements[url];
if (element._checkboxElement.checked)
DOMDebuggerAgent.removeXHRBreakpoint(url);
},

_contextMenu: function(url, event)
{
var contextMenu = new WebInspector.ContextMenu();
function removeBreakpoint()
{
this._removeBreakpoint(url);
this._saveBreakpoints();
}
contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), removeBreakpoint.bind(this));
contextMenu.show(event);
},

_checkboxClicked: function(url, event)
{
if (event.target.checked)
DOMDebuggerAgent.setXHRBreakpoint(url);
else
DOMDebuggerAgent.removeXHRBreakpoint(url);
this._saveBreakpoints();
},

_labelClicked: function(url)
{
var element = this._breakpointElements[url];
var inputElement = document.createElement("span");
inputElement.className = "breakpoint-condition editing";
inputElement.textContent = url;
this.listElement.insertBefore(inputElement, element);
element.addStyleClass("hidden");

function finishEditing(accept, e, text)
{
this._removeListElement(inputElement);
if (accept) {
this._removeBreakpoint(url);
this._setBreakpoint(text, element._checkboxElement.checked);
this._saveBreakpoints();
} else
element.removeStyleClass("hidden");
}

WebInspector.startEditing(inputElement, {
commitHandler: finishEditing.bind(this, true),
cancelHandler: finishEditing.bind(this, false)
});
},

highlightBreakpoint: function(url)
{
var element = this._breakpointElements[url];
if (!element)
return;
this.expanded = true;
element.addStyleClass("breakpoint-hit");
this._highlightedElement = element;
},

clearBreakpointHighlight: function()
{
if (this._highlightedElement) {
this._highlightedElement.removeStyleClass("breakpoint-hit");
delete this._highlightedElement;
}
},

_saveBreakpoints: function()
{
var breakpoints = [];
for (var url in this._breakpointElements)
breakpoints.push({ url: url, enabled: this._breakpointElements[url]._checkboxElement.checked });
WebInspector.settings.xhrBreakpoints = breakpoints;
},

_restoreBreakpoints: function()
{
var breakpoints = WebInspector.settings.xhrBreakpoints;
for (var i = 0; i < breakpoints.length; ++i) {
var breakpoint = breakpoints[i];
if (breakpoint && typeof breakpoint.url === "string")
this._setBreakpoint(breakpoint.url, breakpoint.enabled);
}
}
}

WebInspector.XHRBreakpointsSidebarPane.prototype.__proto__ = WebInspector.NativeBreakpointsSidebarPane.prototype;

WebInspector.EventListenerBreakpointsSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listener Breakpoints"));

this.categoriesElement = document.createElement("ol");
this.categoriesElement.tabIndex = 0;
this.categoriesElement.addStyleClass("properties-tree");
this.categoriesElement.addStyleClass("event-listener-breakpoints");
this.categoriesTreeOutline = new TreeOutline(this.categoriesElement);
this.bodyElement.appendChild(this.categoriesElement);

this._breakpointItems = {};
this._createCategory(WebInspector.UIString("Keyboard"), "listener", ["keydown", "keyup", "keypress", "textInput"]);
this._createCategory(WebInspector.UIString("Mouse"), "listener", ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mousemove", "mouseout", "mousewheel"]);



this._createCategory(WebInspector.UIString("Control"), "listener", ["resize", "scroll", "zoom", "focus", "blur", "select", "change", "submit", "reset"]);
this._createCategory(WebInspector.UIString("Clipboard"), "listener", ["copy", "cut", "paste", "beforecopy", "beforecut", "beforepaste"]);
this._createCategory(WebInspector.UIString("Load"), "listener", ["load", "unload", "abort", "error"]);
this._createCategory(WebInspector.UIString("DOM Mutation"), "listener", ["DOMActivate", "DOMFocusIn", "DOMFocusOut", "DOMAttrModified", "DOMCharacterDataModified", "DOMNodeInserted", "DOMNodeInsertedIntoDocument", "DOMNodeRemoved", "DOMNodeRemovedFromDocument", "DOMSubtreeModified", "DOMContentLoaded"]);
this._createCategory(WebInspector.UIString("Device"), "listener", ["deviceorientation", "devicemotion"]);
this._createCategory(WebInspector.UIString("Timer"), "instrumentation", ["setTimer", "clearTimer", "timerFired"]);

this._restoreBreakpoints();
}

WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI = function(eventName)
{
if (!WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI) {
WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI = {
"instrumentation:setTimer": WebInspector.UIString("Set Timer"),
"instrumentation:clearTimer": WebInspector.UIString("Clear Timer"),
"instrumentation:timerFired": WebInspector.UIString("Timer Fired")
};
}
return WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI[eventName] || eventName.substring(eventName.indexOf(":") + 1);
}

WebInspector.EventListenerBreakpointsSidebarPane.prototype = {
_createCategory: function(name, type, eventNames)
{
var categoryItem = {};
categoryItem.element = new TreeElement(name);
this.categoriesTreeOutline.appendChild(categoryItem.element);
categoryItem.element.listItemElement.addStyleClass("event-category");
categoryItem.element.selectable = true;

categoryItem.checkbox = this._createCheckbox(categoryItem.element);
categoryItem.checkbox.addEventListener("click", this._categoryCheckboxClicked.bind(this, categoryItem), true);

categoryItem.children = {};
for (var i = 0; i < eventNames.length; ++i) {
var eventName = type + ":" + eventNames[i];

var breakpointItem = {};
var title = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName);
breakpointItem.element = new TreeElement(title);
categoryItem.element.appendChild(breakpointItem.element);
var hitMarker = document.createElement("div");
hitMarker.className = "breakpoint-hit-marker";
breakpointItem.element.listItemElement.appendChild(hitMarker);
breakpointItem.element.listItemElement.addStyleClass("source-code");
breakpointItem.element.selectable = true;

breakpointItem.checkbox = this._createCheckbox(breakpointItem.element);
breakpointItem.checkbox.addEventListener("click", this._breakpointCheckboxClicked.bind(this, eventName), true);
breakpointItem.parent = categoryItem;

this._breakpointItems[eventName] = breakpointItem;
categoryItem.children[eventName] = breakpointItem;
}
},

_createCheckbox: function(treeElement)
{
var checkbox = document.createElement("input");
checkbox.className = "checkbox-elem";
checkbox.type = "checkbox";
treeElement.listItemElement.insertBefore(checkbox, treeElement.listItemElement.firstChild);
return checkbox;
},

_categoryCheckboxClicked: function(categoryItem)
{
var checked = categoryItem.checkbox.checked;
for (var eventName in categoryItem.children) {
var breakpointItem = categoryItem.children[eventName];
if (breakpointItem.checkbox.checked === checked)
continue;
if (checked)
this._setBreakpoint(eventName);
else
this._removeBreakpoint(eventName);
}
this._saveBreakpoints();
},

_breakpointCheckboxClicked: function(eventName, event)
{
if (event.target.checked)
this._setBreakpoint(eventName);
else
this._removeBreakpoint(eventName);
this._saveBreakpoints();
},

_setBreakpoint: function(eventName)
{
var breakpointItem = this._breakpointItems[eventName];
if (!breakpointItem)
return;
breakpointItem.checkbox.checked = true;
DOMDebuggerAgent.setEventListenerBreakpoint(eventName);
this._updateCategoryCheckbox(breakpointItem.parent);
},

_removeBreakpoint: function(eventName)
{
var breakpointItem = this._breakpointItems[eventName];
if (!breakpointItem)
return;
breakpointItem.checkbox.checked = false;
DOMDebuggerAgent.removeEventListenerBreakpoint(eventName);
this._updateCategoryCheckbox(breakpointItem.parent);
},

_updateCategoryCheckbox: function(categoryItem)
{
var hasEnabled = false, hasDisabled = false;
for (var eventName in categoryItem.children) {
var breakpointItem = categoryItem.children[eventName];
if (breakpointItem.checkbox.checked)
hasEnabled = true;
else
hasDisabled = true;
}
categoryItem.checkbox.checked = hasEnabled;
categoryItem.checkbox.indeterminate = hasEnabled && hasDisabled;
},

highlightBreakpoint: function(eventName)
{
var breakpointItem = this._breakpointItems[eventName];
if (!breakpointItem)
return;
this.expanded = true;
breakpointItem.parent.element.expand();
breakpointItem.element.listItemElement.addStyleClass("breakpoint-hit");
this._highlightedElement = breakpointItem.element.listItemElement;
},

clearBreakpointHighlight: function()
{
if (this._highlightedElement) {
this._highlightedElement.removeStyleClass("breakpoint-hit");
delete this._highlightedElement;
}
},

_saveBreakpoints: function()
{
var breakpoints = [];
for (var eventName in this._breakpointItems) {
if (this._breakpointItems[eventName].checkbox.checked)
breakpoints.push({ eventName: eventName });
}
WebInspector.settings.eventListenerBreakpoints = breakpoints;
},

_restoreBreakpoints: function()
{
var breakpoints = WebInspector.settings.eventListenerBreakpoints;
for (var i = 0; i < breakpoints.length; ++i) {
var breakpoint = breakpoints[i];
if (breakpoint && typeof breakpoint.eventName === "string")
this._setBreakpoint(breakpoint.eventName);
}
}
}

WebInspector.EventListenerBreakpointsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;





WebInspector.DOMBreakpointsSidebarPane = function()
{
WebInspector.NativeBreakpointsSidebarPane.call(this, WebInspector.UIString("DOM Breakpoints"));

this._breakpointElements = {};

this._breakpointTypes = {
SubtreeModified: 0,
AttributeModified: 1,
NodeRemoved: 2
};
this._breakpointTypeLabels = [
WebInspector.UIString("Subtree Modified"),
WebInspector.UIString("Attribute Modified"),
WebInspector.UIString("Node Removed")
];
this._contextMenuLabels = [
WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Break on subtree modifications" : "Break on Subtree Modifications"),
WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Break on attributes modifications" : "Break on Attributes Modifications"),
WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Break on node removal" : "Break on Node Removal")
];
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, this._inspectedURLChanged, this);
}

WebInspector.DOMBreakpointsSidebarPane.prototype = {
_inspectedURLChanged: function(event)
{
this._reset();
var url = event.data;
this._inspectedURL = url.removeURLFragment();
},

populateNodeContextMenu: function(node, contextMenu)
{
var nodeBreakpoints = {};
for (var id in this._breakpointElements) {
var element = this._breakpointElements[id];
if (element._node === node)
nodeBreakpoints[element._type] = true;
}

function toggleBreakpoint(type)
{
if (!nodeBreakpoints[type])
this._setBreakpoint(node, type, true);
else
this._removeBreakpoint(node, type);
this._saveBreakpoints();
}

for (var type = 0; type < 3; ++type) {
var label = this._contextMenuLabels[type];
contextMenu.appendCheckboxItem(label, toggleBreakpoint.bind(this, type), nodeBreakpoints[type]);
}
},

createBreakpointHitStatusMessage: function(eventData, callback)
{
if (eventData.type === this._breakpointTypes.SubtreeModified) {
var targetNodeObject = WebInspector.RemoteObject.fromPayload(eventData.targetNode);
function didPushNodeToFrontend(targetNodeId)
{
if (targetNodeId)
targetNodeObject.release();
this._doCreateBreakpointHitStatusMessage(eventData, targetNodeId, callback);
}
targetNodeObject.pushNodeToFrontend(didPushNodeToFrontend.bind(this));
} else
this._doCreateBreakpointHitStatusMessage(eventData, null, callback);
},

_doCreateBreakpointHitStatusMessage: function (eventData, targetNodeId, callback)
{
var message;
var typeLabel = this._breakpointTypeLabels[eventData.type];
var linkifiedNode = WebInspector.panels.elements.linkifyNodeById(eventData.nodeId);
var substitutions = [typeLabel, linkifiedNode];
var targetNode = "";
if (targetNodeId)
targetNode = WebInspector.panels.elements.linkifyNodeById(targetNodeId);

if (eventData.type === this._breakpointTypes.SubtreeModified) {
if (eventData.insertion) {
if (targetNodeId !== eventData.nodeId) {
message = "Paused on a \"%s\" breakpoint set on %s, because a new child was added to its descendant %s.";
substitutions.push(targetNode);
} else
message = "Paused on a \"%s\" breakpoint set on %s, because a new child was added to that node.";
} else {
message = "Paused on a \"%s\" breakpoint set on %s, because its descendant %s was removed.";
substitutions.push(targetNode);
}
} else
message = "Paused on a \"%s\" breakpoint set on %s.";

var element = document.createElement("span");
var formatters = {
s: function(substitution)
{
return substitution;
}
};
function append(a, b)
{
if (typeof b === "string")
b = document.createTextNode(b);
element.appendChild(b);
}
WebInspector.formatLocalized(message, substitutions, formatters, "", append);

callback(element);
},

nodeRemoved: function(node)
{
this._removeBreakpointsForNode(node);
if (!node.children)
return;
for (var i = 0; i < node.children.length; ++i)
this._removeBreakpointsForNode(node.children[i]);
this._saveBreakpoints();
},

_removeBreakpointsForNode: function(node)
{
for (var id in this._breakpointElements) {
var element = this._breakpointElements[id];
if (element._node === node)
this._removeBreakpoint(element._node, element._type);
}
},

_setBreakpoint: function(node, type, enabled)
{
var breakpointId = this._createBreakpointId(node.id, type);
if (breakpointId in this._breakpointElements)
return;

var element = document.createElement("li");
element._node = node;
element._type = type;
element.addEventListener("contextmenu", this._contextMenu.bind(this, node, type), true);

var checkboxElement = document.createElement("input");
checkboxElement.className = "checkbox-elem";
checkboxElement.type = "checkbox";
checkboxElement.checked = enabled;
checkboxElement.addEventListener("click", this._checkboxClicked.bind(this, node, type), false);
element._checkboxElement = checkboxElement;
element.appendChild(checkboxElement);

var labelElement = document.createElement("span");
element.appendChild(labelElement);

var linkifiedNode = WebInspector.panels.elements.linkifyNodeById(node.id);
linkifiedNode.addStyleClass("monospace");
labelElement.appendChild(linkifiedNode);

var description = document.createElement("div");
description.className = "source-text";
description.textContent = this._breakpointTypeLabels[type];
labelElement.appendChild(description);

var currentElement = this.listElement.firstChild;
while (currentElement) {
if (currentElement._type && currentElement._type < element._type)
break;
currentElement = currentElement.nextSibling;
}
this._addListElement(element, currentElement);
this._breakpointElements[breakpointId] = element;
if (enabled)
DOMDebuggerAgent.setDOMBreakpoint(node.id, type);
},

_removeBreakpoint: function(node, type)
{
var breakpointId = this._createBreakpointId(node.id, type);
var element = this._breakpointElements[breakpointId];
if (!element)
return;

this._removeListElement(element);
delete this._breakpointElements[breakpointId];
if (element._checkboxElement.checked)
DOMDebuggerAgent.removeDOMBreakpoint(node.id, type);
},

_contextMenu: function(node, type, event)
{
var contextMenu = new WebInspector.ContextMenu();
function removeBreakpoint()
{
this._removeBreakpoint(node, type);
this._saveBreakpoints();
}
contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), removeBreakpoint.bind(this));
contextMenu.show(event);
},

_checkboxClicked: function(node, type, event)
{
if (event.target.checked)
DOMDebuggerAgent.setDOMBreakpoint(node.id, type);
else
DOMDebuggerAgent.removeDOMBreakpoint(node.id, type);
this._saveBreakpoints();
},

highlightBreakpoint: function(eventData)
{
var breakpointId = this._createBreakpointId(eventData.nodeId, eventData.type);
var element = this._breakpointElements[breakpointId];
if (!element)
return;
this.expanded = true;
element.addStyleClass("breakpoint-hit");
this._highlightedElement = element;
},

clearBreakpointHighlight: function()
{
if (this._highlightedElement) {
this._highlightedElement.removeStyleClass("breakpoint-hit");
delete this._highlightedElement;
}
},

_createBreakpointId: function(nodeId, type)
{
return nodeId + ":" + type;
},

_saveBreakpoints: function()
{
var breakpoints = [];
var storedBreakpoints = WebInspector.settings.domBreakpoints;
for (var i = 0; i < storedBreakpoints.length; ++i) {
var breakpoint = storedBreakpoints[i];
if (breakpoint.url !== this._inspectedURL)
breakpoints.push(breakpoint);
}
for (var id in this._breakpointElements) {
var element = this._breakpointElements[id];
breakpoints.push({ url: this._inspectedURL, path: element._node.path(), type: element._type, enabled: element._checkboxElement.checked });
}
WebInspector.settings.domBreakpoints = breakpoints;
},

restoreBreakpoints: function()
{
var pathToBreakpoints = {};

function didPushNodeByPathToFrontend(path, nodeId)
{
var node = WebInspector.domAgent.nodeForId(nodeId);
if (!node)
return;

var breakpoints = pathToBreakpoints[path];
for (var i = 0; i < breakpoints.length; ++i)
this._setBreakpoint(node, breakpoints[i].type, breakpoints[i].enabled);
}

var breakpoints = WebInspector.settings.domBreakpoints;
for (var i = 0; i < breakpoints.length; ++i) {
var breakpoint = breakpoints[i];
if (breakpoint.url !== this._inspectedURL)
continue;
var path = breakpoint.path;
if (!pathToBreakpoints[path]) {
pathToBreakpoints[path] = [];
WebInspector.domAgent.pushNodeByPathToFrontend(path, didPushNodeByPathToFrontend.bind(this, path));
}
pathToBreakpoints[path].push(breakpoint);
}
}
}

WebInspector.DOMBreakpointsSidebarPane.prototype.__proto__ = WebInspector.NativeBreakpointsSidebarPane.prototype;





WebInspector.CallStackSidebarPane = function(model)
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Call Stack"));
this._model = model;

this.bodyElement.addEventListener("contextmenu", this._contextMenu.bind(this), true);
}

WebInspector.CallStackSidebarPane.prototype = {
update: function(callFrames, details)
{
this.bodyElement.removeChildren();

this.placards = [];

if (!callFrames) {
var infoElement = document.createElement("div");
infoElement.className = "info";
infoElement.textContent = WebInspector.UIString("Not Paused");
this.bodyElement.appendChild(infoElement);
return;
}

for (var i = 0; i < callFrames.length; ++i) {
var callFrame = callFrames[i];
var title = callFrame.functionName || WebInspector.UIString("(anonymous function)");

var subtitle;
if (!callFrame.isInternalScript)
subtitle = WebInspector.displayNameForURL(callFrame.url);
else
subtitle = WebInspector.UIString("(internal script)");

var placard = new WebInspector.Placard(title, subtitle);
placard.callFrame = callFrame;
placard.element.addEventListener("click", this._placardSelected.bind(this, placard), false);

function didGetSourceLine(placard, sourceFileId, lineNumber)
{
if (placard.subtitle)
placard.subtitle += ":" + (lineNumber + 1);
else
placard.subtitle = WebInspector.UIString("line %d", lineNumber + 1);
placard._text = WebInspector.UIString("%s() at %s", placard.title, placard.subtitle);
}
callFrame.sourceLine(didGetSourceLine.bind(this, placard));

this.placards.push(placard);
this.bodyElement.appendChild(placard.element);
}
},

set selectedCallFrame(x)
{
for (var i = 0; i < this.placards.length; ++i) {
var placard = this.placards[i];
placard.selected = (placard.callFrame === x);
}
},

_selectNextCallFrameOnStack: function()
{
var index = this._selectedCallFrameIndex();
if (index == -1)
return;
this._selectedPlacardByIndex(index + 1);
},

_selectPreviousCallFrameOnStack: function()
{
var index = this._selectedCallFrameIndex();
if (index == -1)
return;
this._selectedPlacardByIndex(index - 1);
},

_selectedPlacardByIndex: function(index)
{
if (index < 0 || index >= this.placards.length)
return;
this._placardSelected(this.placards[index])
},

_selectedCallFrameIndex: function()
{
if (!this._model.selectedCallFrame)
return -1;
for (var i = 0; i < this.placards.length; ++i) {
var placard = this.placards[i];
if (placard.callFrame === this._model.selectedCallFrame)
return i;
}
return -1;
},

_placardSelected: function(placard, event)
{
this._model.selectedCallFrame = placard.callFrame;
},

_contextMenu: function(event)
{
if (!this.placards.length)
return;

var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendItem(WebInspector.UIString("Copy Stack Trace"), this._copyStackTrace.bind(this));
contextMenu.show(event);
},

_copyStackTrace: function()
{
var text = "";
for (var i = 0; i < this.placards.length; ++i)
text += this.placards[i]._text;
InspectorFrontendHost.copyText(text);
},

registerShortcuts: function(section, registerShortcutDelegate)
{
var nextCallFrame = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Period,
WebInspector.KeyboardShortcut.Modifiers.Ctrl);
registerShortcutDelegate(nextCallFrame.key, this._selectNextCallFrameOnStack.bind(this));

var prevCallFrame = WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Comma,
WebInspector.KeyboardShortcut.Modifiers.Ctrl);
registerShortcutDelegate(prevCallFrame.key, this._selectPreviousCallFrameOnStack.bind(this));

section.addRelatedKeys([ nextCallFrame.name, prevCallFrame.name ], WebInspector.UIString("Next/previous call frame"));
},

setStatus: function(status)
{
var statusMessageElement = document.createElement("div");
statusMessageElement.className = "info";
if (typeof status === "string")
statusMessageElement.textContent = status;
else
statusMessageElement.appendChild(status);
this.bodyElement.appendChild(statusMessageElement);
}
}

WebInspector.CallStackSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;





WebInspector.ScopeChainSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Scope Variables"));
this._sections = [];
this._expandedSections = {};
this._expandedProperties = [];
}

WebInspector.ScopeChainSidebarPane.prototype = {
update: function(callFrame)
{
this.bodyElement.removeChildren();

if (!callFrame) {
var infoElement = document.createElement("div");
infoElement.className = "info";
infoElement.textContent = WebInspector.UIString("Not Paused");
this.bodyElement.appendChild(infoElement);
return;
}

for (var i = 0; i < this._sections.length; ++i) {
var section = this._sections[i];
if (!section.title)
continue;
if (section.expanded)
this._expandedSections[section.title] = true;
else
delete this._expandedSections[section.title];
}

this._sections = [];

var foundLocalScope = false;
var scopeChain = callFrame.scopeChain;
for (var i = 0; i < scopeChain.length; ++i) {
var scope = scopeChain[i];
var title = null;
var subtitle = scope.object.description;
var emptyPlaceholder = null;
var extraProperties = null;

switch (scope.type) {
case "local":
foundLocalScope = true;
title = WebInspector.UIString("Local");
emptyPlaceholder = WebInspector.UIString("No Variables");
subtitle = null;
if (callFrame.this)
extraProperties = [ new WebInspector.RemoteObjectProperty("this", WebInspector.RemoteObject.fromPayload(callFrame.this)) ];
if (i == 0) {
var exception = WebInspector.debuggerModel.debuggerPausedDetails.exception;
if (exception) {
extraProperties = extraProperties || [];
extraProperties.push(new WebInspector.RemoteObjectProperty("<exception>", WebInspector.RemoteObject.fromPayload(exception)));
}
}
break;
case "closure":
title = WebInspector.UIString("Closure");
emptyPlaceholder = WebInspector.UIString("No Variables");
subtitle = null;
break;
case "catch":
title = WebInspector.UIString("Catch");
break;
case "with":
title = WebInspector.UIString("With Block");
break;
case "global":
title = WebInspector.UIString("Global");
break;
}

if (!title || title === subtitle)
subtitle = null;

var section = new WebInspector.ObjectPropertiesSection(WebInspector.RemoteObject.fromPayload(scope.object), title, subtitle, emptyPlaceholder, true, extraProperties, WebInspector.ScopeVariableTreeElement);
section.editInSelectedCallFrameWhenPaused = true;
section.pane = this;

if (!foundLocalScope || scope.type === "local" || title in this._expandedSections)
section.expanded = true;

this._sections.push(section);
this.bodyElement.appendChild(section.element);
}
}
}

WebInspector.ScopeChainSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;

WebInspector.ScopeVariableTreeElement = function(property)
{
WebInspector.ObjectPropertyTreeElement.call(this, property);
}

WebInspector.ScopeVariableTreeElement.prototype = {
onattach: function()
{
WebInspector.ObjectPropertyTreeElement.prototype.onattach.call(this);
if (this.hasChildren && this.propertyIdentifier in this.treeOutline.section.pane._expandedProperties)
this.expand();
},

onexpand: function()
{
this.treeOutline.section.pane._expandedProperties[this.propertyIdentifier] = true;
},

oncollapse: function()
{
delete this.treeOutline.section.pane._expandedProperties[this.propertyIdentifier];
},

get propertyIdentifier()
{
if ("_propertyIdentifier" in this)
return this._propertyIdentifier;
var section = this.treeOutline.section;
this._propertyIdentifier = section.title + ":" + (section.subtitle ? section.subtitle + ":" : "") + this.propertyPath;
return this._propertyIdentifier;
},

get propertyPath()
{
if ("_propertyPath" in this)
return this._propertyPath;

var current = this;
var result;

do {
if (result)
result = current.property.name + "." + result;
else
result = current.property.name;
current = current.parent;
} while (current && !current.root);

this._propertyPath = result;
return result;
}
}

WebInspector.ScopeVariableTreeElement.prototype.__proto__ = WebInspector.ObjectPropertyTreeElement.prototype;





WebInspector.WatchExpressionsSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Watch Expressions"));
this.reset();
}

WebInspector.WatchExpressionsSidebarPane.prototype = {
reset: function()
{
this.bodyElement.removeChildren();

this.expanded = WebInspector.settings.watchExpressions.length > 0;
this.section = new WebInspector.WatchExpressionsSection();
this.bodyElement.appendChild(this.section.element);

var refreshButton = document.createElement("button");
refreshButton.className = "pane-title-button refresh";
refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
this.titleElement.appendChild(refreshButton);

var addButton = document.createElement("button");
addButton.className = "pane-title-button add";
addButton.addEventListener("click", this._addButtonClicked.bind(this), false);
this.titleElement.appendChild(addButton);

this.onexpand = this.refreshExpressions.bind(this);
},

_addButtonClicked: function(event)
{
event.stopPropagation();
this.expanded = true;
this.section.addExpression();
},

_refreshButtonClicked: function(event)
{
event.stopPropagation();
this.refreshExpressions();
},

refreshExpressions: function()
{
this.section.update();
}
}

WebInspector.WatchExpressionsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;

WebInspector.WatchExpressionsSection = function()
{
this._watchObjectGroupId = "watch-group";

WebInspector.ObjectPropertiesSection.call(this);
this.emptyElement = document.createElement("div");
this.emptyElement.className = "info";
this.emptyElement.textContent = WebInspector.UIString("No Watch Expressions");

this.watchExpressions = WebInspector.settings.watchExpressions;

this.headerElement.className = "hidden";
this.editable = true;
this.expanded = true;
this.propertiesElement.addStyleClass("watch-expressions");

this.element.addEventListener("mousemove", this._mouseMove.bind(this), true);
this.element.addEventListener("mouseout", this._mouseOut.bind(this), true);
}

WebInspector.WatchExpressionsSection.NewWatchExpression = "\xA0";

WebInspector.WatchExpressionsSection.prototype = {
update: function(e)
{
e && e.stopPropagation();

function appendResult(expression, watchIndex, result)
{
var property = new WebInspector.RemoteObjectProperty(expression, result);
property.watchIndex = watchIndex;








properties.push(property);

if (properties.length == propertyCount) {
this.updateProperties(properties, WebInspector.WatchExpressionTreeElement, WebInspector.WatchExpressionsSection.CompareProperties);



if (this._newExpressionAdded) {
delete this._newExpressionAdded;

treeElement = this.findAddedTreeElement();
if (treeElement)
treeElement.startEditing();
}


if (this._lastMouseMovePageY)
this._updateHoveredElement(this._lastMouseMovePageY);
}
}


RuntimeAgent.releaseObjectGroup(this._watchObjectGroupId)
var properties = [];



var propertyCount = 0;
for (var i = 0; i < this.watchExpressions.length; ++i) {
if (!this.watchExpressions[i])
continue;
++propertyCount;
}



for (var i = 0; i < this.watchExpressions.length; ++i) {
var expression = this.watchExpressions[i];
if (!expression)
continue;

WebInspector.console.evalInInspectedWindow(expression, this._watchObjectGroupId, false, appendResult.bind(this, expression, i));
}

if (!propertyCount) {
if (!this.emptyElement.parentNode)
this.element.appendChild(this.emptyElement);
} else {
if (this.emptyElement.parentNode)
this.element.removeChild(this.emptyElement);
}




this.expanded = (propertyCount != 0);
},

addExpression: function()
{
this._newExpressionAdded = true;
this.watchExpressions.push(WebInspector.WatchExpressionsSection.NewWatchExpression);
this.update();
},

updateExpression: function(element, value)
{
this.watchExpressions[element.property.watchIndex] = value;
this.saveExpressions();
this.update();
},

findAddedTreeElement: function()
{
var children = this.propertiesTreeOutline.children;
for (var i = 0; i < children.length; ++i)
if (children[i].property.name === WebInspector.WatchExpressionsSection.NewWatchExpression)
return children[i];
},

saveExpressions: function()
{
var toSave = [];
for (var i = 0; i < this.watchExpressions.length; i++)
if (this.watchExpressions[i])
toSave.push(this.watchExpressions[i]);

WebInspector.settings.watchExpressions = toSave;
return toSave.length;
},

_mouseMove: function(e)
{
if (this.propertiesElement.firstChild)
this._updateHoveredElement(e.pageY);
},

_mouseOut: function()
{
if (this._hoveredElement)
this._hoveredElement.removeStyleClass("hovered");
delete this._lastMouseMovePageY;
},

_updateHoveredElement: function(pageY)
{
if (this._hoveredElement)
this._hoveredElement.removeStyleClass("hovered");

this._hoveredElement = this.propertiesElement.firstChild;
while (true) {
var next = this._hoveredElement.nextSibling;
while(next && !next.clientHeight)
next = next.nextSibling;
if (!next || next.totalOffsetTop > pageY)
break;
this._hoveredElement = next;
}
this._hoveredElement.addStyleClass("hovered");

this._lastMouseMovePageY = pageY;
}
}

WebInspector.WatchExpressionsSection.prototype.__proto__ = WebInspector.ObjectPropertiesSection.prototype;

WebInspector.WatchExpressionsSection.CompareProperties = function(propertyA, propertyB)
{
if (propertyA.watchIndex == propertyB.watchIndex)
return 0;
else if (propertyA.watchIndex < propertyB.watchIndex)
return -1;
else
return 1;
}

WebInspector.WatchExpressionTreeElement = function(property)
{
WebInspector.ObjectPropertyTreeElement.call(this, property);
}

WebInspector.WatchExpressionTreeElement.prototype = {
update: function()
{
WebInspector.ObjectPropertyTreeElement.prototype.update.call(this);

if (this.property.value.isError())
this.valueElement.addStyleClass("watch-expressions-error-level");

var deleteButton = document.createElement("input");
deleteButton.type = "button";
deleteButton.title = WebInspector.UIString("Delete watch expression.");
deleteButton.addStyleClass("enabled-button");
deleteButton.addStyleClass("delete-button");
deleteButton.addEventListener("click", this._deleteButtonClicked.bind(this), false);
this.listItemElement.insertBefore(deleteButton, this.listItemElement.firstChild);
},

_deleteButtonClicked: function()
{
this.treeOutline.section.updateExpression(this, null);
},

startEditing: function()
{
if (WebInspector.isBeingEdited(this.nameElement) || !this.treeOutline.section.editable)
return;

this.nameElement.textContent = this.property.name.trim();

var context = { expanded: this.expanded };


this.hasChildren = false;

this.listItemElement.addStyleClass("editing-sub-part");

WebInspector.startEditing(this.nameElement, {
context: context,
commitHandler: this.editingCommitted.bind(this),
cancelHandler: this.editingCancelled.bind(this)
});
},

editingCancelled: function(element, context)
{
if (!this.nameElement.textContent)
this.treeOutline.section.updateExpression(this, null);

this.update();
this.editingEnded(context);
},

applyExpression: function(expression, updateInterface)
{
expression = expression.trim();

if (!expression)
expression = null;

this.property.name = expression;
this.treeOutline.section.updateExpression(this, expression);
}
}

WebInspector.WatchExpressionTreeElement.prototype.__proto__ = WebInspector.ObjectPropertyTreeElement.prototype;





WebInspector.WorkersSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Workers"));

this._workers = {};

this._enableWorkersCheckbox = new WebInspector.Checkbox(
WebInspector.UIString("Debug"),
"sidebar-pane-subtitle",
WebInspector.UIString("Allow debugging workers. Enabling this option will replace native workers with the iframe-based JavaScript implementation"));
this.titleElement.insertBefore(this._enableWorkersCheckbox.element, this.titleElement.firstChild);

this._enableWorkersCheckbox.addEventListener(this._onTriggerInstrument.bind(this));
this._enableWorkersCheckbox.checked = false;

this._listElement = document.createElement("ol");
this._listElement.className = "workers-list";

this.bodyElement.appendChild(this._listElement);
this._treeOutline = new TreeOutline(this._listElement);
}

WebInspector.WorkersSidebarPane.prototype = {
addWorker: function(id, url, isShared)
{
if (id in this._workers) 
return;
var worker = new WebInspector.Worker(id, url, isShared);
this._workers[id] = worker;

var title = WebInspector.linkifyURL(url, WebInspector.displayNameForURL(url), "worker-item", true, url);
var treeElement = new TreeElement(null, worker, false);
treeElement.titleHTML = title;
this._treeOutline.appendChild(treeElement);
},

removeWorker: function(id)
{
if (id in this._workers) {
this._treeOutline.removeChild(this._treeOutline.findTreeElement(this._workers[id]));
delete this._workers[id];
}
},

setInstrumentation: function(enabled)
{
PageAgent.removeAllScriptsToEvaluateOnLoad();
if (enabled)
PageAgent.addScriptToEvaluateOnLoad("(" + InjectedFakeWorker + ")");
},

reset: function()
{
this.setInstrumentation(this._enableWorkersCheckbox.checked);
this._treeOutline.removeChildren();
this._workers = {};
},

_onTriggerInstrument: function(event)
{
this.setInstrumentation(this._enableWorkersCheckbox.checked);
}
};

WebInspector.WorkersSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;

WebInspector.Worker = function(id, url, shared)
{
this.id = id;
this.url = url;
this.shared = shared;
}





WebInspector.MetricsSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Metrics"));
}

WebInspector.MetricsSidebarPane.prototype = {
update: function(node)
{
if (node)
this.node = node;
else
node = this.node;

if (!node || node.nodeType() !== Node.ELEMENT_NODE) {
this.bodyElement.removeChildren();
return;
}

var self = this;
var callback = function(style) {
if (!style)
return;
self._update(style);
};
WebInspector.cssModel.getComputedStyleAsync(node.id, callback);

var inlineStyleCallback = function(style) {
if (!style)
return;
self.inlineStyle = style;
};
WebInspector.cssModel.getInlineStyleAsync(node.id, inlineStyleCallback);
},

_getPropertyValueAsPx: function(style, propertyName)
{
return Number(style.getPropertyValue(propertyName).replace(/px$/, "") || 0);
},

_getBox: function(computedStyle, componentName)
{
var suffix = componentName === "border" ? "-width" : "";
var left = this._getPropertyValueAsPx(computedStyle, componentName + "-left" + suffix);
var top = this._getPropertyValueAsPx(computedStyle, componentName + "-top" + suffix);
var right = this._getPropertyValueAsPx(computedStyle, componentName + "-right" + suffix);
var bottom = this._getPropertyValueAsPx(computedStyle, componentName + "-bottom" + suffix);
return { left: left, top: top, right: right, bottom: bottom };
},

_highlightDOMNode: function(showHighlight, mode, event)
{
function enclosingOrSelfWithClassInArray(element, classNames)
{
for (var node = element; node && node !== element.ownerDocument; node = node.parentNode) {
if (node.nodeType === Node.ELEMENT_NODE) {
for (var i = 0; i < classNames.length; ++i) {
if (node.hasStyleClass(classNames[i]))
return node;
}
}
}
return null;
}

function getBoxRectangleElement(element)
{
if (!element)
return null;
return enclosingOrSelfWithClassInArray(element, ["metrics", "margin", "border", "padding", "content"]);
}

event.stopPropagation();
var fromElement = getBoxRectangleElement(event.fromElement);
var toElement = getBoxRectangleElement(event.toElement);

if (fromElement === toElement)
return;

if (showHighlight) {

if (this.node && toElement)
toElement.addStyleClass("hovered");
var nodeId = this.node ? this.node.id : 0;
} else {

if (fromElement)
fromElement.removeStyleClass("hovered");
var nodeId = 0;
}
if (nodeId) {
if (this._highlightMode === mode)
return;
this._highlightMode = mode;
} else
delete this._highlightMode;
WebInspector.highlightDOMNode(nodeId, mode);
},

_update: function(style)
{

var metricsElement = document.createElement("div");
metricsElement.className = "metrics";
var self = this;

function createBoxPartElement(style, name, side, suffix)
{
var propertyName = (name !== "position" ? name + "-" : "") + side + suffix;
var value = style.getPropertyValue(propertyName);
if (value === "" || (name !== "position" && value === "0px"))
value = "\u2012";
else if (name === "position" && value === "auto")
value = "\u2012";
value = value.replace(/px$/, "");

var element = document.createElement("div");
element.className = side;
element.textContent = value;
element.addEventListener("dblclick", this.startEditing.bind(this, element, name, propertyName, style), false);
return element;
}

function getContentAreaWidthPx(style)
{
var width = style.getPropertyValue("width").replace(/px$/, "");
if (style.getPropertyValue("box-sizing") === "border-box") {
var borderBox = self._getBox(style, "border");
var paddingBox = self._getBox(style, "padding");

width = width - borderBox.left - borderBox.right - paddingBox.left - paddingBox.right;
}

return width;
}

function getContentAreaHeightPx(style)
{
var height = style.getPropertyValue("height").replace(/px$/, "");
if (style.getPropertyValue("box-sizing") === "border-box") {
var borderBox = self._getBox(style, "border");
var paddingBox = self._getBox(style, "padding");

height = height - borderBox.top - borderBox.bottom - paddingBox.top - paddingBox.bottom;
}

return height;
}


var noMarginDisplayType = {
"table-cell": true,
"table-column": true,
"table-column-group": true,
"table-footer-group": true,
"table-header-group": true,
"table-row": true,
"table-row-group": true
};


var noPaddingDisplayType = {
"table-column": true,
"table-column-group": true,
"table-footer-group": true,
"table-header-group": true,
"table-row": true,
"table-row-group": true
};


var noPositionType = {
"static": true
};

var boxes = ["content", "padding", "border", "margin", "position"];
var boxLabels = [WebInspector.UIString("content"), WebInspector.UIString("padding"), WebInspector.UIString("border"), WebInspector.UIString("margin"), WebInspector.UIString("position")];
var previousBox;
for (var i = 0; i < boxes.length; ++i) {
var name = boxes[i];

if (name === "margin" && noMarginDisplayType[style.getPropertyValue("display")])
continue;
if (name === "padding" && noPaddingDisplayType[style.getPropertyValue("display")])
continue;
if (name === "position" && noPositionType[style.getPropertyValue("position")])
continue;

var boxElement = document.createElement("div");
boxElement.className = name;
boxElement.addEventListener("mouseover", this._highlightDOMNode.bind(this, true, name), false);
boxElement.addEventListener("mouseout", this._highlightDOMNode.bind(this, false, ""), false);

if (name === "content") {
var widthElement = document.createElement("span");
widthElement.textContent = getContentAreaWidthPx(style);
widthElement.addEventListener("dblclick", this.startEditing.bind(this, widthElement, "width", "width", style), false);

var heightElement = document.createElement("span");
heightElement.textContent = getContentAreaHeightPx(style);
heightElement.addEventListener("dblclick", this.startEditing.bind(this, heightElement, "height", "height", style), false);

boxElement.appendChild(widthElement);
boxElement.appendChild(document.createTextNode(" \u00D7 "));
boxElement.appendChild(heightElement);
} else {
var suffix = (name === "border" ? "-width" : "");

var labelElement = document.createElement("div");
labelElement.className = "label";
labelElement.textContent = boxLabels[i];
boxElement.appendChild(labelElement);

boxElement.appendChild(createBoxPartElement.call(this, style, name, "top", suffix));
boxElement.appendChild(document.createElement("br"));
boxElement.appendChild(createBoxPartElement.call(this, style, name, "left", suffix));

if (previousBox)
boxElement.appendChild(previousBox);

boxElement.appendChild(createBoxPartElement.call(this, style, name, "right", suffix));
boxElement.appendChild(document.createElement("br"));
boxElement.appendChild(createBoxPartElement.call(this, style, name, "bottom", suffix));
}

previousBox = boxElement;
}

metricsElement.appendChild(previousBox);
metricsElement.addEventListener("mouseover", this._highlightDOMNode.bind(this, true, ""), false);
metricsElement.addEventListener("mouseout", this._highlightDOMNode.bind(this, false, ""), false);
this.bodyElement.removeChildren();
this.bodyElement.appendChild(metricsElement);

WebInspector.highlightDOMNode(0);
},

startEditing: function(targetElement, box, styleProperty, computedStyle)
{
if (WebInspector.isBeingEdited(targetElement))
return;

var context = { box: box, styleProperty: styleProperty, computedStyle: computedStyle };
var boundKeyDown = this._handleKeyDown.bind(this, context, styleProperty);
context.keyDownHandler = boundKeyDown;
targetElement.addEventListener("keydown", boundKeyDown, false);

WebInspector.panels.elements.startEditingStyle();
WebInspector.startEditing(targetElement, {
context: context,
commitHandler: this.editingCommitted.bind(this),
cancelHandler: this.editingCancelled.bind(this)
});
window.getSelection().setBaseAndExtent(targetElement, 0, targetElement, 1);
},

_handleKeyDown: function(context, styleProperty, event)
{
if (!/^(?:Page)?(?:Up|Down)$/.test(event.keyIdentifier))
return;
var element = event.currentTarget;

var selection = window.getSelection();
if (!selection.rangeCount)
return;

var selectionRange = selection.getRangeAt(0);
if (selectionRange.commonAncestorContainer !== element && !selectionRange.commonAncestorContainer.isDescendant(element))
return;

var originalValue = element.textContent;
var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, WebInspector.StylesSidebarPane.StyleValueDelimiters, element);
var wordString = wordRange.toString();

var matches = /(.*?)(-?(?:\d+(?:\.\d+)?|\.\d+))(.*)/.exec(wordString);
var replacementString;
if (matches && matches.length) {
prefix = matches[1];
suffix = matches[3];
number = WebInspector.StylesSidebarPane.alteredFloatNumber(parseFloat(matches[2]), event);
if (number === null) {

return;
}

if (styleProperty !== "margin" && number < 0)
number = 0;

replacementString = prefix + number + suffix;
}
if (!replacementString)
return;

var replacementTextNode = document.createTextNode(replacementString);

wordRange.deleteContents();
wordRange.insertNode(replacementTextNode);

var finalSelectionRange = document.createRange();
finalSelectionRange.setStart(replacementTextNode, 0);
finalSelectionRange.setEnd(replacementTextNode, replacementString.length);

selection.removeAllRanges();
selection.addRange(finalSelectionRange);

event.handled = true;
event.preventDefault();
this._applyUserInput(element, replacementString, originalValue, context, false);
},

editingEnded: function(element, context)
{
delete this.originalPropertyData;
delete this.previousPropertyDataCandidate;
element.removeEventListener("keydown", context.keyDownHandler, false);
WebInspector.panels.elements.endEditingStyle();
},

editingCancelled: function(element, context)
{
if ("originalPropertyData" in this && this.inlineStyle) {
if (!this.originalPropertyData) {

var pastLastSourcePropertyIndex = this.inlineStyle.pastLastSourcePropertyIndex();
if (pastLastSourcePropertyIndex)
this.inlineStyle.allProperties[pastLastSourcePropertyIndex - 1].setText("", false);
} else
this.inlineStyle.allProperties[this.originalPropertyData.index].setText(this.originalPropertyData.propertyText, false);
}
this.editingEnded(element, context);
this.update();
},

_applyUserInput: function(element, userInput, previousContent, context, commitEditor)
{
if (!this.inlineStyle) {

delete this.originalPropertyValue;
return this.editingCancelled(element, context); 
}

if (commitEditor && userInput === previousContent)
return this.editingCancelled(element, context); 

if (context.box !== "position" && (!userInput || userInput === "\u2012"))
userInput = "0px";
else if (context.box === "position" && (!userInput || userInput === "\u2012"))
userInput = "auto";

userInput = userInput.toLowerCase();

if (/^\d+$/.test(userInput))
userInput += "px";

var styleProperty = context.styleProperty;
var computedStyle = context.computedStyle;

if (computedStyle.getPropertyValue("box-sizing") === "border-box" && (styleProperty === "width" || styleProperty === "height")) {
if (!userInput.match(/px$/)) {
WebInspector.log("For elements with box-sizing: border-box, only absolute content area dimensions can be applied", WebInspector.ConsoleMessage.MessageLevel.Error);
WebInspector.showConsole();
return;
}

var borderBox = this._getBox(computedStyle, "border");
var paddingBox = this._getBox(computedStyle, "padding");
var userValuePx = Number(userInput.replace(/px$/, ""));
if (isNaN(userValuePx))
return;
if (styleProperty === "width")
userValuePx += borderBox.left + borderBox.right + paddingBox.left + paddingBox.right;
else
userValuePx += borderBox.top + borderBox.bottom + paddingBox.top + paddingBox.bottom;

userInput = userValuePx + "px";
}

this.previousPropertyDataCandidate = null;
var self = this;
var callback = function(style) {
if (!style)
return;
self.inlineStyle = style;
if (!("originalPropertyData" in self))
self.originalPropertyData = self.previousPropertyDataCandidate;
if ("_highlightMode" in self) {
WebInspector.highlightDOMNode(0, "");
WebInspector.highlightDOMNode(self.node.id, self._highlightMode);
}
if (commitEditor) {
self.dispatchEventToListeners("metrics edited");
self.update();
}
};

var allProperties = this.inlineStyle.allProperties;
for (var i = 0; i < allProperties.length; ++i) {
var property = allProperties[i];
if (property.name !== context.styleProperty || property.inactive)
continue;

this.previousPropertyDataCandidate = property;
property.setValue(userInput, commitEditor, callback);
return;
}

this.inlineStyle.appendProperty(context.styleProperty, userInput, callback);
},

editingCommitted: function(element, userInput, previousContent, context)
{
this.editingEnded(element, context);
this._applyUserInput(element, userInput, previousContent, context, true);
}
}

WebInspector.MetricsSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;





WebInspector.PropertiesSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Properties"));
}

WebInspector.PropertiesSidebarPane.prototype = {
update: function(node)
{
var body = this.bodyElement;

if (!node) {
body.removeChildren();
this.sections = [];
return;
}

WebInspector.RemoteObject.resolveNode(node, nodeResolved.bind(this));

function nodeResolved(object)
{
if (!object)
return;
object.evaluate("var proto = this; result = {}; var counter = 1; while (proto) { result[counter++] = proto; proto = proto.__proto__ }; return result;", nodePrototypesReady.bind(this));
object.release();
}

function nodePrototypesReady(error, objectPayload, wasThrown)
{
if (error || wasThrown)
return;
var object = WebInspector.RemoteObject.fromPayload(objectPayload);
object.getOwnProperties(fillSection.bind(this));
}

function fillSection(prototypes)
{
if (!prototypes)
return;

var body = this.bodyElement;
body.removeChildren();
this.sections = [];


for (var i = 0; i < prototypes.length; ++i) {
if (!parseInt(prototypes[i].name))
continue;

var prototype = prototypes[i].value;
var title = prototype.description;
if (title.match(/Prototype$/))
title = title.replace(/Prototype$/, "");
var section = new WebInspector.ObjectPropertiesSection(prototype, title);
this.sections.push(section);
body.appendChild(section.element);
}
}
}
}

WebInspector.PropertiesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;





WebInspector.EventListenersSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Event Listeners"));
this.bodyElement.addStyleClass("events-pane");

this.sections = [];

this.settingsSelectElement = document.createElement("select");

var option = document.createElement("option");
option.value = "all";
option.label = WebInspector.UIString("All Nodes");
this.settingsSelectElement.appendChild(option);

option = document.createElement("option");
option.value = "selected";
option.label = WebInspector.UIString("Selected Node Only");
this.settingsSelectElement.appendChild(option);

var filter = WebInspector.settings.eventListenersFilter;
if (filter === "all")
this.settingsSelectElement[0].selected = true;
else if (filter === "selected")
this.settingsSelectElement[1].selected = true;
this.settingsSelectElement.addEventListener("click", function(event) { event.stopPropagation() }, false);
this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false);

this.titleElement.appendChild(this.settingsSelectElement);
}

WebInspector.EventListenersSidebarPane.prototype = {
update: function(node)
{
var body = this.bodyElement;
body.removeChildren();
this.sections = [];

var self = this;
function callback(error, eventListeners) {
if (error)
return;

var sectionNames = [];
var sectionMap = {};
for (var i = 0; i < eventListeners.length; ++i) {
var eventListener = eventListeners[i];
eventListener.node = WebInspector.domAgent.nodeForId(eventListener.nodeId);
delete eventListener.nodeId; 
if (/^function _inspectorCommandLineAPI_logEvent\(/.test(eventListener.listenerBody.toString()))
continue; 
var type = eventListener.type;
var section = sectionMap[type];
if (!section) {
section = new WebInspector.EventListenersSection(type, node.id);
sectionMap[type] = section;
sectionNames.push(type);
self.sections.push(section);
}
section.addListener(eventListener);
}

if (sectionNames.length === 0) {
var div = document.createElement("div");
div.className = "info";
div.textContent = WebInspector.UIString("No Event Listeners");
body.appendChild(div);
return;
}

sectionNames.sort();
for (var i = 0; i < sectionNames.length; ++i) {
var section = sectionMap[sectionNames[i]];
section.update();
body.appendChild(section.element);
}
}

if (node)
node.eventListeners(callback);
},

_changeSetting: function(event)
{
var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex];
WebInspector.settings.eventListenersFilter = selectedOption.value;

for (var i = 0; i < this.sections.length; ++i)
this.sections[i].update();
}
}

WebInspector.EventListenersSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;

WebInspector.EventListenersSection = function(title, nodeId)
{
this.eventListeners = [];
this._nodeId = nodeId;
WebInspector.PropertiesSection.call(this, title);


this.propertiesElement.parentNode.removeChild(this.propertiesElement);
delete this.propertiesElement;
delete this.propertiesTreeOutline;

this.eventBars = document.createElement("div");
this.eventBars.className = "event-bars";
this.element.appendChild(this.eventBars);
}

WebInspector.EventListenersSection.prototype = {
update: function()
{

var filteredEventListeners = this.eventListeners;
if (WebInspector.settings.eventListenersFilter === "selected") {
filteredEventListeners = [];
for (var i = 0; i < this.eventListeners.length; ++i) {
var eventListener = this.eventListeners[i];
if (eventListener.node.id === this._nodeId)
filteredEventListeners.push(eventListener);
}
}

this.eventBars.removeChildren();
var length = filteredEventListeners.length;
for (var i = 0; i < length; ++i) {
var eventListener = filteredEventListeners[i];
var eventListenerBar = new WebInspector.EventListenerBar(eventListener, this._nodeId);
this.eventBars.appendChild(eventListenerBar.element);
}
},

addListener: function(eventListener)
{
this.eventListeners.push(eventListener);
}
}

WebInspector.EventListenersSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;

WebInspector.EventListenerBar = function(eventListener, nodeId)
{
this.eventListener = eventListener;
this._nodeId = nodeId;
WebInspector.ObjectPropertiesSection.call(this);
this._setNodeTitle();
this._setFunctionSubtitle();
this.editable = false;
this.element.className = "event-bar";  
this.headerElement.addStyleClass("source-code");
this.propertiesElement.className = "event-properties properties-tree source-code";  
}

WebInspector.EventListenerBar.prototype = {
update: function()
{
function updateWithNodeObject(nodeObject)
{
var properties = [];
if (nodeObject)
properties.push(new WebInspector.RemoteObjectProperty("node", nodeObject));

for (var propertyName in this.eventListener) {
var value = WebInspector.RemoteObject.fromPrimitiveValue(this.eventListener[propertyName]);
properties.push(new WebInspector.RemoteObjectProperty(propertyName, value));
}
this.updateProperties(properties);
if (nodeObject)
nodeObject.release();
}
var node = this.eventListener.node;
delete this.eventListener.node;
WebInspector.RemoteObject.resolveNode(node, updateWithNodeObject.bind(this));
},

_setNodeTitle: function()
{
var node = this.eventListener.node;
if (!node)
return;

if (node.nodeType() === Node.DOCUMENT_NODE) {
this.titleElement.textContent = "document";
return;
}

if (node.id === this._nodeId) {
this.titleElement.textContent = node.appropriateSelectorFor();
return;
}

this.titleElement.removeChildren();
this.titleElement.appendChild(WebInspector.panels.elements.linkifyNodeReference(this.eventListener.node));
},

_setFunctionSubtitle: function()
{

if (this.eventListener.sourceName) {
this.subtitleElement.removeChildren();
this.subtitleElement.appendChild(WebInspector.linkifyResourceAsNode(this.eventListener.sourceName, "scripts", this.eventListener.lineNumber));
} else {
var match = this.eventListener.listenerBody.match(/function ([^\(]+?)\(/);
if (match)
this.subtitleElement.textContent = match[1];
else
this.subtitleElement.textContent = WebInspector.UIString("(anonymous function)");
}
}
}

WebInspector.EventListenerBar.prototype.__proto__ = WebInspector.ObjectPropertiesSection.prototype;





WebInspector.Color = function(str)
{
this.value = str;
this._parse();
}

WebInspector.Color.prototype = {
get shorthex()
{
if ("_short" in this)
return this._short;

if (!this.simple)
return null;

var hex = this.hex;
if (hex.charAt(0) === hex.charAt(1) && hex.charAt(2) === hex.charAt(3) && hex.charAt(4) === hex.charAt(5))
this._short = hex.charAt(0) + hex.charAt(2) + hex.charAt(4);
else
this._short = hex;

return this._short;
},

get hex()
{
if (!this.simple)
return null;

return this._hex;
},

set hex(x)
{
this._hex = x;
},

get rgb()
{
if ("_rgb" in this)
return this._rgb;

if (this.simple)
this._rgb = this._hexToRGB(this.hex);
else {
var rgba = this.rgba;
this._rgb = [rgba[0], rgba[1], rgba[2]];
}

return this._rgb;
},

set rgb(x)
{
this._rgb = x;
},

get hsl()
{
if ("_hsl" in this)
return this._hsl;

this._hsl = this._rgbToHSL(this.rgb);
return this._hsl;
},

set hsl(x)
{
this._hsl = x;
},

get nickname()
{
if (typeof this._nickname !== "undefined") 
return this._nickname;
else
return null;
},

set nickname(x)
{
this._nickname = x;
},

get rgba()
{
return this._rgba;
},

set rgba(x)
{
this._rgba = x;
},

get hsla()
{
return this._hsla;
},

set hsla(x)
{
this._hsla = x;
},

hasShortHex: function()
{
var shorthex = this.shorthex;
return (shorthex && shorthex.length === 3);
},

toString: function(format)
{
if (!format)
format = this.format;

switch (format) {
case "original":
return this.value;
case "rgb":
return "rgb(" + this.rgb.join(", ") + ")";
case "rgba":
return "rgba(" + this.rgba.join(", ") + ")";
case "hsl":
var hsl = this.hsl;
return "hsl(" + hsl[0] + ", " + hsl[1] + "%, " + hsl[2] + "%)";
case "hsla":
var hsla = this.hsla;
return "hsla(" + hsla[0] + ", " + hsla[1] + "%, " + hsla[2] + "%, " + hsla[3] + ")";
case "hex":
return "#" + this.hex;
case "shorthex":
return "#" + this.shorthex;
case "nickname":
return this.nickname;
}

throw "invalid color format";
},

_rgbToHex: function(rgb)
{
var r = parseInt(rgb[0]).toString(16);
var g = parseInt(rgb[1]).toString(16);
var b = parseInt(rgb[2]).toString(16);
if (r.length === 1)
r = "0" + r;
if (g.length === 1)
g = "0" + g;
if (b.length === 1)
b = "0" + b;

return (r + g + b).toUpperCase();
},

_hexToRGB: function(hex)
{
var r = parseInt(hex.substring(0,2), 16);
var g = parseInt(hex.substring(2,4), 16);
var b = parseInt(hex.substring(4,6), 16);

return [r, g, b];
},

_rgbToHSL: function(rgb)
{
var r = parseInt(rgb[0]) / 255;
var g = parseInt(rgb[1]) / 255;
var b = parseInt(rgb[2]) / 255;
var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var diff = max - min;
var add = max + min;

if (min === max)
var h = 0;
else if (r === max)
var h = ((60 * (g - b) / diff) + 360) % 360;
else if (g === max)
var h = (60 * (b - r) / diff) + 120;
else
var h = (60 * (r - g) / diff) + 240;

var l = 0.5 * add;

if (l === 0)
var s = 0;
else if (l === 1)
var s = 1;
else if (l <= 0.5)
var s = diff / add;
else
var s = diff / (2 - add);

h = Math.round(h);
s = Math.round(s*100);
l = Math.round(l*100);

return [h, s, l];
},

_hslToRGB: function(hsl)
{
var h = parseFloat(hsl[0]) / 360;
var s = parseFloat(hsl[1]) / 100;
var l = parseFloat(hsl[2]) / 100;

if (l <= 0.5)
var q = l * (1 + s);
else
var q = l + s - (l * s);

var p = 2 * l - q;

var tr = h + (1 / 3);
var tg = h;
var tb = h - (1 / 3);

var r = Math.round(hueToRGB(p, q, tr) * 255);
var g = Math.round(hueToRGB(p, q, tg) * 255);
var b = Math.round(hueToRGB(p, q, tb) * 255);
return [r, g, b];

function hueToRGB(p, q, h) {
if (h < 0)
h += 1;
else if (h > 1)
h -= 1;

if ((h * 6) < 1)
return p + (q - p) * h * 6;
else if ((h * 2) < 1)
return q;
else if ((h * 3) < 2)
return p + (q - p) * ((2 / 3) - h) * 6;
else
return p;
}
},

_rgbaToHSLA: function(rgba)
{
var alpha = rgba[3];
var hsl = this._rgbToHSL(rgba)
hsl.push(alpha);
return hsl;
},

_hslaToRGBA: function(hsla)
{
var alpha = hsla[3];
var rgb = this._hslToRGB(hsla);
rgb.push(alpha);
return rgb;
},

_parse: function()
{

var value = this.value.toLowerCase().replace(/%|\s+/g, "");
if (value in WebInspector.Color.AdvancedNickNames) {
this.format = "nickname";
var set = WebInspector.Color.AdvancedNickNames[value];
this.simple = false;
this.rgba = set[0];
this.hsla = set[1];
this.nickname = set[2];
this.alpha = set[0][3];
return;
}


var simple = /^(?:#([0-9a-f]{3,6})|rgb\(([^)]+)\)|(\w+)|hsl\(([^)]+)\))$/i;
var match = this.value.match(simple);
if (match) {
this.simple = true;

if (match[1]) { 
var hex = match[1].toUpperCase();
if (hex.length === 3) {
this.format = "shorthex";
this.hex = hex.charAt(0) + hex.charAt(0) + hex.charAt(1) + hex.charAt(1) + hex.charAt(2) + hex.charAt(2);
} else {
this.format = "hex";
this.hex = hex;
}
} else if (match[2]) { 
this.format = "rgb";
var rgb = match[2].split(/\s*,\s*/);
this.rgb = rgb;
this.hex = this._rgbToHex(rgb);
} else if (match[3]) { 
var nickname = match[3].toLowerCase();
if (nickname in WebInspector.Color.Nicknames) {
this.format = "nickname";
this.hex = WebInspector.Color.Nicknames[nickname];
} else 
throw "unknown color name";
} else if (match[4]) { 
this.format = "hsl";
var hsl = match[4].replace(/%/g, "").split(/\s*,\s*/);
this.hsl = hsl;
this.rgb = this._hslToRGB(hsl);
this.hex = this._rgbToHex(this.rgb);
}


var hex = this.hex;
if (hex && hex in WebInspector.Color.HexTable) {
var set = WebInspector.Color.HexTable[hex];
this.rgb = set[0];
this.hsl = set[1];
this.nickname = set[2];
}

return;
}


var advanced = /^(?:rgba\(([^)]+)\)|hsla\(([^)]+)\))$/;
match = this.value.match(advanced);
if (match) {
this.simple = false;
if (match[1]) { 
this.format = "rgba";
this.rgba = match[1].split(/\s*,\s*/);
this.hsla = this._rgbaToHSLA(this.rgba);
this.alpha = this.rgba[3];
} else if (match[2]) { 
this.format = "hsla";
this.hsla = match[2].replace(/%/g, "").split(/\s*,\s*/);
this.rgba = this._hslaToRGBA(this.hsla);
this.alpha = this.hsla[3];
}

return;
}


throw "could not parse color";
}
}


WebInspector.Color.HexTable = {
"000000": [[0, 0, 0], [0, 0, 0], "black"],
"000080": [[0, 0, 128], [240, 100, 25], "navy"],
"00008B": [[0, 0, 139], [240, 100, 27], "darkBlue"],
"0000CD": [[0, 0, 205], [240, 100, 40], "mediumBlue"],
"0000FF": [[0, 0, 255], [240, 100, 50], "blue"],
"006400": [[0, 100, 0], [120, 100, 20], "darkGreen"],
"008000": [[0, 128, 0], [120, 100, 25], "green"],
"008080": [[0, 128, 128], [180, 100, 25], "teal"],
"008B8B": [[0, 139, 139], [180, 100, 27], "darkCyan"],
"00BFFF": [[0, 191, 255], [195, 100, 50], "deepSkyBlue"],
"00CED1": [[0, 206, 209], [181, 100, 41], "darkTurquoise"],
"00FA9A": [[0, 250, 154], [157, 100, 49], "mediumSpringGreen"],
"00FF00": [[0, 255, 0], [120, 100, 50], "lime"],
"00FF7F": [[0, 255, 127], [150, 100, 50], "springGreen"],
"00FFFF": [[0, 255, 255], [180, 100, 50], "cyan"],
"191970": [[25, 25, 112], [240, 64, 27], "midnightBlue"],
"1E90FF": [[30, 144, 255], [210, 100, 56], "dodgerBlue"],
"20B2AA": [[32, 178, 170], [177, 70, 41], "lightSeaGreen"],
"228B22": [[34, 139, 34], [120, 61, 34], "forestGreen"],
"2E8B57": [[46, 139, 87], [146, 50, 36], "seaGreen"],
"2F4F4F": [[47, 79, 79], [180, 25, 25], "darkSlateGray"],
"32CD32": [[50, 205, 50], [120, 61, 50], "limeGreen"],
"3CB371": [[60, 179, 113], [147, 50, 47], "mediumSeaGreen"],
"40E0D0": [[64, 224, 208], [174, 72, 56], "turquoise"],
"4169E1": [[65, 105, 225], [225, 73, 57], "royalBlue"],
"4682B4": [[70, 130, 180], [207, 44, 49], "steelBlue"],
"483D8B": [[72, 61, 139], [248, 39, 39], "darkSlateBlue"],
"48D1CC": [[72, 209, 204], [178, 60, 55], "mediumTurquoise"],
"4B0082": [[75, 0, 130], [275, 100, 25], "indigo"],
"556B2F": [[85, 107, 47], [82, 39, 30], "darkOliveGreen"],
"5F9EA0": [[95, 158, 160], [182, 25, 50], "cadetBlue"],
"6495ED": [[100, 149, 237], [219, 79, 66], "cornflowerBlue"],
"66CDAA": [[102, 205, 170], [160, 51, 60], "mediumAquaMarine"],
"696969": [[105, 105, 105], [0, 0, 41], "dimGray"],
"6A5ACD": [[106, 90, 205], [248, 53, 58], "slateBlue"],
"6B8E23": [[107, 142, 35], [80, 60, 35], "oliveDrab"],
"708090": [[112, 128, 144], [210, 13, 50], "slateGray"],
"778899": [[119, 136, 153], [210, 14, 53], "lightSlateGray"],
"7B68EE": [[123, 104, 238], [249, 80, 67], "mediumSlateBlue"],
"7CFC00": [[124, 252, 0], [90, 100, 49], "lawnGreen"],
"7FFF00": [[127, 255, 0], [90, 100, 50], "chartreuse"],
"7FFFD4": [[127, 255, 212], [160, 100, 75], "aquamarine"],
"800000": [[128, 0, 0], [0, 100, 25], "maroon"],
"800080": [[128, 0, 128], [300, 100, 25], "purple"],
"808000": [[128, 128, 0], [60, 100, 25], "olive"],
"808080": [[128, 128, 128], [0, 0, 50], "gray"],
"87CEEB": [[135, 206, 235], [197, 71, 73], "skyBlue"],
"87CEFA": [[135, 206, 250], [203, 92, 75], "lightSkyBlue"],
"8A2BE2": [[138, 43, 226], [271, 76, 53], "blueViolet"],
"8B0000": [[139, 0, 0], [0, 100, 27], "darkRed"],
"8B008B": [[139, 0, 139], [300, 100, 27], "darkMagenta"],
"8B4513": [[139, 69, 19], [25, 76, 31], "saddleBrown"],
"8FBC8F": [[143, 188, 143], [120, 25, 65], "darkSeaGreen"],
"90EE90": [[144, 238, 144], [120, 73, 75], "lightGreen"],
"9370D8": [[147, 112, 219], [260, 60, 65], "mediumPurple"],
"9400D3": [[148, 0, 211], [282, 100, 41], "darkViolet"],
"98FB98": [[152, 251, 152], [120, 93, 79], "paleGreen"],
"9932CC": [[153, 50, 204], [280, 61, 50], "darkOrchid"],
"9ACD32": [[154, 205, 50], [80, 61, 50], "yellowGreen"],
"A0522D": [[160, 82, 45], [19, 56, 40], "sienna"],
"A52A2A": [[165, 42, 42], [0, 59, 41], "brown"],
"A9A9A9": [[169, 169, 169], [0, 0, 66], "darkGray"],
"ADD8E6": [[173, 216, 230], [195, 53, 79], "lightBlue"],
"ADFF2F": [[173, 255, 47], [84, 100, 59], "greenYellow"],
"AFEEEE": [[175, 238, 238], [180, 65, 81], "paleTurquoise"],
"B0C4DE": [[176, 196, 222], [214, 41, 78], "lightSteelBlue"],
"B0E0E6": [[176, 224, 230], [187, 52, 80], "powderBlue"],
"B22222": [[178, 34, 34], [0, 68, 42], "fireBrick"],
"B8860B": [[184, 134, 11], [43, 89, 38], "darkGoldenrod"],
"BA55D3": [[186, 85, 211], [288, 59, 58], "mediumOrchid"],
"BC8F8F": [[188, 143, 143], [0, 25, 65], "rosyBrown"],
"BDB76B": [[189, 183, 107], [56, 38, 58], "darkKhaki"],
"C0C0C0": [[192, 192, 192], [0, 0, 75], "silver"],
"C71585": [[199, 21, 133], [322, 81, 43], "mediumVioletRed"],
"CD5C5C": [[205, 92, 92], [0, 53, 58], "indianRed"],
"CD853F": [[205, 133, 63], [30, 59, 53], "peru"],
"D2691E": [[210, 105, 30], [25, 75, 47], "chocolate"],
"D2B48C": [[210, 180, 140], [34, 44, 69], "tan"],
"D3D3D3": [[211, 211, 211], [0, 0, 83], "lightGrey"],
"D87093": [[219, 112, 147], [340, 60, 65], "paleVioletRed"],
"D8BFD8": [[216, 191, 216], [300, 24, 80], "thistle"],
"DA70D6": [[218, 112, 214], [302, 59, 65], "orchid"],
"DAA520": [[218, 165, 32], [43, 74, 49], "goldenrod"],
"DC143C": [[237, 164, 61], [35, 83, 58], "crimson"],
"DCDCDC": [[220, 220, 220], [0, 0, 86], "gainsboro"],
"DDA0DD": [[221, 160, 221], [300, 47, 75], "plum"],
"DEB887": [[222, 184, 135], [34, 57, 70], "burlyWood"],
"E0FFFF": [[224, 255, 255], [180, 100, 94], "lightCyan"],
"E6E6FA": [[230, 230, 250], [240, 67, 94], "lavender"],
"E9967A": [[233, 150, 122], [15, 72, 70], "darkSalmon"],
"EE82EE": [[238, 130, 238], [300, 76, 72], "violet"],
"EEE8AA": [[238, 232, 170], [55, 67, 80], "paleGoldenrod"],
"F08080": [[240, 128, 128], [0, 79, 72], "lightCoral"],
"F0E68C": [[240, 230, 140], [54, 77, 75], "khaki"],
"F0F8FF": [[240, 248, 255], [208, 100, 97], "aliceBlue"],
"F0FFF0": [[240, 255, 240], [120, 100, 97], "honeyDew"],
"F0FFFF": [[240, 255, 255], [180, 100, 97], "azure"],
"F4A460": [[244, 164, 96], [28, 87, 67], "sandyBrown"],
"F5DEB3": [[245, 222, 179], [39, 77, 83], "wheat"],
"F5F5DC": [[245, 245, 220], [60, 56, 91], "beige"],
"F5F5F5": [[245, 245, 245], [0, 0, 96], "whiteSmoke"],
"F5FFFA": [[245, 255, 250], [150, 100, 98], "mintCream"],
"F8F8FF": [[248, 248, 255], [240, 100, 99], "ghostWhite"],
"FA8072": [[250, 128, 114], [6, 93, 71], "salmon"],
"FAEBD7": [[250, 235, 215], [34, 78, 91], "antiqueWhite"],
"FAF0E6": [[250, 240, 230], [30, 67, 94], "linen"],
"FAFAD2": [[250, 250, 210], [60, 80, 90], "lightGoldenrodYellow"],
"FDF5E6": [[253, 245, 230], [39, 85, 95], "oldLace"],
"FF0000": [[255, 0, 0], [0, 100, 50], "red"],
"FF00FF": [[255, 0, 255], [300, 100, 50], "magenta"],
"FF1493": [[255, 20, 147], [328, 100, 54], "deepPink"],
"FF4500": [[255, 69, 0], [16, 100, 50], "orangeRed"],
"FF6347": [[255, 99, 71], [9, 100, 64], "tomato"],
"FF69B4": [[255, 105, 180], [330, 100, 71], "hotPink"],
"FF7F50": [[255, 127, 80], [16, 100, 66], "coral"],
"FF8C00": [[255, 140, 0], [33, 100, 50], "darkOrange"],
"FFA07A": [[255, 160, 122], [17, 100, 74], "lightSalmon"],
"FFA500": [[255, 165, 0], [39, 100, 50], "orange"],
"FFB6C1": [[255, 182, 193], [351, 100, 86], "lightPink"],
"FFC0CB": [[255, 192, 203], [350, 100, 88], "pink"],
"FFD700": [[255, 215, 0], [51, 100, 50], "gold"],
"FFDAB9": [[255, 218, 185], [28, 100, 86], "peachPuff"],
"FFDEAD": [[255, 222, 173], [36, 100, 84], "navajoWhite"],
"FFE4B5": [[255, 228, 181], [38, 100, 85], "moccasin"],
"FFE4C4": [[255, 228, 196], [33, 100, 88], "bisque"],
"FFE4E1": [[255, 228, 225], [6, 100, 94], "mistyRose"],
"FFEBCD": [[255, 235, 205], [36, 100, 90], "blanchedAlmond"],
"FFEFD5": [[255, 239, 213], [37, 100, 92], "papayaWhip"],
"FFF0F5": [[255, 240, 245], [340, 100, 97], "lavenderBlush"],
"FFF5EE": [[255, 245, 238], [25, 100, 97], "seaShell"],
"FFF8DC": [[255, 248, 220], [48, 100, 93], "cornsilk"],
"FFFACD": [[255, 250, 205], [54, 100, 90], "lemonChiffon"],
"FFFAF0": [[255, 250, 240], [40, 100, 97], "floralWhite"],
"FFFAFA": [[255, 250, 250], [0, 100, 99], "snow"],
"FFFF00": [[255, 255, 0], [60, 100, 50], "yellow"],
"FFFFE0": [[255, 255, 224], [60, 100, 94], "lightYellow"],
"FFFFF0": [[255, 255, 240], [60, 100, 97], "ivory"],
"FFFFFF": [[255, 255, 255], [0, 100, 100], "white"]
};


WebInspector.Color.Nicknames = {
"aliceblue": "F0F8FF",
"antiquewhite": "FAEBD7",
"aqua": "00FFFF",
"aquamarine": "7FFFD4",
"azure": "F0FFFF",
"beige": "F5F5DC",
"bisque": "FFE4C4",
"black": "000000",
"blanchedalmond": "FFEBCD",
"blue": "0000FF",
"blueviolet": "8A2BE2",
"brown": "A52A2A",
"burlywood": "DEB887",
"cadetblue": "5F9EA0",
"chartreuse": "7FFF00",
"chocolate": "D2691E",
"coral": "FF7F50",
"cornflowerblue": "6495ED",
"cornsilk": "FFF8DC",
"crimson": "DC143C",
"cyan": "00FFFF",
"darkblue": "00008B",
"darkcyan": "008B8B",
"darkgoldenrod": "B8860B",
"darkgray": "A9A9A9",
"darkgreen": "006400",
"darkkhaki": "BDB76B",
"darkmagenta": "8B008B",
"darkolivegreen": "556B2F",
"darkorange": "FF8C00",
"darkorchid": "9932CC",
"darkred": "8B0000",
"darksalmon": "E9967A",
"darkseagreen": "8FBC8F",
"darkslateblue": "483D8B",
"darkslategray": "2F4F4F",
"darkturquoise": "00CED1",
"darkviolet": "9400D3",
"deeppink": "FF1493",
"deepskyblue": "00BFFF",
"dimgray": "696969",
"dodgerblue": "1E90FF",
"firebrick": "B22222",
"floralwhite": "FFFAF0",
"forestgreen": "228B22",
"fuchsia": "FF00FF",
"gainsboro": "DCDCDC",
"ghostwhite": "F8F8FF",
"gold": "FFD700",
"goldenrod": "DAA520",
"gray": "808080",
"green": "008000",
"greenyellow": "ADFF2F",
"honeydew": "F0FFF0",
"hotpink": "FF69B4",
"indianred": "CD5C5C",
"indigo": "4B0082",
"ivory": "FFFFF0",
"khaki": "F0E68C",
"lavender": "E6E6FA",
"lavenderblush": "FFF0F5",
"lawngreen": "7CFC00",
"lemonchiffon": "FFFACD",
"lightblue": "ADD8E6",
"lightcoral": "F08080",
"lightcyan": "E0FFFF",
"lightgoldenrodyellow": "FAFAD2",
"lightgreen": "90EE90",
"lightgrey": "D3D3D3",
"lightpink": "FFB6C1",
"lightsalmon": "FFA07A",
"lightseagreen": "20B2AA",
"lightskyblue": "87CEFA",
"lightslategray": "778899",
"lightsteelblue": "B0C4DE",
"lightyellow": "FFFFE0",
"lime": "00FF00",
"limegreen": "32CD32",
"linen": "FAF0E6",
"magenta": "FF00FF",
"maroon": "800000",
"mediumaquamarine": "66CDAA",
"mediumblue": "0000CD",
"mediumorchid": "BA55D3",
"mediumpurple": "9370DB",
"mediumseagreen": "3CB371",
"mediumslateblue": "7B68EE",
"mediumspringgreen": "00FA9A",
"mediumturquoise": "48D1CC",
"mediumvioletred": "C71585",
"midnightblue": "191970",
"mintcream": "F5FFFA",
"mistyrose": "FFE4E1",
"moccasin": "FFE4B5",
"navajowhite": "FFDEAD",
"navy": "000080",
"oldlace": "FDF5E6",
"olive": "808000",
"olivedrab": "6B8E23",
"orange": "FFA500",
"orangered": "FF4500",
"orchid": "DA70D6",
"palegoldenrod": "EEE8AA",
"palegreen": "98FB98",
"paleturquoise": "AFEEEE",
"palevioletred": "DB7093",
"papayawhip": "FFEFD5",
"peachpuff": "FFDAB9",
"peru": "CD853F",
"pink": "FFC0CB",
"plum": "DDA0DD",
"powderblue": "B0E0E6",
"purple": "800080",
"red": "FF0000",
"rosybrown": "BC8F8F",
"royalblue": "4169E1",
"saddlebrown": "8B4513",
"salmon": "FA8072",
"sandybrown": "F4A460",
"seagreen": "2E8B57",
"seashell": "FFF5EE",
"sienna": "A0522D",
"silver": "C0C0C0",
"skyblue": "87CEEB",
"slateblue": "6A5ACD",
"slategray": "708090",
"snow": "FFFAFA",
"springgreen": "00FF7F",
"steelblue": "4682B4",
"tan": "D2B48C",
"teal": "008080",
"thistle": "D8BFD8",
"tomato": "FF6347",
"turquoise": "40E0D0",
"violet": "EE82EE",
"wheat": "F5DEB3",
"white": "FFFFFF",
"whitesmoke": "F5F5F5",
"yellow": "FFFF00",
"yellowgreen": "9ACD32"
};


WebInspector.Color.AdvancedNickNames = {
"transparent": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"],
"rgba(0,0,0,0)": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"],
"hsla(0,0,0,0)": [[0, 0, 0, 0], [0, 0, 0, 0], "transparent"],
};





WebInspector.CSSCompletions = function(values, acceptEmptyPrefix)
{
this._values = values.slice();
this._values.sort();
this._acceptEmptyPrefix = acceptEmptyPrefix;
}

WebInspector.CSSCompletions.prototype = {
startsWith: function(prefix)
{
var firstIndex = this._firstIndexOfPrefix(prefix);
if (firstIndex === -1)
return [];

var results = [];
while (firstIndex < this._values.length && this._values[firstIndex].indexOf(prefix) === 0)
results.push(this._values[firstIndex++]);
return results;
},

firstStartsWith: function(prefix)
{
var foundIndex = this._firstIndexOfPrefix(prefix);
return (foundIndex === -1 ? "" : this._values[foundIndex]);
},

_firstIndexOfPrefix: function(prefix)
{
if (!this._values.length)
return -1;
if (!prefix)
return this._acceptEmptyPrefix ? 0 : -1;

var maxIndex = this._values.length - 1;
var minIndex = 0;
var foundIndex;

do {
var middleIndex = (maxIndex + minIndex) >> 1;
if (this._values[middleIndex].indexOf(prefix) === 0) {
foundIndex = middleIndex;
break;
}
if (this._values[middleIndex] < prefix)
minIndex = middleIndex + 1;
else
maxIndex = middleIndex - 1;
} while (minIndex <= maxIndex);

if (foundIndex === undefined)
return -1;

while (foundIndex && this._values[foundIndex - 1].indexOf(prefix) === 0)
foundIndex--;

return foundIndex;
},

keySet: function()
{
return this._values.keySet();
},

next: function(str, prefix)
{
return this._closest(str, prefix, 1);
},

previous: function(str, prefix)
{
return this._closest(str, prefix, -1);
},

_closest: function(str, prefix, shift)
{
if (!str)
return "";

var index = this._values.indexOf(str);
if (index === -1)
return "";

if (!prefix) {
index = (index + this._values.length + shift) % this._values.length;
return this._values[index];
}

var propertiesWithPrefix = this.startsWith(prefix);
var j = propertiesWithPrefix.indexOf(str);
j = (j + propertiesWithPrefix.length + shift) % propertiesWithPrefix.length;
return propertiesWithPrefix[j];
}
}





WebInspector.CSSKeywordCompletions = {
forProperty: function(propertyName)
{
var acceptedKeywords = ["initial"];
if (propertyName in this._propertyKeywordMap)
acceptedKeywords = acceptedKeywords.concat(this._propertyKeywordMap[propertyName]);
if (propertyName in this._colorAwareProperties)
acceptedKeywords = acceptedKeywords.concat(WebInspector.CSSKeywordCompletions._colors);
if (propertyName in WebInspector.StylesSidebarPane.InheritedProperties)
acceptedKeywords.push("inherit");
return new WebInspector.CSSCompletions(acceptedKeywords, true);
},

isColorAwareProperty: function(propertyName)
{
return WebInspector.CSSKeywordCompletions._colorAwareProperties[propertyName] === true;
}
};

WebInspector.CSSKeywordCompletions._colors = [
"aqua", "black", "blue", "fuchsia", "gray", "green", "lime", "maroon", "navy", "olive", "orange", "purple", "red",
"silver", "teal", "white", "yellow", "transparent", "currentcolor", "grey", "aliceblue", "antiquewhite",
"aquamarine", "azure", "beige", "bisque", "blanchedalmond", "blueviolet", "brown", "burlywood", "cadetblue",
"chartreuse", "chocolate", "coral", "cornflowerblue", "cornsilk", "crimson", "cyan", "darkblue", "darkcyan",
"darkgoldenrod", "darkgray", "darkgreen", "darkgrey", "darkkhaki", "darkmagenta", "darkolivegreen", "darkorange",
"darkorchid", "darkred", "darksalmon", "darkseagreen", "darkslateblue", "darkslategray", "darkslategrey",
"darkturquoise", "darkviolet", "deeppink", "deepskyblue", "dimgray", "dimgrey", "dodgerblue", "firebrick",
"floralwhite", "forestgreen", "gainsboro", "ghostwhite", "gold", "goldenrod", "greenyellow", "honeydew", "hotpink",
"indianred", "indigo", "ivory", "khaki", "lavender", "lavenderblush", "lawngreen", "lemonchiffon", "lightblue",
"lightcoral", "lightcyan", "lightgoldenrodyellow", "lightgray", "lightgreen", "lightgrey", "lightpink",
"lightsalmon", "lightseagreen", "lightskyblue", "lightslategray", "lightslategrey", "lightsteelblue", "lightyellow",
"limegreen", "linen", "magenta", "mediumaquamarine", "mediumblue", "mediumorchid", "mediumpurple", "mediumseagreen",
"mediumslateblue", "mediumspringgreen", "mediumturquoise", "mediumvioletred", "midnightblue", "mintcream",
"mistyrose", "moccasin", "navajowhite", "oldlace", "olivedrab", "orangered", "orchid", "palegoldenrod", "palegreen",
"paleturquoise", "palevioletred", "papayawhip", "peachpuff", "peru", "pink", "plum", "powderblue", "rosybrown",
"royalblue", "saddlebrown", "salmon", "sandybrown", "seagreen", "seashell", "sienna", "skyblue", "slateblue",
"slategray", "slategrey", "snow", "springgreen", "steelblue", "tan", "thistle", "tomato", "turquoise", "violet",
"wheat", "whitesmoke", "yellowgreen"
],

WebInspector.CSSKeywordCompletions._colorAwareProperties = [
"background", "background-color", "border", "border-color", "border-top", "border-right", "border-bottom",
"border-left", "border-top-color", "border-right-color", "border-bottom-color", "border-left-color", "color",
"outline", "outline-color", "text-line-through", "text-line-through-color", "text-overline", "text-overline-color",
"text-shadow", "text-underline", "text-underline-color", "-webkit-text-emphasis", "-webkit-text-emphasis-color"
].keySet();

WebInspector.CSSKeywordCompletions._propertyKeywordMap = {
"table-layout": [
"auto", "fixed"
],
"visibility": [
"hidden", "visible", "collapse"
],
"background-repeat": [
"repeat", "repeat-x", "repeat-y", "no-repeat", "space", "round"
],
"text-underline": [
"none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave"
],
"content": [
"list-item", "close-quote", "no-close-quote", "no-open-quote", "open-quote"
],
"list-style-image": [
"none"
],
"clear": [
"none", "left", "right", "both"
],
"text-underline-mode": [
"continuous", "skip-white-space"
],
"overflow-x": [
"hidden", "auto", "visible", "overlay", "scroll"
],
"stroke-linejoin": [
"round", "miter", "bevel"
],
"baseline-shift": [
"baseline", "sub", "super"
],
"border-bottom-width": [
"medium", "thick", "thin"
],
"marquee-speed": [
"normal", "slow", "fast"
],
"margin-top-collapse": [
"collapse", "separate", "discard"
],
"max-height": [
"none"
],
"box-orient": [
"horizontal", "vertical", "inline-axis", "block-axis"
],
"font-stretch": [
"normal", "wider", "narrower", "ultra-condensed", "extra-condensed", "condensed", "semi-condensed",
"semi-expanded", "expanded", "extra-expanded", "ultra-expanded"
],
"-webkit-color-correction": [
"default", "srgb"
],
"text-underline-style": [
"none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave"
],
"text-overline-mode": [
"continuous", "skip-white-space"
],
"-webkit-background-composite": [
"highlight", "clear", "copy", "source-over", "source-in", "source-out", "source-atop", "destination-over",
"destination-in", "destination-out", "destination-atop", "xor", "plus-darker", "plus-lighter"
],
"border-left-width": [
"medium", "thick", "thin"
],
"-webkit-writing-mode": [
"lr", "rl", "tb", "lr-tb", "rl-tb", "tb-rl", "horizontal-tb", "vertical-rl", "vertical-lr", "horizontal-bt"
],
"text-line-through-mode": [
"continuous", "skip-white-space"
],
"border-collapse": [
"collapse", "separate"
],
"page-break-inside": [
"auto", "avoid"
],
"border-top-width": [
"medium", "thick", "thin"
],
"outline-color": [
"invert"
],
"text-line-through-style": [
"none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave"
],
"outline-style": [
"none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
],
"cursor": [
"none", "copy", "auto", "crosshair", "default", "pointer", "move", "vertical-text", "cell", "context-menu",
"alias", "progress", "no-drop", "not-allowed", "-webkit-zoom-in", "-webkit-zoom-out", "e-resize", "ne-resize",
"nw-resize", "n-resize", "se-resize", "sw-resize", "s-resize", "w-resize", "ew-resize", "ns-resize",
"nesw-resize", "nwse-resize", "col-resize", "row-resize", "text", "wait", "help", "all-scroll", "-webkit-grab",
"-webkit-grabbing"
],
"border-width": [
"medium", "thick", "thin"
],
"size": [
"a3", "a4", "a5", "b4", "b5", "landscape", "ledger", "legal", "letter", "portrait"
],
"background-size": [
"contain", "cover"
],
"direction": [
"ltr", "rtl"
],
"marquee-direction": [
"left", "right", "auto", "reverse", "forwards", "backwards", "ahead", "up", "down"
],
"enable-background": [
"accumulate", "new"
],
"float": [
"none", "left", "right"
],
"overflow-y": [
"hidden", "auto", "visible", "overlay", "scroll"
],
"margin-bottom-collapse": [
"collapse",  "separate", "discard"
],
"box-reflect": [
"left", "right", "above", "below"
],
"overflow": [
"hidden", "auto", "visible", "overlay", "scroll"
],
"text-rendering": [
"auto", "optimizespeed", "optimizelegibility", "geometricprecision"
],
"text-align": [
"-webkit-auto", "left", "right", "center", "justify", "-webkit-left", "-webkit-right", "-webkit-center"
],
"list-style-position": [
"outside", "inside"
],
"margin-bottom": [
"auto"
],
"color-interpolation": [
"linearrgb"
],
"background-origin": [
"border-box", "content-box", "padding-box"
],
"word-wrap": [
"normal", "break-word"
],
"font-weight": [
"normal", "bold", "bolder", "lighter", "100", "200", "300", "400", "500", "600", "700", "800", "900"
],
"margin-before-collapse": [
"collapse", "separate", "discard"
],
"text-overline-width": [
"normal", "medium", "auto", "thick", "thin"
],
"text-transform": [
"none", "capitalize", "uppercase", "lowercase"
],
"border-right-style": [
"none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
],
"border-left-style": [
"none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
],
"-webkit-text-emphasis": [
"circle", "filled", "open", "dot", "double-circle", "triangle", "sesame"
],
"font-style": [
"italic", "oblique", "normal"
],
"speak": [
"none", "normal", "spell-out", "digits", "literal-punctuation", "no-punctuation"
],
"text-line-through": [
"none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave", "continuous",
"skip-white-space"
],
"color-rendering": [
"auto", "optimizespeed", "optimizequality"
],
"list-style-type": [
"none", "disc", "circle", "square", "decimal", "decimal-leading-zero", "arabic-indic", "binary", "bengali",
"cambodian", "khmer", "devanagari", "gujarati", "gurmukhi", "kannada", "lower-hexadecimal", "lao", "malayalam",
"mongolian", "myanmar", "octal", "oriya", "persian", "urdu", "telugu", "tibetan", "thai", "upper-hexadecimal",
"lower-roman", "upper-roman", "lower-greek", "lower-alpha", "lower-latin", "upper-alpha", "upper-latin", "afar",
"ethiopic-halehame-aa-et", "ethiopic-halehame-aa-er", "amharic", "ethiopic-halehame-am-et", "amharic-abegede",
"ethiopic-abegede-am-et", "cjk-earthly-branch", "cjk-heavenly-stem", "ethiopic", "ethiopic-halehame-gez",
"ethiopic-abegede", "ethiopic-abegede-gez", "hangul-consonant", "hangul", "lower-norwegian", "oromo",
"ethiopic-halehame-om-et", "sidama", "ethiopic-halehame-sid-et", "somali", "ethiopic-halehame-so-et", "tigre",
"ethiopic-halehame-tig", "tigrinya-er", "ethiopic-halehame-ti-er", "tigrinya-er-abegede",
"ethiopic-abegede-ti-er", "tigrinya-et", "ethiopic-halehame-ti-et", "tigrinya-et-abegede",
"ethiopic-abegede-ti-et", "upper-greek", "upper-norwegian", "asterisks", "footnotes", "hebrew", "armenian",
"lower-armenian", "upper-armenian", "georgian", "cjk-ideographic", "hiragana", "katakana", "hiragana-iroha",
"katakana-iroha"
],
"-webkit-text-combine": [
"none", "horizontal"
],
"outline": [
"none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
],
"font": [
"caption", "icon", "menu", "message-box", "small-caption", "-webkit-mini-control", "-webkit-small-control",
"-webkit-control", "status-bar", "italic", "oblique", "small-caps", "normal", "bold", "bolder", "lighter",
"100", "200", "300", "400", "500", "600", "700", "800", "900", "xx-small", "x-small", "small", "medium",
"large", "x-large", "xx-large", "-webkit-xxx-large", "smaller", "larger", "serif", "sans-serif", "cursive",
"fantasy", "monospace", "-webkit-body"
],
"dominant-baseline": [
"middle", "auto", "central", "text-before-edge", "text-after-edge", "ideographic", "alphabetic", "hanging",
"mathematical", "use-script", "no-change", "reset-size"
],
"display": [
"none", "inline", "block", "list-item", "run-in", "compact", "inline-block", "table", "inline-table",
"table-row-group", "table-header-group", "table-footer-group", "table-row", "table-column-group",
"table-column", "table-cell", "table-caption", "-webkit-box", "-webkit-inline-box", "-wap-marquee"
],
"-webkit-text-emphasis-position": [
"over", "under"
],
"image-rendering": [
"auto", "optimizespeed", "optimizequality"
],
"alignment-baseline": [
"baseline", "middle", "auto", "before-edge", "after-edge", "central", "text-before-edge", "text-after-edge",
"ideographic", "alphabetic", "hanging", "mathematical"
],
"outline-width": [
"medium", "thick", "thin"
],
"text-line-through-width": [
"normal", "medium", "auto", "thick", "thin"
],
"box-align": [
"baseline", "center", "stretch", "start", "end"
],
"border-right-width": [
"medium", "thick", "thin"
],
"border-top-style": [
"none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
],
"line-height": [
"normal"
],
"text-overflow": [
"clip", "ellipsis"
],
"box-direction": [
"normal", "reverse"
],
"margin-after-collapse": [
"collapse", "separate", "discard"
],
"page-break-before": [
"left", "right", "auto", "always", "avoid"
],
"-webkit-hyphens": [
"none", "auto", "manual"
],
"border-image": [
"repeat", "stretch"
],
"text-decoration": [
"blink", "line-through", "overline", "underline"
],
"position": [
"absolute", "fixed", "relative", "static"
],
"font-family": [
"serif", "sans-serif", "cursive", "fantasy", "monospace", "-webkit-body"
],
"text-overflow-mode": [
"clip", "ellipsis"
],
"border-bottom-style": [
"none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
],
"unicode-bidi": [
"normal", "bidi-override", "embed"
],
"clip-rule": [
"nonzero", "evenodd"
],
"margin-left": [
"auto"
],
"margin-top": [
"auto"
],
"zoom": [
"document", "reset"
],
"text-overline-style": [
"none", "dotted", "dashed", "solid", "double", "dot-dash", "dot-dot-dash", "wave"
],
"max-width": [
"none"
],
"empty-cells": [
"hide", "show"
],
"pointer-events": [
"none", "all", "auto", "visible", "visiblepainted", "visiblefill", "visiblestroke", "painted", "fill", "stroke"
],
"letter-spacing": [
"normal"
],
"background-clip": [
"border-box", "content-box", "padding-box"
],
"-webkit-font-smoothing": [
"none", "auto", "antialiased", "subpixel-antialiased"
],
"border": [
"none", "hidden", "inset", "groove", "ridge", "outset", "dotted", "dashed", "solid", "double"
],
"font-size": [
"xx-small", "x-small", "small", "medium", "large", "x-large", "xx-large", "-webkit-xxx-large", "smaller",
"larger"
],
"font-variant": [
"small-caps", "normal"
],
"vertical-align": [
"baseline", "middle", "sub", "super", "text-top", "text-bottom", "top", "bottom", "-webkit-baseline-middle"
],
"marquee-style": [
"none", "scroll", "slide", "alternate"
],
"white-space": [
"normal", "nowrap", "pre", "pre-line", "pre-wrap"
],
"text-underline-width": [
"normal", "medium", "auto", "thick", "thin"
],
"box-lines": [
"single", "multiple"
],
"page-break-after": [
"left", "right", "auto", "always", "avoid"
],
"clip-path": [
"none"
],
"margin": [
"auto"
],
"marquee-repetition": [
"infinite"
],
"margin-right": [
"auto"
],
"-webkit-text-emphasis-style": [
"circle", "filled", "open", "dot", "double-circle", "triangle", "sesame"
]
}





WebInspector.StylesSidebarPane = function(computedStylePane)
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Styles"));

this.settingsSelectElement = document.createElement("select");

var option = document.createElement("option");
option.value = "original";
option.action = this._changeColorFormat.bind(this);
option.label = WebInspector.UIString("As Authored");
this.settingsSelectElement.appendChild(option);

var option = document.createElement("option");
option.value = "hex";
option.action = this._changeColorFormat.bind(this);
option.label = WebInspector.UIString("Hex Colors");
this.settingsSelectElement.appendChild(option);

option = document.createElement("option");
option.value = "rgb";
option.action = this._changeColorFormat.bind(this);
option.label = WebInspector.UIString("RGB Colors");
this.settingsSelectElement.appendChild(option);

option = document.createElement("option");
option.value = "hsl";
option.action = this._changeColorFormat.bind(this);
option.label = WebInspector.UIString("HSL Colors");
this.settingsSelectElement.appendChild(option);

this.settingsSelectElement.appendChild(document.createElement("hr"));

option = document.createElement("option");
option.action = this._createNewRule.bind(this);
option.label = WebInspector.UIString("New Style Rule");
this.settingsSelectElement.appendChild(option);

this.settingsSelectElement.addEventListener("click", function(event) { event.stopPropagation() }, false);
this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false);
var format = WebInspector.settings.colorFormat;
if (format === "original")
this.settingsSelectElement[0].selected = true;
else if (format === "hex")
this.settingsSelectElement[1].selected = true;
else if (format === "rgb")
this.settingsSelectElement[2].selected = true;
else if (format === "hsl")
this.settingsSelectElement[3].selected = true;

this.titleElement.appendChild(this.settingsSelectElement);
this._computedStylePane = computedStylePane;
this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true);
}

WebInspector.StylesSidebarPane.StyleValueDelimiters = " \t\n\"':;,/()";


WebInspector.StylesSidebarPane.InheritedProperties = [
"azimuth", "border-collapse", "border-spacing", "caption-side", "color", "cursor", "direction", "elevation",
"empty-cells", "font-family", "font-size", "font-style", "font-variant", "font-weight", "font", "letter-spacing",
"line-height", "list-style-image", "list-style-position", "list-style-type", "list-style", "orphans", "pitch-range",
"pitch", "quotes", "richness", "speak-header", "speak-numeral", "speak-punctuation", "speak", "speech-rate", "stress",
"text-align", "text-indent", "text-transform", "text-shadow", "visibility", "voice-family", "volume", "white-space", "widows", "word-spacing"
].keySet();





WebInspector.StylesSidebarPane.PseudoIdNames = [
"", "first-line", "first-letter", "before", "after", "selection", "", "-webkit-scrollbar", "-webkit-file-upload-button",
"-webkit-input-placeholder", "-webkit-slider-thumb", "-webkit-search-cancel-button", "-webkit-search-decoration",
"-webkit-search-results-decoration", "-webkit-search-results-button", "-webkit-media-controls-panel",
"-webkit-media-controls-play-button", "-webkit-media-controls-mute-button", "-webkit-media-controls-timeline",
"-webkit-media-controls-timeline-container", "-webkit-media-controls-volume-slider",
"-webkit-media-controls-volume-slider-container", "-webkit-media-controls-current-time-display",
"-webkit-media-controls-time-remaining-display", "-webkit-media-controls-seek-back-button", "-webkit-media-controls-seek-forward-button",
"-webkit-media-controls-fullscreen-button", "-webkit-media-controls-rewind-button", "-webkit-media-controls-return-to-realtime-button",
"-webkit-media-controls-toggle-closed-captions-button", "-webkit-media-controls-status-display", "-webkit-scrollbar-thumb",
"-webkit-scrollbar-button", "-webkit-scrollbar-track", "-webkit-scrollbar-track-piece", "-webkit-scrollbar-corner",
"-webkit-resizer", "-webkit-input-list-button", "-webkit-inner-spin-button", "-webkit-outer-spin-button"
];

WebInspector.StylesSidebarPane.CSSNumberRegex = /^(-?(?:\d+(?:\.\d+)?|\.\d+))$/;

WebInspector.StylesSidebarPane.alteredFloatNumber = function(number, event)
{
var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down");

var numberNearZero = (number < 1 && number > -1);
if (number === 1 && event.keyIdentifier === "Down")
numberNearZero = true;
else if (number === -1 && event.keyIdentifier === "Up")
numberNearZero = true;

var result;
if (numberNearZero && event.altKey && arrowKeyPressed) {
if (event.keyIdentifier === "Down")
result = Math.ceil(number - 1);
else
result = Math.floor(number + 1);
} else {


var changeAmount = 1;
if (event.shiftKey && !arrowKeyPressed)
changeAmount = 100;
else if (event.shiftKey || !arrowKeyPressed)
changeAmount = 10;
else if (event.altKey || numberNearZero)
changeAmount = 0.1;

if (event.keyIdentifier === "Down" || event.keyIdentifier === "PageDown")
changeAmount *= -1;



result = Number((number + changeAmount).toFixed(6));
if (!String(result).match(WebInspector.StylesSidebarPane.CSSNumberRegex))
return null;
}

return result;
}

WebInspector.StylesSidebarPane.alteredHexNumber = function(hexString, event)
{
var number = parseInt(hexString, 16);
if (isNaN(number) || !isFinite(number))
return hexString;

var maxValue = Math.pow(16, hexString.length) - 1;
var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down");

var delta;
if (arrowKeyPressed)
delta = (event.keyIdentifier === "Up") ? 1 : -1;
else
delta = (event.keyIdentifier === "PageUp") ? 16 : -16;

if (event.shiftKey)
delta *= 16;

var result = number + delta;
if (result < 0)
result = 0; 
else if (result > maxValue)
return hexString;


var resultString = result.toString(16).toUpperCase();
for (var i = 0, lengthDelta = hexString.length - resultString.length; i < lengthDelta; ++i)
resultString = "0" + resultString;
return resultString;
},

WebInspector.StylesSidebarPane.prototype = {
_contextMenuEventFired: function(event)
{
var href = event.target.enclosingNodeOrSelfWithClass("webkit-html-resource-link") || event.target.enclosingNodeOrSelfWithClass("webkit-html-external-link");
if (href) {
var contextMenu = new WebInspector.ContextMenu();
var filled = WebInspector.panels.elements.populateHrefContextMenu(contextMenu, event, href);
if (filled)
contextMenu.show(event);
}
},

update: function(node, editedSection, forceUpdate)
{
var refresh = false;

if (forceUpdate)
delete this.node;

if (!forceUpdate && (!node || node === this.node))
refresh = true;

if (node && node.nodeType() === Node.TEXT_NODE && node.parentNode)
node = node.parentNode;

if (node && node.nodeType() !== Node.ELEMENT_NODE)
node = null;

if (node)
this.node = node;
else
node = this.node;

if (!node) {
this.bodyElement.removeChildren();
this._computedStylePane.bodyElement.removeChildren();
this.sections = {};
return;
}

function stylesCallback(styles)
{
if (styles)
this._rebuildUpdate(node, styles);
}

function computedStyleCallback(computedStyle)
{
if (computedStyle)
this._refreshUpdate(node, computedStyle, editedSection);
}

if (refresh)
WebInspector.cssModel.getComputedStyleAsync(node.id, computedStyleCallback.bind(this));
else
WebInspector.cssModel.getStylesAsync(node.id, stylesCallback.bind(this));
},

_refreshUpdate: function(node, computedStyle, editedSection)
{
for (var pseudoId in this.sections) {
var styleRules = this._refreshStyleRules(this.sections[pseudoId], computedStyle);
var usedProperties = {};
var disabledComputedProperties = {};
this._markUsedProperties(styleRules, usedProperties, disabledComputedProperties);
this._refreshSectionsForStyleRules(styleRules, usedProperties, disabledComputedProperties, editedSection);
}

this.sections[0][0].rebuildComputedTrace(this.sections[0]);
},

_rebuildUpdate: function(node, styles)
{
this.bodyElement.removeChildren();
this._computedStylePane.bodyElement.removeChildren();

var styleRules = this._rebuildStyleRules(node, styles);
var usedProperties = {};
var disabledComputedProperties = {};
this._markUsedProperties(styleRules, usedProperties, disabledComputedProperties);
this.sections[0] = this._rebuildSectionsForStyleRules(styleRules, usedProperties, disabledComputedProperties, 0);
var anchorElement = this.sections[0].inheritedPropertiesSeparatorElement;

this.sections[0][0].rebuildComputedTrace(this.sections[0]);

for (var i = 0; i < styles.pseudoElements.length; ++i) {
var pseudoElementCSSRules = styles.pseudoElements[i];

styleRules = [];
var pseudoId = pseudoElementCSSRules.pseudoId;

var entry = { isStyleSeparator: true, pseudoId: pseudoId };
styleRules.push(entry);


for (var j = pseudoElementCSSRules.rules.length - 1; j >= 0; --j) {
var rule = pseudoElementCSSRules.rules[j];
styleRules.push({ style: rule.style, selectorText: rule.selectorText, sourceURL: rule.sourceURL, rule: rule, editable: !!(rule.style && rule.style.id) });
}
usedProperties = {};
disabledComputedProperties = {};
this._markUsedProperties(styleRules, usedProperties, disabledComputedProperties);
this.sections[pseudoId] = this._rebuildSectionsForStyleRules(styleRules, usedProperties, disabledComputedProperties, pseudoId, anchorElement);
}
},

_refreshStyleRules: function(sections, computedStyle)
{
var nodeComputedStyle = computedStyle;
var styleRules = [];
for (var i = 0; sections && i < sections.length; ++i) {
var section = sections[i];
if (section instanceof WebInspector.BlankStylePropertiesSection)
continue;
if (section.computedStyle)
section.styleRule.style = nodeComputedStyle;
var styleRule = { section: section, style: section.styleRule.style, computedStyle: section.computedStyle, rule: section.rule, editable: !!(section.styleRule.style && section.styleRule.style.id) };
styleRules.push(styleRule);
}
return styleRules;
},

_rebuildStyleRules: function(node, styles)
{
var nodeComputedStyle = styles.computedStyle;
this.sections = {};

var styleRules = [];

styleRules.push({ computedStyle: true, selectorText: "", style: nodeComputedStyle, editable: false });

var styleAttributes = {};
for (var name in styles.styleAttributes) {
var attrStyle = { style: styles.styleAttributes[name], editable: false };
attrStyle.selectorText = WebInspector.panels.elements.treeOutline.nodeNameToCorrectCase(node.nodeName()) + "[" + name;
if (node.getAttribute(name))
attrStyle.selectorText += "=" + node.getAttribute(name);
attrStyle.selectorText += "]";
styleRules.push(attrStyle);
}


if (styles.inlineStyle && node.nodeType() === Node.ELEMENT_NODE) {
var inlineStyle = { selectorText: "element.style", style: styles.inlineStyle, isAttribute: true };
styleRules.push(inlineStyle);
}


if (styles.matchedCSSRules.length)
styleRules.push({ isStyleSeparator: true, text: WebInspector.UIString("Matched CSS Rules") });
for (var i = styles.matchedCSSRules.length - 1; i >= 0; --i) {
var rule = styles.matchedCSSRules[i];
styleRules.push({ style: rule.style, selectorText: rule.selectorText, sourceURL: rule.sourceURL, rule: rule, editable: !!(rule.style && rule.style.id) });
}


var parentNode = node.parentNode;
function insertInheritedNodeSeparator(node)
{
var entry = {};
entry.isStyleSeparator = true;
entry.node = node;
styleRules.push(entry);
}

for (var parentOrdinal = 0; parentOrdinal < styles.inherited.length; ++parentOrdinal) {
var parentStyles = styles.inherited[parentOrdinal];
var separatorInserted = false;
if (parentStyles.inlineStyle) {
if (this._containsInherited(parentStyles.inlineStyle)) {
var inlineStyle = { selectorText: WebInspector.UIString("Style Attribute"), style: parentStyles.inlineStyle, isAttribute: true, isInherited: true };
if (!separatorInserted) {
insertInheritedNodeSeparator(parentNode);
separatorInserted = true;
}
styleRules.push(inlineStyle);
}
}

for (var i = parentStyles.matchedCSSRules.length - 1; i >= 0; --i) {
var rulePayload = parentStyles.matchedCSSRules[i];
if (!this._containsInherited(rulePayload.style))
continue;
var rule = rulePayload;
if (!separatorInserted) {
insertInheritedNodeSeparator(parentNode);
separatorInserted = true;
}
styleRules.push({ style: rule.style, selectorText: rule.selectorText, sourceURL: rule.sourceURL, rule: rule, isInherited: true, editable: !!(rule.style && rule.style.id) });
}
parentNode = parentNode.parentNode;
}
return styleRules;
},

_markUsedProperties: function(styleRules, usedProperties, disabledComputedProperties)
{
var priorityUsed = false;


for (var i = 0; i < styleRules.length; ++i) {
var styleRule = styleRules[i];
if (styleRule.computedStyle || styleRule.isStyleSeparator)
continue;
if (styleRule.section && styleRule.section.noAffect)
continue;

styleRule.usedProperties = {};

var style = styleRule.style;
var allProperties = style.allProperties;
for (var j = 0; j < allProperties.length; ++j) {
var property = allProperties[j];
if (!property.isLive || !property.parsedOk)
continue;
var name = property.name;

if (!priorityUsed && property.priority.length)
priorityUsed = true;



if (!(name in usedProperties))
styleRule.usedProperties[name] = true;

if (name === "font") {



styleRule.usedProperties["font-family"] = true;
styleRule.usedProperties["font-size"] = true;
styleRule.usedProperties["font-style"] = true;
styleRule.usedProperties["font-variant"] = true;
styleRule.usedProperties["font-weight"] = true;
styleRule.usedProperties["line-height"] = true;
}
}



for (var name in styleRules[i].usedProperties)
usedProperties[name] = true;
}

if (priorityUsed) {

var foundPriorityProperties = [];


for (var i = (styleRules.length - 1); i >= 0; --i) {
if (styleRules[i].computedStyle || styleRules[i].isStyleSeparator)
continue;

var style = styleRules[i].style;
var allProperties = style.allProperties;
for (var j = 0; j < allProperties.length; ++j) {
var property = allProperties[j];
if (!property.isLive)
continue;
var name = property.name;
if (property.priority.length) {
if (!(name in foundPriorityProperties))
styleRules[i].usedProperties[name] = true;
else
delete styleRules[i].usedProperties[name];
foundPriorityProperties[name] = true;
} else if (name in foundPriorityProperties)
delete styleRules[i].usedProperties[name];
}
}
}
},

_refreshSectionsForStyleRules: function(styleRules, usedProperties, disabledComputedProperties, editedSection)
{

for (var i = 0; i < styleRules.length; ++i) {
var styleRule = styleRules[i];
var section = styleRule.section;
if (styleRule.computedStyle) {
section._disabledComputedProperties = disabledComputedProperties;
section._usedProperties = usedProperties;
section.update();
} else {
section._usedProperties = styleRule.usedProperties;
section.update(section === editedSection);
}
}
},

_rebuildSectionsForStyleRules: function(styleRules, usedProperties, disabledComputedProperties, pseudoId, anchorElement)
{

var sections = [];
var lastWasSeparator = true;
for (var i = 0; i < styleRules.length; ++i) {
var styleRule = styleRules[i];
if (styleRule.isStyleSeparator) {
var separatorElement = document.createElement("div");
separatorElement.className = "styles-sidebar-separator";
if (styleRule.node) {
var link = WebInspector.panels.elements.linkifyNodeReference(styleRule.node);
separatorElement.appendChild(document.createTextNode(WebInspector.UIString("Inherited from") + " "));
separatorElement.appendChild(link);
if (!sections.inheritedPropertiesSeparatorElement)
sections.inheritedPropertiesSeparatorElement = separatorElement;
} else if ("pseudoId" in styleRule) {
var pseudoName = WebInspector.StylesSidebarPane.PseudoIdNames[styleRule.pseudoId];
if (pseudoName)
separatorElement.textContent = WebInspector.UIString("Pseudo ::%s element", pseudoName);
else
separatorElement.textContent = WebInspector.UIString("Pseudo element");
} else
separatorElement.textContent = styleRule.text;
this.bodyElement.insertBefore(separatorElement, anchorElement);
lastWasSeparator = true;
continue;
}
var computedStyle = styleRule.computedStyle;


var editable = styleRule.editable;
if (typeof editable === "undefined")
editable = true;

if (computedStyle)
var section = new WebInspector.ComputedStylePropertiesSection(styleRule, usedProperties, disabledComputedProperties, styleRules);
else
var section = new WebInspector.StylePropertiesSection(this, styleRule, editable, styleRule.isInherited, lastWasSeparator);
section.pane = this;
section.expanded = true;

if (computedStyle) {
this._computedStylePane.bodyElement.appendChild(section.element);
lastWasSeparator = true;
} else {
this.bodyElement.insertBefore(section.element, anchorElement);
lastWasSeparator = false;
}
sections.push(section);
}
return sections;
},

_containsInherited: function(style)
{
var properties = style.allProperties;
for (var i = 0; i < properties.length; ++i) {
var property = properties[i];

if (property.isLive && property.name in WebInspector.StylesSidebarPane.InheritedProperties)
return true;
}
return false;
},

_changeSetting: function(event)
{
var options = this.settingsSelectElement.options;
var selectedOption = options[this.settingsSelectElement.selectedIndex];
selectedOption.action(event);


var selectedIndex = 0;
for (var i = 0; i < options.length; ++i) {
if (options[i].value === WebInspector.settings.colorFormat) {
selectedIndex = i;
break;
}
}

this.settingsSelectElement.selectedIndex = selectedIndex;
},

_changeColorFormat: function(event)
{
var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex];
WebInspector.settings.colorFormat = selectedOption.value;

for (var pseudoId in this.sections) {
var sections = this.sections[pseudoId];
for (var i = 0; i < sections.length; ++i)
sections[i].update(true);
}
},

_createNewRule: function(event)
{
this.expanded = true;
this.addBlankSection().startEditingSelector();
},

addBlankSection: function()
{
var blankSection = new WebInspector.BlankStylePropertiesSection(this, this.node ? this.node.appropriateSelectorFor(true) : "");
blankSection.pane = this;

var elementStyleSection = this.sections[0][1];
this.bodyElement.insertBefore(blankSection.element, elementStyleSection.element.nextSibling);

this.sections[0].splice(2, 0, blankSection);

return blankSection;
},

removeSection: function(section)
{
for (var pseudoId in this.sections) {
var sections = this.sections[pseudoId];
var index = sections.indexOf(section);
if (index === -1)
continue;
sections.splice(index, 1);
if (section.element.parentNode)
section.element.parentNode.removeChild(section.element);
}
},

registerShortcuts: function()
{
var section = WebInspector.shortcutsHelp.section(WebInspector.UIString("Styles Pane"));
var shortcut = WebInspector.KeyboardShortcut;
var keys = [
shortcut.shortcutToString(shortcut.Keys.Tab),
shortcut.shortcutToString(shortcut.Keys.Tab, shortcut.Modifiers.Shift)
];
section.addRelatedKeys(keys, WebInspector.UIString("Next/previous property"));
keys = [
shortcut.shortcutToString(shortcut.Keys.Up),
shortcut.shortcutToString(shortcut.Keys.Down)
];
section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement value"));
keys = [
shortcut.shortcutToString(shortcut.Keys.Up, shortcut.Modifiers.Shift),
shortcut.shortcutToString(shortcut.Keys.Down, shortcut.Modifiers.Shift)
];
section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 10));
keys = [
shortcut.shortcutToString(shortcut.Keys.PageUp),
shortcut.shortcutToString(shortcut.Keys.PageDown)
];
section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 10));
keys = [
shortcut.shortcutToString(shortcut.Keys.PageUp, shortcut.Modifiers.Shift),
shortcut.shortcutToString(shortcut.Keys.PageDown, shortcut.Modifiers.Shift)
];
section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 100));
keys = [
shortcut.shortcutToString(shortcut.Keys.PageUp, shortcut.Modifiers.Alt),
shortcut.shortcutToString(shortcut.Keys.PageDown, shortcut.Modifiers.Alt)
];
section.addRelatedKeys(keys, WebInspector.UIString("Increment/decrement by %f", 0.1));
}
}

WebInspector.StylesSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;

WebInspector.ComputedStyleSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Computed Style"));
var showInheritedCheckbox = new WebInspector.Checkbox(WebInspector.UIString("Show inherited"), "sidebar-pane-subtitle");
this.titleElement.appendChild(showInheritedCheckbox.element);

if (WebInspector.settings.showInheritedComputedStyleProperties) {
this.bodyElement.addStyleClass("show-inherited");
showInheritedCheckbox.checked = true;
}

function showInheritedToggleFunction(event)
{
WebInspector.settings.showInheritedComputedStyleProperties = showInheritedCheckbox.checked;
if (WebInspector.settings.showInheritedComputedStyleProperties)
this.bodyElement.addStyleClass("show-inherited");
else
this.bodyElement.removeStyleClass("show-inherited");
}

showInheritedCheckbox.addEventListener(showInheritedToggleFunction.bind(this));
}

WebInspector.ComputedStyleSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;

WebInspector.StylePropertiesSection = function(parentPane, styleRule, editable, isInherited, isFirstSection)
{
WebInspector.PropertiesSection.call(this, "");
this.element.className = "styles-section monospace" + (isFirstSection ? " first-styles-section" : "");

this._selectorElement = document.createElement("span");
this._selectorElement.textContent = styleRule.selectorText;
this.titleElement.appendChild(this._selectorElement);
if (Preferences.debugMode)
this._selectorElement.addEventListener("click", this._debugShowStyle.bind(this), false);

var openBrace = document.createElement("span");
openBrace.textContent = " {";
this.titleElement.appendChild(openBrace);

var closeBrace = document.createElement("div");
closeBrace.textContent = "}";
this.element.appendChild(closeBrace);

this._selectorElement.addEventListener("dblclick", this._handleSelectorDoubleClick.bind(this), false);
this.element.addEventListener("dblclick", this._handleEmptySpaceDoubleClick.bind(this), false);

this._parentPane = parentPane;
this.styleRule = styleRule;
this.rule = this.styleRule.rule;
this.editable = editable;
this.isInherited = isInherited;


var isUserAgent = this.rule && this.rule.isUserAgent;
var isUser = this.rule && this.rule.isUser;
var isViaInspector = this.rule && this.rule.isViaInspector;

if (isUserAgent || isUser)
this.editable = false;

this._usedProperties = styleRule.usedProperties;

if (this.rule)
this.titleElement.addStyleClass("styles-selector");

function linkifyUncopyable(url, line)
{
var link = WebInspector.linkifyResourceAsNode(url, "resources", line + 1);
return link;
}

var subtitle = "";
if (this.styleRule.sourceURL)
this.subtitleElement.appendChild(linkifyUncopyable(this.styleRule.sourceURL, this.rule.sourceLine));
else if (isUserAgent)
subtitle = WebInspector.UIString("user agent stylesheet");
else if (isUser)
subtitle = WebInspector.UIString("user stylesheet");
else if (isViaInspector)
subtitle = WebInspector.UIString("via inspector");
else if (this.rule && this.rule.sourceURL)
this.subtitleElement.appendChild(linkifyUncopyable(this.rule.sourceURL, this.rule.sourceLine));

if (isInherited)
this.element.addStyleClass("show-inherited"); 
if (subtitle)
this.subtitle = subtitle;

this.identifier = styleRule.selectorText;
if (this.subtitle)
this.identifier += ":" + this.subtitle;

if (!this.editable)
this.element.addStyleClass("read-only");
}

WebInspector.StylePropertiesSection.prototype = {
collapse: function(dontRememberState)
{

},

isPropertyInherited: function(propertyName)
{
if (this.isInherited) {


return !(propertyName in WebInspector.StylesSidebarPane.InheritedProperties);
}
return false;
},

isPropertyOverloaded: function(propertyName, shorthand)
{
if (!this._usedProperties || this.noAffect)
return false;

if (this.isInherited && !(propertyName in WebInspector.StylesSidebarPane.InheritedProperties)) {

return false;
}

var used = (propertyName in this._usedProperties);
if (used || !shorthand)
return !used;



var longhandProperties = this.styleRule.style.getLonghandProperties(propertyName);
for (var j = 0; j < longhandProperties.length; ++j) {
var individualProperty = longhandProperties[j];
if (individualProperty.name in this._usedProperties)
return false;
}

return true;
},

nextEditableSibling: function()
{
var curSection = this;
do {
curSection = curSection.nextSibling;
} while (curSection && !curSection.editable);

return curSection;
},

previousEditableSibling: function()
{
var curSection = this;
do {
curSection = curSection.previousSibling;
} while (curSection && !curSection.editable);

return curSection;
},

update: function(full)
{
if (full) {
this.propertiesTreeOutline.removeChildren();
this.populated = false;
} else {
var child = this.propertiesTreeOutline.children[0];
while (child) {
child.overloaded = this.isPropertyOverloaded(child.name, child.shorthand);
child = child.traverseNextTreeElement(false, null, true);
}
}
this.afterUpdate();
},

afterUpdate: function()
{
if (this._afterUpdate) {
this._afterUpdate(this);
delete this._afterUpdate;
}
},

onpopulate: function()
{
var style = this.styleRule.style;

var handledProperties = {};
var shorthandNames = {};

this.uniqueProperties = [];
var allProperties = style.allProperties;
for (var i = 0; i < allProperties.length; ++i)
this.uniqueProperties.push(allProperties[i]);


for (var i = 0; i < this.uniqueProperties.length; ++i) {
var property = this.uniqueProperties[i];
if (property.disabled)
continue;
if (property.shorthand)
shorthandNames[property.shorthand] = true;
}


for (var i = 0; i < this.uniqueProperties.length; ++i) {
var property = this.uniqueProperties[i];
var disabled = property.disabled;
if (!disabled && this.disabledComputedProperties && !(property.name in this.usedProperties) && property.name in this.disabledComputedProperties)
disabled = true;

var shorthand = !disabled ? property.shorthand : null;

if (shorthand && shorthand in handledProperties)
continue;

if (shorthand) {
property = style.getLiveProperty(shorthand);
if (!property)
property = new WebInspector.CSSProperty(style, style.allProperties.length, shorthand, style.getShorthandValue(shorthand), style.getShorthandPriority(shorthand), "style", true, true, "");
}

var isShorthand = !!(property.isLive && (shorthand || shorthandNames[property.name]));
var inherited = this.isPropertyInherited(property.name);
var overloaded = this.isPropertyOverloaded(property.name, isShorthand);

var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this.styleRule, style, property, isShorthand, inherited, overloaded);
this.propertiesTreeOutline.appendChild(item);
handledProperties[property.name] = property;
}
},

findTreeElementWithName: function(name)
{
var treeElement = this.propertiesTreeOutline.children[0];
while (treeElement) {
if (treeElement.name === name)
return treeElement;
treeElement = treeElement.traverseNextTreeElement(true, null, true);
}
return null;
},

addNewBlankProperty: function(optionalIndex)
{
var style = this.styleRule.style;
var property = style.newBlankProperty();
var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this.styleRule, style, property, false, false, false);
this.propertiesTreeOutline.appendChild(item);
item.listItemElement.textContent = "";
item._newProperty = true;
item.updateTitle();
return item;
},

_debugShowStyle: function(anchor)
{
var boundHandler;
function removeStyleBox(element, event)
{
if (event.target === element) {
event.stopPropagation();
return;
}
document.body.removeChild(element);
document.getElementById("main").removeEventListener("mousedown", boundHandler, true);
}

if (!event.shiftKey)
return;

var container = document.createElement("div");
var element = document.createElement("span");
container.appendChild(element);
element.style.background = "yellow";
element.style.display = "inline-block";
container.style.cssText = "z-index: 2000000; position: absolute; top: 50px; left: 50px; white-space: pre; overflow: auto; background: white; font-family: monospace; font-size: 12px; border: 1px solid black; opacity: 0.85; -webkit-user-select: text; padding: 2px;";
container.style.width = (document.body.offsetWidth - 100) + "px";
container.style.height = (document.body.offsetHeight - 100) + "px";
document.body.appendChild(container);
if (this.rule)
element.textContent = this.rule.selectorText + " {" + ((this.styleRule.style.cssText !== undefined) ? this.styleRule.style.cssText : "<no cssText>") + "}";
else
element.textContent = this.styleRule.style.cssText;
boundHandler = removeStyleBox.bind(null, container);
document.getElementById("main").addEventListener("mousedown", boundHandler, true);
},

_handleEmptySpaceDoubleClick: function(event)
{
if (event.target.hasStyleClass("header") || this.element.hasStyleClass("read-only")) {
event.stopPropagation();
return;
}
this.expand();
this.addNewBlankProperty().startEditing();
},

_handleSelectorClick: function(event)
{
event.stopPropagation();
},

_handleSelectorDoubleClick: function(event)
{
this._startEditingOnMouseEvent();
event.stopPropagation();
},

_startEditingOnMouseEvent: function()
{
if (!this.editable)
return;

if (!this.rule && this.propertiesTreeOutline.children.length === 0) {
this.expand();
this.addNewBlankProperty().startEditing();
return;
}

if (!this.rule)
return;

this.startEditingSelector();
},

startEditingSelector: function()
{
var element = this._selectorElement;
if (WebInspector.isBeingEdited(element))
return;

WebInspector.startEditing(this._selectorElement, {
context: null,
commitHandler: this.editingSelectorCommitted.bind(this),
cancelHandler: this.editingSelectorCancelled.bind(this)
});
window.getSelection().setBaseAndExtent(element, 0, element, 1);
},

editingSelectorCommitted: function(element, newContent, oldContent, context, moveDirection)
{
function moveToNextIfNeeded() {
if (!moveDirection)
return;

if (moveDirection === "forward") {
this.expand();
if (this.propertiesTreeOutline.children.length === 0)
this.addNewBlankProperty().startEditing();
else {
var item = this.propertiesTreeOutline.children[0]
item.startEditing(item.nameElement);
}
} else {
var previousSection = this.previousEditableSibling();
if (!previousSection)
return;

previousSection.expand();
previousSection.addNewBlankProperty().startEditing();
}
}

if (newContent === oldContent)
return moveToNextIfNeeded.call(this);

var self = this;

function successCallback(newRule, doesAffectSelectedNode)
{
if (!doesAffectSelectedNode) {
self.noAffect = true;
self.element.addStyleClass("no-affect");
} else {
delete self.noAffect;
self.element.removeStyleClass("no-affect");
}

self.rule = newRule;
self.styleRule = { section: self, style: newRule.style, selectorText: newRule.selectorText, sourceURL: newRule.sourceURL, rule: newRule };

var oldIdentifier = this.identifier;
self.identifier = newRule.selectorText + ":" + self.subtitleElement.textContent;

self.pane.update();

WebInspector.panels.elements.renameSelector(oldIdentifier, this.identifier, oldContent, newContent);

moveToNextIfNeeded.call(self);
}

var focusedNode = WebInspector.panels.elements.focusedDOMNode;
WebInspector.cssModel.setRuleSelector(this.rule.id, focusedNode ? focusedNode.id : 0, newContent, successCallback, moveToNextIfNeeded.bind(this));
},

editingSelectorCancelled: function()
{

}
}

WebInspector.StylePropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;

WebInspector.ComputedStylePropertiesSection = function(styleRule, usedProperties, disabledComputedProperties)
{
WebInspector.PropertiesSection.call(this, "");
this.headerElement.addStyleClass("hidden");
this.element.className = "styles-section monospace first-styles-section read-only computed-style";
this.styleRule = styleRule;
this._usedProperties = usedProperties;
this._disabledComputedProperties = disabledComputedProperties;
this._alwaysShowComputedProperties = { "display": true, "height": true, "width": true };
this.computedStyle = true;
this._propertyTreeElements = {};
this._expandedPropertyNames = {};
}

WebInspector.ComputedStylePropertiesSection.prototype = {
collapse: function(dontRememberState)
{

},

_isPropertyInherited: function(propertyName)
{
return !(propertyName in this._usedProperties) && !(propertyName in this._alwaysShowComputedProperties) && !(propertyName in this._disabledComputedProperties);
},

update: function()
{
this._expandedPropertyNames = {};
for (var name in this._propertyTreeElements) {
if (this._propertyTreeElements[name].expanded)
this._expandedPropertyNames[name] = true;
}
this._propertyTreeElements = {};
this.propertiesTreeOutline.removeChildren();
this.populated = false;
},

onpopulate: function()
{
function sorter(a, b)
{
return a.name.localeCompare(b.name);
}

var style = this.styleRule.style;
var uniqueProperties = [];
var allProperties = style.allProperties;
for (var i = 0; i < allProperties.length; ++i)
uniqueProperties.push(allProperties[i]);
uniqueProperties.sort(sorter);

this._propertyTreeElements = {};
for (var i = 0; i < uniqueProperties.length; ++i) {
var property = uniqueProperties[i];
var inherited = this._isPropertyInherited(property.name);
var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this.styleRule, style, property, false, inherited, false);
this.propertiesTreeOutline.appendChild(item);
this._propertyTreeElements[property.name] = item;
}
},

rebuildComputedTrace: function(sections)
{
for (var i = 0; i < sections.length; ++i) {
var section = sections[i];
if (section.computedStyle || section instanceof WebInspector.BlankStylePropertiesSection)
continue;

for (var j = 0; j < section.uniqueProperties.length; ++j) {
var property = section.uniqueProperties[j];
if (property.disabled)
continue;
if (section.isInherited && !(property.name in WebInspector.StylesSidebarPane.InheritedProperties))
continue;

var treeElement = this._propertyTreeElements[property.name];
if (treeElement) {
var selectorText = section.styleRule.selectorText;
var value = property.value;
var title = "<span style='color: gray'>" + selectorText + "</span> - " + value;
var subtitle = " <span style='float:right'>" + section.subtitleElement.innerHTML + "</span>";
var childElement = new TreeElement(null, null, false);
childElement.titleHTML = title + subtitle;
treeElement.appendChild(childElement);
if (section.isPropertyOverloaded(property.name))
childElement.listItemElement.addStyleClass("overloaded");
if (!property.parsedOk)
childElement.listItemElement.addStyleClass("not-parsed-ok");
}
}
}


for (var name in this._expandedPropertyNames) {
if (name in this._propertyTreeElements)
this._propertyTreeElements[name].expand();
}
}
}

WebInspector.ComputedStylePropertiesSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;

WebInspector.BlankStylePropertiesSection = function(parentPane, defaultSelectorText)
{
WebInspector.StylePropertiesSection.call(this, parentPane, {selectorText: defaultSelectorText, rule: {isViaInspector: true}}, true, false, false);
this.element.addStyleClass("blank-section");
}

WebInspector.BlankStylePropertiesSection.prototype = {
expand: function()
{

},

editingSelectorCommitted: function(element, newContent, oldContent, context)
{
var self = this;
function successCallback(newRule, doesSelectorAffectSelectedNode)
{
var styleRule = { section: self, style: newRule.style, selectorText: newRule.selectorText, sourceURL: newRule.sourceURL, rule: newRule };
self.makeNormal(styleRule);

if (!doesSelectorAffectSelectedNode) {
self.noAffect = true;
self.element.addStyleClass("no-affect");
}

self.subtitleElement.textContent = WebInspector.UIString("via inspector");
self.expand();

self.addNewBlankProperty().startEditing();
}

WebInspector.cssModel.addRule(this.pane.node.id, newContent, successCallback, this.editingSelectorCancelled.bind(this));
},

editingSelectorCancelled: function()
{
this.pane.removeSection(this);
},

makeNormal: function(styleRule)
{
this.element.removeStyleClass("blank-section");
this.styleRule = styleRule;
this.rule = styleRule.rule;
this.identifier = styleRule.selectorText + ":via inspector";
this.__proto__ = WebInspector.StylePropertiesSection.prototype;
}
}

WebInspector.BlankStylePropertiesSection.prototype.__proto__ = WebInspector.StylePropertiesSection.prototype;

WebInspector.StylePropertyTreeElement = function(parentPane, styleRule, style, property, shorthand, inherited, overloaded)
{
this._parentPane = parentPane;
this._styleRule = styleRule;
this.style = style;
this.property = property;
this.shorthand = shorthand;
this._inherited = inherited;
this._overloaded = overloaded;


TreeElement.call(this, "", null, shorthand);
}

WebInspector.StylePropertyTreeElement.prototype = {
get inherited()
{
return this._inherited;
},

set inherited(x)
{
if (x === this._inherited)
return;
this._inherited = x;
this.updateState();
},

get overloaded()
{
return this._overloaded;
},

set overloaded(x)
{
if (x === this._overloaded)
return;
this._overloaded = x;
this.updateState();
},

get disabled()
{
return this.property.disabled;
},

get name()
{
if (!this.disabled || !this.property.text)
return this.property.name;

var text = this.property.text;
var index = text.indexOf(":");
if (index < 1)
return this.property.name;

return text.substring(0, index).trim();
},

get priority()
{
if (this.disabled)
return ""; 
return this.property.priority;
},

get value()
{
if (!this.disabled || !this.property.text)
return this.property.value;

var match = this.property.text.match(/(.*);\s*/);
if (!match || !match[1])
return this.property.value;

var text = match[1];
var index = text.indexOf(":");
if (index < 1)
return this.property.value;

return text.substring(index + 1).trim();
},

get parsedOk()
{
return this.property.parsedOk;
},

onattach: function()
{
this.updateTitle();
},

updateTitle: function()
{
var value = this.value;

this.updateState();

var enabledCheckboxElement;
if (this.parsedOk) {
enabledCheckboxElement = document.createElement("input");
enabledCheckboxElement.className = "enabled-button";
enabledCheckboxElement.type = "checkbox";
enabledCheckboxElement.checked = !this.disabled;
enabledCheckboxElement.addEventListener("change", this.toggleEnabled.bind(this), false);
}

var nameElement = document.createElement("span");
nameElement.className = "webkit-css-property";
nameElement.textContent = this.name;
this.nameElement = nameElement;

var valueElement = document.createElement("span");
valueElement.className = "value";
this.valueElement = valueElement;

if (value) {
var self = this;

function processValue(regex, processor, nextProcessor, valueText)
{
var container = document.createDocumentFragment();

var items = valueText.replace(regex, "\0$1\0").split("\0");
for (var i = 0; i < items.length; ++i) {
if ((i % 2) === 0) {
if (nextProcessor)
container.appendChild(nextProcessor(items[i]));
else
container.appendChild(document.createTextNode(items[i]));
} else {
var processedNode = processor(items[i]);
if (processedNode)
container.appendChild(processedNode);
}
}

return container;
}

function linkifyURL(url)
{
var hrefUrl = url;
var match = hrefUrl.match(/['"]?([^'"]+)/);
if (match)
hrefUrl = match[1];
var container = document.createDocumentFragment();
container.appendChild(document.createTextNode("url("));
if (self._styleRule.sourceURL)
hrefUrl = WebInspector.completeURL(self._styleRule.sourceURL, hrefUrl);
else if (WebInspector.panels.elements.focusedDOMNode)
hrefUrl = WebInspector.resourceURLForRelatedNode(WebInspector.panels.elements.focusedDOMNode, hrefUrl);
var hasResource = !!WebInspector.resourceForURL(hrefUrl);

container.appendChild(WebInspector.linkifyURLAsNode(hrefUrl, url, null, hasResource));
container.appendChild(document.createTextNode(")"));
return container;
}

function processColor(text)
{
try {
var color = new WebInspector.Color(text);
} catch (e) {
return document.createTextNode(text);
}

var swatchElement = document.createElement("span");
swatchElement.title = WebInspector.UIString("Click to change color format");
swatchElement.className = "swatch";
swatchElement.style.setProperty("background-color", text);

swatchElement.addEventListener("click", changeColorDisplay, false);
swatchElement.addEventListener("dblclick", function(event) { event.stopPropagation() }, false);

var format;
if (WebInspector.settings.colorFormat === "original")
format = "original";
else if (Preferences.showColorNicknames && color.nickname)
format = "nickname";
else if (WebInspector.settings.colorFormat === "rgb")
format = (color.simple ? "rgb" : "rgba");
else if (WebInspector.settings.colorFormat === "hsl")
format = (color.simple ? "hsl" : "hsla");
else if (color.simple)
format = (color.hasShortHex() ? "shorthex" : "hex");
else
format = "rgba";

var colorValueElement = document.createElement("span");
colorValueElement.textContent = color.toString(format);

function nextFormat(curFormat)
{








switch (curFormat) {
case "original":
return color.simple ? "rgb" : "rgba";

case "rgb":
case "rgba":
return color.simple ? "hsl" : "hsla";

case "hsl":
case "hsla":
if (color.nickname)
return "nickname";
if (color.simple)
return color.hasShortHex() ? "shorthex" : "hex";
else
return "original";

case "shorthex":
return "hex";

case "hex":
return "original";

case "nickname":
if (color.simple)
return color.hasShortHex() ? "shorthex" : "hex";
else
return "original";

default:
return null;
}
}

function changeColorDisplay(event)
{
do {
format = nextFormat(format);
var currentValue = color.toString(format || "");
} while (format && currentValue === color.value && format !== "original");

if (format)
colorValueElement.textContent = currentValue;
}

var container = document.createDocumentFragment();
container.appendChild(swatchElement);
container.appendChild(colorValueElement);
return container;
}

var colorRegex = /((?:rgb|hsl)a?\([^)]+\)|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3}|\b\w+\b(?!-))/g;
var colorProcessor = processValue.bind(window, colorRegex, processColor, null);

valueElement.appendChild(processValue(/url\(\s*([^)\s]+)\s*\)/g, linkifyURL, WebInspector.CSSKeywordCompletions.isColorAwareProperty(self.name) ? colorProcessor : null, value));
}

this.listItemElement.removeChildren();
nameElement.normalize();
valueElement.normalize();

if (!this.treeOutline)
return;


if (enabledCheckboxElement && this.treeOutline.section && this.treeOutline.section.editable && this.parent.root)
this.listItemElement.appendChild(enabledCheckboxElement);
this.listItemElement.appendChild(nameElement);
this.listItemElement.appendChild(document.createTextNode(": "));
this.listItemElement.appendChild(valueElement);
this.listItemElement.appendChild(document.createTextNode(";"));

if (!this.parsedOk) {

this.hasChildren = false;
this.listItemElement.addStyleClass("not-parsed-ok");
}
if (this.property.inactive)
this.listItemElement.addStyleClass("inactive");

this.tooltip = this.property.propertyText;
},

updateAll: function(updateAllRules)
{
if (!this.treeOutline)
return;
if (updateAllRules && this.treeOutline.section && this.treeOutline.section.pane)
this.treeOutline.section.pane.update(null, this.treeOutline.section);
else if (this.treeOutline.section)
this.treeOutline.section.update(true);
else
this.updateTitle(); 
},

toggleEnabled: function(event)
{
var disabled = !event.target.checked;

function callback(newStyle)
{
if (!newStyle)
return;

this.style = newStyle;
this._styleRule.style = newStyle;

if (this.treeOutline.section && this.treeOutline.section.pane)
this.treeOutline.section.pane.dispatchEventToListeners("style property toggled");

this.updateAll(true);
}

this.property.setDisabled(disabled, callback.bind(this));
},

updateState: function()
{
if (!this.listItemElement)
return;

if (this.style.isPropertyImplicit(this.name) || this.value === "initial")
this.listItemElement.addStyleClass("implicit");
else
this.listItemElement.removeStyleClass("implicit");

this.selectable = !this.inherited;
if (this.inherited)
this.listItemElement.addStyleClass("inherited");
else
this.listItemElement.removeStyleClass("inherited");

if (this.overloaded)
this.listItemElement.addStyleClass("overloaded");
else
this.listItemElement.removeStyleClass("overloaded");

if (this.disabled)
this.listItemElement.addStyleClass("disabled");
else
this.listItemElement.removeStyleClass("disabled");
},

onpopulate: function()
{

if (this.children.length || !this.shorthand)
return;

var longhandProperties = this.style.getLonghandProperties(this.name);
for (var i = 0; i < longhandProperties.length; ++i) {
var name = longhandProperties[i].name;


if (this.treeOutline.section) {
var inherited = this.treeOutline.section.isPropertyInherited(name);
var overloaded = this.treeOutline.section.isPropertyOverloaded(name);
}

var liveProperty = this.style.getLiveProperty(name);
var item = new WebInspector.StylePropertyTreeElement(this._parentPane, this._styleRule, this.style, liveProperty, false, inherited, overloaded);
this.appendChild(item);
}
},

ondblclick: function(event)
{
this.startEditing(event.target);
event.stopPropagation();
},

restoreNameElement: function()
{

if (this.nameElement === this.listItemElement.querySelector(".webkit-css-property"))
return;

this.nameElement = document.createElement("span");
this.nameElement.className = "webkit-css-property";
this.nameElement.textContent = "";
this.listItemElement.insertBefore(this.nameElement, this.listItemElement.firstChild);
},

startEditing: function(selectElement)
{

if (this.parent.shorthand)
return;

if (this.treeOutline.section && !this.treeOutline.section.editable)
return;

if (!selectElement)
selectElement = this.nameElement; 
else
selectElement = selectElement.enclosingNodeOrSelfWithClass("webkit-css-property") || selectElement.enclosingNodeOrSelfWithClass("value");

var isEditingName = selectElement === this.nameElement;
if (!isEditingName && selectElement !== this.valueElement) {

isEditingName = false;
selectElement = this.valueElement;
}

if (WebInspector.isBeingEdited(selectElement))
return;

var context = {
expanded: this.expanded,
hasChildren: this.hasChildren,
keyDownListener: isEditingName ? null : this.editingValueKeyDown.bind(this),
isEditingName: isEditingName,
};


this.hasChildren = false;

if (!isEditingName)
selectElement.addEventListener("keydown", context.keyDownListener, false);
if (selectElement.parentElement)
selectElement.parentElement.addStyleClass("child-editing");
selectElement.textContent = selectElement.textContent; 

function shouldCommitValueSemicolon(text, cursorPosition)
{

var openQuote = "";
for (var i = 0; i < cursorPosition; ++i) {
var ch = text[i];
if (ch === "\\" && openQuote !== "")
++i; 
else if (!openQuote && (ch === "\"" || ch === "'"))
openQuote = ch;
else if (openQuote === ch)
openQuote = "";
}
return !openQuote;
}

function nameValueFinishHandler(context, isEditingName, event)
{

var isFieldInputTerminated = (event.keyCode === WebInspector.KeyboardShortcut.Keys.Semicolon.code) &&
(isEditingName ? event.shiftKey : (!event.shiftKey && shouldCommitValueSemicolon(event.target.textContent, event.target.selectionLeftOffset)));
if (isEnterKey(event) || isFieldInputTerminated) {

event.preventDefault();
return "move-forward";
} else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code || event.keyIdentifier === "U+001B")
return "cancel";
else if (!isEditingName && this._newProperty && event.keyCode === WebInspector.KeyboardShortcut.Keys.Backspace.code) {

var selection = window.getSelection();
if (selection.isCollapsed && !selection.focusOffset) {
event.preventDefault();
return "move-backward";
}
} else if (event.keyIdentifier === "U+0009") 
return "move-" + (event.shiftKey ? "backward" : "forward");
}

function pasteHandler(context, event)
{
var data = event.clipboardData.getData("Text");
if (!data)
return;
var colonIdx = data.indexOf(":");
if (colonIdx < 0)
return;
var name = data.substring(0, colonIdx).trim();
var value = data.substring(colonIdx + 1).trim();

event.preventDefault();

if (!("originalName" in context)) {
context.originalName = this.nameElement.textContent;
context.originalValue = this.valueElement.textContent;
}
this.nameElement.textContent = name;
this.valueElement.textContent = value;
this.nameElement.normalize();
this.valueElement.normalize();

return "move-forward";
}

delete this.originalPropertyText;
WebInspector.panels.elements.startEditingStyle();
WebInspector.startEditing(selectElement, {
context: context,
commitHandler: this.editingCommitted.bind(this),
cancelHandler: this.editingCancelled.bind(this),
customFinishHandler: nameValueFinishHandler.bind(this, context, isEditingName),
pasteHandler: isEditingName ? pasteHandler.bind(this, context) : null
});

this._prompt = new WebInspector.StylesSidebarPane.CSSPropertyPrompt(selectElement, isEditingName ? WebInspector.cssNameCompletions : WebInspector.CSSKeywordCompletions.forProperty(this.nameElement.textContent));
window.getSelection().setBaseAndExtent(selectElement, 0, selectElement, 1);
},

editingValueKeyDown: function(event)
{
if (event.handled)
return;
if (this._handleUpOrDownKeyPressed(event))
return;

this._applyFreeFlowStyleTextEdit();
},

_applyFreeFlowStyleTextEdit: function(now)
{
if (this._applyFreeFlowStyleTextEditTimer)
clearTimeout(this._applyFreeFlowStyleTextEditTimer);

function apply()
{
this.applyStyleText(this.nameElement.textContent + ": " + this.valueElement.textContent);
}
if (now)
apply.call(this);
else
this._applyFreeFlowStyleTextEditTimer = setTimeout(apply.bind(this), 100);
},

kickFreeFlowStyleEditForTest: function()
{
this._applyFreeFlowStyleTextEdit(true);
},

_handleUpOrDownKeyPressed: function(event)
{
var arrowKeyPressed = (event.keyIdentifier === "Up" || event.keyIdentifier === "Down");
var pageKeyPressed = (event.keyIdentifier === "PageUp" || event.keyIdentifier === "PageDown");
if (!arrowKeyPressed && !pageKeyPressed)
return false;

var selection = window.getSelection();
if (!selection.rangeCount)
return false;

var selectionRange = selection.getRangeAt(0);
if (selectionRange.commonAncestorContainer !== this.valueElement && !selectionRange.commonAncestorContainer.isDescendant(this.valueElement))
return false;

var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, WebInspector.StylesSidebarPane.StyleValueDelimiters, this.valueElement);
var wordString = wordRange.toString();
var replacementString;
var prefix, suffix, number;

var matches;
matches = /(.*#)([\da-fA-F]+)(.*)/.exec(wordString);
if (matches && matches.length) {
prefix = matches[1];
suffix = matches[3];
number = WebInspector.StylesSidebarPane.alteredHexNumber(matches[2], event);

replacementString = prefix + number + suffix;
} else {
matches = /(.*?)(-?(?:\d+(?:\.\d+)?|\.\d+))(.*)/.exec(wordString);
if (matches && matches.length) {
prefix = matches[1];
suffix = matches[3];
number = WebInspector.StylesSidebarPane.alteredFloatNumber(parseFloat(matches[2]), event);
if (number === null) {

return false;
}

replacementString = prefix + number + suffix;
}
}

if (replacementString) {
var replacementTextNode = document.createTextNode(replacementString);

wordRange.deleteContents();
wordRange.insertNode(replacementTextNode);

var finalSelectionRange = document.createRange();
finalSelectionRange.setStart(replacementTextNode, 0);
finalSelectionRange.setEnd(replacementTextNode, replacementString.length);

selection.removeAllRanges();
selection.addRange(finalSelectionRange);

event.handled = true;
event.preventDefault();


this.applyStyleText(this.nameElement.textContent + ": " + this.valueElement.textContent);
}
return true;
},

editingEnded: function(context)
{
if (this._applyFreeFlowStyleTextEditTimer)
clearTimeout(this._applyFreeFlowStyleTextEditTimer);

this.hasChildren = context.hasChildren;
if (context.expanded)
this.expand();
var editedElement = context.isEditingName ? this.nameElement : this.valueElement;
if (!context.isEditingName)
editedElement.removeEventListener("keydown", context.keyDownListener, false);
if (editedElement.parentElement)
editedElement.parentElement.removeStyleClass("child-editing");

WebInspector.panels.elements.endEditingStyle();
},

editingCancelled: function(element, context)
{
this._removePrompt();
this._revertStyleUponEditingCanceled(this.originalPropertyText);

this.editingEnded(context);
},

_revertStyleUponEditingCanceled: function(originalPropertyText)
{
if (typeof originalPropertyText === "string") {
delete this.originalPropertyText;
this.applyStyleText(originalPropertyText, true, false, true);
} else {
if (this._newProperty)
this.treeOutline.removeChild(this);
else
this.updateTitle();
}
}, 

editingCommitted: function(element, userInput, previousContent, context, moveDirection)
{
this._removePrompt();
this.editingEnded(context);
var isEditingName = context.isEditingName;


var createNewProperty, moveToPropertyName, moveToSelector;
var moveTo = this;
var moveToOther = (isEditingName ^ (moveDirection === "forward"));
var abandonNewProperty = this._newProperty && !userInput && (moveToOther || isEditingName);
if (moveDirection === "forward" && !isEditingName || moveDirection === "backward" && isEditingName) {
do {
moveTo = (moveDirection === "forward" ? moveTo.nextSibling : moveTo.previousSibling);
} while(moveTo && !moveTo.selectable);

if (moveTo)
moveToPropertyName = moveTo.name;
else if (moveDirection === "forward" && (!this._newProperty || userInput))
createNewProperty = true;
else if (moveDirection === "backward" && this.treeOutline.section.rule)
moveToSelector = true;
}


var blankInput = /^\s*$/.test(userInput);
var isDataPasted = "originalName" in context;
var isDirtyViaPaste = isDataPasted && (this.nameElement.textContent !== context.originalName || this.valueElement.textContent !== context.originalValue);
var shouldCommitNewProperty = this._newProperty && (moveToOther || (!moveDirection && !isEditingName) || (isEditingName && blankInput));
if (((userInput !== previousContent || isDirtyViaPaste) && !this._newProperty) || shouldCommitNewProperty) {
WebInspector.panels.elements.startEditingStyle();
this.treeOutline.section._afterUpdate = moveToNextCallback.bind(this, this._newProperty, !blankInput, this.treeOutline.section);
var propertyText;
if (blankInput || (this._newProperty && /^\s*$/.test(this.valueElement.textContent)))
propertyText = "";
else {
if (isEditingName)
propertyText = userInput + ": " + this.valueElement.textContent;
else
propertyText = this.nameElement.textContent + ": " + userInput;
}
this.applyStyleText(propertyText, true, true);
} else {
if (!isDataPasted && !this._newProperty)
this.updateTitle();
moveToNextCallback.call(this, this._newProperty, false, this.treeOutline.section);
}

var moveToIndex = moveTo && this.treeOutline ? this.treeOutline.children.indexOf(moveTo) : -1;


function moveToNextCallback(alreadyNew, valueChanged, section)
{
WebInspector.panels.elements.endEditingStyle();

if (!moveDirection)
return;


if (moveTo && moveTo.parent) {
moveTo.startEditing(!isEditingName ? moveTo.nameElement : moveTo.valueElement);
return;
}



if (moveTo && !moveTo.parent) {
var propertyElements = section.propertiesTreeOutline.children;
if (moveDirection === "forward" && blankInput && !isEditingName)
--moveToIndex;
if (moveToIndex >= propertyElements.length && !this._newProperty)
createNewProperty = true;
else {
var treeElement = moveToIndex >= 0 ? propertyElements[moveToIndex] : null;
if (treeElement) {
treeElement.startEditing(!isEditingName ? treeElement.nameElement : treeElement.valueElement);
return;
} else if (!alreadyNew)
moveToSelector = true;
}
}


if (createNewProperty) {
if (alreadyNew && !valueChanged && (isEditingName ^ (moveDirection === "backward")))
return;

section.addNewBlankProperty().startEditing();
return;
}

if (abandonNewProperty) {
var sectionToEdit = moveDirection === "backward" ? section : section.nextEditableSibling();
if (sectionToEdit && sectionToEdit.rule)
sectionToEdit.startEditingSelector();
return;
}

if (moveToSelector)
section.startEditingSelector();
}
},

_removePrompt: function()
{

if (this._prompt) {
this._prompt.removeFromElement();
delete this._prompt;
}
},

_hasBeenModifiedIncrementally: function()
{


return typeof this.originalPropertyText === "string";
},

applyStyleText: function(styleText, updateInterface, majorChange, isRevert)
{

if (!isRevert && !updateInterface && !this._hasBeenModifiedIncrementally()) {


this.originalPropertyText = this.property.propertyText;
}

var section = this.treeOutline.section;
var elementsPanel = WebInspector.panels.elements;
styleText = styleText.replace(/\s/g, " ").trim(); 
var styleTextLength = styleText.length;
if (!styleTextLength && updateInterface && !isRevert && this._newProperty && !this._hasBeenModifiedIncrementally()) {

this.parent.removeChild(this);
section.afterUpdate();
return;
}

function callback(originalPropertyText, newStyle)
{
if (!newStyle) {
if (updateInterface) {

this._revertStyleUponEditingCanceled(originalPropertyText);
}
return;
}

this.style = newStyle;
this.property = newStyle.propertyAt(this.property.index);
this._styleRule.style = this.style;

if (section && section.pane)
section.pane.dispatchEventToListeners("style edited");

if (updateInterface)
this.updateAll(true);
}



if (styleText.length && !/;\s*$/.test(styleText))
styleText += ";";
this.property.setText(styleText, majorChange, callback.bind(this, this.originalPropertyText));
}
}

WebInspector.StylePropertyTreeElement.prototype.__proto__ = TreeElement.prototype;

WebInspector.StylesSidebarPane.CSSPropertyPrompt = function(element, cssCompletions)
{
WebInspector.TextPrompt.call(this, element, this._buildPropertyCompletions.bind(this), WebInspector.StylesSidebarPane.StyleValueDelimiters, true);
this._cssCompletions = cssCompletions;
}

WebInspector.StylesSidebarPane.CSSPropertyPrompt.prototype = {
upKeyPressed: function(event)
{
this._handleNameOrValueUpDown(event);
},

downKeyPressed: function(event)
{
this._handleNameOrValueUpDown(event);
},

tabKeyPressed: function(event)
{
this.acceptAutoComplete();
},

_handleNameOrValueUpDown: function(event)
{
var reverse = event.keyIdentifier === "Up";
if (this.autoCompleteElement)
this.complete(false, reverse); 
else {

this._selectCurrentWordSuffix();
}

this.complete(false, reverse); 
event.handled = true;
},

_selectCurrentWordSuffix: function()
{
var selection = window.getSelection();
if (!selection.rangeCount)
return;

var selectionRange = selection.getRangeAt(0);
if (!selectionRange.commonAncestorContainer.isDescendant(this.element))
return;
var wordSuffixRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, WebInspector.StylesSidebarPane.StyleValueDelimiters, this.element, "forward");
if (!wordSuffixRange.toString())
return;
selection.removeAllRanges();
selection.addRange(wordSuffixRange);
},

_buildPropertyCompletions: function(wordRange, bestMatchOnly, completionsReadyCallback)
{
var prefix = wordRange.toString().toLowerCase();
if (!prefix && bestMatchOnly)
return;

var results;
if (bestMatchOnly) {
results = [];
var firstMatch = this._cssCompletions.firstStartsWith(prefix);
if (firstMatch)
results.push(firstMatch);
return completionsReadyCallback(results);
}

results = this._cssCompletions.startsWith(prefix);
if (results)
completionsReadyCallback(results);
}
}

WebInspector.StylesSidebarPane.CSSPropertyPrompt.prototype.__proto__ = WebInspector.TextPrompt.prototype;





WebInspector.PanelEnablerView = function(identifier, headingText, disclaimerText, buttonTitle)
{
WebInspector.View.call(this);

this.element.addStyleClass("panel-enabler-view");
this.element.addStyleClass(identifier);

this.contentElement = document.createElement("div");
this.contentElement.className = "panel-enabler-view-content";
this.element.appendChild(this.contentElement);

this.imageElement = document.createElement("img");
this.contentElement.appendChild(this.imageElement);

this.choicesForm = document.createElement("form");
this.contentElement.appendChild(this.choicesForm);

this.headerElement = document.createElement("h1");
this.headerElement.textContent = headingText;
this.choicesForm.appendChild(this.headerElement);

var self = this;
function enableOption(text, checked) {
var label = document.createElement("label");
var option = document.createElement("input");
option.type = "radio";
option.name = "enable-option";
if (checked)
option.checked = true;
label.appendChild(option);
label.appendChild(document.createTextNode(text));
self.choicesForm.appendChild(label);
return option;
};

this.enabledForSession = enableOption(WebInspector.UIString("Only enable for this session"), true);
this.enabledAlways = enableOption(WebInspector.UIString("Always enable"));

this.disclaimerElement = document.createElement("div");
this.disclaimerElement.className = "panel-enabler-disclaimer";
this.disclaimerElement.textContent = disclaimerText;
this.choicesForm.appendChild(this.disclaimerElement);

this.enableButton = document.createElement("button");
this.enableButton.setAttribute("type", "button");
this.enableButton.textContent = buttonTitle;
this.enableButton.addEventListener("click", this._enableButtonCicked.bind(this), false);
this.choicesForm.appendChild(this.enableButton);
}

WebInspector.PanelEnablerView.prototype = {
_enableButtonCicked: function()
{
this.dispatchEventToListeners("enable clicked");
},

show: function(parentElement)
{
WebInspector.View.prototype.show.call(this, parentElement);

setTimeout(this.resize.bind(this), 0);
},

resize: function()
{
this.imageElement.removeStyleClass("hidden");

if (this.element.offsetWidth < (this.choicesForm.offsetWidth + this.imageElement.offsetWidth))
this.imageElement.addStyleClass("hidden");
},

get alwaysEnabled() {
return this.enabledAlways.checked;
}
}

WebInspector.PanelEnablerView.prototype.__proto__ = WebInspector.View.prototype;





WebInspector.WelcomeView = function(identifier, headingText, instructionsText)
{
WebInspector.View.call(this);

this.element.addStyleClass("panel-enabler-view");
this.element.addStyleClass(identifier);
this.element.addStyleClass("welcome");

this.contentElement = document.createElement("div");
this.contentElement.className = "panel-enabler-view-content";
this.element.appendChild(this.contentElement);

this.alignerElement = document.createElement("div");
this.alignerElement.className = "welcome-instructions-aligner";
this.contentElement.appendChild(this.alignerElement);

this.instructionsElement = document.createElement("div");
this.instructionsElement.className = "instructions";
this.contentElement.appendChild(this.instructionsElement);

this.headerElement = document.createElement("h1");
this.headerElement.textContent = headingText;
this.instructionsElement.appendChild(this.headerElement);

if (instructionsText)
this.addMessage(instructionsText);
}

WebInspector.WelcomeView.prototype = {
addMessage: function(message)
{
var messageElement = document.createElement("div");
messageElement.className = "message";
if (typeof message == "string")


messageElement.innerHTML = message;
else
messageElement.appendChild(message);
this.instructionsElement.appendChild(messageElement);
}
}

WebInspector.WelcomeView.prototype.__proto__ = WebInspector.View.prototype;





WebInspector.StatusBarButton = function(title, className, states)
{
this.element = document.createElement("button");
this.element.className = className + " status-bar-item";
this.element.addEventListener("click", this._clicked.bind(this), false);

this.glyph = document.createElement("div");
this.glyph.className = "glyph";
this.element.appendChild(this.glyph);

this.glyphShadow = document.createElement("div");
this.glyphShadow.className = "glyph shadow";
this.element.appendChild(this.glyphShadow);

this.states = states;
if (!states)
this.states = 2;

if (states == 2)
this._state = false;
else
this._state = 0;

this.title = title;
this.disabled = false;
this._visible = true;
}

WebInspector.StatusBarButton.prototype = {
_clicked: function()
{
this.dispatchEventToListeners("click");
},

get disabled()
{
return this._disabled;
},

set disabled(x)
{
if (this._disabled === x)
return;
this._disabled = x;
this.element.disabled = x;
},

get title()
{
return this._title;
},

set title(x)
{
if (this._title === x)
return;
this._title = x;
this.element.title = x;
},

get state()
{
return this._state;
},

set state(x)
{
if (this._state === x)
return;

if (this.states === 2) {
if (x)
this.element.addStyleClass("toggled-on");
else
this.element.removeStyleClass("toggled-on");
} else {
if (x !== 0) {
this.element.removeStyleClass("toggled-" + this._state);
this.element.addStyleClass("toggled-" + x);
} else 
this.element.removeStyleClass("toggled-" + this._state);
}
this._state = x;
},

get toggled()
{
if (this.states !== 2)
throw("Only used toggled when there are 2 states, otherwise, use state");
return this.state;
},

set toggled(x)
{
if (this.states !== 2)
throw("Only used toggled when there are 2 states, otherwise, use state");
this.state = x;
},

get visible()
{
return this._visible;
},

set visible(x)
{
if (this._visible === x)
return;

if (x)
this.element.removeStyleClass("hidden");
else
this.element.addStyleClass("hidden");
this._visible = x;
}
}

WebInspector.StatusBarButton.prototype.__proto__ = WebInspector.Object.prototype;





WebInspector.SummaryBar = function(categories)
{
this.categories = categories;

this.element = document.createElement("div");
this.element.className = "summary-bar";

this.graphElement = document.createElement("canvas");
this.graphElement.setAttribute("width", "450");
this.graphElement.setAttribute("height", "38");
this.graphElement.className = "summary-graph";
this.element.appendChild(this.graphElement);

this.legendElement = document.createElement("div");
this.legendElement.className = "summary-graph-legend";
this.element.appendChild(this.legendElement);
}

WebInspector.SummaryBar.prototype = {

get calculator() {
return this._calculator;
},

set calculator(x) {
this._calculator = x;
},

reset: function()
{
this.legendElement.removeChildren();
this._drawSummaryGraph();
},

update: function(data)
{
var graphInfo = this.calculator.computeSummaryValues(data);

var fillSegments = [];

this.legendElement.removeChildren();

for (var category in this.categories) {
var size = graphInfo.categoryValues[category];
if (!size)
continue;

var colorString = this.categories[category].color;

var fillSegment = {color: colorString, value: size};
fillSegments.push(fillSegment);

var legendLabel = this._makeLegendElement(this.categories[category].title, this.calculator.formatValue(size), colorString);
this.legendElement.appendChild(legendLabel);
}

if (graphInfo.total) {
var totalLegendLabel = this._makeLegendElement(WebInspector.UIString("Total"), this.calculator.formatValue(graphInfo.total));
totalLegendLabel.addStyleClass("total");
this.legendElement.appendChild(totalLegendLabel);
}

this._drawSummaryGraph(fillSegments);
},

_drawSwatch: function(canvas, color)
{
var ctx = canvas.getContext("2d");

function drawSwatchSquare() {
ctx.fillStyle = color;
ctx.fillRect(0, 0, 13, 13);

var gradient = ctx.createLinearGradient(0, 0, 13, 13);
gradient.addColorStop(0.0, "rgba(255, 255, 255, 0.2)");
gradient.addColorStop(1.0, "rgba(255, 255, 255, 0.0)");

ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 13, 13);

gradient = ctx.createLinearGradient(13, 13, 0, 0);
gradient.addColorStop(0.0, "rgba(0, 0, 0, 0.2)");
gradient.addColorStop(1.0, "rgba(0, 0, 0, 0.0)");

ctx.fillStyle = gradient;
ctx.fillRect(0, 0, 13, 13);

ctx.strokeStyle = "rgba(0, 0, 0, 0.6)";
ctx.strokeRect(0.5, 0.5, 12, 12);
}

ctx.clearRect(0, 0, 13, 24);

drawSwatchSquare();

ctx.save();

ctx.translate(0, 25);
ctx.scale(1, -1);

drawSwatchSquare();

ctx.restore();

this._fadeOutRect(ctx, 0, 13, 13, 13, 0.5, 0.0);
},

_drawSummaryGraph: function(segments)
{
if (!segments || !segments.length) {
segments = [{color: "white", value: 1}];
this._showingEmptySummaryGraph = true;
} else
delete this._showingEmptySummaryGraph;


var total = 0;
for (var i = 0; i < segments.length; ++i)
total += segments[i].value;


var percents = segments.map(function(s) { return Math.max(Math.round(100 * s.value / total), 1) });


var percentTotal = 0;
for (var i = 0; i < percents.length; ++i)
percentTotal += percents[i];



while (percentTotal > 100) {
for (var i = 0; i < percents.length && percentTotal > 100; ++i) {
if (percents[i] > 1) {
--percents[i];
--percentTotal;
}
}
}



while (percentTotal < 100) {
for (var i = 0; i < percents.length && percentTotal < 100; ++i) {
++percents[i];
++percentTotal;
}
}

var ctx = this.graphElement.getContext("2d");

var x = 0;
var y = 0;
var w = 450;
var h = 19;
var r = (h / 2);

function drawPillShadow()
{





ctx.beginPath();
ctx.moveTo(x + 4, y + h - 3 - 0.5);
ctx.lineTo(x + w - 4, y + h - 3 - 0.5);
ctx.closePath();

ctx.save();

ctx.shadowBlur = 2;
ctx.shadowColor = "rgba(0, 0, 0, 0.5)";
ctx.shadowOffsetX = 3;
ctx.shadowOffsetY = 5;

ctx.strokeStyle = "white";
ctx.lineWidth = 1;

ctx.stroke();

ctx.shadowOffsetX = -3;

ctx.stroke();

ctx.restore();

ctx.save();

ctx.globalCompositeOperation = "destination-out";
ctx.strokeStyle = "rgba(0, 0, 0, 1)";
ctx.lineWidth = 1;

ctx.stroke();

ctx.restore();
}

function drawPill()
{

ctx.beginPath();
ctx.moveTo(x, y + r);
ctx.lineTo(x, y + h - r);
ctx.arc(x + r, y + h - r, r, Math.PI, Math.PI / 2, true);
ctx.lineTo(x + w - r, y + h);
ctx.arc(x + w - r, y + h - r, r, Math.PI / 2, 0, true);
ctx.lineTo(x + w, y + r);
ctx.arc(x + w - r, y + r, r, 0, 3 * Math.PI / 2, true);
ctx.lineTo(x + r, y);
ctx.arc(x + r, y + r, r, Math.PI / 2, Math.PI, true);
ctx.closePath();


ctx.save();
ctx.clip();


var previousSegmentsWidth = 0;
for (var i = 0; i < segments.length; ++i) {
var segmentWidth = Math.round(w * percents[i] / 100);
ctx.fillStyle = segments[i].color;
ctx.fillRect(x + previousSegmentsWidth, y, segmentWidth, h);
previousSegmentsWidth += segmentWidth;
}


ctx.lineWidth = 1;
for (var i = 1; i < 20; ++i) {
ctx.beginPath();
ctx.moveTo(x + (i * Math.round(w / 20)) + 0.5, y);
ctx.lineTo(x + (i * Math.round(w / 20)) + 0.5, y + h);
ctx.closePath();

ctx.strokeStyle = "rgba(0, 0, 0, 0.2)";
ctx.stroke();

ctx.beginPath();
ctx.moveTo(x + (i * Math.round(w / 20)) + 1.5, y);
ctx.lineTo(x + (i * Math.round(w / 20)) + 1.5, y + h);
ctx.closePath();

ctx.strokeStyle = "rgba(255, 255, 255, 0.2)";
ctx.stroke();
}


var lightGradient = ctx.createLinearGradient(x, y, x, y + (h / 1.5));
lightGradient.addColorStop(0.0, "rgba(220, 220, 220, 0.6)");
lightGradient.addColorStop(0.4, "rgba(220, 220, 220, 0.2)");
lightGradient.addColorStop(1.0, "rgba(255, 255, 255, 0.0)");

var darkGradient = ctx.createLinearGradient(x, y + (h / 3), x, y + h);
darkGradient.addColorStop(0.0, "rgba(0, 0, 0, 0.0)");
darkGradient.addColorStop(0.8, "rgba(0, 0, 0, 0.2)");
darkGradient.addColorStop(1.0, "rgba(0, 0, 0, 0.5)");

ctx.fillStyle = darkGradient;
ctx.fillRect(x, y, w, h);

ctx.fillStyle = lightGradient;
ctx.fillRect(x, y, w, h);

ctx.restore();
}

ctx.clearRect(x, y, w, (h * 2));

drawPillShadow();
drawPill();

ctx.save();

ctx.translate(0, (h * 2) + 1);
ctx.scale(1, -1);

drawPill();

ctx.restore();

this._fadeOutRect(ctx, x, y + h + 1, w, h, 0.5, 0.0);
},

_fadeOutRect: function(ctx, x, y, w, h, a1, a2)
{
ctx.save();

var gradient = ctx.createLinearGradient(x, y, x, y + h);
gradient.addColorStop(0.0, "rgba(0, 0, 0, " + (1.0 - a1) + ")");
gradient.addColorStop(0.8, "rgba(0, 0, 0, " + (1.0 - a2) + ")");
gradient.addColorStop(1.0, "rgba(0, 0, 0, 1.0)");

ctx.globalCompositeOperation = "destination-out";

ctx.fillStyle = gradient;
ctx.fillRect(x, y, w, h);

ctx.restore();
},

_makeLegendElement: function(label, value, color)
{
var legendElement = document.createElement("label");
legendElement.className = "summary-graph-legend-item";

if (color) {
var swatch = document.createElement("canvas");
swatch.className = "summary-graph-legend-swatch";
swatch.setAttribute("width", "13");
swatch.setAttribute("height", "24");

legendElement.appendChild(swatch);

this._drawSwatch(swatch, color);
}

var labelElement = document.createElement("div");
labelElement.className = "summary-graph-legend-label";
legendElement.appendChild(labelElement);

var headerElement = document.createElement("div");
headerElement.className = "summary-graph-legend-header";
headerElement.textContent = label;
labelElement.appendChild(headerElement);

var valueElement = document.createElement("div");
valueElement.className = "summary-graph-legend-value";
valueElement.textContent = value;
labelElement.appendChild(valueElement);

return legendElement;
}
}

WebInspector.SummaryBar.prototype.__proto__ = WebInspector.Object.prototype;





WebInspector.ElementsPanel = function()
{
WebInspector.Panel.call(this, "elements");

this.contentElement = document.createElement("div");
this.contentElement.id = "elements-content";
this.contentElement.className = "outline-disclosure source-code";
if (!WebInspector.settings.domWordWrap)
this.contentElement.classList.add("nowrap");

this.contentElement.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true);

this.treeOutline = new WebInspector.ElementsTreeOutline();
this.treeOutline.panel = this;
this.treeOutline.includeRootDOMNode = false;
this.treeOutline.selectEnabled = true;

this.treeOutline.focusedNodeChanged = function(forceUpdate)
{
if (this.panel.visible && WebInspector.currentFocusElement !== document.getElementById("search"))
WebInspector.currentFocusElement = this.element;

this.panel.updateBreadcrumb(forceUpdate);

for (var pane in this.panel.sidebarPanes)
this.panel.sidebarPanes[pane].needsUpdate = true;

this.panel.updateStyles(true);
this.panel.updateMetrics();
this.panel.updateProperties();
this.panel.updateEventListeners();

if (this._focusedDOMNode) {
ConsoleAgent.addInspectedNode(this._focusedDOMNode.id);
WebInspector.extensionServer.notifyObjectSelected(this.panel.name);
}
};

this.contentElement.appendChild(this.treeOutline.element);

this.crumbsElement = document.createElement("div");
this.crumbsElement.className = "crumbs";
this.crumbsElement.addEventListener("mousemove", this._mouseMovedInCrumbs.bind(this), false);
this.crumbsElement.addEventListener("mouseout", this._mouseMovedOutOfCrumbs.bind(this), false);

this.sidebarPanes = {};
this.sidebarPanes.computedStyle = new WebInspector.ComputedStyleSidebarPane();
this.sidebarPanes.styles = new WebInspector.StylesSidebarPane(this.sidebarPanes.computedStyle);
this.sidebarPanes.metrics = new WebInspector.MetricsSidebarPane();
this.sidebarPanes.properties = new WebInspector.PropertiesSidebarPane();
if (Preferences.nativeInstrumentationEnabled)
this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane;
this.sidebarPanes.eventListeners = new WebInspector.EventListenersSidebarPane();

this.sidebarPanes.styles.onexpand = this.updateStyles.bind(this);
this.sidebarPanes.metrics.onexpand = this.updateMetrics.bind(this);
this.sidebarPanes.properties.onexpand = this.updateProperties.bind(this);
this.sidebarPanes.eventListeners.onexpand = this.updateEventListeners.bind(this);

this.sidebarPanes.styles.expanded = true;

this.sidebarPanes.styles.addEventListener("style edited", this._stylesPaneEdited, this);
this.sidebarPanes.styles.addEventListener("style property toggled", this._stylesPaneEdited, this);
this.sidebarPanes.metrics.addEventListener("metrics edited", this._metricsPaneEdited, this);
WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetChanged, this);

this.sidebarElement = document.createElement("div");
this.sidebarElement.id = "elements-sidebar";

for (var pane in this.sidebarPanes)
this.sidebarElement.appendChild(this.sidebarPanes[pane].element);

this.sidebarResizeElement = document.createElement("div");
this.sidebarResizeElement.className = "sidebar-resizer-vertical";
this.sidebarResizeElement.addEventListener("mousedown", this.rightSidebarResizerDragStart.bind(this), false);

this._nodeSearchButton = new WebInspector.StatusBarButton(WebInspector.UIString("Select an element in the page to inspect it."), "node-search-status-bar-item");
this._nodeSearchButton.addEventListener("click", this.toggleSearchingForNode.bind(this), false);

this.element.appendChild(this.contentElement);
this.element.appendChild(this.sidebarElement);
this.element.appendChild(this.sidebarResizeElement);

this._registerShortcuts();

WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.NodeInserted, this._nodeInserted, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.NodeRemoved, this._nodeRemoved, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrModified, this._attributesUpdated, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.CharacterDataModified, this._characterDataModified, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, this._documentUpdated, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.ChildNodeCountUpdated, this._childNodeCountUpdated, this);

this.recentlyModifiedNodes = [];
}

WebInspector.ElementsPanel.prototype = {
get toolbarItemLabel()
{
return WebInspector.UIString("Elements");
},

get statusBarItems()
{
return [this._nodeSearchButton.element, this.crumbsElement];
},

get defaultFocusedElement()
{
return this.treeOutline.element;
},

updateStatusBarItems: function()
{
this.updateBreadcrumbSizes();
},

show: function()
{
WebInspector.Panel.prototype.show.call(this);
this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px";
this.updateBreadcrumb();
this.treeOutline.updateSelection();
if (this.recentlyModifiedNodes.length)
this.updateModifiedNodes();

if (Preferences.nativeInstrumentationEnabled)
this.sidebarElement.insertBefore(this.sidebarPanes.domBreakpoints.element, this.sidebarPanes.eventListeners.element);

if (!this.rootDOMNode)
WebInspector.domAgent.requestDocument();
},

hide: function()
{
WebInspector.Panel.prototype.hide.call(this);

WebInspector.highlightDOMNode(0);
this.setSearchingForNode(false);
},

resize: function()
{
this.treeOutline.updateSelection();
this.updateBreadcrumbSizes();
},

_reset: function()
{
if (this.focusedDOMNode)
this._selectedPathOnReset = this.focusedDOMNode.path();

this.rootDOMNode = null;
this.focusedDOMNode = null;

WebInspector.highlightDOMNode(0);

this.recentlyModifiedNodes = [];

delete this.currentQuery;
},

_documentUpdated: function(event)
{
this._setDocument(event.data);
},

_setDocument: function(inspectedRootDocument)
{
this._reset();
this.searchCanceled();

if (!inspectedRootDocument)
return;

if (Preferences.nativeInstrumentationEnabled)
this.sidebarPanes.domBreakpoints.restoreBreakpoints();

this.rootDOMNode = inspectedRootDocument;

function selectNode(candidateFocusNode)
{
if (!candidateFocusNode)
candidateFocusNode = inspectedRootDocument.body || inspectedRootDocument.documentElement;

if (!candidateFocusNode)
return;

this.focusedDOMNode = candidateFocusNode;
if (this.treeOutline.selectedTreeElement)
this.treeOutline.selectedTreeElement.expand();
}

function selectLastSelectedNode(nodeId)
{
if (this.focusedDOMNode) {

return;
}
var node = nodeId ? WebInspector.domAgent.nodeForId(nodeId) : 0;
selectNode.call(this, node);
}

if (this._selectedPathOnReset)
WebInspector.domAgent.pushNodeByPathToFrontend(this._selectedPathOnReset, selectLastSelectedNode.bind(this));
else
selectNode.call(this);
delete this._selectedPathOnReset;
},

searchCanceled: function()
{
delete this._searchQuery;
this._hideSearchHighlights();

WebInspector.searchController.updateSearchMatchesCount(0, this);

delete this._currentSearchResultIndex;
this._searchResults = [];
WebInspector.domAgent.cancelSearch();
},

performSearch: function(query)
{

this.searchCanceled();

const whitespaceTrimmedQuery = query.trim();
if (!whitespaceTrimmedQuery.length)
return;

this._updatedMatchCountOnce = false;
this._matchesCountUpdateTimeout = null;
this._searchQuery = query;

WebInspector.domAgent.performSearch(whitespaceTrimmedQuery, this._addNodesToSearchResult.bind(this));
},

_contextMenuEventFired: function(event)
{
function isTextWrapped()
{
return !this.contentElement.hasStyleClass("nowrap");
}

function toggleWordWrap()
{
this.contentElement.classList.toggle("nowrap");
WebInspector.settings.domWordWrap = !this.contentElement.classList.contains("nowrap");

var treeElement = this.treeOutline.findTreeElement(this.focusedDOMNode);
if (treeElement)
treeElement.updateSelection(); 
}

var contextMenu = new WebInspector.ContextMenu();

var populated = this.treeOutline.populateContextMenu(contextMenu, event);
if (populated)
contextMenu.appendSeparator();
contextMenu.appendCheckboxItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Word wrap" : "Word Wrap"), toggleWordWrap.bind(this), isTextWrapped.call(this));

contextMenu.show(event);
},

populateHrefContextMenu: function(contextMenu, event, anchorElement)
{
if (!anchorElement.href)
return false;

var resourceURL = WebInspector.resourceURLForRelatedNode(this.focusedDOMNode, anchorElement.href);
if (!resourceURL)
return false;


contextMenu.appendItem(WebInspector.openLinkExternallyLabel(), WebInspector.openResource.bind(WebInspector, resourceURL, false));
if (WebInspector.resourceForURL(resourceURL))
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open link in Resources panel" : "Open Link in Resources Panel"), WebInspector.openResource.bind(null, resourceURL, true));
return true;
},

switchToAndFocus: function(node)
{

WebInspector.searchController.cancelSearch();
WebInspector.currentPanel = this;
this.focusedDOMNode = node;
},

_updateMatchesCount: function()
{
WebInspector.searchController.updateSearchMatchesCount(this._searchResults.length, this);
this._matchesCountUpdateTimeout = null;
this._updatedMatchCountOnce = true;
},

_updateMatchesCountSoon: function()
{
if (!this._updatedMatchCountOnce)
return this._updateMatchesCount();
if (this._matchesCountUpdateTimeout)
return;

this._matchesCountUpdateTimeout = setTimeout(this._updateMatchesCount.bind(this), 500);
},

_addNodesToSearchResult: function(nodeIds)
{
if (!nodeIds.length)
return;

var oldSearchResultIndex = this._currentSearchResultIndex;
for (var i = 0; i < nodeIds.length; ++i) {
var nodeId = nodeIds[i];
var node = WebInspector.domAgent.nodeForId(nodeId);
if (!node)
continue;

this._currentSearchResultIndex = 0;
this._searchResults.push(node);
}


if (oldSearchResultIndex !== this._currentSearchResultIndex)
this._highlightCurrentSearchResult();
this._updateMatchesCountSoon();
},

jumpToNextSearchResult: function()
{
if (!this._searchResults || !this._searchResults.length)
return;

if (++this._currentSearchResultIndex >= this._searchResults.length)
this._currentSearchResultIndex = 0;
this._highlightCurrentSearchResult();
},

jumpToPreviousSearchResult: function()
{
if (!this._searchResults || !this._searchResults.length)
return;

if (--this._currentSearchResultIndex < 0)
this._currentSearchResultIndex = (this._searchResults.length - 1);
this._highlightCurrentSearchResult();
},

_highlightCurrentSearchResult: function()
{
this._hideSearchHighlights();
var node = this._searchResults[this._currentSearchResultIndex];
var treeElement = this.treeOutline.findTreeElement(node);
if (treeElement) {
treeElement.highlightSearchResults(this._searchQuery);
treeElement.reveal();
}
},

_hideSearchHighlights: function(node)
{
for (var i = 0; this._searchResults && i < this._searchResults.length; ++i) {
var node = this._searchResults[i];
var treeElement = this.treeOutline.findTreeElement(node);
if (treeElement)
treeElement.hideSearchHighlights();
}
},

renameSelector: function(oldIdentifier, newIdentifier, oldSelector, newSelector)
{

},

get rootDOMNode()
{
return this.treeOutline.rootDOMNode;
},

set rootDOMNode(x)
{
this.treeOutline.rootDOMNode = x;
},

get focusedDOMNode()
{
return this.treeOutline.focusedDOMNode;
},

set focusedDOMNode(x)
{
this.treeOutline.focusedDOMNode = x;
},

startEditingStyle: function()
{
this._isEditingStyle = true;
},

endEditingStyle: function()
{
delete this._isEditingStyle;
},

_attributesUpdated: function(event)
{
this.recentlyModifiedNodes.push({node: event.data, updated: true});
if (this.visible)
this._updateModifiedNodesSoon();

if (!this._isEditingStyle && event.data === this.focusedDOMNode)
this._styleSheetChanged();
},

_characterDataModified: function(event)
{
this.recentlyModifiedNodes.push({node: event.data, updated: true});
if (this.visible)
this._updateModifiedNodesSoon();
},

_nodeInserted: function(event)
{
this.recentlyModifiedNodes.push({node: event.data, parent: event.data.parentNode, inserted: true});
if (this.visible)
this._updateModifiedNodesSoon();
},

_nodeRemoved: function(event)
{
this.recentlyModifiedNodes.push({node: event.data.node, parent: event.data.parent, removed: true});
if (this.visible)
this._updateModifiedNodesSoon();
},

_childNodeCountUpdated: function(event)
{
var treeElement = this.treeOutline.findTreeElement(event.data);
if (treeElement)
treeElement.hasChildren = event.data.hasChildNodes();
},

_updateModifiedNodesSoon: function()
{
if ("_updateModifiedNodesTimeout" in this)
return;
this._updateModifiedNodesTimeout = setTimeout(this.updateModifiedNodes.bind(this), 0);
},

updateModifiedNodes: function()
{
if ("_updateModifiedNodesTimeout" in this) {
clearTimeout(this._updateModifiedNodesTimeout);
delete this._updateModifiedNodesTimeout;
}

var updatedParentTreeElements = [];
var updateBreadcrumbs = false;

for (var i = 0; i < this.recentlyModifiedNodes.length; ++i) {
var parent = this.recentlyModifiedNodes[i].parent;
var node = this.recentlyModifiedNodes[i].node;

if (this.recentlyModifiedNodes[i].updated) {
var nodeItem = this.treeOutline.findTreeElement(node);
if (nodeItem)
nodeItem.updateTitle();
continue;
}

if (!parent)
continue;

var parentNodeItem = this.treeOutline.findTreeElement(parent);
if (parentNodeItem && !parentNodeItem.alreadyUpdatedChildren) {
parentNodeItem.updateChildren();
parentNodeItem.alreadyUpdatedChildren = true;
updatedParentTreeElements.push(parentNodeItem);
}

if (!updateBreadcrumbs && (this.focusedDOMNode === parent || isAncestorNode(this.focusedDOMNode, parent)))
updateBreadcrumbs = true;
}

for (var i = 0; i < updatedParentTreeElements.length; ++i)
delete updatedParentTreeElements[i].alreadyUpdatedChildren;

this.recentlyModifiedNodes = [];

if (updateBreadcrumbs)
this.updateBreadcrumb(true);
},

_stylesPaneEdited: function()
{

this.sidebarPanes.metrics.needsUpdate = true;
this.updateMetrics();
},

_metricsPaneEdited: function()
{

this.sidebarPanes.styles.needsUpdate = true;
this.updateStyles(true);
},

_styleSheetChanged: function()
{
this._metricsPaneEdited();
this._stylesPaneEdited();
},

_mouseMovedInCrumbs: function(event)
{
var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
var crumbElement = nodeUnderMouse.enclosingNodeOrSelfWithClass("crumb");

WebInspector.highlightDOMNode(crumbElement ? crumbElement.representedObject.id : 0);

if ("_mouseOutOfCrumbsTimeout" in this) {
clearTimeout(this._mouseOutOfCrumbsTimeout);
delete this._mouseOutOfCrumbsTimeout;
}
},

_mouseMovedOutOfCrumbs: function(event)
{
var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
if (nodeUnderMouse && nodeUnderMouse.isDescendant(this.crumbsElement))
return;

WebInspector.highlightDOMNode(0);

this._mouseOutOfCrumbsTimeout = setTimeout(this.updateBreadcrumbSizes.bind(this), 1000);
},

updateBreadcrumb: function(forceUpdate)
{
if (!this.visible)
return;

var crumbs = this.crumbsElement;

var handled = false;
var foundRoot = false;
var crumb = crumbs.firstChild;
while (crumb) {
if (crumb.representedObject === this.rootDOMNode)
foundRoot = true;

if (foundRoot)
crumb.addStyleClass("dimmed");
else
crumb.removeStyleClass("dimmed");

if (crumb.representedObject === this.focusedDOMNode) {
crumb.addStyleClass("selected");
handled = true;
} else {
crumb.removeStyleClass("selected");
}

crumb = crumb.nextSibling;
}

if (handled && !forceUpdate) {


this.updateBreadcrumbSizes();
return;
}

crumbs.removeChildren();

var panel = this;

function selectCrumbFunction(event)
{
var crumb = event.currentTarget;
if (crumb.hasStyleClass("collapsed")) {

if (crumb === panel.crumbsElement.firstChild) {


var currentCrumb = crumb;
while (currentCrumb) {
var hidden = currentCrumb.hasStyleClass("hidden");
var collapsed = currentCrumb.hasStyleClass("collapsed");
if (!hidden && !collapsed)
break;
crumb = currentCrumb;
currentCrumb = currentCrumb.nextSibling;
}
}

panel.updateBreadcrumbSizes(crumb);
} else {


if (event.detail >= 2 || crumb.hasStyleClass("dimmed"))
panel.rootDOMNode = crumb.representedObject.parentNode;
panel.focusedDOMNode = crumb.representedObject;
}

event.preventDefault();
}

foundRoot = false;
for (var current = this.focusedDOMNode; current; current = current.parentNode) {
if (current.nodeType() === Node.DOCUMENT_NODE)
continue;

if (current === this.rootDOMNode)
foundRoot = true;

var crumb = document.createElement("span");
crumb.className = "crumb";
crumb.representedObject = current;
crumb.addEventListener("mousedown", selectCrumbFunction, false);

var crumbTitle;
switch (current.nodeType()) {
case Node.ELEMENT_NODE:
this.decorateNodeLabel(current, crumb);
break;

case Node.TEXT_NODE:
if (isNodeWhitespace.call(current))
crumbTitle = WebInspector.UIString("(whitespace)");
else
crumbTitle = WebInspector.UIString("(text)");
break

case Node.COMMENT_NODE:
crumbTitle = "<!-->";
break;

case Node.DOCUMENT_TYPE_NODE:
crumbTitle = "<!DOCTYPE>";
break;

default:
crumbTitle = this.treeOutline.nodeNameToCorrectCase(current.nodeName());
}

if (!crumb.childNodes.length) {
var nameElement = document.createElement("span");
nameElement.textContent = crumbTitle;
crumb.appendChild(nameElement);
crumb.title = crumbTitle;
}

if (foundRoot)
crumb.addStyleClass("dimmed");
if (current === this.focusedDOMNode)
crumb.addStyleClass("selected");
if (!crumbs.childNodes.length)
crumb.addStyleClass("end");

crumbs.appendChild(crumb);
}

if (crumbs.hasChildNodes())
crumbs.lastChild.addStyleClass("start");

this.updateBreadcrumbSizes();
},

decorateNodeLabel: function(node, parentElement)
{
var title = this.treeOutline.nodeNameToCorrectCase(node.nodeName());

var nameElement = document.createElement("span");
nameElement.textContent = title;
parentElement.appendChild(nameElement);

var idAttribute = node.getAttribute("id");
if (idAttribute) {
var idElement = document.createElement("span");
parentElement.appendChild(idElement);

var part = "#" + idAttribute;
title += part;
idElement.appendChild(document.createTextNode(part));


nameElement.className = "extra";
}

var classAttribute = node.getAttribute("class");
if (classAttribute) {
var classes = classAttribute.split(/\s+/);
var foundClasses = {};

if (classes.length) {
var classesElement = document.createElement("span");
classesElement.className = "extra";
parentElement.appendChild(classesElement);

for (var i = 0; i < classes.length; ++i) {
var className = classes[i];
if (className && !(className in foundClasses)) {
var part = "." + className;
title += part;
classesElement.appendChild(document.createTextNode(part));
foundClasses[className] = true;
}
}
}
}
parentElement.title = title;
},

linkifyNodeReference: function(node)
{
var link = document.createElement("span");
link.className = "node-link";
this.decorateNodeLabel(node, link);
WebInspector.wireElementWithDOMNode(link, node.id);
return link;
},

linkifyNodeById: function(nodeId)
{
var node = WebInspector.domAgent.nodeForId(nodeId);
if (!node)
return document.createTextNode(WebInspector.UIString("<node>"));
return this.linkifyNodeReference(node);
},

updateBreadcrumbSizes: function(focusedCrumb)
{
if (!this.visible)
return;

if (document.body.offsetWidth <= 0) {


return;
}

var crumbs = this.crumbsElement;
if (!crumbs.childNodes.length || crumbs.offsetWidth <= 0)
return; 


var selectedIndex = 0;
var focusedIndex = 0;
var selectedCrumb;

var i = 0;
var crumb = crumbs.firstChild;
while (crumb) {

if (!selectedCrumb && crumb.hasStyleClass("selected")) {
selectedCrumb = crumb;
selectedIndex = i;
}


if (crumb === focusedCrumb)
focusedIndex = i;



if (crumb !== crumbs.lastChild)
crumb.removeStyleClass("start");
if (crumb !== crumbs.firstChild)
crumb.removeStyleClass("end");

crumb.removeStyleClass("compact");
crumb.removeStyleClass("collapsed");
crumb.removeStyleClass("hidden");

crumb = crumb.nextSibling;
++i;
}



crumbs.firstChild.addStyleClass("end");
crumbs.lastChild.addStyleClass("start");

function crumbsAreSmallerThanContainer()
{
var rightPadding = 20;
var errorWarningElement = document.getElementById("error-warning-count");
if (!WebInspector.drawer.visible && errorWarningElement)
rightPadding += errorWarningElement.offsetWidth;
return ((crumbs.totalOffsetLeft + crumbs.offsetWidth + rightPadding) < window.innerWidth);
}

if (crumbsAreSmallerThanContainer())
return; 

var BothSides = 0;
var AncestorSide = -1;
var ChildSide = 1;

function makeCrumbsSmaller(shrinkingFunction, direction, significantCrumb)
{
if (!significantCrumb)
significantCrumb = (focusedCrumb || selectedCrumb);

if (significantCrumb === selectedCrumb)
var significantIndex = selectedIndex;
else if (significantCrumb === focusedCrumb)
var significantIndex = focusedIndex;
else {
var significantIndex = 0;
for (var i = 0; i < crumbs.childNodes.length; ++i) {
if (crumbs.childNodes[i] === significantCrumb) {
significantIndex = i;
break;
}
}
}

function shrinkCrumbAtIndex(index)
{
var shrinkCrumb = crumbs.childNodes[index];
if (shrinkCrumb && shrinkCrumb !== significantCrumb)
shrinkingFunction(shrinkCrumb);
if (crumbsAreSmallerThanContainer())
return true; 
return false;
}



if (direction) {

var index = (direction > 0 ? 0 : crumbs.childNodes.length - 1);
while (index !== significantIndex) {
if (shrinkCrumbAtIndex(index))
return true;
index += (direction > 0 ? 1 : -1);
}
} else {


var startIndex = 0;
var endIndex = crumbs.childNodes.length - 1;
while (startIndex != significantIndex || endIndex != significantIndex) {
var startDistance = significantIndex - startIndex;
var endDistance = endIndex - significantIndex;
if (startDistance >= endDistance)
var index = startIndex++;
else
var index = endIndex--;
if (shrinkCrumbAtIndex(index))
return true;
}
}


return false;
}

function coalesceCollapsedCrumbs()
{
var crumb = crumbs.firstChild;
var collapsedRun = false;
var newStartNeeded = false;
var newEndNeeded = false;
while (crumb) {
var hidden = crumb.hasStyleClass("hidden");
if (!hidden) {
var collapsed = crumb.hasStyleClass("collapsed");
if (collapsedRun && collapsed) {
crumb.addStyleClass("hidden");
crumb.removeStyleClass("compact");
crumb.removeStyleClass("collapsed");

if (crumb.hasStyleClass("start")) {
crumb.removeStyleClass("start");
newStartNeeded = true;
}

if (crumb.hasStyleClass("end")) {
crumb.removeStyleClass("end");
newEndNeeded = true;
}

continue;
}

collapsedRun = collapsed;

if (newEndNeeded) {
newEndNeeded = false;
crumb.addStyleClass("end");
}
} else
collapsedRun = true;
crumb = crumb.nextSibling;
}

if (newStartNeeded) {
crumb = crumbs.lastChild;
while (crumb) {
if (!crumb.hasStyleClass("hidden")) {
crumb.addStyleClass("start");
break;
}
crumb = crumb.previousSibling;
}
}
}

function compact(crumb)
{
if (crumb.hasStyleClass("hidden"))
return;
crumb.addStyleClass("compact");
}

function collapse(crumb, dontCoalesce)
{
if (crumb.hasStyleClass("hidden"))
return;
crumb.addStyleClass("collapsed");
crumb.removeStyleClass("compact");
if (!dontCoalesce)
coalesceCollapsedCrumbs();
}

function compactDimmed(crumb)
{
if (crumb.hasStyleClass("dimmed"))
compact(crumb);
}

function collapseDimmed(crumb)
{
if (crumb.hasStyleClass("dimmed"))
collapse(crumb);
}

if (!focusedCrumb) {




if (makeCrumbsSmaller(compact, ChildSide))
return;


if (makeCrumbsSmaller(collapse, ChildSide))
return;


if (makeCrumbsSmaller(compactDimmed, AncestorSide))
return;


if (makeCrumbsSmaller(collapseDimmed, AncestorSide))
return;
}


if (makeCrumbsSmaller(compact, (focusedCrumb ? BothSides : AncestorSide)))
return;


if (makeCrumbsSmaller(collapse, (focusedCrumb ? BothSides : AncestorSide)))
return;

if (!selectedCrumb)
return;


compact(selectedCrumb);
if (crumbsAreSmallerThanContainer())
return;


collapse(selectedCrumb, true);
},

updateStyles: function(forceUpdate)
{
var stylesSidebarPane = this.sidebarPanes.styles;
var computedStylePane = this.sidebarPanes.computedStyle;
if ((!stylesSidebarPane.expanded && !computedStylePane.expanded) || !stylesSidebarPane.needsUpdate || this._isEditingStyle)
return;

stylesSidebarPane.update(this.focusedDOMNode, null, forceUpdate);
stylesSidebarPane.needsUpdate = false;
},

updateMetrics: function()
{
var metricsSidebarPane = this.sidebarPanes.metrics;
if (!metricsSidebarPane.expanded || !metricsSidebarPane.needsUpdate)
return;

metricsSidebarPane.update(this.focusedDOMNode);
metricsSidebarPane.needsUpdate = false;
},

updateProperties: function()
{
var propertiesSidebarPane = this.sidebarPanes.properties;
if (!propertiesSidebarPane.expanded || !propertiesSidebarPane.needsUpdate)
return;

propertiesSidebarPane.update(this.focusedDOMNode);
propertiesSidebarPane.needsUpdate = false;
},

updateEventListeners: function()
{
var eventListenersSidebarPane = this.sidebarPanes.eventListeners;
if (!eventListenersSidebarPane.expanded || !eventListenersSidebarPane.needsUpdate)
return;

eventListenersSidebarPane.update(this.focusedDOMNode);
eventListenersSidebarPane.needsUpdate = false;
},

_registerShortcuts: function()
{
var shortcut = WebInspector.KeyboardShortcut;
var section = WebInspector.shortcutsHelp.section(WebInspector.UIString("Elements Panel"));
var keys = [
shortcut.shortcutToString(shortcut.Keys.Up),
shortcut.shortcutToString(shortcut.Keys.Down)
];
section.addRelatedKeys(keys, WebInspector.UIString("Navigate elements"));
var keys = [
shortcut.shortcutToString(shortcut.Keys.Right),
shortcut.shortcutToString(shortcut.Keys.Left)
];
section.addRelatedKeys(keys, WebInspector.UIString("Expand/collapse"));
section.addKey(shortcut.shortcutToString(shortcut.Keys.Enter), WebInspector.UIString("Edit attribute"));

this.sidebarPanes.styles.registerShortcuts();
},

handleShortcut: function(event)
{


if (event.keyIdentifier === "U+0043") {     
if (WebInspector.isMac())
var isNodeSearchKey = event.metaKey && !event.ctrlKey && !event.altKey && event.shiftKey;
else
var isNodeSearchKey = event.ctrlKey && !event.metaKey && !event.altKey && event.shiftKey;

if (isNodeSearchKey) {
this.toggleSearchingForNode();
event.handled = true;
return;
}
}
},

handleCopyEvent: function(event)
{

if (!window.getSelection().isCollapsed)
return;
event.clipboardData.clearData();
event.preventDefault();
this.focusedDOMNode.copyNode();
},

rightSidebarResizerDragStart: function(event)
{
WebInspector.elementDragStart(this.sidebarElement, this.rightSidebarResizerDrag.bind(this), this.rightSidebarResizerDragEnd.bind(this), event, "col-resize");
},

rightSidebarResizerDragEnd: function(event)
{
WebInspector.elementDragEnd(event);
this.saveSidebarWidth();
},

rightSidebarResizerDrag: function(event)
{
var x = event.pageX;
var newWidth = Number.constrain(window.innerWidth - x, Preferences.minElementsSidebarWidth, window.innerWidth * 0.66);
this.setSidebarWidth(newWidth);
event.preventDefault();
},

setSidebarWidth: function(newWidth)
{
this.sidebarElement.style.width = newWidth + "px";
this.contentElement.style.right = newWidth + "px";
this.sidebarResizeElement.style.right = (newWidth - 3) + "px";
this.treeOutline.updateSelection();
},

updateFocusedNode: function(nodeId)
{
var node = WebInspector.domAgent.nodeForId(nodeId);
if (!node)
return;

this.focusedDOMNode = node;
if (this._nodeSearchButton.toggled) {
InspectorFrontendHost.bringToFront();
this._nodeSearchButton.toggled = false;
}
},

_setSearchingForNode: function(enabled)
{
this._nodeSearchButton.toggled = enabled;
},

setSearchingForNode: function(enabled)
{
DOMAgent.setInspectModeEnabled(enabled, this._setSearchingForNode.bind(this, enabled));
},

toggleSearchingForNode: function()
{
this.setSearchingForNode(!this._nodeSearchButton.toggled);
},

elementsToRestoreScrollPositionsFor: function()
{
return [ this.contentElement, this.sidebarElement ];
}
}

WebInspector.ElementsPanel.prototype.__proto__ = WebInspector.Panel.prototype;





WebInspector.NetworkPanel = function()
{
function eventsCollectionEnabled(error, enabled)
{
this._backgroundCollectionEnabled = enabled;
}
NetworkAgent.isBackgroundEventsCollectionEnabled(eventsCollectionEnabled.bind(this));

WebInspector.Panel.call(this, "network");

this.createSidebar();
this.sidebarElement.className = "network-sidebar";

this._resources = [];
this._resourcesById = {};
this._resourcesByURL = {};
this._staleResources = [];
this._resourceGridNodes = {};
this._lastResourceGridNodeId = 0;
this._mainResourceLoadTime = -1;
this._mainResourceDOMContentTime = -1;
this._hiddenCategories = {};

this._categories = WebInspector.resourceCategories;

this.containerElement = document.createElement("div");
this.containerElement.id = "network-container";
this.sidebarElement.appendChild(this.containerElement);

this._viewsContainerElement = document.createElement("div");
this._viewsContainerElement.id = "network-views";
this._viewsContainerElement.className = "hidden";
this.element.appendChild(this._viewsContainerElement);

this._closeButtonElement = document.createElement("button");
this._closeButtonElement.id = "network-close-button";
this._closeButtonElement.addEventListener("click", this._toggleGridMode.bind(this), false);
this._viewsContainerElement.appendChild(this._closeButtonElement);

this._createSortingFunctions();
this._createTable();
this._createTimelineGrid();
this._createStatusbarButtons();
this._createFilterStatusBarItems();
this._createSummaryBar();

if (!WebInspector.settings.resourcesLargeRows)
this._setLargerResources(WebInspector.settings.resourcesLargeRows);

this._popoverHelper = new WebInspector.PopoverHelper(this.element, this._getPopoverAnchor.bind(this), this._showPopover.bind(this), true);

this._popoverHelper.setTimeout(100);

this.calculator = new WebInspector.NetworkTransferTimeCalculator();
this._filter(this._filterAllElement, false);

this._toggleGridMode();

WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceStarted, this._onResourceStarted, this);
WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceUpdated, this._onResourceUpdated, this);
WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._onResourceUpdated, this);

WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.OnLoad, this._onLoadEventFired, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, this._domContentLoadedEventFired, this);

this.registerShortcuts();
}

WebInspector.NetworkPanel.prototype = {
get toolbarItemLabel()
{
return WebInspector.UIString("Network");
},

get statusBarItems()
{
return [this._largerResourcesButton.element, this._preserveLogToggle.element, this._clearButton.element, this._filterBarElement];
},

isCategoryVisible: function(categoryName)
{
return true;
},

elementsToRestoreScrollPositionsFor: function()
{
return [this.containerElement, this._dataGrid.scrollContainer];
},

resize: function()
{
WebInspector.Panel.prototype.resize.call(this);
this._dataGrid.updateWidths();
this._updateOffscreenRows();
},

updateSidebarWidth: function(width)
{
if (!this._viewingResourceMode)
return;
WebInspector.Panel.prototype.updateSidebarWidth.call(this, width);
},

updateMainViewWidth: function(width)
{
this._viewsContainerElement.style.left = width + "px";
},

handleShortcut: function(event)
{
if (this._viewingResourceMode && event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {
this._toggleGridMode();
event.handled = true;
return;
}

WebInspector.Panel.prototype.handleShortcut.call(this, event);
},

_createTimelineGrid: function()
{
this._timelineGrid = new WebInspector.TimelineGrid();
this._timelineGrid.element.addStyleClass("network-timeline-grid");
this._dataGrid.element.appendChild(this._timelineGrid.element);
},

_createTable: function()
{
var columns = {name: {}, method: {}, status: {}, type: {}, size: {}, time: {}, timeline: {}};
columns.name.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Name"), WebInspector.UIString("Path"));
columns.name.sortable = true;
columns.name.width = "20%";
columns.name.disclosure = true;

columns.method.title = WebInspector.UIString("Method");
columns.method.sortable = true;
columns.method.width = "6%";

columns.status.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Status"), WebInspector.UIString("Text"));
columns.status.sortable = true;
columns.status.width = "6%";

columns.type.title = WebInspector.UIString("Type");
columns.type.sortable = true;
columns.type.width = "6%";

columns.size.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Size"), WebInspector.UIString("Content"));
columns.size.sortable = true;
columns.size.width = "6%";
columns.size.aligned = "right";

columns.time.titleDOMFragment = this._makeHeaderFragment(WebInspector.UIString("Time"), WebInspector.UIString("Latency"));
columns.time.sortable = true;
columns.time.width = "6%";
columns.time.aligned = "right";

columns.timeline.title = "";
columns.timeline.sortable = false;
columns.timeline.width = "50%";
columns.timeline.sort = "ascending";

this._dataGrid = new WebInspector.DataGrid(columns);
this._dataGrid.resizeMethod = WebInspector.DataGrid.ResizeMethod.Last;
this._dataGrid.element.addEventListener("contextmenu", this._contextMenu.bind(this), true);
this.containerElement.appendChild(this._dataGrid.element);
this._dataGrid.addEventListener("sorting changed", this._sortItems, this);
this._dataGrid.addEventListener("width changed", this._updateDividersIfNeeded, this);
this._dataGrid.scrollContainer.addEventListener("scroll", this._updateOffscreenRows.bind(this));

this._patchTimelineHeader();
},

_makeHeaderFragment: function(title, subtitle)
{
var fragment = document.createDocumentFragment();
fragment.appendChild(document.createTextNode(title));
var subtitleDiv = document.createElement("div");
subtitleDiv.className = "network-header-subtitle";
subtitleDiv.textContent = subtitle;
fragment.appendChild(subtitleDiv);
return fragment;
},

_patchTimelineHeader: function()
{
var timelineSorting = document.createElement("select");

var option = document.createElement("option");
option.value = "startTime";
option.label = WebInspector.UIString("Timeline");
timelineSorting.appendChild(option);

option = document.createElement("option");
option.value = "startTime";
option.label = WebInspector.UIString("Start Time");
timelineSorting.appendChild(option);

option = document.createElement("option");
option.value = "responseTime";
option.label = WebInspector.UIString("Response Time");
timelineSorting.appendChild(option);

option = document.createElement("option");
option.value = "endTime";
option.label = WebInspector.UIString("End Time");
timelineSorting.appendChild(option);

option = document.createElement("option");
option.value = "duration";
option.label = WebInspector.UIString("Duration");
timelineSorting.appendChild(option);

option = document.createElement("option");
option.value = "latency";
option.label = WebInspector.UIString("Latency");
timelineSorting.appendChild(option);

var header = this._dataGrid.headerTableHeader("timeline");
header.replaceChild(timelineSorting, header.firstChild);

timelineSorting.addEventListener("click", function(event) { event.stopPropagation() }, false);
timelineSorting.addEventListener("change", this._sortByTimeline.bind(this), false);
this._timelineSortSelector = timelineSorting;
},

_createSortingFunctions: function()
{
this._sortingFunctions = {};
this._sortingFunctions.name = WebInspector.NetworkDataGridNode.NameComparator;
this._sortingFunctions.method = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "method", false);
this._sortingFunctions.status = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "statusCode", false);
this._sortingFunctions.type = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "mimeType", false);
this._sortingFunctions.size = WebInspector.NetworkDataGridNode.SizeComparator;
this._sortingFunctions.time = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "duration", false);
this._sortingFunctions.timeline = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "startTime", false);
this._sortingFunctions.startTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "startTime", false);
this._sortingFunctions.endTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "endTime", false);
this._sortingFunctions.responseTime = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "responseReceivedTime", false);
this._sortingFunctions.duration = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "duration", true);
this._sortingFunctions.latency = WebInspector.NetworkDataGridNode.ResourcePropertyComparator.bind(null, "latency", true);

var timeCalculator = new WebInspector.NetworkTransferTimeCalculator();
var durationCalculator = new WebInspector.NetworkTransferDurationCalculator();

this._calculators = {};
this._calculators.timeline = timeCalculator;
this._calculators.startTime = timeCalculator;
this._calculators.endTime = timeCalculator;
this._calculators.responseTime = timeCalculator;
this._calculators.duration = durationCalculator;
this._calculators.latency = durationCalculator;
},

_sortItems: function()
{
var columnIdentifier = this._dataGrid.sortColumnIdentifier;
if (columnIdentifier === "timeline") {
this._sortByTimeline();
return;
}
var sortingFunction = this._sortingFunctions[columnIdentifier];
if (!sortingFunction)
return;

this._dataGrid.sortNodes(sortingFunction, this._dataGrid.sortOrder === "descending");
this._timelineSortSelector.selectedIndex = 0;
this._updateOffscreenRows();
},

_sortByTimeline: function()
{
var selectedIndex = this._timelineSortSelector.selectedIndex;
if (!selectedIndex)
selectedIndex = 1; 
var selectedOption = this._timelineSortSelector[selectedIndex];
var value = selectedOption.value;

var sortingFunction = this._sortingFunctions[value];
this._dataGrid.sortNodes(sortingFunction);
this.calculator = this._calculators[value];
if (this.calculator.startAtZero)
this._timelineGrid.hideEventDividers();
else
this._timelineGrid.showEventDividers();
this._dataGrid.markColumnAsSortedBy("timeline", "ascending");
this._updateOffscreenRows();
},

_createFilterStatusBarItems: function()
{
var filterBarElement = document.createElement("div");
filterBarElement.className = "scope-bar status-bar-item";
filterBarElement.id = "network-filter";

function createFilterElement(category, label)
{
var categoryElement = document.createElement("li");
categoryElement.category = category;
categoryElement.className = category;
categoryElement.appendChild(document.createTextNode(label));
categoryElement.addEventListener("click", this._updateFilter.bind(this), false);
filterBarElement.appendChild(categoryElement);

return categoryElement;
}

this._filterAllElement = createFilterElement.call(this, "all", WebInspector.UIString("All"));


var dividerElement = document.createElement("div");
dividerElement.addStyleClass("scope-bar-divider");
filterBarElement.appendChild(dividerElement);

for (var category in this._categories)
createFilterElement.call(this, category, this._categories[category].title);
this._filterBarElement = filterBarElement;
},

_createSummaryBar: function()
{
var tbody = this._dataGrid.dataTableBody;
var tfoot = document.createElement("tfoot");
var tr = tfoot.createChild("tr", "revealed network-summary-bar");
var td = tr.createChild("td");
td.setAttribute("colspan", 7);
tbody.parentNode.insertBefore(tfoot, tbody);
this._summaryBarElement = td;
},

_updateSummaryBar: function()
{
var numRequests = this._resources.length;

if (!numRequests) {
if (this._summaryBarElement._isDisplayingWarning)
return;
this._summaryBarElement._isDisplayingWarning = true;

var img = document.createElement("img");
img.src = "Images/warningIcon.png";
this._summaryBarElement.removeChildren();
this._summaryBarElement.appendChild(img);
this._summaryBarElement.appendChild(document.createTextNode(
WebInspector.UIString("No requests captured. Reload the page to see detailed information on the network activity.")));
return;
}
delete this._summaryBarElement._isDisplayingWarning;

var transferSize = 0;
var baseTime = -1;
var maxTime = -1;
for (var i = 0; i < this._resources.length; ++i) {
var resource = this._resources[i];
transferSize += (resource.cached || !resource.transferSize) ? 0 : resource.transferSize;
if (resource === WebInspector.mainResource)
baseTime = resource.startTime;
if (resource.endTime > maxTime)
maxTime = resource.endTime;
}
var text = String.sprintf(WebInspector.UIString("%d requests"), numRequests);
text += "  \u2758  " + String.sprintf(WebInspector.UIString("%s transferred"), Number.bytesToString(transferSize));
if (baseTime !== -1 && this._mainResourceLoadTime !== -1 && this._mainResourceDOMContentTime !== -1 && this._mainResourceDOMContentTime > baseTime) {
text += "  \u2758  " + String.sprintf(WebInspector.UIString("%s (onload: %s, DOMContentLoaded: %s)"),
Number.secondsToString(maxTime - baseTime),
Number.secondsToString(this._mainResourceLoadTime - baseTime),
Number.secondsToString(this._mainResourceDOMContentTime - baseTime));
}
this._summaryBarElement.textContent = text;
},

_showCategory: function(category)
{
this._dataGrid.element.addStyleClass("filter-" + category);
delete this._hiddenCategories[category];
},

_hideCategory: function(category)
{
this._dataGrid.element.removeStyleClass("filter-" + category);
this._hiddenCategories[category] = true;
},

_updateFilter: function(e)
{
var isMac = WebInspector.isMac();
var selectMultiple = false;
if (isMac && e.metaKey && !e.ctrlKey && !e.altKey && !e.shiftKey)
selectMultiple = true;
if (!isMac && e.ctrlKey && !e.metaKey && !e.altKey && !e.shiftKey)
selectMultiple = true;

this._filter(e.target, selectMultiple);
},

_filter: function(target, selectMultiple)
{
function unselectAll()
{
for (var i = 0; i < this._filterBarElement.childNodes.length; ++i) {
var child = this._filterBarElement.childNodes[i];
if (!child.category)
continue;

child.removeStyleClass("selected");
this._hideCategory(child.category);
}
}

if (target.category === this._filterAllElement) {
if (target.hasStyleClass("selected")) {

return;
}


unselectAll.call(this);
} else {

if (this._filterAllElement.hasStyleClass("selected")) {
this._filterAllElement.removeStyleClass("selected");
this._hideCategory("all");
}
}

if (!selectMultiple) {


unselectAll.call(this);

target.addStyleClass("selected");
this._showCategory(target.category);
this._updateOffscreenRows();
return;
}

if (target.hasStyleClass("selected")) {


target.removeStyleClass("selected");
this._hideCategory(target.category);
} else {


target.addStyleClass("selected");
this._showCategory(target.category);
}
this._updateOffscreenRows();
},

_scheduleRefresh: function()
{
if (this._needsRefresh)
return;

this._needsRefresh = true;

if (this.visible && !("_refreshTimeout" in this))
this._refreshTimeout = setTimeout(this.refresh.bind(this), 500);
},

_updateDividersIfNeeded: function(force)
{
var timelineColumn = this._dataGrid.columns.timeline;
for (var i = 0; i < this._dataGrid.resizers.length; ++i) {
if (timelineColumn.ordinal === this._dataGrid.resizers[i].rightNeighboringColumnID) {

this._timelineGrid.element.style.left = this._dataGrid.resizers[i].style.left;
this._timelineGrid.element.style.right = "18px";
}
}

var proceed = true;
if (!this.visible) {
this._scheduleRefresh();
proceed = false;
} else
proceed = this._timelineGrid.updateDividers(force, this.calculator);

if (!proceed)
return;

if (this.calculator.startAtZero || !this.calculator.computePercentageFromEventTime) {






return;
}

this._timelineGrid.removeEventDividers();
if (this._mainResourceLoadTime !== -1) {
var percent = this.calculator.computePercentageFromEventTime(this._mainResourceLoadTime);

var loadDivider = document.createElement("div");
loadDivider.className = "network-event-divider network-red-divider";

var loadDividerPadding = document.createElement("div");
loadDividerPadding.className = "network-event-divider-padding";
loadDividerPadding.title = WebInspector.UIString("Load event fired");
loadDividerPadding.appendChild(loadDivider);
loadDividerPadding.style.left = percent + "%";
this._timelineGrid.addEventDivider(loadDividerPadding);
}

if (this._mainResourceDOMContentTime !== -1) {
var percent = this.calculator.computePercentageFromEventTime(this._mainResourceDOMContentTime);

var domContentDivider = document.createElement("div");
domContentDivider.className = "network-event-divider network-blue-divider";

var domContentDividerPadding = document.createElement("div");
domContentDividerPadding.className = "network-event-divider-padding";
domContentDividerPadding.title = WebInspector.UIString("DOMContent event fired");
domContentDividerPadding.appendChild(domContentDivider);
domContentDividerPadding.style.left = percent + "%";
this._timelineGrid.addEventDivider(domContentDividerPadding);
}
},

_refreshIfNeeded: function()
{
if (this._needsRefresh)
this.refresh();
},

_invalidateAllItems: function()
{
this._staleResources = this._resources.slice();
},

get calculator()
{
return this._calculator;
},

set calculator(x)
{
if (!x || this._calculator === x)
return;

this._calculator = x;
this._calculator.reset();

this._invalidateAllItems();
this.refresh();
},

_resourceGridNode: function(resource)
{
return this._resourceGridNodes[resource.__gridNodeId];
},

_createResourceGridNode: function(resource)
{
var node = new WebInspector.NetworkDataGridNode(this, resource);
resource.__gridNodeId = this._lastResourceGridNodeId++;
this._resourceGridNodes[resource.__gridNodeId] = node;
return node;
},

revealAndSelectItem: function(resource)
{
var node = this._resourceGridNode(resource);
if (node) {
node.reveal();
node.select(true);
}
},

addEventDivider: function(divider)
{
this._timelineGrid.addEventDivider(divider);
},

_createStatusbarButtons: function()
{
this._preserveLogToggle = new WebInspector.StatusBarButton(WebInspector.UIString("Preserve Log upon Navigation"), "record-profile-status-bar-item");
this._preserveLogToggle.addEventListener("click", this._onPreserveLogClicked.bind(this), false);

this._clearButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear"), "clear-status-bar-item");
this._clearButton.addEventListener("click", this._reset.bind(this), false);

this._largerResourcesButton = new WebInspector.StatusBarButton(WebInspector.UIString("Use small resource rows."), "network-larger-resources-status-bar-item");
this._largerResourcesButton.toggled = WebInspector.settings.resourcesLargeRows;
this._largerResourcesButton.addEventListener("click", this._toggleLargerResources.bind(this), false);
},

_onLoadEventFired: function(event)
{
this._mainResourceLoadTime = event.data || -1;

this._updateDividersIfNeeded(true);
},

_domContentLoadedEventFired: function(event)
{
this._mainResourceDOMContentTime = event.data || -1;
this._updateDividersIfNeeded(true);
},

show: function()
{
WebInspector.Panel.prototype.show.call(this);
this._refreshIfNeeded();

if (this.visibleView)
this.visibleView.show(this._viewsContainerElement);

this._dataGrid.updateWidths();
},

hide: function()
{
WebInspector.Panel.prototype.hide.call(this);
this._popoverHelper.hidePopup();
},

get searchableViews()
{
var views = [];
return views;
},

searchMatchFound: function(view, matches)
{
this._resourceGridNode(view.resource).searchMatches = matches;
},

searchCanceled: function(startingNewSearch)
{
WebInspector.Panel.prototype.searchCanceled.call(this, startingNewSearch);

if (startingNewSearch || !this._resources)
return;
},

performSearch: function(query)
{
WebInspector.Panel.prototype.performSearch.call(this, query);
},

refresh: function()
{
this._needsRefresh = false;
if ("_refreshTimeout" in this) {
clearTimeout(this._refreshTimeout);
delete this._refreshTimeout;
}

var wasScrolledToLastRow = this._dataGrid.isScrolledToLastRow();
var staleItemsLength = this._staleResources.length;
var boundariesChanged = false;

for (var i = 0; i < staleItemsLength; ++i) {
var resource = this._staleResources[i];
var node = this._resourceGridNode(resource);
if (!node) {

node = this._createResourceGridNode(resource);
this._dataGrid.appendChild(node);
}
node.refreshResource();

if (this.calculator.updateBoundaries(resource))
boundariesChanged = true;
}

if (boundariesChanged) {

this._invalidateAllItems();
staleItemsLength = this._staleResources.length;
}

for (var i = 0; i < staleItemsLength; ++i)
this._resourceGridNode(this._staleResources[i]).refreshGraph(this.calculator);

this._staleResources = [];
this._sortItems();
this._updateSummaryBar();
this._updateOffscreenRows();
this._dataGrid.updateWidths();

if (wasScrolledToLastRow)
this._dataGrid.scrollToLastRow();
},

_onPreserveLogClicked: function(e)
{
this._preserveLogToggle.toggled = !this._preserveLogToggle.toggled;
},

_reset: function()
{
this._popoverHelper.hidePopup();
this._closeVisibleResource();

this._toggleGridMode();


if (this._calculator)
this._calculator.reset();

this._resources = [];
this._resourcesById = {};
this._resourcesByURL = {};
this._staleResources = [];
this._resourceGridNodes = {};

this._dataGrid.removeChildren();
this._updateDividersIfNeeded(true);


this._mainResourceLoadTime = -1;
this._mainResourceDOMContentTime = -1;

this._viewsContainerElement.removeChildren();
this._viewsContainerElement.appendChild(this._closeButtonElement);
this._updateSummaryBar();
WebInspector.extensionServer.resetResources();
},

get resources()
{
return this._resources;
},

resourceById: function(id)
{
return this._resourcesById[id];
},

_onResourceStarted: function(event)
{
this._appendResource(event.data);
},

_appendResource: function(resource)
{
this._resources.push(resource);
this._resourcesById[resource.identifier] = resource;
this._resourcesByURL[resource.url] = resource;


if (resource.redirects) {
for (var i = 0; i < resource.redirects.length; ++i)
this._refreshResource(resource.redirects[i]);
}

this._refreshResource(resource);
},

_onResourceUpdated: function(event)
{
this._refreshResource(event.data);
},

_refreshResource: function(resource)
{
this._staleResources.push(resource);
this._scheduleRefresh();
},

clear: function()
{
if (this._preserveLogToggle.toggled)
return;
this._reset();
},

_frameNavigated: function(event)
{
if (!event.data.isMainFrame)
return;

var loaderId = event.data.loaderId;

if (this._preserveLogToggle.toggled)
return;


var resourcesToPreserve = [];
for (var i = 0; i < this._resources.length; ++i) {
var resource = this._resources[i];
if (resource.loaderId === loaderId)
resourcesToPreserve.push(resource);
}

this._reset();


for (var i = 0; i < resourcesToPreserve.length; ++i)
this._appendResource(resourcesToPreserve[i]);
},

canShowAnchorLocation: function(anchor)
{
return !!this._resourcesByURL[anchor.href];
},

showAnchorLocation: function(anchor)
{
this._showResource(this._resourcesByURL[anchor.href], anchor.getAttribute("line_number") - 1);
},

_showResource: function(resource, line)
{
if (!resource)
return;

this._popoverHelper.hidePopup();

this._toggleViewingResourceMode();

if (this.visibleView) {
this.visibleView.detach();
delete this.visibleView;
}

var view = new WebInspector.NetworkItemView(resource);
view.show(this._viewsContainerElement);
this.visibleView = view;

this.updateSidebarWidth();
},

_closeVisibleResource: function()
{
this.element.removeStyleClass("viewing-resource");

if (this.visibleView) {
this.visibleView.detach();
delete this.visibleView;
}

if (this._lastSelectedGraphTreeElement)
this._lastSelectedGraphTreeElement.select(true);

this.updateSidebarWidth();
},

_toggleLargerResources: function()
{
WebInspector.settings.resourcesLargeRows = !WebInspector.settings.resourcesLargeRows;
this._setLargerResources(WebInspector.settings.resourcesLargeRows);
},

_setLargerResources: function(enabled)
{
this._largerResourcesButton.toggled = enabled;
if (!enabled) {
this._largerResourcesButton.title = WebInspector.UIString("Use large resource rows.");
this._dataGrid.element.addStyleClass("small");
this._timelineGrid.element.addStyleClass("small");
this._viewsContainerElement.addStyleClass("small");
} else {
this._largerResourcesButton.title = WebInspector.UIString("Use small resource rows.");
this._dataGrid.element.removeStyleClass("small");
this._timelineGrid.element.removeStyleClass("small");
this._viewsContainerElement.removeStyleClass("small");
}
this._updateOffscreenRows();
},

_getPopoverAnchor: function(element)
{
var anchor = element.enclosingNodeOrSelfWithClass("network-graph-bar") || element.enclosingNodeOrSelfWithClass("network-graph-label");
if (!anchor)
return null;
var resource = anchor.parentElement.resource;
return resource && resource.timing ? anchor : null;
},

_showPopover: function(anchor)
{
var resource = anchor.parentElement.resource;
var tableElement = WebInspector.ResourceTimingView.createTimingTable(resource);
var popover = new WebInspector.Popover(tableElement);
popover.show(anchor);
return popover;
},

_toggleGridMode: function()
{
if (this._viewingResourceMode) {
this._viewingResourceMode = false;
this.element.removeStyleClass("viewing-resource");
this._dataGrid.element.removeStyleClass("viewing-resource-mode");
this._viewsContainerElement.addStyleClass("hidden");
this.sidebarElement.style.right = 0;
this.sidebarElement.style.removeProperty("width");
if (this._dataGrid.selectedNode)
this._dataGrid.selectedNode.selected = false;
}

if (this._briefGrid) {
this._dataGrid.element.removeStyleClass("full-grid-mode");
this._dataGrid.element.addStyleClass("brief-grid-mode");

this._dataGrid.hideColumn("method");
this._dataGrid.hideColumn("status");
this._dataGrid.hideColumn("type");
this._dataGrid.hideColumn("size");
this._dataGrid.hideColumn("time");

var widths = {};
widths.name = 20;
widths.timeline = 80;
} else {
this._dataGrid.element.addStyleClass("full-grid-mode");
this._dataGrid.element.removeStyleClass("brief-grid-mode");

this._dataGrid.showColumn("method");
this._dataGrid.showColumn("status");
this._dataGrid.showColumn("type");
this._dataGrid.showColumn("size");
this._dataGrid.showColumn("time");

var widths = {};
widths.name = 20;
widths.method = 6;
widths.status = 6;
widths.type = 6;
widths.size = 6;
widths.time = 6;
widths.timeline = 50;
}

this._dataGrid.showColumn("timeline");
this._dataGrid.applyColumnWidthsMap(widths);

},

_toggleViewingResourceMode: function()
{
if (this._viewingResourceMode)
return;
this._viewingResourceMode = true;
this._preservedColumnWidths = this._dataGrid.columnWidthsMap();

this.element.addStyleClass("viewing-resource");
this._dataGrid.element.addStyleClass("viewing-resource-mode");
this._dataGrid.element.removeStyleClass("full-grid-mode");
this._dataGrid.element.removeStyleClass("brief-grid-mode");

this._dataGrid.hideColumn("method");
this._dataGrid.hideColumn("status");
this._dataGrid.hideColumn("type");
this._dataGrid.hideColumn("size");
this._dataGrid.hideColumn("time");
this._dataGrid.hideColumn("timeline");

this._viewsContainerElement.removeStyleClass("hidden");
this.updateSidebarWidth(200);

var widths = {};
widths.name = 100;
this._dataGrid.applyColumnWidthsMap(widths);
},

_contextMenu: function(event)
{
var contextMenu = new WebInspector.ContextMenu();
var gridNode = this._dataGrid.dataGridNodeFromNode(event.target);
var resource = gridNode && gridNode._resource;

if (resource) {
contextMenu.appendItem(WebInspector.openLinkExternallyLabel(), WebInspector.openResource.bind(WebInspector, resource.url, false));
contextMenu.appendSeparator();
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy location" : "Copy Location"), this._copyLocation.bind(this, resource));
if (resource.requestHeadersText)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy request headers" : "Copy Request Headers"), this._copyRequestHeaders.bind(this, resource));
if (resource.responseHeadersText)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy response headers" : "Copy Response Headers"), this._copyResponseHeaders.bind(this, resource));
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy entry as HAR" : "Copy Entry as HAR"), this._copyResource.bind(this, resource));
}
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy all as HAR" : "Copy All as HAR"), this._copyAll.bind(this));

if (Preferences.saveAsAvailable) {
contextMenu.appendSeparator();
if (resource)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save entry as HAR" : "Save Entry as HAR"), this._exportResource.bind(this, resource));
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save all as HAR" : "Save All as HAR"), this._exportAll.bind(this));
}

contextMenu.appendSeparator();
contextMenu.appendCheckboxItem(WebInspector.UIString("Enabled background events collection"), this._toggleBackgroundEventsCollection.bind(this), this._backgroundCollectionEnabled);

contextMenu.show(event);
},

_copyAll: function()
{
var harArchive = {
log: (new WebInspector.HARLog()).build()
};
InspectorFrontendHost.copyText(JSON.stringify(harArchive));
},

_copyResource: function(resource)
{
var har = (new WebInspector.HAREntry(resource)).build();
InspectorFrontendHost.copyText(JSON.stringify(har));
},

_copyLocation: function(resource)
{
InspectorFrontendHost.copyText(resource.url);
},

_copyRequestHeaders: function(resource)
{
InspectorFrontendHost.copyText(resource.requestHeadersText);
},

_copyResponseHeaders: function(resource)
{
InspectorFrontendHost.copyText(resource.responseHeadersText);
},

_exportAll: function()
{
var harArchive = {
log: (new WebInspector.HARLog()).build()
};
InspectorFrontendHost.saveAs(WebInspector.mainResource.domain + ".har", JSON.stringify(harArchive));
},

_exportResource: function(resource)
{
var har = (new WebInspector.HAREntry(resource)).build();
InspectorFrontendHost.saveAs(resource.displayName + ".har", JSON.stringify(har));
},

_toggleBackgroundEventsCollection: function(resource)
{
this._backgroundCollectionEnabled = !this._backgroundCollectionEnabled;
NetworkAgent.setBackgroundEventsCollectionEnabled(this._backgroundCollectionEnabled);
},

_updateOffscreenRows: function(e)
{
var dataTableBody = this._dataGrid.dataTableBody;
var rows = dataTableBody.children;
var recordsCount = rows.length;
if (recordsCount < 2)
return;  

var visibleTop = this._dataGrid.scrollContainer.scrollTop;
var visibleBottom = visibleTop + this._dataGrid.scrollContainer.offsetHeight;

var rowHeight = 0;


var unfilteredRowIndex = 0;
for (var i = 0; i < recordsCount - 1; ++i) {
var row = rows[i];

var dataGridNode = this._dataGrid.dataGridNodeFromNode(row);
if (dataGridNode.isFilteredOut()) {
row.removeStyleClass("offscreen");
continue;
}

if (!rowHeight)
rowHeight = row.offsetHeight;

var rowIsVisible = unfilteredRowIndex * rowHeight < visibleBottom && (unfilteredRowIndex + 1) * rowHeight > visibleTop;
if (rowIsVisible !== row.rowIsVisible) {
if (rowIsVisible)
row.removeStyleClass("offscreen");
else
row.addStyleClass("offscreen");
row.rowIsVisible = rowIsVisible;
}
unfilteredRowIndex++;
}
}
}

WebInspector.NetworkPanel.prototype.__proto__ = WebInspector.Panel.prototype;

WebInspector.NetworkBaseCalculator = function()
{
}

WebInspector.NetworkBaseCalculator.prototype = {
computeSummaryValues: function(items)
{
var total = 0;
var categoryValues = {};

var itemsLength = items.length;
for (var i = 0; i < itemsLength; ++i) {
var item = items[i];
var value = this._value(item);
if (typeof value === "undefined")
continue;
if (!(item.category.name in categoryValues))
categoryValues[item.category.name] = 0;
categoryValues[item.category.name] += value;
total += value;
}

return {categoryValues: categoryValues, total: total};
},

computeBarGraphPercentages: function(item)
{
return {start: 0, middle: 0, end: (this._value(item) / this.boundarySpan) * 100};
},

computeBarGraphLabels: function(item)
{
const label = this.formatValue(this._value(item));
return {left: label, right: label, tooltip: label};
},

get boundarySpan()
{
return this.maximumBoundary - this.minimumBoundary;
},

updateBoundaries: function(item)
{
this.minimumBoundary = 0;

var value = this._value(item);
if (typeof this.maximumBoundary === "undefined" || value > this.maximumBoundary) {
this.maximumBoundary = value;
return true;
}
return false;
},

reset: function()
{
delete this.minimumBoundary;
delete this.maximumBoundary;
},

_value: function(item)
{
return 0;
},

formatValue: function(value)
{
return value.toString();
}
}

WebInspector.NetworkTimeCalculator = function(startAtZero)
{
WebInspector.NetworkBaseCalculator.call(this);
this.startAtZero = startAtZero;
}

WebInspector.NetworkTimeCalculator.prototype = {
computeSummaryValues: function(resources)
{
var resourcesByCategory = {};
var resourcesLength = resources.length;
for (var i = 0; i < resourcesLength; ++i) {
var resource = resources[i];
if (!(resource.category.name in resourcesByCategory))
resourcesByCategory[resource.category.name] = [];
resourcesByCategory[resource.category.name].push(resource);
}

var earliestStart;
var latestEnd;
var categoryValues = {};
for (var category in resourcesByCategory) {
resourcesByCategory[category].sort(WebInspector.Resource.CompareByTime);
categoryValues[category] = 0;

var segment = {start: -1, end: -1};

var categoryResources = resourcesByCategory[category];
var resourcesLength = categoryResources.length;
for (var i = 0; i < resourcesLength; ++i) {
var resource = categoryResources[i];
if (resource.startTime === -1 || resource.endTime === -1)
continue;

if (typeof earliestStart === "undefined")
earliestStart = resource.startTime;
else
earliestStart = Math.min(earliestStart, resource.startTime);

if (typeof latestEnd === "undefined")
latestEnd = resource.endTime;
else
latestEnd = Math.max(latestEnd, resource.endTime);

if (resource.startTime <= segment.end) {
segment.end = Math.max(segment.end, resource.endTime);
continue;
}

categoryValues[category] += segment.end - segment.start;

segment.start = resource.startTime;
segment.end = resource.endTime;
}


categoryValues[category] += segment.end - segment.start;
}

return {categoryValues: categoryValues, total: latestEnd - earliestStart};
},

computeBarGraphPercentages: function(resource)
{
if (resource.startTime !== -1)
var start = ((resource.startTime - this.minimumBoundary) / this.boundarySpan) * 100;
else
var start = 0;

if (resource.responseReceivedTime !== -1)
var middle = ((resource.responseReceivedTime - this.minimumBoundary) / this.boundarySpan) * 100;
else
var middle = (this.startAtZero ? start : 100);

if (resource.endTime !== -1)
var end = ((resource.endTime - this.minimumBoundary) / this.boundarySpan) * 100;
else
var end = (this.startAtZero ? middle : 100);

if (this.startAtZero) {
end -= start;
middle -= start;
start = 0;
}

return {start: start, middle: middle, end: end};
},

computePercentageFromEventTime: function(eventTime)
{



if (eventTime !== -1 && !this.startAtZero)
return ((eventTime - this.minimumBoundary) / this.boundarySpan) * 100;

return 0;
},

computeBarGraphLabels: function(resource)
{
var rightLabel = "";
if (resource.responseReceivedTime !== -1 && resource.endTime !== -1)
rightLabel = this.formatValue(resource.endTime - resource.responseReceivedTime);

var hasLatency = resource.latency > 0;
if (hasLatency)
var leftLabel = this.formatValue(resource.latency);
else
var leftLabel = rightLabel;

if (resource.timing)
return {left: leftLabel, right: rightLabel};

if (hasLatency && rightLabel) {
var total = this.formatValue(resource.duration);
var tooltip = WebInspector.UIString("%s latency, %s download (%s total)", leftLabel, rightLabel, total);
} else if (hasLatency)
var tooltip = WebInspector.UIString("%s latency", leftLabel);
else if (rightLabel)
var tooltip = WebInspector.UIString("%s download", rightLabel);

if (resource.cached)
tooltip = WebInspector.UIString("%s (from cache)", tooltip);
return {left: leftLabel, right: rightLabel, tooltip: tooltip};
},

updateBoundaries: function(resource)
{
var didChange = false;

var lowerBound;
if (this.startAtZero)
lowerBound = 0;
else
lowerBound = this._lowerBound(resource);

if (lowerBound !== -1 && (typeof this.minimumBoundary === "undefined" || lowerBound < this.minimumBoundary)) {
this.minimumBoundary = lowerBound;
didChange = true;
}

var upperBound = this._upperBound(resource);
if (upperBound !== -1 && (typeof this.maximumBoundary === "undefined" || upperBound > this.maximumBoundary)) {
this.maximumBoundary = upperBound;
didChange = true;
}

return didChange;
},

formatValue: function(value)
{
return Number.secondsToString(value);
},

_lowerBound: function(resource)
{
return 0;
},

_upperBound: function(resource)
{
return 0;
}
}

WebInspector.NetworkTimeCalculator.prototype.__proto__ = WebInspector.NetworkBaseCalculator.prototype;

WebInspector.NetworkTransferTimeCalculator = function()
{
WebInspector.NetworkTimeCalculator.call(this, false);
}

WebInspector.NetworkTransferTimeCalculator.prototype = {
formatValue: function(value)
{
return Number.secondsToString(value);
},

_lowerBound: function(resource)
{
return resource.startTime;
},

_upperBound: function(resource)
{
return resource.endTime;
}
}

WebInspector.NetworkTransferTimeCalculator.prototype.__proto__ = WebInspector.NetworkTimeCalculator.prototype;

WebInspector.NetworkTransferDurationCalculator = function()
{
WebInspector.NetworkTimeCalculator.call(this, true);
}

WebInspector.NetworkTransferDurationCalculator.prototype = {
formatValue: function(value)
{
return Number.secondsToString(value);
},

_upperBound: function(resource)
{
return resource.duration;
}
}

WebInspector.NetworkTransferDurationCalculator.prototype.__proto__ = WebInspector.NetworkTimeCalculator.prototype;

WebInspector.NetworkDataGridNode = function(panel, resource)
{
WebInspector.DataGridNode.call(this, {});
this._panel = panel;
this._resource = resource;
}

WebInspector.NetworkDataGridNode.prototype = {
createCells: function()
{
this._nameCell = this._createDivInTD("name");
this._methodCell = this._createDivInTD("method");
this._statusCell = this._createDivInTD("status");
this._typeCell = this._createDivInTD("type");
this._sizeCell = this._createDivInTD("size");
this._timeCell = this._createDivInTD("time");
this._createTimelineCell();
this._nameCell.addEventListener("click", this.select.bind(this), false);
this._nameCell.addEventListener("dblclick", this._openInNewTab.bind(this), false);
},

isFilteredOut: function()
{
if (!this._panel._hiddenCategories.all)
return false;
return this._resource.category.name in this._panel._hiddenCategories;
},

select: function()
{
this._panel._showResource(this._resource);
WebInspector.DataGridNode.prototype.select.apply(this, arguments);
},

_openInNewTab: function()
{
PageAgent.open(this._resource.url, true);
},

get selectable()
{
if (!this._panel._viewingResourceMode)
return false;
return !this.isFilteredOut();
},

_createDivInTD: function(columnIdentifier)
{
var td = document.createElement("td");
td.className = columnIdentifier + "-column";
var div = document.createElement("div");
td.appendChild(div);
this._element.appendChild(td);
return div;
},

_createTimelineCell: function()
{
this._graphElement = document.createElement("div");
this._graphElement.className = "network-graph-side";

this._barAreaElement = document.createElement("div");

this._barAreaElement.className = "network-graph-bar-area";
this._barAreaElement.resource = this._resource;
this._graphElement.appendChild(this._barAreaElement);

this._barLeftElement = document.createElement("div");
this._barLeftElement.className = "network-graph-bar waiting";
this._barAreaElement.appendChild(this._barLeftElement);

this._barRightElement = document.createElement("div");
this._barRightElement.className = "network-graph-bar";
this._barAreaElement.appendChild(this._barRightElement);


this._labelLeftElement = document.createElement("div");
this._labelLeftElement.className = "network-graph-label waiting";
this._barAreaElement.appendChild(this._labelLeftElement);

this._labelRightElement = document.createElement("div");
this._labelRightElement.className = "network-graph-label";
this._barAreaElement.appendChild(this._labelRightElement);

this._graphElement.addEventListener("mouseover", this._refreshLabelPositions.bind(this), false);

this._timelineCell = document.createElement("td");
this._timelineCell.className = "timeline-column";
this._element.appendChild(this._timelineCell);
this._timelineCell.appendChild(this._graphElement);
},

refreshResource: function()
{
this._refreshNameCell();

this._methodCell.setTextAndTitle(this._resource.requestMethod);

this._refreshStatusCell();
this._refreshTypeCell();
this._refreshSizeCell();
this._refreshTimeCell();

if (this._resource.cached)
this._graphElement.addStyleClass("resource-cached");

this._element.addStyleClass("network-item");
if (!this._element.hasStyleClass("network-category-" + this._resource.category.name)) {
this._element.removeMatchingStyleClasses("network-category-\\w+");
this._element.addStyleClass("network-category-" + this._resource.category.name);
}
},

_refreshNameCell: function()
{
this._nameCell.removeChildren();

if (this._resource.category === WebInspector.resourceCategories.images) {
var previewImage = document.createElement("img");
previewImage.className = "image-network-icon-preview";
this._resource.populateImageSource(previewImage);

var iconElement = document.createElement("div");
iconElement.className = "icon";
iconElement.appendChild(previewImage);
} else {
var iconElement = document.createElement("img");
iconElement.className = "icon";
}
this._nameCell.appendChild(iconElement);
this._nameCell.appendChild(document.createTextNode(this._fileName()));


var subtitle = this._resource.displayDomain;

if (this._resource.path && this._resource.lastPathComponent) {
var lastPathComponentIndex = this._resource.path.lastIndexOf("/" + this._resource.lastPathComponent);
if (lastPathComponentIndex != -1)
subtitle += this._resource.path.substring(0, lastPathComponentIndex);
}

this._appendSubtitle(this._nameCell, subtitle);
this._nameCell.title = this._resource.url;
},

_fileName: function()
{
var fileName = this._resource.displayName;
if (this._resource.queryString)
fileName += "?" + this._resource.queryString;
return fileName;
},

_refreshStatusCell: function()
{
this._statusCell.removeChildren();

if (this._resource.failed) {
if (this._resource.canceled)
this._statusCell.setTextAndTitle(WebInspector.UIString("(canceled)"));
else
this._statusCell.setTextAndTitle(WebInspector.UIString("(failed)"));
this._statusCell.addStyleClass("network-dim-cell");
return;
}

var fromCache = this._resource.cached;
if (fromCache) {
this._statusCell.setTextAndTitle(WebInspector.UIString("(from cache)"));
this._statusCell.addStyleClass("network-dim-cell");
return;
}

this._statusCell.removeStyleClass("network-dim-cell");
if (this._resource.statusCode) {
this._statusCell.appendChild(document.createTextNode(this._resource.statusCode));
this._statusCell.removeStyleClass("network-dim-cell");
this._appendSubtitle(this._statusCell, this._resource.statusText);
this._statusCell.title = this._resource.statusCode + " " + this._resource.statusText;
} else {
if (this._resource.isDataURL() && this._resource.finished)
this._statusCell.setTextAndTitle(WebInspector.UIString("(data url)"));
else if (this._resource.isPingRequest())
this._statusCell.setTextAndTitle(WebInspector.UIString("(ping)"));
else
this._statusCell.setTextAndTitle(WebInspector.UIString("(Pending)"));
this._statusCell.addStyleClass("network-dim-cell");
}
},

_refreshTypeCell: function()
{
if (this._resource.mimeType) {
this._typeCell.removeStyleClass("network-dim-cell");
this._typeCell.setTextAndTitle(this._resource.mimeType);
} else if (this._resource.isPingRequest) {
this._typeCell.removeStyleClass("network-dim-cell");
this._typeCell.setTextAndTitle(this._resource.requestContentType());
} else {
this._typeCell.addStyleClass("network-dim-cell");
this._typeCell.setTextAndTitle(WebInspector.UIString("Pending"));
}
},

_refreshSizeCell: function()
{
if (this._resource.cached) {
this._sizeCell.setTextAndTitle(WebInspector.UIString("(from cache)"));
this._sizeCell.addStyleClass("network-dim-cell");
} else {
var resourceSize = typeof this._resource.resourceSize === "number" ? Number.bytesToString(this._resource.resourceSize) : "?";
var transferSize = typeof this._resource.transferSize === "number" ? Number.bytesToString(this._resource.transferSize) : "?";
this._sizeCell.setTextAndTitle(transferSize);
this._sizeCell.removeStyleClass("network-dim-cell");
this._appendSubtitle(this._sizeCell, resourceSize);
}
},

_refreshTimeCell: function()
{
if (this._resource.duration > 0) {
this._timeCell.removeStyleClass("network-dim-cell");
this._timeCell.setTextAndTitle(Number.secondsToString(this._resource.duration));
this._appendSubtitle(this._timeCell, Number.secondsToString(this._resource.latency));
} else {
this._timeCell.addStyleClass("network-dim-cell");
this._timeCell.setTextAndTitle(WebInspector.UIString("Pending"));
}
},

_appendSubtitle: function(cellElement, subtitleText)
{
var subtitleElement = document.createElement("div");
subtitleElement.className = "network-cell-subtitle";
subtitleElement.textContent = subtitleText;
cellElement.appendChild(subtitleElement);
},

refreshGraph: function(calculator)
{
var percentages = calculator.computeBarGraphPercentages(this._resource);
this._percentages = percentages;

this._barAreaElement.removeStyleClass("hidden");

if (!this._graphElement.hasStyleClass("network-category-" + this._resource.category.name)) {
this._graphElement.removeMatchingStyleClasses("network-category-\\w+");
this._graphElement.addStyleClass("network-category-" + this._resource.category.name);
}

this._barLeftElement.style.setProperty("left", percentages.start + "%");
this._barRightElement.style.setProperty("right", (100 - percentages.end) + "%");

this._barLeftElement.style.setProperty("right", (100 - percentages.end) + "%");
this._barRightElement.style.setProperty("left", percentages.middle + "%");

var labels = calculator.computeBarGraphLabels(this._resource);
this._labelLeftElement.textContent = labels.left;
this._labelRightElement.textContent = labels.right;

var tooltip = (labels.tooltip || "");
this._barLeftElement.title = tooltip;
this._labelLeftElement.title = tooltip;
this._labelRightElement.title = tooltip;
this._barRightElement.title = tooltip;
},

_refreshLabelPositions: function()
{
if (!this._percentages)
return;
this._labelLeftElement.style.removeProperty("left");
this._labelLeftElement.style.removeProperty("right");
this._labelLeftElement.removeStyleClass("before");
this._labelLeftElement.removeStyleClass("hidden");

this._labelRightElement.style.removeProperty("left");
this._labelRightElement.style.removeProperty("right");
this._labelRightElement.removeStyleClass("after");
this._labelRightElement.removeStyleClass("hidden");

const labelPadding = 10;
const barRightElementOffsetWidth = this._barRightElement.offsetWidth;
const barLeftElementOffsetWidth = this._barLeftElement.offsetWidth;

if (this._barLeftElement) {
var leftBarWidth = barLeftElementOffsetWidth - labelPadding;
var rightBarWidth = (barRightElementOffsetWidth - barLeftElementOffsetWidth) - labelPadding;
} else {
var leftBarWidth = (barLeftElementOffsetWidth - barRightElementOffsetWidth) - labelPadding;
var rightBarWidth = barRightElementOffsetWidth - labelPadding;
}

const labelLeftElementOffsetWidth = this._labelLeftElement.offsetWidth;
const labelRightElementOffsetWidth = this._labelRightElement.offsetWidth;

const labelBefore = (labelLeftElementOffsetWidth > leftBarWidth);
const labelAfter = (labelRightElementOffsetWidth > rightBarWidth);
const graphElementOffsetWidth = this._graphElement.offsetWidth;

if (labelBefore && (graphElementOffsetWidth * (this._percentages.start / 100)) < (labelLeftElementOffsetWidth + 10))
var leftHidden = true;

if (labelAfter && (graphElementOffsetWidth * ((100 - this._percentages.end) / 100)) < (labelRightElementOffsetWidth + 10))
var rightHidden = true;

if (barLeftElementOffsetWidth == barRightElementOffsetWidth) {

if (labelBefore && !labelAfter)
leftHidden = true;
else if (labelAfter && !labelBefore)
rightHidden = true;
}

if (labelBefore) {
if (leftHidden)
this._labelLeftElement.addStyleClass("hidden");
this._labelLeftElement.style.setProperty("right", (100 - this._percentages.start) + "%");
this._labelLeftElement.addStyleClass("before");
} else {
this._labelLeftElement.style.setProperty("left", this._percentages.start + "%");
this._labelLeftElement.style.setProperty("right", (100 - this._percentages.middle) + "%");
}

if (labelAfter) {
if (rightHidden)
this._labelRightElement.addStyleClass("hidden");
this._labelRightElement.style.setProperty("left", this._percentages.end + "%");
this._labelRightElement.addStyleClass("after");
} else {
this._labelRightElement.style.setProperty("left", this._percentages.middle + "%");
this._labelRightElement.style.setProperty("right", (100 - this._percentages.end) + "%");
}
}
}

WebInspector.NetworkDataGridNode.NameComparator = function(a, b)
{
var aFileName = a._resource.displayName + (a._resource.queryString ? a._resource.queryString : "");
var bFileName = b._resource.displayName + (b._resource.queryString ? b._resource.queryString : "");
if (aFileName > bFileName)
return 1;
if (bFileName > aFileName)
return -1;
return 0;
}

WebInspector.NetworkDataGridNode.SizeComparator = function(a, b)
{
if (b._resource.cached && !a._resource.cached)
return 1;
if (a._resource.cached && !b._resource.cached)
return -1;

if (a._resource.resourceSize === b._resource.resourceSize)
return 0;

return a._resource.resourceSize - b._resource.resourceSize;
}

WebInspector.NetworkDataGridNode.ResourcePropertyComparator = function(propertyName, revert, a, b)
{
var aValue = a._resource[propertyName];
var bValue = b._resource[propertyName];
if (aValue > bValue)
return revert ? -1 : 1;
if (bValue > aValue)
return revert ? 1 : -1;
return 0;
}

WebInspector.NetworkDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;





var InjectedFakeWorker = function(InjectedScriptHost, inspectedWindow, injectedScriptId)
{

Worker = function(url)
{
var impl = new FakeWorker(this, url);
if (impl === null)
return null;

this.isFake = true;
this.postMessage = bind(impl.postMessage, impl);
this.terminate = bind(impl.terminate, impl);

function onmessageGetter()
{
return impl.channel.port1.onmessage;
}
function onmessageSetter(callback)
{
impl.channel.port1.onmessage = callback;
}
this.__defineGetter__("onmessage", onmessageGetter);
this.__defineSetter__("onmessage", onmessageSetter);
this.addEventListener = bind(impl.channel.port1.addEventListener, impl.channel.port1);
this.removeEventListener = bind(impl.channel.port1.removeEventListener, impl.channel.port1);
this.dispatchEvent = bind(impl.channel.port1.dispatchEvent, impl.channel.port1);
}

function FakeWorker(worker, url)
{
var scriptURL = this._expandURLAndCheckOrigin(document.baseURI, location.href, url);

this._worker = worker;
this._id = InjectedScriptHost.nextWorkerId();
this.channel = new MessageChannel();
this._listeners = [];
this._buildWorker(scriptURL);

InjectedScriptHost.didCreateWorker(this._id, scriptURL.url, false);
}

FakeWorker.prototype = {
postMessage: function(msg, opt_ports)
{
if (this._frame != null)
this.channel.port1.postMessage.apply(this.channel.port1, arguments);
else if (this._pendingMessages)
this._pendingMessages.push(arguments)
else
this._pendingMessages = [ arguments ];
},

terminate: function()
{
InjectedScriptHost.didDestroyWorker(this._id);

this.channel.port1.close();
this.channel.port2.close();
if (this._frame != null)
this._frame.frameElement.parentNode.removeChild(this._frame.frameElement);
this._frame = null;
this._worker = null; 
},

_buildWorker: function(url)
{
var code = this._loadScript(url.url);
var iframeElement = document.createElement("iframe");
iframeElement.style.display = "none";

this._document = document;
iframeElement.onload = bind(this._onWorkerFrameLoaded, this, iframeElement, url, code);

if (document.body)
this._attachWorkerFrameToDocument(iframeElement, url, code);
else
window.addEventListener("load", bind(this._attachWorkerFrameToDocument, this, iframeElement), false);
},

_attachWorkerFrameToDocument: function(iframeElement)
{
document.body.appendChild(iframeElement);
},

_onWorkerFrameLoaded: function(iframeElement, url, code)
{
var frame = iframeElement.contentWindow;
this._frame = frame;
this._setupWorkerContext(frame, url);

var frameContents = '(function() { var location = __devtools.location; var window; ' + code + '})();\n' + '//@ sourceURL=' + url.url;

frame.eval(frameContents);
if (this._pendingMessages) {
for (var msg = 0; msg < this._pendingMessages.length; ++msg)
this.postMessage.apply(this, this._pendingMessages[msg]);
delete this._pendingMessages;
}
},

_setupWorkerContext: function(workerFrame, url)
{
workerFrame.__devtools = {
handleException: bind(this._handleException, this),
location: url.mockLocation()
};

var self = this;

function onmessageGetter()
{
return self.channel.port2.onmessage ? self.channel.port2.onmessage.originalCallback : null;
}

function onmessageSetter(callback)
{
var wrappedCallback = bind(self._callbackWrapper, self, callback);
wrappedCallback.originalCallback = callback;
self.channel.port2.onmessage = wrappedCallback;
}

workerFrame.__defineGetter__("onmessage", onmessageGetter);
workerFrame.__defineSetter__("onmessage", onmessageSetter);
workerFrame.addEventListener = bind(this._addEventListener, this);
workerFrame.removeEventListener = bind(this._removeEventListener, this);
workerFrame.dispatchEvent = bind(this.channel.port2.dispatchEvent, this.channel.port2);
workerFrame.postMessage = bind(this.channel.port2.postMessage, this.channel.port2);
workerFrame.importScripts = bind(this._importScripts, this, workerFrame);
workerFrame.close = bind(this.terminate, this);
},

_addEventListener: function(type, callback, useCapture)
{
var wrappedCallback = bind(this._callbackWrapper, this, callback);
wrappedCallback.originalCallback = callback;
wrappedCallback.type = type;
wrappedCallback.useCapture = Boolean(useCapture);

this.channel.port2.addEventListener(type, wrappedCallback, useCapture);
this._listeners.push(wrappedCallback);
},

_removeEventListener: function(type, callback, useCapture)
{
var listeners = this._listeners;
for (var i = 0; i < listeners.length; ++i) {
if (listeners[i].originalCallback === callback &&
listeners[i].type === type && 
listeners[i].useCapture === Boolean(useCapture)) {
this.channel.port2.removeEventListener(type, listeners[i], useCapture);
listeners[i] = listeners[listeners.length - 1];
listeners.pop();
break;
}
}
},

_callbackWrapper: function(callback, msg)
{

if (!this._frame.onerror && !this._worker.onerror) {
callback(msg);
return;
}

try {
callback(msg);
} catch (e) {
this._handleException(e, this._frame.onerror, this._worker.onerror);
}
},

_handleException: function(e)
{


var errorEvent = this._document.createEvent("Event");
errorEvent.initEvent("Event", false, false);
errorEvent.message = "Uncaught exception";

for (var i = 1; i < arguments.length; ++i) {
if (arguments[i] && arguments[i](errorEvent))
return;
}

throw e;
},

_importScripts: function(targetFrame)
{
for (var i = 1; i < arguments.length; ++i) {
var workerOrigin = targetFrame.__devtools.location.href;
var url = this._expandURLAndCheckOrigin(workerOrigin, workerOrigin, arguments[i]);
targetFrame.eval(this._loadScript(url.url) + "\n//@ sourceURL= " + url.url);
}
},

_loadScript: function(url)
{
var xhr = new XMLHttpRequest();
xhr.open("GET", url, false);
xhr.send(null);

var text = xhr.responseText;
if (xhr.status != 0 && xhr.status/100 !== 2) { 
console.error("Failed to load worker: " + url + "[" + xhr.status + "]");
text = ""; 
}
return text;
},

_expandURLAndCheckOrigin: function(baseURL, origin, url)
{
var scriptURL = new URL(baseURL).completeWith(url);

if (!scriptURL.sameOrigin(origin))
throw new DOMCoreException("SECURITY_ERR",18);
return scriptURL;
}
};

function URL(url)
{
this.url = url;
this.split();
}

URL.prototype = {
urlRegEx: (/^(http[s]?|file):\/\/([^\/:]*)(:[\d]+)?(?:(\/[^#?]*)(\?[^#]*)?(?:#(.*))?)?$/i),

split: function()
{
function emptyIfNull(str)
{
return str == null ? "" : str;
}
var parts = this.urlRegEx.exec(this.url);

this.schema = parts[1];
this.host = parts[2];
this.port = emptyIfNull(parts[3]);
this.path = emptyIfNull(parts[4]);
this.query = emptyIfNull(parts[5]);
this.fragment = emptyIfNull(parts[6]);
},

mockLocation: function()
{
var host = this.host.replace(/^[^@]*@/, "");

return {
href:     this.url,
protocol: this.schema + ":",
host:     host,
hostname: host,
port:     this.port,
pathname: this.path,
search:   this.query,
hash:     this.fragment
};
},

completeWith: function(url)
{
if (url === "" || /^[^/]*:/.exec(url)) // If given absolute url, return as is now.
return new URL(url);

var relParts = /^([^#?]*)(.*)$/.exec(url); 

var path = (relParts[1].slice(0, 1) === "/" ? "" : this.path.replace(/[^/]*$/, "")) + relParts[1];
path = path.replace(/(\/\.)+(\/|$)/g, "/").replace(/[^/]*\/\.\.(\/|$)/g, "");

return new URL(this.schema + "://" + this.host + this.port + path + relParts[2]);
},

sameOrigin: function(url)
{
function normalizePort(schema, port)
{
var portNo = port.slice(1);
return (schema === "https" && portNo == 443 || schema === "http" && portNo == 80) ? "" : port;
}

var other = new URL(url);

return this.schema === other.schema &&
this.host === other.host &&
normalizePort(this.schema, this.port) === normalizePort(other.schema, other.port);
}
};

function DOMCoreException(name, code)
{
function formatError()
{
return "Error: " + this.message;
}

this.name = name;
this.message = name + ": DOM Exception " + code;
this.code = code;
this.toString = bind(formatError, this);
}

function bind(func, thisObject)
{
var args = Array.prototype.slice.call(arguments, 2);
return function() { return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0))); };
}

function noop()
{
}

}





WebInspector.TextViewer = function(textModel, platform, url, delegate)
{
WebInspector.View.call(this);

this._textModel = textModel;
this._textModel.changeListener = this._textChanged.bind(this);
this._textModel.resetUndoStack();
this._delegate = delegate;

this.element.className = "text-editor monospace";

var enterTextChangeMode = this._enterInternalTextChangeMode.bind(this);
var exitTextChangeMode = this._exitInternalTextChangeMode.bind(this);
var syncScrollListener = this._syncScroll.bind(this);
var syncDecorationsForLineListener = this._syncDecorationsForLine.bind(this);
this._mainPanel = new WebInspector.TextEditorMainPanel(this._textModel, url, syncScrollListener, syncDecorationsForLineListener, enterTextChangeMode, exitTextChangeMode);
this._gutterPanel = new WebInspector.TextEditorGutterPanel(this._textModel, syncDecorationsForLineListener);
this.element.appendChild(this._mainPanel.element);
this.element.appendChild(this._gutterPanel.element);


this._gutterPanel.element.addEventListener("mousewheel", function(e) {
this._mainPanel.element.dispatchEvent(e);
}.bind(this), false);

this.element.addEventListener("dblclick", this._doubleClick.bind(this), true);
this.element.addEventListener("keydown", this._handleKeyDown.bind(this), false);
this.element.addEventListener("contextmenu", this._contextMenu.bind(this), true);

this._registerShortcuts();
}

WebInspector.TextViewer.prototype = {
set mimeType(mimeType)
{
this._mainPanel.mimeType = mimeType;
},

set readOnly(readOnly)
{
if (this._mainPanel.readOnly === readOnly)
return;
this._mainPanel.readOnly = readOnly;
},

get readOnly()
{
return this._mainPanel.readOnly;
},

get textModel()
{
return this._textModel;
},

revealLine: function(lineNumber)
{
this._mainPanel.revealLine(lineNumber);
},

addDecoration: function(lineNumber, decoration)
{
this._mainPanel.addDecoration(lineNumber, decoration);
this._gutterPanel.addDecoration(lineNumber, decoration);
},

removeDecoration: function(lineNumber, decoration)
{
this._mainPanel.removeDecoration(lineNumber, decoration);
this._gutterPanel.removeDecoration(lineNumber, decoration);
},

markAndRevealRange: function(range)
{
this._mainPanel.markAndRevealRange(range);
},

highlightLine: function(lineNumber)
{
if (typeof lineNumber !== "number" || lineNumber < 0)
return;

lineNumber = Math.min(lineNumber, this._textModel.linesCount - 1);
this._mainPanel.highlightLine(lineNumber);
},

clearLineHighlight: function()
{
this._mainPanel.clearLineHighlight();
},

freeCachedElements: function()
{
this._mainPanel.freeCachedElements();
this._gutterPanel.freeCachedElements();
},

get scrollTop()
{
return this._mainPanel.element.scrollTop;
},

set scrollTop(scrollTop)
{
this._mainPanel.element.scrollTop = scrollTop;
},

get scrollLeft()
{
return this._mainPanel.element.scrollLeft;
},

set scrollLeft(scrollLeft)
{
this._mainPanel.element.scrollLeft = scrollLeft;
},

beginUpdates: function()
{
this._mainPanel.beginUpdates();
this._gutterPanel.beginUpdates();
},

endUpdates: function()
{
this._mainPanel.endUpdates();
this._gutterPanel.endUpdates();
this._updatePanelOffsets();
},

resize: function()
{
this._mainPanel.resize();
this._gutterPanel.resize();
this._updatePanelOffsets();
},


_textChanged: function(oldRange, newRange, oldText, newText)
{
if (!this._internalTextChangeMode)
this._textModel.resetUndoStack();
this._mainPanel.textChanged(oldRange, newRange);
this._gutterPanel.textChanged(oldRange, newRange);
this._updatePanelOffsets();
},

_enterInternalTextChangeMode: function()
{
this._internalTextChangeMode = true;
this._delegate.beforeTextChanged();
},

_exitInternalTextChangeMode: function(oldRange, newRange)
{
this._internalTextChangeMode = false;
this._delegate.afterTextChanged(oldRange, newRange);
},

_updatePanelOffsets: function()
{
var lineNumbersWidth = this._gutterPanel.element.offsetWidth;
if (lineNumbersWidth)
this._mainPanel.element.style.setProperty("left", lineNumbersWidth + "px");
else
this._mainPanel.element.style.removeProperty("left"); 
},

_syncScroll: function()
{

setTimeout(function() {
var mainElement = this._mainPanel.element;
var gutterElement = this._gutterPanel.element;

this._gutterPanel.syncClientHeight(mainElement.clientHeight);
gutterElement.scrollTop = mainElement.scrollTop;
}.bind(this), 0);
},

_syncDecorationsForLine: function(lineNumber)
{
if (lineNumber >= this._textModel.linesCount)
return;

var mainChunk = this._mainPanel.chunkForLine(lineNumber);
if (mainChunk.linesCount === 1 && mainChunk.decorated) {
var gutterChunk = this._gutterPanel.makeLineAChunk(lineNumber);
var height = mainChunk.height;
if (height)
gutterChunk.element.style.setProperty("height", height + "px");
else
gutterChunk.element.style.removeProperty("height");
} else {
var gutterChunk = this._gutterPanel.chunkForLine(lineNumber);
if (gutterChunk.linesCount === 1)
gutterChunk.element.style.removeProperty("height");
}
},

_doubleClick: function(event)
{
if (!this.readOnly)
return;

var lineRow = event.target.enclosingNodeOrSelfWithClass("webkit-line-content");
if (!lineRow)
return;  

this._delegate.doubleClick(lineRow.lineNumber);
window.getSelection().collapseToStart();
},

_registerShortcuts: function()
{
var keys = WebInspector.KeyboardShortcut.Keys;
var modifiers = WebInspector.KeyboardShortcut.Modifiers;

this._shortcuts = {};
var commitEditing = this._commitEditing.bind(this);
var cancelEditing = this._cancelEditing.bind(this);
this._shortcuts[WebInspector.KeyboardShortcut.makeKey("s", modifiers.CtrlOrMeta)] = commitEditing;
this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Enter.code, modifiers.CtrlOrMeta)] = commitEditing;
this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Esc.code)] = cancelEditing;

var handleUndo = this._mainPanel.handleUndoRedo.bind(this._mainPanel, false);
var handleRedo = this._mainPanel.handleUndoRedo.bind(this._mainPanel, true);
this._shortcuts[WebInspector.KeyboardShortcut.makeKey("z", modifiers.CtrlOrMeta)] = handleUndo;
this._shortcuts[WebInspector.KeyboardShortcut.makeKey("z", modifiers.Shift | modifiers.CtrlOrMeta)] = handleRedo;

var handleTabKey = this._mainPanel.handleTabKeyPress.bind(this._mainPanel, false);
var handleShiftTabKey = this._mainPanel.handleTabKeyPress.bind(this._mainPanel, true);
this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Tab.code)] = handleTabKey;
this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Tab.code, modifiers.Shift)] = handleShiftTabKey;
},

_handleKeyDown: function(e)
{
var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(e);
var handler = this._shortcuts[shortcutKey];
if (handler && handler.call(this)) {
e.preventDefault();
e.stopPropagation();
}
},

_contextMenu: function(event)
{
var contextMenu = new WebInspector.ContextMenu();
var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number");
if (target)
this._delegate.populateLineGutterContextMenu(target.lineNumber, contextMenu);
else {
var selection = this._mainPanel._getSelection();
if (selection && !selection.isEmpty())
return; 
this._delegate.populateTextAreaContextMenu(contextMenu);
}

var fileName = this._delegate.suggestedFileName();
if (fileName)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save as..." : "Save As..."), InspectorFrontendHost.saveAs.bind(InspectorFrontendHost, fileName, this._textModel.text));

contextMenu.show(event);
},

_commitEditing: function()
{
if (this.readOnly)
return false;

this._delegate.commitEditing();
return true;
},

_cancelEditing: function()
{
if (this.readOnly)
return false;

this._delegate.cancelEditing();
return true;
}
}

WebInspector.TextViewer.prototype.__proto__ = WebInspector.View.prototype;

WebInspector.TextViewerDelegate = function()
{
}

WebInspector.TextViewerDelegate.prototype = {
doubleClick: function(lineNumber)
{

},

beforeTextChanged: function()
{

},

afterTextChanged: function(oldRange, newRange)
{

},

commitEditing: function()
{

},

cancelEditing: function()
{

},

populateLineGutterContextMenu: function(contextMenu)
{

},

populateTextAreaContextMenu: function(contextMenu)
{

},

suggestedFileName: function()
{

}
}

WebInspector.TextViewerDelegate.prototype.__proto__ = WebInspector.Object.prototype;

WebInspector.TextEditorChunkedPanel = function(textModel)
{
this._textModel = textModel;

this._defaultChunkSize = 50;
this._paintCoalescingLevel = 0;
this._domUpdateCoalescingLevel = 0;
}

WebInspector.TextEditorChunkedPanel.prototype = {
get textModel()
{
return this._textModel;
},

revealLine: function(lineNumber)
{
if (lineNumber >= this._textModel.linesCount)
return;

var chunk = this.makeLineAChunk(lineNumber);
chunk.element.scrollIntoViewIfNeeded();
},

addDecoration: function(lineNumber, decoration)
{
if (lineNumber >= this._textModel.linesCount)
return;

var chunk = this.makeLineAChunk(lineNumber);
chunk.addDecoration(decoration);
},

removeDecoration: function(lineNumber, decoration)
{
if (lineNumber >= this._textModel.linesCount)
return;

var chunk = this.chunkForLine(lineNumber);
chunk.removeDecoration(decoration);
},

_buildChunks: function()
{
this.beginDomUpdates();

this._container.removeChildren();

this._textChunks = [];
for (var i = 0; i < this._textModel.linesCount; i += this._defaultChunkSize) {
var chunk = this._createNewChunk(i, i + this._defaultChunkSize);
this._textChunks.push(chunk);
this._container.appendChild(chunk.element);
}

this._repaintAll();

this.endDomUpdates();
},

makeLineAChunk: function(lineNumber)
{
var chunkNumber = this._chunkNumberForLine(lineNumber);
var oldChunk = this._textChunks[chunkNumber];

if (!oldChunk) {
console.error("No chunk for line number: " + lineNumber);
return;
}

if (oldChunk.linesCount === 1)
return oldChunk;

return this._splitChunkOnALine(lineNumber, chunkNumber, true);
},

_splitChunkOnALine: function(lineNumber, chunkNumber, createSuffixChunk)
{
this.beginDomUpdates();

var oldChunk = this._textChunks[chunkNumber];
var wasExpanded = oldChunk.expanded;
oldChunk.expanded = false;

var insertIndex = chunkNumber + 1;


if (lineNumber > oldChunk.startLine) {
var prefixChunk = this._createNewChunk(oldChunk.startLine, lineNumber);
prefixChunk.readOnly = oldChunk.readOnly;
this._textChunks.splice(insertIndex++, 0, prefixChunk);
this._container.insertBefore(prefixChunk.element, oldChunk.element);
}


var endLine = createSuffixChunk ? lineNumber + 1 : oldChunk.startLine + oldChunk.linesCount;
var lineChunk = this._createNewChunk(lineNumber, endLine);
lineChunk.readOnly = oldChunk.readOnly;
this._textChunks.splice(insertIndex++, 0, lineChunk);
this._container.insertBefore(lineChunk.element, oldChunk.element);


if (oldChunk.startLine + oldChunk.linesCount > endLine) {
var suffixChunk = this._createNewChunk(endLine, oldChunk.startLine + oldChunk.linesCount);
suffixChunk.readOnly = oldChunk.readOnly;
this._textChunks.splice(insertIndex, 0, suffixChunk);
this._container.insertBefore(suffixChunk.element, oldChunk.element);
}


this._textChunks.splice(chunkNumber, 1);
this._container.removeChild(oldChunk.element);

if (wasExpanded) {
if (prefixChunk)
prefixChunk.expanded = true;
lineChunk.expanded = true;
if (suffixChunk)
suffixChunk.expanded = true;
}

this.endDomUpdates();

return lineChunk;
},

_scroll: function()
{

if (this.element.scrollLeft <= 2)
this.element.scrollLeft = 0;

this._scheduleRepaintAll();
if (this._syncScrollListener)
this._syncScrollListener();
},

_scheduleRepaintAll: function()
{
if (this._repaintAllTimer)
clearTimeout(this._repaintAllTimer);
this._repaintAllTimer = setTimeout(this._repaintAll.bind(this), 50);
},

beginUpdates: function()
{
this._paintCoalescingLevel++;
},

endUpdates: function()
{
this._paintCoalescingLevel--;
if (!this._paintCoalescingLevel)
this._repaintAll();
},

beginDomUpdates: function()
{
this._domUpdateCoalescingLevel++;
},

endDomUpdates: function()
{
this._domUpdateCoalescingLevel--;
},

_chunkNumberForLine: function(lineNumber)
{
function compareLineNumbers(value, chunk)
{
return value < chunk.startLine ? -1 : 1;
}
var insertBefore = insertionIndexForObjectInListSortedByFunction(lineNumber, this._textChunks, compareLineNumbers);
return insertBefore - 1;
},

chunkForLine: function(lineNumber)
{
return this._textChunks[this._chunkNumberForLine(lineNumber)];
},

_findFirstVisibleChunkNumber: function(visibleFrom)
{
function compareOffsetTops(value, chunk)
{
return value < chunk.offsetTop ? -1 : 1;
}
var insertBefore = insertionIndexForObjectInListSortedByFunction(visibleFrom, this._textChunks, compareOffsetTops);
return insertBefore - 1;
},

_findVisibleChunks: function(visibleFrom, visibleTo)
{
var from = this._findFirstVisibleChunkNumber(visibleFrom);
for (var to = from + 1; to < this._textChunks.length; ++to) {
if (this._textChunks[to].offsetTop >= visibleTo)
break;
}
return { start: from, end: to };
},

_findFirstVisibleLineNumber: function(visibleFrom)
{
var chunk = this._textChunks[this._findFirstVisibleChunkNumber(visibleFrom)];
if (!chunk.expanded)
return chunk.startLine;

var lineNumbers = [];
for (var i = 0; i < chunk.linesCount; ++i) {
lineNumbers.push(chunk.startLine + i);
}

function compareLineRowOffsetTops(value, lineNumber)
{
var lineRow = chunk.getExpandedLineRow(lineNumber);
return value < lineRow.offsetTop ? -1 : 1;
}
var insertBefore = insertionIndexForObjectInListSortedByFunction(visibleFrom, lineNumbers, compareLineRowOffsetTops);
return lineNumbers[insertBefore - 1];
},

_repaintAll: function()
{
delete this._repaintAllTimer;

if (this._paintCoalescingLevel || this._dirtyLines)
return;

var visibleFrom = this.element.scrollTop;
var visibleTo = this.element.scrollTop + this.element.clientHeight;

if (visibleTo) {
var result = this._findVisibleChunks(visibleFrom, visibleTo);
this._expandChunks(result.start, result.end);
}
},

_expandChunks: function(fromIndex, toIndex)
{

for (var i = 0; i < fromIndex; ++i)
this._textChunks[i].expanded = false;
for (var i = toIndex; i < this._textChunks.length; ++i)
this._textChunks[i].expanded = false;
for (var i = fromIndex; i < toIndex; ++i)
this._textChunks[i].expanded = true;
},

_totalHeight: function(firstElement, lastElement)
{
lastElement = (lastElement || firstElement).nextElementSibling;
if (lastElement)
return lastElement.offsetTop - firstElement.offsetTop;

var offsetParent = firstElement.offsetParent;
if (offsetParent && offsetParent.scrollHeight > offsetParent.clientHeight)
return offsetParent.scrollHeight - firstElement.offsetTop;

var total = 0;
while (firstElement && firstElement !== lastElement) {
total += firstElement.offsetHeight;
firstElement = firstElement.nextElementSibling;
}
return total;
},

resize: function()
{
this._repaintAll();
}
}

WebInspector.TextEditorGutterPanel = function(textModel, syncDecorationsForLineListener)
{
WebInspector.TextEditorChunkedPanel.call(this, textModel);

this._syncDecorationsForLineListener = syncDecorationsForLineListener;

this.element = document.createElement("div");
this.element.className = "text-editor-lines";

this._container = document.createElement("div");
this._container.className = "inner-container";
this.element.appendChild(this._container);

this.element.addEventListener("scroll", this._scroll.bind(this), false);

this.freeCachedElements();
this._buildChunks();
}

WebInspector.TextEditorGutterPanel.prototype = {
freeCachedElements: function()
{
this._cachedRows = [];
},

_createNewChunk: function(startLine, endLine)
{
return new WebInspector.TextEditorGutterChunk(this, startLine, endLine);
},

textChanged: function(oldRange, newRange)
{
this.beginDomUpdates();

var linesDiff = newRange.linesCount - oldRange.linesCount;
if (linesDiff) {

for (var chunkNumber = this._textChunks.length - 1; chunkNumber >= 0 ; --chunkNumber) {
var chunk = this._textChunks[chunkNumber];
if (chunk.startLine + chunk.linesCount <= this._textModel.linesCount)
break;
chunk.expanded = false;
this._container.removeChild(chunk.element);
}
this._textChunks.length = chunkNumber + 1;


var totalLines = 0;
if (this._textChunks.length) {
var lastChunk = this._textChunks[this._textChunks.length - 1];
totalLines = lastChunk.startLine + lastChunk.linesCount;
}
for (var i = totalLines; i < this._textModel.linesCount; i += this._defaultChunkSize) {
var chunk = this._createNewChunk(i, i + this._defaultChunkSize);
this._textChunks.push(chunk);
this._container.appendChild(chunk.element);
}
this._repaintAll();
} else {

var chunkNumber = this._chunkNumberForLine(newRange.startLine);
var chunk = this._textChunks[chunkNumber];
while (chunk && chunk.startLine <= newRange.endLine) {
if (chunk.linesCount === 1)
this._syncDecorationsForLineListener(chunk.startLine);
chunk = this._textChunks[++chunkNumber];
}
}

this.endDomUpdates();
},

syncClientHeight: function(clientHeight)
{
if (this.element.offsetHeight > clientHeight)
this._container.style.setProperty("padding-bottom", (this.element.offsetHeight - clientHeight) + "px");
else
this._container.style.removeProperty("padding-bottom");
}
}

WebInspector.TextEditorGutterPanel.prototype.__proto__ = WebInspector.TextEditorChunkedPanel.prototype;

WebInspector.TextEditorGutterChunk = function(textViewer, startLine, endLine)
{
this._textViewer = textViewer;
this._textModel = textViewer._textModel;

this.startLine = startLine;
endLine = Math.min(this._textModel.linesCount, endLine);
this.linesCount = endLine - startLine;

this._expanded = false;

this.element = document.createElement("div");
this.element.lineNumber = startLine;
this.element.className = "webkit-line-number";

if (this.linesCount === 1) {


var innerSpan = document.createElement("span");
innerSpan.className = "webkit-line-number-inner";
innerSpan.textContent = startLine + 1;
var outerSpan = document.createElement("div");
outerSpan.className = "webkit-line-number-outer";
outerSpan.appendChild(innerSpan);
this.element.appendChild(outerSpan);
} else {
var lineNumbers = [];
for (var i = startLine; i < endLine; ++i)
lineNumbers.push(i + 1);
this.element.textContent = lineNumbers.join("\n");
}
}

WebInspector.TextEditorGutterChunk.prototype = {
addDecoration: function(decoration)
{
this._textViewer.beginDomUpdates();
if (typeof decoration === "string")
this.element.addStyleClass(decoration);
this._textViewer.endDomUpdates();
},

removeDecoration: function(decoration)
{
this._textViewer.beginDomUpdates();
if (typeof decoration === "string")
this.element.removeStyleClass(decoration);
this._textViewer.endDomUpdates();
},

get expanded()
{
return this._expanded;
},

set expanded(expanded)
{
if (this.linesCount === 1)
this._textViewer._syncDecorationsForLineListener(this.startLine);

if (this._expanded === expanded)
return;

this._expanded = expanded;

if (this.linesCount === 1)
return;

this._textViewer.beginDomUpdates();

if (expanded) {
this._expandedLineRows = [];
var parentElement = this.element.parentElement;
for (var i = this.startLine; i < this.startLine + this.linesCount; ++i) {
var lineRow = this._createRow(i);
parentElement.insertBefore(lineRow, this.element);
this._expandedLineRows.push(lineRow);
}
parentElement.removeChild(this.element);
} else {
var elementInserted = false;
for (var i = 0; i < this._expandedLineRows.length; ++i) {
var lineRow = this._expandedLineRows[i];
var parentElement = lineRow.parentElement;
if (parentElement) {
if (!elementInserted) {
elementInserted = true;
parentElement.insertBefore(this.element, lineRow);
}
parentElement.removeChild(lineRow);
}
this._textViewer._cachedRows.push(lineRow);
}
delete this._expandedLineRows;
}

this._textViewer.endDomUpdates();
},

get height()
{
if (!this._expandedLineRows)
return this._textViewer._totalHeight(this.element);
return this._textViewer._totalHeight(this._expandedLineRows[0], this._expandedLineRows[this._expandedLineRows.length - 1]);
},

get offsetTop()
{
return (this._expandedLineRows && this._expandedLineRows.length) ? this._expandedLineRows[0].offsetTop : this.element.offsetTop;
},

_createRow: function(lineNumber)
{
var lineRow = this._textViewer._cachedRows.pop() || document.createElement("div");
lineRow.lineNumber = lineNumber;
lineRow.className = "webkit-line-number";
lineRow.textContent = lineNumber + 1;
return lineRow;
}
}

WebInspector.TextEditorMainPanel = function(textModel, url, syncScrollListener, syncDecorationsForLineListener, enterTextChangeMode, exitTextChangeMode)
{
WebInspector.TextEditorChunkedPanel.call(this, textModel);

this._syncScrollListener = syncScrollListener;
this._syncDecorationsForLineListener = syncDecorationsForLineListener;
this._enterTextChangeMode = enterTextChangeMode;
this._exitTextChangeMode = exitTextChangeMode;

this._url = url;
this._highlighter = new WebInspector.TextEditorHighlighter(textModel, this._highlightDataReady.bind(this));
this._readOnly = true;

this.element = document.createElement("div");
this.element.className = "text-editor-contents";
this.element.tabIndex = 0;

this._container = document.createElement("div");
this._container.className = "inner-container";
this._container.tabIndex = 0;
this.element.appendChild(this._container);

this.element.addEventListener("scroll", this._scroll.bind(this), false);









this._handleDOMUpdatesCallback = this._handleDOMUpdates.bind(this);
this._container.addEventListener("DOMCharacterDataModified", this._handleDOMUpdatesCallback, false);
this._container.addEventListener("DOMNodeInserted", this._handleDOMUpdatesCallback, false);
this._container.addEventListener("DOMSubtreeModified", this._handleDOMUpdatesCallback, false);

this.freeCachedElements();
this._buildChunks();
}

WebInspector.TextEditorMainPanel.prototype = {
set mimeType(mimeType)
{
this._highlighter.mimeType = mimeType;
},

set readOnly(readOnly)
{
if (this._readOnly === readOnly)
return;

this.beginDomUpdates();
this._readOnly = readOnly;
if (this._readOnly)
this._container.removeStyleClass("text-editor-editable");
else
this._container.addStyleClass("text-editor-editable");
this.endDomUpdates();
},

get readOnly()
{
return this._readOnly;
},

setEditableRange: function(startLine, endLine)
{
this.beginDomUpdates();

var firstChunkNumber = this._chunkNumberForLine(startLine);
var firstChunk = this._textChunks[firstChunkNumber];
if (firstChunk.startLine !== startLine) {
this._splitChunkOnALine(startLine, firstChunkNumber);
firstChunkNumber += 1;
}

var lastChunkNumber = this._textChunks.length;
if (endLine !== this._textModel.linesCount) {
lastChunkNumber = this._chunkNumberForLine(endLine);
var lastChunk = this._textChunks[lastChunkNumber];
if (lastChunk && lastChunk.startLine !== endLine) {
this._splitChunkOnALine(endLine, lastChunkNumber);
lastChunkNumber += 1;
}
}

for (var chunkNumber = 0; chunkNumber < firstChunkNumber; ++chunkNumber)
this._textChunks[chunkNumber].readOnly = true;
for (var chunkNumber = firstChunkNumber; chunkNumber < lastChunkNumber; ++chunkNumber)
this._textChunks[chunkNumber].readOnly = false;
for (var chunkNumber = lastChunkNumber; chunkNumber < this._textChunks.length; ++chunkNumber)
this._textChunks[chunkNumber].readOnly = true;

this.endDomUpdates();
},

clearEditableRange: function()
{
for (var chunkNumber = 0; chunkNumber < this._textChunks.length; ++chunkNumber)
this._textChunks[chunkNumber].readOnly = false;
},

markAndRevealRange: function(range)
{
if (this._rangeToMark) {
var markedLine = this._rangeToMark.startLine;
delete this._rangeToMark;

if (!this._dirtyLines) {
this.beginDomUpdates();
var chunk = this.chunkForLine(markedLine);
var wasExpanded = chunk.expanded;
chunk.expanded = false;
chunk.updateCollapsedLineRow();
chunk.expanded = wasExpanded;
this.endDomUpdates();
} else
this._paintLines(markedLine, markedLine + 1);
}

if (range) {
this._rangeToMark = range;
this.revealLine(range.startLine);
var chunk = this.makeLineAChunk(range.startLine);
this._paintLine(chunk.element);
if (this._markedRangeElement)
this._markedRangeElement.scrollIntoViewIfNeeded();
}
delete this._markedRangeElement;
},

highlightLine: function(lineNumber)
{
this.clearLineHighlight();
this._highlightedLine = lineNumber;
this.revealLine(lineNumber);
this.addDecoration(lineNumber, "webkit-highlighted-line");
},

clearLineHighlight: function()
{
if (typeof this._highlightedLine === "number") {
this.removeDecoration(this._highlightedLine, "webkit-highlighted-line");
delete this._highlightedLine;
}
},

freeCachedElements: function()
{
this._cachedSpans = [];
this._cachedTextNodes = [];
this._cachedRows = [];
},

handleUndoRedo: function(redo)
{
if (this._readOnly || this._dirtyLines)
return false;

this.beginUpdates();
this._enterTextChangeMode();

var callback = function(oldRange, newRange) {
this._exitTextChangeMode(oldRange, newRange);
this._enterTextChangeMode();
}.bind(this);

var range = redo ? this._textModel.redo(callback) : this._textModel.undo(callback);
if (range)
this._setCaretLocation(range.endLine, range.endColumn, true);

this._exitTextChangeMode(null, null);
this.endUpdates();

return true;
},

handleTabKeyPress: function(shiftKey)
{
if (this._readOnly || this._dirtyLines)
return false;

var selection = this._getSelection();
if (!selection)
return false;

if (shiftKey)
return true;

this.beginUpdates();
this._enterTextChangeMode();

var range = selection;
if (range.startLine > range.endLine || (range.startLine === range.endLine && range.startColumn > range.endColumn))
range = new WebInspector.TextRange(range.endLine, range.endColumn, range.startLine, range.startColumn);

var newRange = this._setText(range, "\t");

this._exitTextChangeMode(range, newRange);
this.endUpdates();

this._setCaretLocation(newRange.endLine, newRange.endColumn, true);
return true;
},

_splitChunkOnALine: function(lineNumber, chunkNumber, createSuffixChunk)
{
var selection = this._getSelection();
var chunk = WebInspector.TextEditorChunkedPanel.prototype._splitChunkOnALine.call(this, lineNumber, chunkNumber, createSuffixChunk);
this._restoreSelection(selection);
return chunk;
},

beginDomUpdates: function()
{
WebInspector.TextEditorChunkedPanel.prototype.beginDomUpdates.call(this);
if (this._domUpdateCoalescingLevel === 1) {
this._container.removeEventListener("DOMCharacterDataModified", this._handleDOMUpdatesCallback, false);
this._container.removeEventListener("DOMNodeInserted", this._handleDOMUpdatesCallback, false);
this._container.removeEventListener("DOMSubtreeModified", this._handleDOMUpdatesCallback, false);
}
},

endDomUpdates: function()
{
WebInspector.TextEditorChunkedPanel.prototype.endDomUpdates.call(this);
if (this._domUpdateCoalescingLevel === 0) {
this._container.addEventListener("DOMCharacterDataModified", this._handleDOMUpdatesCallback, false);
this._container.addEventListener("DOMNodeInserted", this._handleDOMUpdatesCallback, false);
this._container.addEventListener("DOMSubtreeModified", this._handleDOMUpdatesCallback, false);
}
},

_enableDOMNodeRemovedListener: function(lineRow, enable)
{
if (enable)
lineRow.addEventListener("DOMNodeRemoved", this._handleDOMUpdatesCallback, false);
else
lineRow.removeEventListener("DOMNodeRemoved", this._handleDOMUpdatesCallback, false);
},

_buildChunks: function()
{
for (var i = 0; i < this._textModel.linesCount; ++i)
this._textModel.removeAttribute(i, "highlight");

WebInspector.TextEditorChunkedPanel.prototype._buildChunks.call(this);
},

_createNewChunk: function(startLine, endLine)
{
return new WebInspector.TextEditorMainChunk(this, startLine, endLine);
},

_expandChunks: function(fromIndex, toIndex)
{
var lastChunk = this._textChunks[toIndex - 1];
var lastVisibleLine = lastChunk.startLine + lastChunk.linesCount;

var selection = this._getSelection();

this._muteHighlightListener = true;
this._highlighter.highlight(lastVisibleLine);
delete this._muteHighlightListener;

this._restorePaintLinesOperationsCredit();
WebInspector.TextEditorChunkedPanel.prototype._expandChunks.call(this, fromIndex, toIndex);
this._adjustPaintLinesOperationsRefreshValue();

this._restoreSelection(selection);
},

_highlightDataReady: function(fromLine, toLine)
{
if (this._muteHighlightListener)
return;
this._restorePaintLinesOperationsCredit();
this._paintLines(fromLine, toLine, true  );
},

_schedulePaintLines: function(startLine, endLine)
{
if (startLine >= endLine)
return;

if (!this._scheduledPaintLines) {
this._scheduledPaintLines = [ { startLine: startLine, endLine: endLine } ];
this._paintScheduledLinesTimer = setTimeout(this._paintScheduledLines.bind(this), 0);
} else {
for (var i = 0; i < this._scheduledPaintLines.length; ++i) {
var chunk = this._scheduledPaintLines[i];
if (chunk.startLine <= endLine && chunk.endLine >= startLine) {
chunk.startLine = Math.min(chunk.startLine, startLine);
chunk.endLine = Math.max(chunk.endLine, endLine);
return;
}
if (chunk.startLine > endLine) {
this._scheduledPaintLines.splice(i, 0, { startLine: startLine, endLine: endLine });
return;
}
}
this._scheduledPaintLines.push({ startLine: startLine, endLine: endLine });
}
},

_paintScheduledLines: function(skipRestoreSelection)
{
if (this._paintScheduledLinesTimer)
clearTimeout(this._paintScheduledLinesTimer);
delete this._paintScheduledLinesTimer;

if (!this._scheduledPaintLines)
return;


if (this._dirtyLines || this._repaintAllTimer) {
this._paintScheduledLinesTimer = setTimeout(this._paintScheduledLines.bind(this), 50);
return;
}

var scheduledPaintLines = this._scheduledPaintLines;
delete this._scheduledPaintLines;

this._restorePaintLinesOperationsCredit();
this._paintLineChunks(scheduledPaintLines, !skipRestoreSelection);
this._adjustPaintLinesOperationsRefreshValue();
},

_restorePaintLinesOperationsCredit: function()
{
if (!this._paintLinesOperationsRefreshValue)
this._paintLinesOperationsRefreshValue = 250;
this._paintLinesOperationsCredit = this._paintLinesOperationsRefreshValue;
this._paintLinesOperationsLastRefresh = Date.now();
},

_adjustPaintLinesOperationsRefreshValue: function()
{
var operationsDone = this._paintLinesOperationsRefreshValue - this._paintLinesOperationsCredit;
if (operationsDone <= 0)
return;
var timePast = Date.now() - this._paintLinesOperationsLastRefresh;
if (timePast <= 0)
return;

var value = Math.floor(operationsDone / timePast * 50);
this._paintLinesOperationsRefreshValue = Number.constrain(value, 150, 1500);
},

_paintLines: function(fromLine, toLine, restoreSelection)
{
this._paintLineChunks([ { startLine: fromLine, endLine: toLine } ], restoreSelection);
},

_paintLineChunks: function(lineChunks, restoreSelection)
{


var visibleFrom = this.element.scrollTop;
var firstVisibleLineNumber = this._findFirstVisibleLineNumber(visibleFrom);

var chunk;
var selection;
var invisibleLineRows = [];
for (var i = 0; i < lineChunks.length; ++i) {
var lineChunk = lineChunks[i];
if (this._dirtyLines || this._scheduledPaintLines) {
this._schedulePaintLines(lineChunk.startLine, lineChunk.endLine);
continue;
}
for (var lineNumber = lineChunk.startLine; lineNumber < lineChunk.endLine; ++lineNumber) {
if (!chunk || lineNumber < chunk.startLine || lineNumber >= chunk.startLine + chunk.linesCount)
chunk = this.chunkForLine(lineNumber);
var lineRow = chunk.getExpandedLineRow(lineNumber);
if (!lineRow)
continue;
if (lineNumber < firstVisibleLineNumber) {
invisibleLineRows.push(lineRow);
continue;
}
if (restoreSelection && !selection)
selection = this._getSelection();
this._paintLine(lineRow);
if (this._paintLinesOperationsCredit < 0) {
this._schedulePaintLines(lineNumber + 1, lineChunk.endLine);
break;
}
}
}

for (var i = 0; i < invisibleLineRows.length; ++i) {
if (restoreSelection && !selection)
selection = this._getSelection();
this._paintLine(invisibleLineRows[i]);
}

if (restoreSelection)
this._restoreSelection(selection);
},

_paintLine: function(lineRow)
{
var lineNumber = lineRow.lineNumber;
if (this._dirtyLines) {
this._schedulePaintLines(lineNumber, lineNumber + 1);
return;
}

this.beginDomUpdates();
try {
if (this._scheduledPaintLines || this._paintLinesOperationsCredit < 0) {
this._schedulePaintLines(lineNumber, lineNumber + 1);
return;
}

var highlight = this._textModel.getAttribute(lineNumber, "highlight");
if (!highlight)
return;

lineRow.removeChildren();
var line = this._textModel.line(lineNumber);
if (!line)
lineRow.appendChild(document.createElement("br"));

var plainTextStart = -1;
for (var j = 0; j < line.length;) {
if (j > 1000) {

if (plainTextStart === -1)
plainTextStart = j;
break;
}
var attribute = highlight[j];
if (!attribute || !attribute.tokenType) {
if (plainTextStart === -1)
plainTextStart = j;
j++;
} else {
if (plainTextStart !== -1) {
this._appendTextNode(lineRow, line.substring(plainTextStart, j));
plainTextStart = -1;
--this._paintLinesOperationsCredit;
}
this._appendSpan(lineRow, line.substring(j, j + attribute.length), attribute.tokenType);
j += attribute.length;
--this._paintLinesOperationsCredit;
}
}
if (plainTextStart !== -1) {
this._appendTextNode(lineRow, line.substring(plainTextStart, line.length));
--this._paintLinesOperationsCredit;
}
if (lineRow.decorationsElement)
lineRow.appendChild(lineRow.decorationsElement);
} finally {
if (this._rangeToMark && this._rangeToMark.startLine === lineNumber)
this._markedRangeElement = highlightSearchResult(lineRow, this._rangeToMark.startColumn, this._rangeToMark.endColumn - this._rangeToMark.startColumn);
this.endDomUpdates();
}
},

_releaseLinesHighlight: function(lineRow)
{
if (!lineRow)
return;
if ("spans" in lineRow) {
var spans = lineRow.spans;
for (var j = 0; j < spans.length; ++j)
this._cachedSpans.push(spans[j]);
delete lineRow.spans;
}
if ("textNodes" in lineRow) {
var textNodes = lineRow.textNodes;
for (var j = 0; j < textNodes.length; ++j)
this._cachedTextNodes.push(textNodes[j]);
delete lineRow.textNodes;
}
this._cachedRows.push(lineRow);
},

_getSelection: function()
{
var selection = window.getSelection();
if (!selection.rangeCount)
return null;
var selectionRange = selection.getRangeAt(0);

if (!this._container.isAncestor(selectionRange.startContainer) || !this._container.isAncestor(selectionRange.endContainer))
return null;
var start = this._selectionToPosition(selectionRange.startContainer, selectionRange.startOffset);
var end = selectionRange.collapsed ? start : this._selectionToPosition(selectionRange.endContainer, selectionRange.endOffset);
if (selection.anchorNode === selectionRange.startContainer && selection.anchorOffset === selectionRange.startOffset)
return new WebInspector.TextRange(start.line, start.column, end.line, end.column);
else
return new WebInspector.TextRange(end.line, end.column, start.line, start.column);
},

_restoreSelection: function(range, scrollIntoView)
{
if (!range)
return;
var start = this._positionToSelection(range.startLine, range.startColumn);
var end = range.isEmpty() ? start : this._positionToSelection(range.endLine, range.endColumn);
window.getSelection().setBaseAndExtent(start.container, start.offset, end.container, end.offset);

if (scrollIntoView) {
for (var node = end.container; node; node = node.parentElement) {
if (node.scrollIntoViewIfNeeded) {
node.scrollIntoViewIfNeeded();
break;
}
}
}
},

_setCaretLocation: function(line, column, scrollIntoView)
{
var range = new WebInspector.TextRange(line, column, line, column);
this._restoreSelection(range, scrollIntoView);
},

_selectionToPosition: function(container, offset)
{
if (container === this._container && offset === 0)
return { line: 0, column: 0 };
if (container === this._container && offset === 1)
return { line: this._textModel.linesCount - 1, column: this._textModel.lineLength(this._textModel.linesCount - 1) };

var lineRow = this._enclosingLineRowOrSelf(container);
var lineNumber = lineRow.lineNumber;
if (container === lineRow && offset === 0)
return { line: lineNumber, column: 0 };


var column = 0;
var node = lineRow.nodeType === Node.TEXT_NODE ? lineRow : lineRow.traverseNextTextNode(lineRow);
while (node && node !== container) {
var text = node.textContent;
for (var i = 0; i < text.length; ++i) {
if (text.charAt(i) === "\n") {
lineNumber++;
column = 0;
} else
column++;
}
node = node.traverseNextTextNode(lineRow);
}

if (node === container && offset) {
var text = node.textContent;
for (var i = 0; i < offset; ++i) {
if (text.charAt(i) === "\n") {
lineNumber++;
column = 0;
} else
column++;
}
}
return { line: lineNumber, column: column };
},

_positionToSelection: function(line, column)
{
var chunk = this.chunkForLine(line);

var lineRow = chunk.linesCount === 1 ? chunk.element : chunk.getExpandedLineRow(line);
if (lineRow)
var rangeBoundary = lineRow.rangeBoundaryForOffset(column);
else {
var offset = column;
for (var i = chunk.startLine; i < line; ++i)
offset += this._textModel.lineLength(i) + 1; 
lineRow = chunk.element;
if (lineRow.firstChild)
var rangeBoundary = { container: lineRow.firstChild, offset: offset };
else
var rangeBoundary = { container: lineRow, offset: 0 };
}
return rangeBoundary;
},

_enclosingLineRowOrSelf: function(element)
{
var lineRow = element.enclosingNodeOrSelfWithClass("webkit-line-content");
if (lineRow)
return lineRow;
for (var lineRow = element; lineRow; lineRow = lineRow.parentElement) {
if (lineRow.parentElement === this._container)
return lineRow;
}
return null;
},

_appendSpan: function(element, content, className)
{
if (className === "html-resource-link" || className === "html-external-link") {
element.appendChild(this._createLink(content, className === "html-external-link"));
return;
}

var span = this._cachedSpans.pop() || document.createElement("span");
span.className = "webkit-" + className;
span.textContent = content;
element.appendChild(span);
if (!("spans" in element))
element.spans = [];
element.spans.push(span);
},

_appendTextNode: function(element, text)
{
var textNode = this._cachedTextNodes.pop();
if (textNode)
textNode.nodeValue = text;
else
textNode = document.createTextNode(text);
element.appendChild(textNode);
if (!("textNodes" in element))
element.textNodes = [];
element.textNodes.push(textNode);
},

_createLink: function(content, isExternal)
{
var quote = content.charAt(0);
if (content.length > 1 && (quote === "\"" ||   quote === "'"))
content = content.substring(1, content.length - 1);
else
quote = null;

var a = WebInspector.linkifyURLAsNode(this._rewriteHref(content), content, null, isExternal);
var span = document.createElement("span");
span.className = "webkit-html-attribute-value";
if (quote)
span.appendChild(document.createTextNode(quote));
span.appendChild(a);
if (quote)
span.appendChild(document.createTextNode(quote));
return span;
},

_rewriteHref: function(hrefValue, isExternal)
{
if (!this._url || !hrefValue || hrefValue.indexOf("://") > 0)
return hrefValue;
return WebInspector.completeURL(this._url, hrefValue);
},

_handleDOMUpdates: function(e)
{
if (this._domUpdateCoalescingLevel)
return;

var target = e.target;
if (target === this._container)
return;

var lineRow = this._enclosingLineRowOrSelf(target);
if (!lineRow)
return;

if (lineRow.decorationsElement && (lineRow.decorationsElement === target || lineRow.decorationsElement.isAncestor(target))) {
if (this._syncDecorationsForLineListener)
this._syncDecorationsForLineListener(lineRow.lineNumber);
return;
}

if (this._readOnly)
return;

if (target === lineRow && e.type === "DOMNodeInserted") {

delete lineRow.lineNumber;
}

var startLine = 0;
for (var row = lineRow; row; row = row.previousSibling) {
if (typeof row.lineNumber === "number") {
startLine = row.lineNumber;
break;
}
}

var endLine = startLine + 1;
for (var row = lineRow.nextSibling; row; row = row.nextSibling) {
if (typeof row.lineNumber === "number" && row.lineNumber > startLine) {
endLine = row.lineNumber;
break;
}
}

if (target === lineRow && e.type === "DOMNodeRemoved") {

delete lineRow.lineNumber;
}

if (this._dirtyLines) {
this._dirtyLines.start = Math.min(this._dirtyLines.start, startLine);
this._dirtyLines.end = Math.max(this._dirtyLines.end, endLine);
} else {
this._dirtyLines = { start: startLine, end: endLine };
setTimeout(this._applyDomUpdates.bind(this), 0);

this.markAndRevealRange(null);
}
},

_applyDomUpdates: function()
{
if (!this._dirtyLines)
return;


if (this._readOnly) {
delete this._dirtyLines;
return;
}


this._enterTextChangeMode();

var dirtyLines = this._dirtyLines;
delete this._dirtyLines;

var firstChunkNumber = this._chunkNumberForLine(dirtyLines.start);
var startLine = this._textChunks[firstChunkNumber].startLine;
var endLine = this._textModel.linesCount;


var firstLineRow;
if (firstChunkNumber) {
var chunk = this._textChunks[firstChunkNumber - 1];
firstLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine + chunk.linesCount - 1) : chunk.element;
firstLineRow = firstLineRow.nextSibling;
} else
firstLineRow = this._container.firstChild;

var lines = [];
for (var lineRow = firstLineRow; lineRow; lineRow = lineRow.nextSibling) {
if (typeof lineRow.lineNumber === "number" && lineRow.lineNumber >= dirtyLines.end) {
endLine = lineRow.lineNumber;
break;
}

lineRow.lineNumber = startLine + lines.length;
this._collectLinesFromDiv(lines, lineRow);
}


var startOffset = 0;
while (startLine < dirtyLines.start && startOffset < lines.length) {
if (this._textModel.line(startLine) !== lines[startOffset])
break;
++startOffset;
++startLine;
}

var endOffset = lines.length;
while (endLine > dirtyLines.end && endOffset > startOffset) {
if (this._textModel.line(endLine - 1) !== lines[endOffset - 1])
break;
--endOffset;
--endLine;
}

lines = lines.slice(startOffset, endOffset);


var startColumn = 0;
var endColumn = this._textModel.lineLength(endLine - 1);
if (lines.length > 0) {
var line1 = this._textModel.line(startLine);
var line2 = lines[0];
while (line1[startColumn] && line1[startColumn] === line2[startColumn])
++startColumn;
lines[0] = line2.substring(startColumn);

var line1 = this._textModel.line(endLine - 1);
var line2 = lines[lines.length - 1];
for (var i = 0; i < endColumn && i < line2.length; ++i) {
if (startLine === endLine - 1 && endColumn - i <= startColumn)
break;
if (line1[endColumn - i - 1] !== line2[line2.length - i - 1])
break;
}
if (i) {
endColumn -= i;
lines[lines.length - 1] = line2.substring(0, line2.length - i);
}
}

var selection = this._getSelection();

if (lines.length === 0 && endLine < this._textModel.linesCount)
var oldRange = new WebInspector.TextRange(startLine, 0, endLine, 0);
else if (lines.length === 0 && startLine > 0)
var oldRange = new WebInspector.TextRange(startLine - 1, this._textModel.lineLength(startLine - 1), endLine - 1, this._textModel.lineLength(endLine - 1));
else
var oldRange = new WebInspector.TextRange(startLine, startColumn, endLine - 1, endColumn);

var newRange = this._setText(oldRange, lines.join("\n"));

this._paintScheduledLines(true);
this._restoreSelection(selection);

this._exitTextChangeMode(oldRange, newRange);
},

textChanged: function(oldRange, newRange)
{
this.beginDomUpdates();
this._removeDecorationsInRange(oldRange);
this._updateChunksForRanges(oldRange, newRange);
this._updateHighlightsForRange(newRange);
this.endDomUpdates();
},

_setText: function(range, text)
{
if (this._lastEditedRange && (!text || text.indexOf("\n") !== -1 || this._lastEditedRange.endLine !== range.startLine || this._lastEditedRange.endColumn !== range.startColumn))
this._textModel.markUndoableState();

var newRange = this._textModel.setText(range, text);
this._lastEditedRange = newRange;

return newRange;
},

_removeDecorationsInRange: function(range)
{
for (var i = this._chunkNumberForLine(range.startLine); i < this._textChunks.length; ++i) {
var chunk = this._textChunks[i];
if (chunk.startLine > range.endLine)
break;
chunk.removeAllDecorations();
}
},

_updateChunksForRanges: function(oldRange, newRange)
{

var firstChunkNumber = this._chunkNumberForLine(oldRange.startLine);
var lastChunkNumber = firstChunkNumber;
while (lastChunkNumber + 1 < this._textChunks.length) {
if (this._textChunks[lastChunkNumber + 1].startLine > oldRange.endLine)
break;
++lastChunkNumber;
}

var startLine = this._textChunks[firstChunkNumber].startLine;
var linesCount = this._textChunks[lastChunkNumber].startLine + this._textChunks[lastChunkNumber].linesCount - startLine;
var linesDiff = newRange.linesCount - oldRange.linesCount;
linesCount += linesDiff;

if (linesDiff) {

for (var chunkNumber = lastChunkNumber + 1; chunkNumber < this._textChunks.length; ++chunkNumber)
this._textChunks[chunkNumber].startLine += linesDiff;
}

var firstLineRow;
if (firstChunkNumber) {
var chunk = this._textChunks[firstChunkNumber - 1];
firstLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine + chunk.linesCount - 1) : chunk.element;
firstLineRow = firstLineRow.nextSibling;
} else
firstLineRow = this._container.firstChild;


for (var chunkNumber = firstChunkNumber; chunkNumber <= lastChunkNumber; ++chunkNumber) {
var chunk = this._textChunks[chunkNumber];
if (chunk.startLine + chunk.linesCount > this._textModel.linesCount)
break;
var lineNumber = chunk.startLine;
for (var lineRow = firstLineRow; lineRow && lineNumber < chunk.startLine + chunk.linesCount; lineRow = lineRow.nextSibling) {
if (lineRow.lineNumber !== lineNumber || lineRow !== chunk.getExpandedLineRow(lineNumber) || lineRow.textContent !== this._textModel.line(lineNumber) || !lineRow.firstChild)
break;
++lineNumber;
}
if (lineNumber < chunk.startLine + chunk.linesCount)
break;
chunk.updateCollapsedLineRow();
++firstChunkNumber;
firstLineRow = lineRow;
startLine += chunk.linesCount;
linesCount -= chunk.linesCount;
}

if (firstChunkNumber > lastChunkNumber && linesCount === 0)
return;


var chunk = this._textChunks[lastChunkNumber + 1];
var linesInLastChunk = linesCount % this._defaultChunkSize;
if (chunk && !chunk.decorated && linesInLastChunk > 0 && linesInLastChunk + chunk.linesCount <= this._defaultChunkSize) {
++lastChunkNumber;
linesCount += chunk.linesCount;
}

var scrollTop = this.element.scrollTop;
var scrollLeft = this.element.scrollLeft;


var firstUnmodifiedLineRow = null;
var chunk = this._textChunks[lastChunkNumber + 1];
if (chunk) {
firstUnmodifiedLineRow = chunk.expanded ? chunk.getExpandedLineRow(chunk.startLine) : chunk.element;
}
while (firstLineRow && firstLineRow !== firstUnmodifiedLineRow) {
var lineRow = firstLineRow;
firstLineRow = firstLineRow.nextSibling;
this._container.removeChild(lineRow);
}


for (var chunkNumber = firstChunkNumber; linesCount > 0; ++chunkNumber) {
var chunkLinesCount = Math.min(this._defaultChunkSize, linesCount);
var newChunk = this._createNewChunk(startLine, startLine + chunkLinesCount);
this._container.insertBefore(newChunk.element, firstUnmodifiedLineRow);

if (chunkNumber <= lastChunkNumber)
this._textChunks[chunkNumber] = newChunk;
else
this._textChunks.splice(chunkNumber, 0, newChunk);
startLine += chunkLinesCount;
linesCount -= chunkLinesCount;
}
if (chunkNumber <= lastChunkNumber)
this._textChunks.splice(chunkNumber, lastChunkNumber - chunkNumber + 1);

this.element.scrollTop = scrollTop;
this.element.scrollLeft = scrollLeft;
},

_updateHighlightsForRange: function(range)
{
var visibleFrom = this.element.scrollTop;
var visibleTo = this.element.scrollTop + this.element.clientHeight;

var result = this._findVisibleChunks(visibleFrom, visibleTo);
var chunk = this._textChunks[result.end - 1];
var lastVisibleLine = chunk.startLine + chunk.linesCount;

lastVisibleLine = Math.max(lastVisibleLine, range.endLine + 1);
lastVisibleLine = Math.min(lastVisibleLine, this._textModel.linesCount);

var updated = this._highlighter.updateHighlight(range.startLine, lastVisibleLine);
if (!updated) {

for (var i = this._chunkNumberForLine(range.startLine); i < this._textChunks.length; ++i)
this._textChunks[i].expanded = false;
}

this._repaintAll();
},

_collectLinesFromDiv: function(lines, element)
{
var textContents = [];
var node = element.nodeType === Node.TEXT_NODE ? element : element.traverseNextNode(element);
while (node) {
if (element.decorationsElement === node) {
node = node.nextSibling;
continue;
}
if (node.nodeName.toLowerCase() === "br")
textContents.push("\n");
else if (node.nodeType === Node.TEXT_NODE)
textContents.push(node.textContent);
node = node.traverseNextNode(element);
}

var textContent = textContents.join("");

textContent = textContent.replace(/\n$/, "");

textContents = textContent.split("\n");
for (var i = 0; i < textContents.length; ++i)
lines.push(textContents[i]);
}
}

WebInspector.TextEditorMainPanel.prototype.__proto__ = WebInspector.TextEditorChunkedPanel.prototype;

WebInspector.TextEditorMainChunk = function(textViewer, startLine, endLine)
{
this._textViewer = textViewer;
this._textModel = textViewer._textModel;

this.element = document.createElement("div");
this.element.lineNumber = startLine;
this.element.className = "webkit-line-content";
this._textViewer._enableDOMNodeRemovedListener(this.element, true);

this._startLine = startLine;
endLine = Math.min(this._textModel.linesCount, endLine);
this.linesCount = endLine - startLine;

this._expanded = false;
this._readOnly = false;

this.updateCollapsedLineRow();
}

WebInspector.TextEditorMainChunk.prototype = {
addDecoration: function(decoration)
{
this._textViewer.beginDomUpdates();
if (typeof decoration === "string")
this.element.addStyleClass(decoration);
else {
if (!this.element.decorationsElement) {
this.element.decorationsElement = document.createElement("div");
this.element.decorationsElement.className = "webkit-line-decorations";
this.element.appendChild(this.element.decorationsElement);
}
this.element.decorationsElement.appendChild(decoration);
}
this._textViewer.endDomUpdates();
},

removeDecoration: function(decoration)
{
this._textViewer.beginDomUpdates();
if (typeof decoration === "string")
this.element.removeStyleClass(decoration);
else if (this.element.decorationsElement)
this.element.decorationsElement.removeChild(decoration);
this._textViewer.endDomUpdates();
},

removeAllDecorations: function()
{
this._textViewer.beginDomUpdates();
this.element.className = "webkit-line-content";
if (this.element.decorationsElement) {
this.element.removeChild(this.element.decorationsElement);
delete this.element.decorationsElement;
}
this._textViewer.endDomUpdates();
},

get decorated()
{
return this.element.className !== "webkit-line-content" || !!(this.element.decorationsElement && this.element.decorationsElement.firstChild);
},

get startLine()
{
return this._startLine;
},

set startLine(startLine)
{
this._startLine = startLine;
this.element.lineNumber = startLine;
if (this._expandedLineRows) {
for (var i = 0; i < this._expandedLineRows.length; ++i)
this._expandedLineRows[i].lineNumber = startLine + i;
}
},

get expanded()
{
return this._expanded;
},

set expanded(expanded)
{
if (this._expanded === expanded)
return;

this._expanded = expanded;

if (this.linesCount === 1) {
if (expanded)
this._textViewer._paintLine(this.element);
return;
}

this._textViewer.beginDomUpdates();

if (expanded) {
this._expandedLineRows = [];
var parentElement = this.element.parentElement;
for (var i = this.startLine; i < this.startLine + this.linesCount; ++i) {
var lineRow = this._createRow(i);
this._textViewer._enableDOMNodeRemovedListener(lineRow, true);
this._updateElementReadOnlyState(lineRow);
parentElement.insertBefore(lineRow, this.element);
this._expandedLineRows.push(lineRow);
}
this._textViewer._enableDOMNodeRemovedListener(this.element, false);
parentElement.removeChild(this.element);
this._textViewer._paintLines(this.startLine, this.startLine + this.linesCount);
} else {
var elementInserted = false;
for (var i = 0; i < this._expandedLineRows.length; ++i) {
var lineRow = this._expandedLineRows[i];
this._textViewer._enableDOMNodeRemovedListener(lineRow, false);
var parentElement = lineRow.parentElement;
if (parentElement) {
if (!elementInserted) {
elementInserted = true;
this._textViewer._enableDOMNodeRemovedListener(this.element, true);
parentElement.insertBefore(this.element, lineRow);
}
parentElement.removeChild(lineRow);
}
this._textViewer._releaseLinesHighlight(lineRow);
}
delete this._expandedLineRows;
}

this._textViewer.endDomUpdates();
},

set readOnly(readOnly)
{
if (this._readOnly === readOnly)
return;

this._readOnly = readOnly;
this._updateElementReadOnlyState(this.element);
if (this._expandedLineRows) {
for (var i = 0; i < this._expandedLineRows.length; ++i)
this._updateElementReadOnlyState(this._expandedLineRows[i]);
}
},

get readOnly()
{
return this._readOnly;
},

_updateElementReadOnlyState: function(element)
{
if (this._readOnly)
element.addStyleClass("text-editor-read-only");
else
element.removeStyleClass("text-editor-read-only");
},

get height()
{
if (!this._expandedLineRows)
return this._textViewer._totalHeight(this.element);
return this._textViewer._totalHeight(this._expandedLineRows[0], this._expandedLineRows[this._expandedLineRows.length - 1]);
},

get offsetTop()
{
return (this._expandedLineRows && this._expandedLineRows.length) ? this._expandedLineRows[0].offsetTop : this.element.offsetTop;
},

_createRow: function(lineNumber)
{
var lineRow = this._textViewer._cachedRows.pop() || document.createElement("div");
lineRow.lineNumber = lineNumber;
lineRow.className = "webkit-line-content";
lineRow.textContent = this._textModel.line(lineNumber);
if (!lineRow.textContent)
lineRow.appendChild(document.createElement("br"));
return lineRow;
},

getExpandedLineRow: function(lineNumber)
{
if (!this._expanded || lineNumber < this.startLine || lineNumber >= this.startLine + this.linesCount)
return null;
if (!this._expandedLineRows)
return this.element;
return this._expandedLineRows[lineNumber - this.startLine];
},

updateCollapsedLineRow: function()
{
if (this.linesCount === 1 && this._expanded)
return;

var lines = [];
for (var i = this.startLine; i < this.startLine + this.linesCount; ++i)
lines.push(this._textModel.line(i));

this.element.removeChildren();
this.element.textContent = lines.join("\n");


if (!lines[lines.length - 1])
this.element.appendChild(document.createElement("br"));
}
}





WebInspector.SourceFrame = function(delegate, url)
{
WebInspector.TextViewerDelegate.call(this);

this._delegate = delegate;
this._url = url;

this._textModel = new WebInspector.TextEditorModel();
this._textModel.replaceTabsWithSpaces = true;

this._textViewer = new WebInspector.TextViewer(this._textModel, WebInspector.platform, this._url, this);
this._textViewer.element.addStyleClass("script-view");
this._visible = false;

this._currentSearchResultIndex = -1;
this._searchResults = [];

this._messages = [];
this._rowMessages = {};
this._messageBubbles = {};

this._breakpoints = {};
}

WebInspector.SourceFrame.Events = {
Loaded: "loaded"
}

WebInspector.SourceFrame.createSearchRegex = function(query)
{
var regex;


try {
if (/^\/.*\/$/.test(query))
regex = new RegExp(query.substring(1, query.length - 1));
} catch (e) {

}


if (!regex) 
regex = createSearchRegex(query);

return regex;
}


WebInspector.SourceFrame.prototype = {
get visible()
{
return this._textViewer.visible;
},

set visible(x)
{
this._textViewer.visible = x;
},

show: function(parentElement)
{
this._ensureContentLoaded();

this._textViewer.show(parentElement);

if (this.loaded) {
if (this._scrollTop)
this._textViewer.scrollTop = this._scrollTop;
if (this._scrollLeft)
this._textViewer.scrollLeft = this._scrollLeft;
}

this._textViewer.resize();
},

hide: function()
{
if (this.loaded) {
this._scrollTop = this._textViewer.scrollTop;
this._scrollLeft = this._textViewer.scrollLeft;
this._textViewer.freeCachedElements();
}

this._textViewer.hide();
this._hidePopup();
this._clearLineHighlight();
},

detach: function()
{
this._textViewer.detach();
},

get element()
{
return this._textViewer.element;
},

get loaded()
{
return !!this._content;
},

hasContent: function()
{
return true;
},

_ensureContentLoaded: function()
{
if (!this._contentRequested) {
this._contentRequested = true;
this.requestContent(this._initializeTextViewer.bind(this));
}
},

requestContent: function(callback)
{
this._delegate.requestContent(callback);
},

markDiff: function(diffData)
{
if (this._diffLines && this.loaded)
this._removeDiffDecorations();

this._diffLines = diffData;
if (this.loaded)
this._updateDiffDecorations();
},

addMessage: function(msg)
{
this._messages.push(msg);
if (this.loaded)
this.addMessageToSource(msg.line - 1, msg);
},

clearMessages: function()
{
for (var line in this._messageBubbles) {
var bubble = this._messageBubbles[line];
bubble.parentNode.removeChild(bubble);
}

this._messages = [];
this._rowMessages = {};
this._messageBubbles = {};

this._textViewer.resize();
},

get textModel()
{
return this._textModel;
},

get scrollTop()
{
return this.loaded ? this._textViewer.scrollTop : this._scrollTop;
},

set scrollTop(scrollTop)
{
this._scrollTop = scrollTop;
if (this.loaded)
this._textViewer.scrollTop = scrollTop;
},

highlightLine: function(line)
{
if (this.loaded)
this._textViewer.highlightLine(line);
else
this._lineToHighlight = line;
},

_clearLineHighlight: function()
{
if (this.loaded)
this._textViewer.clearLineHighlight();
else
delete this._lineToHighlight;
},

_saveViewerState: function()
{
this._viewerState = {
textModelContent: this._textModel.text,
executionLineNumber: this._executionLineNumber,
messages: this._messages,
diffLines: this._diffLines,
breakpoints: this._breakpoints
};
},

_restoreViewerState: function()
{
if (!this._viewerState)
return;
this._textModel.setText(null, this._viewerState.textModelContent);

this._messages = this._viewerState.messages;
this._diffLines = this._viewerState.diffLines;
this._setTextViewerDecorations();

if (typeof this._viewerState.executionLineNumber === "number") {
this.clearExecutionLine();
this.setExecutionLine(this._viewerState.executionLineNumber);
}

var oldBreakpoints = this._breakpoints;
this._breakpoints = {};
for (var lineNumber in oldBreakpoints)
this.removeBreakpoint(Number(lineNumber));

var newBreakpoints = this._viewerState.breakpoints;
for (var lineNumber in newBreakpoints) {
lineNumber = Number(lineNumber);
var breakpoint = newBreakpoints[lineNumber];
this.addBreakpoint(lineNumber, breakpoint.resolved, breakpoint.conditional, breakpoint.enabled);
}

delete this._viewerState;
},

beforeTextChanged: function()
{
if (!this._viewerState) {
this._saveViewerState();
this._delegate.setScriptSourceIsBeingEdited(true);
}

WebInspector.searchController.cancelSearch();
this.clearMessages();
},

afterTextChanged: function(oldRange, newRange)
{
if (!oldRange || !newRange)
return;


if (typeof this._executionLineNumber === "number") {
var newExecutionLineNumber = this._lineNumberAfterEditing(this._executionLineNumber, oldRange, newRange);
this.clearExecutionLine();
this.setExecutionLine(newExecutionLineNumber, true);
}


var oldBreakpoints = this._breakpoints;
this._breakpoints = {};
for (var lineNumber in oldBreakpoints) {
lineNumber = Number(lineNumber);
var breakpoint = oldBreakpoints[lineNumber];
var newLineNumber = this._lineNumberAfterEditing(lineNumber, oldRange, newRange);
if (lineNumber === newLineNumber)
this._breakpoints[lineNumber] = breakpoint;
else {
this.removeBreakpoint(lineNumber);
this.addBreakpoint(newLineNumber, breakpoint.resolved, breakpoint.conditional, breakpoint.enabled);
}
}
},

_lineNumberAfterEditing: function(lineNumber, oldRange, newRange)
{
var shiftOffset = lineNumber <= oldRange.startLine ? 0 : newRange.linesCount - oldRange.linesCount;


if (lineNumber === oldRange.startLine) {
var whiteSpacesRegex = /^[\s\xA0]*$/;
for (var i = 0; lineNumber + i <= newRange.endLine; ++i) {
if (!whiteSpacesRegex.test(this._textModel.line(lineNumber + i))) {
shiftOffset = i;
break;
}
}
}

var newLineNumber = Math.max(0, lineNumber + shiftOffset);
if (oldRange.startLine < lineNumber && lineNumber < oldRange.endLine)
newLineNumber = oldRange.startLine;
return newLineNumber;
},

_initializeTextViewer: function(mimeType, content)
{
this._textViewer.mimeType = mimeType;

this._content = content;
this._textModel.setText(null, content);

var element = this._textViewer.element;
if (this._delegate.debuggingSupported()) {
element.addEventListener("mousedown", this._mouseDown.bind(this), true);
element.addEventListener("mousemove", this._mouseMove.bind(this), true);
element.addEventListener("scroll", this._scroll.bind(this), true);
}

this._textViewer.beginUpdates();

this._setTextViewerDecorations();

if (typeof this._executionLineNumber === "number")
this.setExecutionLine(this._executionLineNumber);

if (this._lineToHighlight) {
this.highlightLine(this._lineToHighlight);
delete this._lineToHighlight;
}

if (this._delayedFindSearchMatches) {
this._delayedFindSearchMatches();
delete this._delayedFindSearchMatches;
}

this.dispatchEventToListeners(WebInspector.SourceFrame.Events.Loaded);

this._textViewer.endUpdates();

if (this._parentElement)
this.show(this._parentElement)
},

_setTextViewerDecorations: function()
{
this._rowMessages = {};
this._messageBubbles = {};

this._textViewer.beginUpdates();

this._addExistingMessagesToSource();
this._updateDiffDecorations();

this._textViewer.resize();

this._textViewer.endUpdates();
},

performSearch: function(query, callback)
{

this.searchCanceled();

function doFindSearchMatches(query)
{
this._currentSearchResultIndex = -1;
this._searchResults = [];

var regex = WebInspector.SourceFrame.createSearchRegex(query);
this._searchResults = this._collectRegexMatches(regex);

callback(this, this._searchResults.length);
}

if (this.loaded)
doFindSearchMatches.call(this, query);
else
this._delayedFindSearchMatches = doFindSearchMatches.bind(this, query);

this._ensureContentLoaded();
},

searchCanceled: function()
{
delete this._delayedFindSearchMatches;
if (!this.loaded)
return;

this._currentSearchResultIndex = -1;
this._searchResults = [];
this._textViewer.markAndRevealRange(null);
},

hasSearchResults: function()
{
return this._searchResults.length > 0;
},

jumpToFirstSearchResult: function()
{
this.jumpToSearchResult(0);
},

jumpToLastSearchResult: function()
{
this.jumpToSearchResult(this._searchResults.length - 1);
},

jumpToNextSearchResult: function()
{
this.jumpToSearchResult(this._currentSearchResultIndex + 1);
},

jumpToPreviousSearchResult: function()
{
this.jumpToSearchResult(this._currentSearchResultIndex - 1);
},

showingFirstSearchResult: function()
{
return this._searchResults.length &&  this._currentSearchResultIndex === 0;
},

showingLastSearchResult: function()
{
return this._searchResults.length && this._currentSearchResultIndex === (this._searchResults.length - 1);
},

jumpToSearchResult: function(index)
{
if (!this.loaded || !this._searchResults.length)
return;
this._currentSearchResultIndex = (index + this._searchResults.length) % this._searchResults.length;
this._textViewer.markAndRevealRange(this._searchResults[this._currentSearchResultIndex]);
},

_collectRegexMatches: function(regexObject)
{
var ranges = [];
for (var i = 0; i < this._textModel.linesCount; ++i) {
var line = this._textModel.line(i);
var offset = 0;
do {
var match = regexObject.exec(line);
if (match) {
if (match[0].length)
ranges.push(new WebInspector.TextRange(i, offset + match.index, i, offset + match.index + match[0].length));
offset += match.index + 1;
line = line.substring(match.index + 1);
}
} while (match && line);
}
return ranges;
},

_incrementMessageRepeatCount: function(msg, repeatDelta)
{
if (!msg._resourceMessageLineElement)
return;

if (!msg._resourceMessageRepeatCountElement) {
var repeatedElement = document.createElement("span");
msg._resourceMessageLineElement.appendChild(repeatedElement);
msg._resourceMessageRepeatCountElement = repeatedElement;
}

msg.repeatCount += repeatDelta;
msg._resourceMessageRepeatCountElement.textContent = WebInspector.UIString(" (repeated %d times)", msg.repeatCount);
},

setExecutionLine: function(lineNumber, skipRevealLine)
{
this._executionLineNumber = lineNumber;
if (this.loaded) {
this._textViewer.addDecoration(lineNumber, "webkit-execution-line");
if (!skipRevealLine)
this._textViewer.revealLine(lineNumber);
}
},

clearExecutionLine: function()
{
if (this.loaded)
this._textViewer.removeDecoration(this._executionLineNumber, "webkit-execution-line");
delete this._executionLineNumber;
},

_updateDiffDecorations: function()
{
if (!this._diffLines)
return;

function addDecorations(textViewer, lines, className)
{
for (var i = 0; i < lines.length; ++i)
textViewer.addDecoration(lines[i], className);
}
addDecorations(this._textViewer, this._diffLines.added, "webkit-added-line");
addDecorations(this._textViewer, this._diffLines.removed, "webkit-removed-line");
addDecorations(this._textViewer, this._diffLines.changed, "webkit-changed-line");
},

_removeDiffDecorations: function()
{
function removeDecorations(textViewer, lines, className)
{
for (var i = 0; i < lines.length; ++i)
textViewer.removeDecoration(lines[i], className);
}
removeDecorations(this._textViewer, this._diffLines.added, "webkit-added-line");
removeDecorations(this._textViewer, this._diffLines.removed, "webkit-removed-line");
removeDecorations(this._textViewer, this._diffLines.changed, "webkit-changed-line");
},

_addExistingMessagesToSource: function()
{
var length = this._messages.length;
for (var i = 0; i < length; ++i)
this.addMessageToSource(this._messages[i].line - 1, this._messages[i]);
},

addMessageToSource: function(lineNumber, msg)
{
if (lineNumber >= this._textModel.linesCount)
lineNumber = this._textModel.linesCount - 1;
if (lineNumber < 0)
lineNumber = 0;

var messageBubbleElement = this._messageBubbles[lineNumber];
if (!messageBubbleElement || messageBubbleElement.nodeType !== Node.ELEMENT_NODE || !messageBubbleElement.hasStyleClass("webkit-html-message-bubble")) {
messageBubbleElement = document.createElement("div");
messageBubbleElement.className = "webkit-html-message-bubble";
this._messageBubbles[lineNumber] = messageBubbleElement;
this._textViewer.addDecoration(lineNumber, messageBubbleElement);
}

var rowMessages = this._rowMessages[lineNumber];
if (!rowMessages) {
rowMessages = [];
this._rowMessages[lineNumber] = rowMessages;
}

for (var i = 0; i < rowMessages.length; ++i) {
if (rowMessages[i].isEqual(msg)) {
this._incrementMessageRepeatCount(rowMessages[i], msg.repeatDelta);
return;
}
}

rowMessages.push(msg);

var imageURL;
switch (msg.level) {
case WebInspector.ConsoleMessage.MessageLevel.Error:
messageBubbleElement.addStyleClass("webkit-html-error-message");
imageURL = "Images/errorIcon.png";
break;
case WebInspector.ConsoleMessage.MessageLevel.Warning:
messageBubbleElement.addStyleClass("webkit-html-warning-message");
imageURL = "Images/warningIcon.png";
break;
}

var messageLineElement = document.createElement("div");
messageLineElement.className = "webkit-html-message-line";
messageBubbleElement.appendChild(messageLineElement);


var image = document.createElement("img");
image.src = imageURL;
image.className = "webkit-html-message-icon";
messageLineElement.appendChild(image);
messageLineElement.appendChild(document.createTextNode(msg.message));

msg._resourceMessageLineElement = messageLineElement;
},

addBreakpoint: function(lineNumber, resolved, conditional, enabled)
{
this._breakpoints[lineNumber] = {
resolved: resolved,
conditional: conditional,
enabled: enabled
};
this._textViewer.beginUpdates();
this._textViewer.addDecoration(lineNumber, "webkit-breakpoint");
if (!enabled)
this._textViewer.addDecoration(lineNumber, "webkit-breakpoint-disabled");
if (conditional)
this._textViewer.addDecoration(lineNumber, "webkit-breakpoint-conditional");
this._textViewer.endUpdates();
},

removeBreakpoint: function(lineNumber)
{
delete this._breakpoints[lineNumber];
this._textViewer.beginUpdates();
this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint");
this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint-disabled");
this._textViewer.removeDecoration(lineNumber, "webkit-breakpoint-conditional");
this._textViewer.endUpdates();
},

populateLineGutterContextMenu: function(lineNumber, contextMenu)
{
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Continue to here" : "Continue to Here"), this._delegate.continueToLine.bind(this._delegate, lineNumber));

var breakpoint = this._delegate.findBreakpoint(lineNumber);
if (!breakpoint) {

contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add breakpoint" : "Add Breakpoint"), this._delegate.setBreakpoint.bind(this._delegate, lineNumber, "", true));

function addConditionalBreakpoint()
{
this.addBreakpoint(lineNumber, true, true, true);
function didEditBreakpointCondition(committed, condition)
{
this.removeBreakpoint(lineNumber);
if (committed)
this._delegate.setBreakpoint(lineNumber, condition, true);
}
this._editBreakpointCondition(lineNumber, "", didEditBreakpointCondition.bind(this));
}
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add conditional breakpoint…" : "Add Conditional Breakpoint…"), addConditionalBreakpoint.bind(this));
} else {

contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove breakpoint" : "Remove Breakpoint"), this._delegate.removeBreakpoint.bind(this._delegate, lineNumber));
function editBreakpointCondition()
{
function didEditBreakpointCondition(committed, condition)
{
if (committed)
this._delegate.updateBreakpoint(lineNumber, condition, breakpoint.enabled);
}
this._editBreakpointCondition(lineNumber, breakpoint.condition, didEditBreakpointCondition.bind(this));
}
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Edit breakpoint…" : "Edit Breakpoint…"), editBreakpointCondition.bind(this));
function setBreakpointEnabled(enabled)
{
this._delegate.updateBreakpoint(lineNumber, breakpoint.condition, enabled);
}
if (breakpoint.enabled)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Disable breakpoint" : "Disable Breakpoint"), setBreakpointEnabled.bind(this, false));
else
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Enable breakpoint" : "Enable Breakpoint"), setBreakpointEnabled.bind(this, true));
}
},

populateTextAreaContextMenu: function(contextMenu)
{
},

suggestedFileName: function()
{
return this._delegate.suggestedFileName();
},

_scroll: function(event)
{
this._hidePopup();
},

_mouseDown: function(event)
{
this._resetHoverTimer();
this._hidePopup();
if (event.button != 0 || event.altKey || event.ctrlKey || event.metaKey)
return;
var target = event.target.enclosingNodeOrSelfWithClass("webkit-line-number");
if (!target)
return;
var lineNumber = target.lineNumber;

var breakpoint = this._delegate.findBreakpoint(lineNumber);
if (breakpoint) {
if (event.shiftKey)
this._delegate.updateBreakpoint(lineNumber, breakpoint.condition, !breakpoint.enabled);
else
this._delegate.removeBreakpoint(lineNumber);
} else
this._delegate.setBreakpoint(lineNumber, "", true);
event.preventDefault();
},

_mouseMove: function(event)
{

if (this._hoverElement === event.target || event.target.hasStyleClass("source-frame-eval-expression"))
return;

this._resetHoverTimer();

if (this._popup) {
var self = this;
function doHide()
{
self._hidePopup();
delete self._hidePopupTimer;
}
if (!("_hidePopupTimer" in this))
this._hidePopupTimer = setTimeout(doHide, 500);
}

this._hoverElement = event.target;


if (!this._delegate.debuggerPaused())
return;


if (this._hoverElement.hasStyleClass("webkit-javascript-keyword")) {
if (this._hoverElement.textContent !== "this")
return;
} else if (!this._hoverElement.hasStyleClass("webkit-javascript-ident"))
return;

const toolTipDelay = this._popup ? 600 : 1000;
this._hoverTimer = setTimeout(this._mouseHover.bind(this, this._hoverElement), toolTipDelay);
},

_resetHoverTimer: function()
{
if (this._hoverTimer) {
clearTimeout(this._hoverTimer);
delete this._hoverTimer;
}
},

_hidePopup: function()
{
if (!this._popup)
return;


var parentElement = this._popup.highlightElement.parentElement;
var child = this._popup.highlightElement.firstChild;
while (child) {
var nextSibling = child.nextSibling;
parentElement.insertBefore(child, this._popup.highlightElement);
child = nextSibling;
}
parentElement.removeChild(this._popup.highlightElement);

this._popup.hide();
delete this._popup;
this._delegate.releaseEvaluationResult();
},

_mouseHover: function(element)
{
delete this._hoverTimer;

var lineRow = element.enclosingNodeOrSelfWithClass("webkit-line-content");
if (!lineRow)
return;


var tokens = [ element ];
var token = element.previousSibling;
while (token && (token.className === "webkit-javascript-ident" || token.className === "webkit-javascript-keyword" || token.textContent.trim() === ".")) {
tokens.push(token);
token = token.previousSibling;
}
tokens.reverse();


var parentElement = element.parentElement;
var nextElement = element.nextSibling;
var container = document.createElement("span");
for (var i = 0; i < tokens.length; ++i)
container.appendChild(tokens[i]);
parentElement.insertBefore(container, nextElement);
this._showPopup(container);
},

_showPopup: function(element)
{
if (!this._delegate.debuggerPaused())
return;

function killHidePopupTimer()
{
if (this._hidePopupTimer) {
clearTimeout(this._hidePopupTimer);
delete this._hidePopupTimer;



this._resetHoverTimer();
}
}

function showObjectPopup(result, wasThrown)
{
if (wasThrown || !this._delegate.debuggerPaused())
return;

var popupContentElement = null;
if (result.type !== "object" && result.type !== "node" && result.type !== "array") {
popupContentElement = document.createElement("span");
popupContentElement.className = "monospace console-formatted-" + result.type;
popupContentElement.style.whiteSpace = "pre";
popupContentElement.textContent = result.description;
if (result.type === "string")
popupContentElement.textContent = "\"" + popupContentElement.textContent + "\"";
this._popup = new WebInspector.Popover(popupContentElement);
this._popup.show(element);
} else {
var popupContentElement = document.createElement("div");

var titleElement = document.createElement("div");
titleElement.className = "source-frame-popover-title monospace";
titleElement.textContent = result.description;
popupContentElement.appendChild(titleElement);

var section = new WebInspector.ObjectPropertiesSection(result);
section.expanded = true;
section.element.addStyleClass("source-frame-popover-tree");
section.headerElement.addStyleClass("hidden");
popupContentElement.appendChild(section.element);

this._popup = new WebInspector.Popover(popupContentElement);
const popupWidth = 300;
const popupHeight = 250;
this._popup.show(element, popupWidth, popupHeight);
}
this._popup.highlightElement = element;
this._popup.highlightElement.addStyleClass("source-frame-eval-expression");
popupContentElement.addEventListener("mousemove", killHidePopupTimer.bind(this), true);
}

this._delegate.evaluateInSelectedCallFrame(element.textContent, showObjectPopup.bind(this));
},

_editBreakpointCondition: function(lineNumber, condition, callback)
{
this._conditionElement = this._createConditionElement(lineNumber);
this._textViewer.addDecoration(lineNumber, this._conditionElement);

function finishEditing(committed, element, newText)
{
this._textViewer.removeDecoration(lineNumber, this._conditionElement);
delete this._conditionEditorElement;
delete this._conditionElement;
callback(committed, newText);
}

WebInspector.startEditing(this._conditionEditorElement, {
context: null,
commitHandler: finishEditing.bind(this, true),
cancelHandler: finishEditing.bind(this, false)
});
this._conditionEditorElement.value = condition;
this._conditionEditorElement.select();
},

_createConditionElement: function(lineNumber)
{
var conditionElement = document.createElement("div");
conditionElement.className = "source-frame-breakpoint-condition";

var labelElement = document.createElement("label");
labelElement.className = "source-frame-breakpoint-message";
labelElement.htmlFor = "source-frame-breakpoint-condition";
labelElement.appendChild(document.createTextNode(WebInspector.UIString("The breakpoint on line %d will stop only if this expression is true:", lineNumber)));
conditionElement.appendChild(labelElement);

var editorElement = document.createElement("input");
editorElement.id = "source-frame-breakpoint-condition";
editorElement.className = "monospace";
editorElement.type = "text";
conditionElement.appendChild(editorElement);
this._conditionEditorElement = editorElement;

return conditionElement;
},

resize: function()
{
this._textViewer.resize();
},

doubleClick: function(lineNumber)
{
if (!this._delegate.canEditScriptSource())
return;

if (this._commitEditingInProgress)
return;

this._setReadOnly(false);
},

commitEditing: function()
{
if (!this._viewerState) {

this._setReadOnly(true);
return;
}

function didEditContent(error)
{
this._commitEditingInProgress = false;
this._textViewer.readOnly = false;

if (error) {
if (error.data && error.data[0]) {
WebInspector.log(error.data[0], WebInspector.ConsoleMessage.MessageLevel.Error);
WebInspector.showConsole();
}
return;
}

var newBreakpoints = {};
for (var lineNumber in this._breakpoints) {
newBreakpoints[lineNumber] = this._breakpoints[lineNumber];
this.removeBreakpoint(Number(lineNumber));
}

for (var lineNumber in this._viewerState.breakpoints)
this._delegate.removeBreakpoint(Number(lineNumber));

for (var lineNumber in newBreakpoints) {
var breakpoint = newBreakpoints[lineNumber];
this._delegate.setBreakpoint(Number(lineNumber), breakpoint.condition, breakpoint.enabled);
}

delete this._viewerState;
this._delegate.setScriptSourceIsBeingEdited(false);
}
this._commitEditingInProgress = true;
this._textViewer.readOnly = true;
this.editContent(this._textModel.text, didEditContent.bind(this));
},

editContent: function(newContent, callback)
{
this._delegate.editScriptSource(newContent, callback);
},

cancelEditing: function()
{
this._restoreViewerState();
this._setReadOnly(true);
},

_setReadOnly: function(readOnly)
{
this._textViewer.readOnly = readOnly;
WebInspector.markBeingEdited(this._textViewer.element, !readOnly);
if (readOnly)
this._delegate.setScriptSourceIsBeingEdited(false);
}
}

WebInspector.SourceFrame.prototype.__proto__ = WebInspector.TextViewerDelegate.prototype;


WebInspector.SourceFrameDelegate = function()
{
}

WebInspector.SourceFrameDelegate.prototype = {
requestContent: function(callback)
{

},

debuggingSupported: function()
{
return false;
},

setBreakpoint: function(lineNumber, condition, enabled)
{

},

removeBreakpoint: function(lineNumber)
{

},

updateBreakpoint: function(lineNumber, condition, enabled)
{

},

findBreakpoint: function(lineNumber)
{

},

continueToLine: function(lineNumber)
{

},

canEditScriptSource: function()
{
return false;
},

editScriptSource: function(text, callback)
{

},

setScriptSourceIsBeingEdited: function(inEditMode)
{

},

debuggerPaused: function()
{

},

evaluateInSelectedCallFrame: function(string)
{

},

releaseEvaluationResult: function()
{

},

suggestedFileName: function()
{

}
}





WebInspector.ResourceView = function(resource)
{
WebInspector.View.call(this);
this.element.addStyleClass("resource-view");
this.resource = resource;
}

WebInspector.ResourceView.prototype = {
hasContent: function()
{
return false;
}
}

WebInspector.ResourceView.prototype.__proto__ = WebInspector.View.prototype;

WebInspector.ResourceView.hasTextContent = function(resource)
{
switch (resource.category) {
case WebInspector.resourceCategories.documents:
case WebInspector.resourceCategories.scripts:
case WebInspector.resourceCategories.xhr:
case WebInspector.resourceCategories.stylesheets:
return true;
default:
return false;
}
}

WebInspector.ResourceView.nonSourceViewForResource = function(resource)
{
switch (resource.category) {
case WebInspector.resourceCategories.images:
return new WebInspector.ImageView(resource);
case WebInspector.resourceCategories.fonts:
return new WebInspector.FontView(resource);
default:
return new WebInspector.ResourceView(resource);
}
}

WebInspector.ResourceSourceFrame = function(resource)
{
WebInspector.SourceFrame.call(this, new WebInspector.SourceFrameDelegate(resource), resource.url);
this._resource = resource;
}



WebInspector.ResourceSourceFrame.DefaultMIMETypeForResourceType = {
0: "text/html",
1: "text/css",
4: "text/javascript"
}

WebInspector.ResourceSourceFrame.mimeTypeForResource = function(resource) {
return WebInspector.ResourceSourceFrame.DefaultMIMETypeForResourceType[resource.type] || resource.mimeType;
}

WebInspector.ResourceSourceFrame.prototype = {
get resource()
{
return this._resource;
},

requestContent: function(callback)
{
function contentLoaded(text)
{
var mimeType = WebInspector.ResourceSourceFrame.mimeTypeForResource(this.resource);
callback(mimeType, text);
}

this.resource.requestContent(contentLoaded.bind(this));
},

suggestedFileName: function()
{
return this.resource.displayName;
}
}

WebInspector.ResourceSourceFrame.prototype.__proto__ = WebInspector.SourceFrame.prototype;

WebInspector.EditableResourceSourceFrame = function(resource)
{
WebInspector.ResourceSourceFrame.call(this, resource);
}

WebInspector.EditableResourceSourceFrame.prototype = {
doubleClick: function(lineNumber)
{
if (!this.resource.isEditable())
return;

if (this._commitEditingInProgress)
return;

this._textViewer.readOnly = false;
WebInspector.markBeingEdited(this._textViewer.element, true);
},

editContent: function(newText, callback)
{
this._clearIncrementalUpdateTimer();
var majorChange = true;
this.resource.setContent(newText, majorChange, callback);
},

cancelEditing: function()
{
this._clearIncrementalUpdateTimer();
const majorChange = false;
this.resource.setContent(this._viewerState.textModelContent, majorChange);
WebInspector.SourceFrame.prototype.cancelEditing.call(this);
},

afterTextChanged: function(oldRange, newRange)
{
function commitIncrementalEdit()
{
var majorChange = false;
this.resource.setContent(this._textModel.text, majorChange, function() {});
}
const updateTimeout = 200;
this._incrementalUpdateTimer = setTimeout(commitIncrementalEdit.bind(this), updateTimeout);
},

_clearIncrementalUpdateTimer: function()
{
if (this._incrementalUpdateTimer)
clearTimeout(this._incrementalUpdateTimer);
delete this._incrementalUpdateTimer;
},
}

WebInspector.EditableResourceSourceFrame.prototype.__proto__ = WebInspector.ResourceSourceFrame.prototype;

WebInspector.ResourceRevisionSourceFrame = function(revision)
{
WebInspector.ResourceSourceFrame.call(this, revision.resource);
this._revision = revision;
}

WebInspector.ResourceRevisionSourceFrame.prototype = {
get resource()
{
return this._revision.resource;
},

requestContent: function(callback)
{
function contentLoaded(text)
{
var mimeType = WebInspector.ResourceSourceFrame.mimeTypeForResource(this.resource);
callback(mimeType, text);
}

this._revision.requestContent(contentLoaded.bind(this));
},
}

WebInspector.ResourceRevisionSourceFrame.prototype.__proto__ = WebInspector.ResourceSourceFrame.prototype;





WebInspector.ScriptsPanel = function()
{
WebInspector.Panel.call(this, "scripts");

this._presentationModel = new WebInspector.DebuggerPresentationModel();

this.registerShortcuts();

this.topStatusBar = document.createElement("div");
this.topStatusBar.className = "status-bar";
this.topStatusBar.id = "scripts-status-bar";
this.element.appendChild(this.topStatusBar);

this.backButton = document.createElement("button");
this.backButton.className = "status-bar-item";
this.backButton.id = "scripts-back";
this.backButton.title = WebInspector.UIString("Show the previous script resource.");
this.backButton.disabled = true;
this.backButton.appendChild(document.createElement("img"));
this.backButton.addEventListener("click", this._goBack.bind(this), false);
this.topStatusBar.appendChild(this.backButton);

this.forwardButton = document.createElement("button");
this.forwardButton.className = "status-bar-item";
this.forwardButton.id = "scripts-forward";
this.forwardButton.title = WebInspector.UIString("Show the next script resource.");
this.forwardButton.disabled = true;
this.forwardButton.appendChild(document.createElement("img"));
this.forwardButton.addEventListener("click", this._goForward.bind(this), false);
this.topStatusBar.appendChild(this.forwardButton);

this._filesSelectElement = document.createElement("select");
this._filesSelectElement.className = "status-bar-item";
this._filesSelectElement.id = "scripts-files";
this._filesSelectElement.addEventListener("change", this._filesSelectChanged.bind(this), false);
this._filesSelectElement.addEventListener("keyup", this._filesSelectChanged.bind(this), false);
this.topStatusBar.appendChild(this._filesSelectElement);

this.functionsSelectElement = document.createElement("select");
this.functionsSelectElement.className = "status-bar-item";
this.functionsSelectElement.id = "scripts-functions";




this._createSidebarButtons();

this.toggleBreakpointsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Deactivate all breakpoints."), "toggle-breakpoints");
this.toggleBreakpointsButton.toggled = true;
this.toggleBreakpointsButton.addEventListener("click", this.toggleBreakpointsClicked.bind(this), false);
this.sidebarButtonsElement.appendChild(this.toggleBreakpointsButton.element);

this.debuggerStatusElement = document.createElement("div");
this.debuggerStatusElement.id = "scripts-debugger-status";
this.sidebarButtonsElement.appendChild(this.debuggerStatusElement);

this.viewsContainerElement = document.createElement("div");
this.viewsContainerElement.id = "script-resource-views";

this.sidebarElement = document.createElement("div");
this.sidebarElement.id = "scripts-sidebar";

this.sidebarResizeElement = document.createElement("div");
this.sidebarResizeElement.className = "sidebar-resizer-vertical";
this.sidebarResizeElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);

this.sidebarResizeWidgetElement = document.createElement("div");
this.sidebarResizeWidgetElement.id = "scripts-sidebar-resizer-widget";
this.sidebarResizeWidgetElement.addEventListener("mousedown", this._startSidebarResizeDrag.bind(this), false);
this.topStatusBar.appendChild(this.sidebarResizeWidgetElement);

this.sidebarPanes = {};
this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane(this._presentationModel);
this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(this._presentationModel, this._showSourceLine.bind(this));
if (Preferences.nativeInstrumentationEnabled) {
this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane;
this.sidebarPanes.xhrBreakpoints = new WebInspector.XHRBreakpointsSidebarPane();
this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane();
}

this.sidebarPanes.workers = new WebInspector.WorkersSidebarPane();

for (var pane in this.sidebarPanes)
this.sidebarElement.appendChild(this.sidebarPanes[pane].element);

this.sidebarPanes.callstack.expanded = true;

this.sidebarPanes.scopechain.expanded = true;
this.sidebarPanes.jsBreakpoints.expanded = true;

var helpSection = WebInspector.shortcutsHelp.section(WebInspector.UIString("Scripts Panel"));
this.sidebarPanes.callstack.registerShortcuts(helpSection, this.registerShortcut.bind(this));   

var panelEnablerHeading = WebInspector.UIString("You need to enable debugging before you can use the Scripts panel.");
var panelEnablerDisclaimer = WebInspector.UIString("Enabling debugging will make scripts run slower.");
var panelEnablerButton = WebInspector.UIString("Enable Debugging");

this.panelEnablerView = new WebInspector.PanelEnablerView("scripts", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
this.panelEnablerView.addEventListener("enable clicked", this._enableDebugging, this);

this.element.appendChild(this.panelEnablerView.element);
this.element.appendChild(this.viewsContainerElement);
this.element.appendChild(this.sidebarElement);
this.element.appendChild(this.sidebarResizeElement);

this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
this.enableToggleButton.addEventListener("click", this._toggleDebugging.bind(this), false);
if (Preferences.debuggerAlwaysEnabled)
this.enableToggleButton.element.addStyleClass("hidden");

this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item", 3);
this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions.bind(this), false);

this._toggleFormatSourceFilesButton = new WebInspector.StatusBarButton(WebInspector.UIString("Pretty print"), "scripts-toggle-pretty-print-status-bar-item");
this._toggleFormatSourceFilesButton.toggled = false;
this._toggleFormatSourceFilesButton.addEventListener("click", this._toggleFormatSourceFiles.bind(this), false);

this._debuggerEnabled = Preferences.debuggerAlwaysEnabled;

this.reset();

WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasEnabled, this._debuggerWasEnabled, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._debuggerWasDisabled, this);

this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.SourceFileAdded, this._sourceFileAdded, this)
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.SourceFileChanged, this._sourceFileChanged, this);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.ConsoleMessageAdded, this._consoleMessageAdded, this);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.ConsoleMessagesCleared, this._consoleMessagesCleared, this);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.BreakpointAdded, this._breakpointAdded, this);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.BreakpointRemoved, this._breakpointRemoved, this);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.DebuggerPaused, this._debuggerPaused, this);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.DebuggerResumed, this._debuggerResumed, this);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.CallFrameSelected, this._callFrameSelected, this);

var enableDebugger = Preferences.debuggerAlwaysEnabled || WebInspector.settings.debuggerEnabled;
if (enableDebugger || InspectorFrontendHost.loadSessionSetting("debugger-enabled") === "true")
WebInspector.debuggerModel.enableDebugger();
}


WebInspector.ScriptsPanel.PauseOnExceptionsState = {
DontPauseOnExceptions : "none",
PauseOnAllExceptions : "all",
PauseOnUncaughtExceptions: "uncaught"
};

WebInspector.ScriptsPanel.BrowserBreakpointTypes = {
DOM: "DOM",
EventListener: "EventListener",
XHR: "XHR"
}

WebInspector.ScriptsPanel.prototype = {
get toolbarItemLabel()
{
return WebInspector.UIString("Scripts");
},

get statusBarItems()
{
return [this.enableToggleButton.element, this._pauseOnExceptionButton.element, this._toggleFormatSourceFilesButton.element];
},

get defaultFocusedElement()
{
return this._filesSelectElement;
},

get paused()
{
return this._paused;
},

show: function()
{
WebInspector.Panel.prototype.show.call(this);
this.sidebarResizeElement.style.right = (this.sidebarElement.offsetWidth - 3) + "px";
if (Preferences.nativeInstrumentationEnabled)
this.sidebarElement.insertBefore(this.sidebarPanes.domBreakpoints.element, this.sidebarPanes.xhrBreakpoints.element);

if (this.visibleView)
this.visibleView.show(this.viewsContainerElement);
},

hide: function()
{
if (this.visibleView)
this.visibleView.hide();
WebInspector.Panel.prototype.hide.call(this);
},

get breakpointsActivated()
{
return this.toggleBreakpointsButton.toggled;
},

_sourceFileAdded: function(event)
{
var sourceFile = event.data;

if (!sourceFile.url) {

return;
}

this._addOptionToFilesSelect(sourceFile.id);

var lastViewedURL = WebInspector.settings.lastViewedScriptFile;
if (this._filesSelectElement.length === 1) {


this._showSourceFrameAndAddToHistory(sourceFile.id);


WebInspector.settings.lastViewedScriptFile = lastViewedURL;
} else if (sourceFile.url === lastViewedURL)
this._showSourceFrameAndAddToHistory(sourceFile.id);
},

_addOptionToFilesSelect: function(sourceFileId)
{
var sourceFile = this._presentationModel.sourceFile(sourceFileId);
var select = this._filesSelectElement;
var option = document.createElement("option");
option.text = sourceFile.displayName;
option.isContentScript = sourceFile.isContentScript;
if (sourceFile.isContentScript)
option.addStyleClass("extension-script");
function optionCompare(a, b)
{
if (a === select.contentScriptSection)
return b.isContentScript ? -1 : 1;
if (b === select.contentScriptSection)
return a.isContentScript ? 1 : -1;

if (a.isContentScript && !b.isContentScript)
return 1;
if (!a.isContentScript && b.isContentScript)
return -1;

if (a.text === b.text)
return 0;
return a.text < b.text ? -1 : 1;
}

var insertionIndex = insertionIndexForObjectInListSortedByFunction(option, select.childNodes, optionCompare);
select.insertBefore(option, insertionIndex < 0 ? null : select.childNodes.item(insertionIndex));

if (sourceFile.isContentScript && !select.contentScriptSection) {
var contentScriptSection = document.createElement("option");
contentScriptSection.text = WebInspector.UIString("Content scripts");
contentScriptSection.disabled = true;
select.contentScriptSection = contentScriptSection;

var insertionIndex = insertionIndexForObjectInListSortedByFunction(contentScriptSection, select.childNodes, optionCompare);
select.insertBefore(contentScriptSection, insertionIndex < 0 ? null : select.childNodes.item(insertionIndex));
}
option._sourceFileId = sourceFileId;
this._sourceFileIdToFilesSelectOption[sourceFileId] = option;
},

setScriptSourceIsBeingEdited: function(sourceFileId, inEditMode)
{
var option = this._sourceFileIdToFilesSelectOption[sourceFileId];
if (!option)
return;
if (inEditMode)
option.text = option.text.replace(/[^*]$/, "$&*");
else
option.text = option.text.replace(/[*]$/, "");
},

_consoleMessagesCleared: function()
{
for (var sourceFileId in this._sourceFileIdToSourceFrame)
this._sourceFileIdToSourceFrame[sourceFileId].clearMessages();
},

_consoleMessageAdded: function(event)
{
var message = event.data;

var sourceFrame = this._sourceFileIdToSourceFrame[message.sourceFileId];
if (sourceFrame && sourceFrame.loaded)
sourceFrame.addMessageToSource(message.lineNumber, message.originalMessage);
},

_breakpointAdded: function(event)
{
var breakpoint = event.data;

var sourceFrame = this._sourceFileIdToSourceFrame[breakpoint.sourceFileId];
if (sourceFrame && sourceFrame.loaded)
sourceFrame.addBreakpoint(breakpoint.lineNumber, breakpoint.resolved, breakpoint.condition, breakpoint.enabled);

this.sidebarPanes.jsBreakpoints.addBreakpoint(breakpoint);
},

_breakpointRemoved: function(event)
{
var breakpoint = event.data;

var sourceFrame = this._sourceFileIdToSourceFrame[breakpoint.sourceFileId];
if (sourceFrame && sourceFrame.loaded)
sourceFrame.removeBreakpoint(breakpoint.lineNumber);

this.sidebarPanes.jsBreakpoints.removeBreakpoint(breakpoint.sourceFileId, breakpoint.lineNumber);
},

evaluateInSelectedCallFrame: function(code, objectGroup, includeCommandLineAPI, callback)
{
var selectedCallFrame = this._presentationModel.selectedCallFrame;
selectedCallFrame.evaluate(code, objectGroup, includeCommandLineAPI, callback);
},

getSelectedCallFrameVariables: function(callback)
{
var result = { this: true };

var selectedCallFrame = this._presentationModel.selectedCallFrame;
if (!selectedCallFrame)
callback(result);

var pendingRequests = 0;

function propertiesCollected(properties)
{
for (var i = 0; properties && i < properties.length; ++i)
result[properties[i].name] = true;
if (--pendingRequests == 0)
callback(result);
}

for (var i = 0; i < selectedCallFrame.scopeChain.length; ++i) {
var scope = selectedCallFrame.scopeChain[i];
var object = WebInspector.RemoteObject.fromPayload(scope.object);
pendingRequests++;
object.getAllProperties(propertiesCollected);
}
},

_debuggerPaused: function(event)
{
var callFrames = event.data.callFrames;
var details = event.data.details;

this._paused = true;
this._waitingToPause = false;
this._stepping = false;

this._updateDebuggerButtons();

WebInspector.currentPanel = this;

this.sidebarPanes.callstack.update(callFrames, details);
this.sidebarPanes.callstack.selectedCallFrame = this._presentationModel.selectedCallFrame;

if (details.eventType === WebInspector.DebuggerEventTypes.NativeBreakpoint) {
if (details.eventData.breakpointType === WebInspector.ScriptsPanel.BrowserBreakpointTypes.DOM) {
this.sidebarPanes.domBreakpoints.highlightBreakpoint(details.eventData);
function didCreateBreakpointHitStatusMessage(element)
{
this.sidebarPanes.callstack.setStatus(element);
}
this.sidebarPanes.domBreakpoints.createBreakpointHitStatusMessage(details.eventData, didCreateBreakpointHitStatusMessage.bind(this));
} else if (details.eventData.breakpointType === WebInspector.ScriptsPanel.BrowserBreakpointTypes.EventListener) {
var eventName = details.eventData.eventName;
this.sidebarPanes.eventListenerBreakpoints.highlightBreakpoint(details.eventData.eventName);
var eventNameForUI = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName);
this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a \"%s\" Event Listener.", eventNameForUI));
} else if (details.eventData.breakpointType === WebInspector.ScriptsPanel.BrowserBreakpointTypes.XHR) {
this.sidebarPanes.xhrBreakpoints.highlightBreakpoint(details.eventData.breakpointURL);
this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a XMLHttpRequest."));
}
} else {
function didGetSourceLocation(sourceFileId, lineNumber)
{
var exception = WebInspector.debuggerModel.debuggerPausedDetails.exception;
if (exception) {
this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on exception: '%s'.", exception.description));
return;
}

if (!sourceFileId || !this._presentationModel.findBreakpoint(sourceFileId, lineNumber))
return;
this.sidebarPanes.jsBreakpoints.highlightBreakpoint(sourceFileId, lineNumber);
this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint."));
}
callFrames[0].sourceLine(didGetSourceLocation.bind(this));
}

window.focus();
InspectorFrontendHost.bringToFront();
},

_debuggerResumed: function()
{
this._paused = false;
this._waitingToPause = false;
this._stepping = false;

this._clearInterface();
},

_debuggerWasEnabled: function()
{
this._setPauseOnExceptions(WebInspector.settings.pauseOnExceptionStateString);

if (this._debuggerEnabled)
return;

InspectorFrontendHost.saveSessionSetting("debugger-enabled", "true");
this._debuggerEnabled = true;
this.reset(true);
},

_debuggerWasDisabled: function()
{
if (!this._debuggerEnabled)
return;

InspectorFrontendHost.saveSessionSetting("debugger-enabled", "false");
this._debuggerEnabled = false;
this.reset(true);
},

reset: function(preserveItems)
{
this.visibleView = null;

delete this.currentQuery;
this.searchCanceled();

this._debuggerResumed();

this._backForwardList = [];
this._currentBackForwardIndex = -1;
this._updateBackAndForwardButtons();

for (var id in this._sourceFileIdToSourceFrame) {
var sourceFrame = this._sourceFileIdToSourceFrame[id];
sourceFrame.removeEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this);
}

this._sourceFileIdToSourceFrame = {};
this._sourceFileIdToFilesSelectOption = {};
this._filesSelectElement.removeChildren();
this.functionsSelectElement.removeChildren();
this.viewsContainerElement.removeChildren();

this.sidebarPanes.jsBreakpoints.reset();
this.sidebarPanes.watchExpressions.refreshExpressions();
if (!preserveItems)
this.sidebarPanes.workers.reset();
},

get visibleView()
{
return this._visibleView;
},

set visibleView(x)
{
if (this._visibleView === x)
return;

if (this._visibleView)
this._visibleView.hide();

this._visibleView = x;

if (x)
x.show(this.viewsContainerElement);
},

canShowAnchorLocation: function(anchor)
{
return this._debuggerEnabled && this._presentationModel.sourceFileForScriptURL(anchor.href);
},

showAnchorLocation: function(anchor)
{
var sourceFile = this._presentationModel.sourceFileForScriptURL(anchor.href);
var anchorLineNumber = parseInt(anchor.getAttribute("line_number"));
if (anchorLineNumber !== NaN) {
function didRequestSourceMapping(mapping)
{
var lineNumber = mapping.scriptLocationToSourceLine({ lineNumber: anchorLineNumber - 1, columnNumber: 0 });
this._showSourceLine(sourceFile.id, lineNumber);
}
sourceFile.requestSourceMapping(didRequestSourceMapping.bind(this));
return;
}
this._showSourceFrameAndAddToHistory(sourceFile.id);
},

_showSourceLine: function(sourceFileId, lineNumber)
{
var sourceFrame = this._showSourceFrameAndAddToHistory(sourceFileId);
sourceFrame.highlightLine(lineNumber);
},

_showSourceFrameAndAddToHistory: function(sourceFileId)
{
var sourceFrame = this._showSourceFrame(sourceFileId);

var oldIndex = this._currentBackForwardIndex;
if (oldIndex >= 0)
this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex);



var previousEntryIndex = this._backForwardList.indexOf(sourceFileId);
if (previousEntryIndex !== -1)
this._backForwardList.splice(previousEntryIndex, 1);

this._backForwardList.push(sourceFileId);
this._currentBackForwardIndex = this._backForwardList.length - 1;

this._updateBackAndForwardButtons();

return sourceFrame;
},

_showSourceFrame: function(sourceFileId)
{
var index = this._sourceFileIdToFilesSelectOption[sourceFileId].index;
this._filesSelectElement.selectedIndex = index;

var sourceFrame = this._sourceFrameForSourceFileId(sourceFileId);
this.visibleView = sourceFrame;

var sourceFile = this._presentationModel.sourceFile(sourceFileId);
if (sourceFile.url)
WebInspector.settings.lastViewedScriptFile = sourceFile.url;

return sourceFrame;
},

_sourceFrameForSourceFileId: function(sourceFileId)
{
var sourceFrame = this._sourceFileIdToSourceFrame[sourceFileId];
return sourceFrame || this._createSourceFrame(sourceFileId);
},

_createSourceFrame: function(sourceFileId)
{
var sourceFile = this._presentationModel.sourceFile(sourceFileId);
var delegate = new WebInspector.SourceFrameDelegateForScriptsPanel(this._presentationModel, sourceFileId, sourceFile.displayName);
var sourceFrame = new WebInspector.SourceFrame(delegate, sourceFile.url);
sourceFrame._sourceFileId = sourceFileId;
sourceFrame.addEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this);
this._sourceFileIdToSourceFrame[sourceFileId] = sourceFrame;
return sourceFrame;
},

_sourceFileChanged: function(event)
{
var sourceFileId = event.data.id;

var oldSourceFrame = this._sourceFileIdToSourceFrame[sourceFileId];
if (!oldSourceFrame)
return;
oldSourceFrame.removeEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this);
delete this._sourceFileIdToSourceFrame[sourceFileId];
if (this.visibleView !== oldSourceFrame)
return;

var newSourceFrame = this._createSourceFrame(sourceFileId)
newSourceFrame.scrollTop = oldSourceFrame.scrollTop;
this.visibleView = newSourceFrame;
},

_sourceFrameLoaded: function(event)
{
var sourceFrame = event.target;
var sourceFileId = sourceFrame._sourceFileId;
var sourceFile = this._presentationModel.sourceFile(sourceFileId);

var messages = sourceFile.messages;
for (var i = 0; i < messages.length; ++i) {
var message = messages[i];
sourceFrame.addMessageToSource(message.lineNumber, message.originalMessage);
}

var breakpoints = this._presentationModel.breakpointsForSourceFileId(sourceFileId);
for (var i = 0; i < breakpoints.length; ++i) {
var breakpoint = breakpoints[i];
sourceFrame.addBreakpoint(breakpoint.lineNumber, breakpoint.resolved, breakpoint.condition, breakpoint.enabled);
}
},

_clearCurrentExecutionLine: function()
{
if (this._executionSourceFrame)
this._executionSourceFrame.clearExecutionLine();
delete this._executionSourceFrame;
},

_callFrameSelected: function(event)
{
var callFrame = event.data;

this._clearCurrentExecutionLine();

if (!callFrame)
return;

this.sidebarPanes.scopechain.update(callFrame);
this.sidebarPanes.watchExpressions.refreshExpressions();
this.sidebarPanes.callstack.selectedCallFrame = this._presentationModel.selectedCallFrame;

function didGetSourceLocation(sourceFileId, lineNumber)
{
if (!sourceFileId)
return;

if (!(sourceFileId in this._sourceFileIdToFilesSelectOption)) {

this._addOptionToFilesSelect(sourceFileId);
}
var sourceFrame = this._showSourceFrameAndAddToHistory(sourceFileId);
sourceFrame.setExecutionLine(lineNumber);
this._executionSourceFrame = sourceFrame;
}
callFrame.sourceLine(didGetSourceLocation.bind(this));
},

_filesSelectChanged: function()
{
var sourceFileId = this._filesSelectElement[this._filesSelectElement.selectedIndex]._sourceFileId;
this._showSourceFrameAndAddToHistory(sourceFileId);
},

_startSidebarResizeDrag: function(event)
{
WebInspector.elementDragStart(this.sidebarElement, this._sidebarResizeDrag.bind(this), this._endSidebarResizeDrag.bind(this), event, "col-resize");

if (event.target === this.sidebarResizeWidgetElement)
this._dragOffset = (event.target.offsetWidth - (event.pageX - event.target.totalOffsetLeft));
else
this._dragOffset = 0;
},

_endSidebarResizeDrag: function(event)
{
WebInspector.elementDragEnd(event);
delete this._dragOffset;
this.saveSidebarWidth();
},

_sidebarResizeDrag: function(event)
{
var x = event.pageX + this._dragOffset;
var newWidth = Number.constrain(window.innerWidth - x, Preferences.minScriptsSidebarWidth, window.innerWidth * 0.66);
this.setSidebarWidth(newWidth);
event.preventDefault();
},

setSidebarWidth: function(newWidth)
{
this.sidebarElement.style.width = newWidth + "px";
this.sidebarButtonsElement.style.width = newWidth + "px";
this.viewsContainerElement.style.right = newWidth + "px";
this.sidebarResizeWidgetElement.style.right = newWidth + "px";
this.sidebarResizeElement.style.right = (newWidth - 3) + "px";

this.resize();
},

_setPauseOnExceptions: function(pauseOnExceptionsState)
{
pauseOnExceptionsState = pauseOnExceptionsState || WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions;
function callback(error)
{
if (error)
return;
if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions)
this._pauseOnExceptionButton.title = WebInspector.UIString("Don't pause on exceptions.\nClick to Pause on all exceptions.");
else if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnAllExceptions)
this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on all exceptions.\nClick to Pause on uncaught exceptions.");
else if (pauseOnExceptionsState == WebInspector.ScriptsPanel.PauseOnExceptionsState.PauseOnUncaughtExceptions)
this._pauseOnExceptionButton.title = WebInspector.UIString("Pause on uncaught exceptions.\nClick to Not pause on exceptions.");

this._pauseOnExceptionButton.state = pauseOnExceptionsState;
WebInspector.settings.pauseOnExceptionStateString = pauseOnExceptionsState;
}
DebuggerAgent.setPauseOnExceptions(pauseOnExceptionsState, callback.bind(this));
},

_updateDebuggerButtons: function()
{
if (this._debuggerEnabled) {
this.enableToggleButton.title = WebInspector.UIString("Debugging enabled. Click to disable.");
this.enableToggleButton.toggled = true;
this._pauseOnExceptionButton.visible = true;
this.panelEnablerView.visible = false;
} else {
this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable.");
this.enableToggleButton.toggled = false;
this._pauseOnExceptionButton.visible = false;
this.panelEnablerView.visible = true;
}

if (this._paused) {
this.pauseButton.addStyleClass("paused");

this.pauseButton.disabled = false;
this.stepOverButton.disabled = false;
this.stepIntoButton.disabled = false;
this.stepOutButton.disabled = false;

this.debuggerStatusElement.textContent = WebInspector.UIString("Paused");
} else {
this.pauseButton.removeStyleClass("paused");

this.pauseButton.disabled = this._waitingToPause;
this.stepOverButton.disabled = true;
this.stepIntoButton.disabled = true;
this.stepOutButton.disabled = true;

if (this._waitingToPause)
this.debuggerStatusElement.textContent = WebInspector.UIString("Pausing");
else if (this._stepping)
this.debuggerStatusElement.textContent = WebInspector.UIString("Stepping");
else
this.debuggerStatusElement.textContent = "";
}
},

_updateBackAndForwardButtons: function()
{
this.backButton.disabled = this._currentBackForwardIndex <= 0;
this.forwardButton.disabled = this._currentBackForwardIndex >= (this._backForwardList.length - 1);
},

_clearInterface: function()
{
this.sidebarPanes.callstack.update(null);
this.sidebarPanes.scopechain.update(null);
this.sidebarPanes.jsBreakpoints.clearBreakpointHighlight();
if (Preferences.nativeInstrumentationEnabled) {
this.sidebarPanes.domBreakpoints.clearBreakpointHighlight();
this.sidebarPanes.eventListenerBreakpoints.clearBreakpointHighlight();
this.sidebarPanes.xhrBreakpoints.clearBreakpointHighlight();
}

this._clearCurrentExecutionLine();
this._updateDebuggerButtons();
},

_goBack: function()
{
if (this._currentBackForwardIndex <= 0) {
console.error("Can't go back from index " + this._currentBackForwardIndex);
return;
}

this._showSourceFrame(this._backForwardList[--this._currentBackForwardIndex]);
this._updateBackAndForwardButtons();
},

_goForward: function()
{
if (this._currentBackForwardIndex >= this._backForwardList.length - 1) {
console.error("Can't go forward from index " + this._currentBackForwardIndex);
return;
}

this._showSourceFrame(this._backForwardList[++this._currentBackForwardIndex]);
this._updateBackAndForwardButtons();
},

_enableDebugging: function()
{
if (this._debuggerEnabled)
return;
this._toggleDebugging(this.panelEnablerView.alwaysEnabled);
},

_toggleDebugging: function(optionalAlways)
{
this._paused = false;
this._waitingToPause = false;
this._stepping = false;

if (this._debuggerEnabled) {
WebInspector.settings.debuggerEnabled = false;
WebInspector.debuggerModel.disableDebugger();
} else {
WebInspector.settings.debuggerEnabled = !!optionalAlways;
WebInspector.debuggerModel.enableDebugger();
}
},

_togglePauseOnExceptions: function()
{
var nextStateMap = {};
var stateEnum = WebInspector.ScriptsPanel.PauseOnExceptionsState;
nextStateMap[stateEnum.DontPauseOnExceptions] = stateEnum.PauseOnAllExceptions;
nextStateMap[stateEnum.PauseOnAllExceptions] = stateEnum.PauseOnUncaughtExceptions;
nextStateMap[stateEnum.PauseOnUncaughtExceptions] = stateEnum.DontPauseOnExceptions;
this._setPauseOnExceptions(nextStateMap[this._pauseOnExceptionButton.state]);
},

_togglePause: function()
{
if (this._paused) {
this._paused = false;
this._waitingToPause = false;
DebuggerAgent.resume();
} else {
this._stepping = false;
this._waitingToPause = true;
DebuggerAgent.pause();
}

this._clearInterface();
},

_stepOverClicked: function()
{
this._paused = false;
this._stepping = true;

this._clearInterface();

DebuggerAgent.stepOver();
},

_stepIntoClicked: function()
{
this._paused = false;
this._stepping = true;

this._clearInterface();

DebuggerAgent.stepInto();
},

_stepOutClicked: function()
{
this._paused = false;
this._stepping = true;

this._clearInterface();

DebuggerAgent.stepOut();
},

toggleBreakpointsClicked: function()
{
this.toggleBreakpointsButton.toggled = !this.toggleBreakpointsButton.toggled;
if (this.toggleBreakpointsButton.toggled) {
DebuggerAgent.setBreakpointsActive(true);
this.toggleBreakpointsButton.title = WebInspector.UIString("Deactivate all breakpoints.");
document.getElementById("main-panels").removeStyleClass("breakpoints-deactivated");
} else {
DebuggerAgent.setBreakpointsActive(false);
this.toggleBreakpointsButton.title = WebInspector.UIString("Activate all breakpoints.");
document.getElementById("main-panels").addStyleClass("breakpoints-deactivated");
}
},

elementsToRestoreScrollPositionsFor: function()
{
return [ this.sidebarElement ];
},

_createSidebarButtons: function()
{
this.sidebarButtonsElement = document.createElement("div");
this.sidebarButtonsElement.id = "scripts-sidebar-buttons";
this.topStatusBar.appendChild(this.sidebarButtonsElement);

var title, handler, shortcuts;
var platformSpecificModifier = WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta;


title = WebInspector.UIString("Pause script execution (%s).");
handler = this._togglePause.bind(this);
shortcuts = [];
shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F8));
shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Slash, platformSpecificModifier));
this.pauseButton = this._createSidebarButtonAndRegisterShortcuts("scripts-pause", title, handler, shortcuts, WebInspector.UIString("Pause/Continue"));


title = WebInspector.UIString("Step over next function call (%s).");
handler = this._stepOverClicked.bind(this);
shortcuts = [];
shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F10));
shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.SingleQuote, platformSpecificModifier));
this.stepOverButton = this._createSidebarButtonAndRegisterShortcuts("scripts-step-over", title, handler, shortcuts, WebInspector.UIString("Step over"));


title = WebInspector.UIString("Step into next function call (%s).");
handler = this._stepIntoClicked.bind(this);
shortcuts = [];
shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F11));
shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Semicolon, platformSpecificModifier));
this.stepIntoButton = this._createSidebarButtonAndRegisterShortcuts("scripts-step-into", title, handler, shortcuts, WebInspector.UIString("Step into"));


title = WebInspector.UIString("Step out of current function (%s).");
handler = this._stepOutClicked.bind(this);
shortcuts = [];
shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.F11, WebInspector.KeyboardShortcut.Modifiers.Shift));
shortcuts.push(WebInspector.KeyboardShortcut.makeDescriptor(WebInspector.KeyboardShortcut.Keys.Semicolon, WebInspector.KeyboardShortcut.Modifiers.Shift, platformSpecificModifier));
this.stepOutButton = this._createSidebarButtonAndRegisterShortcuts("scripts-step-out", title, handler, shortcuts, WebInspector.UIString("Step out"));
},

_createSidebarButtonAndRegisterShortcuts: function(buttonId, buttonTitle, handler, shortcuts, shortcutDescription)
{
var button = document.createElement("button");
button.className = "status-bar-item";
button.id = buttonId;
button.title = String.vsprintf(buttonTitle, [shortcuts[0].name]);
button.disabled = true;
button.appendChild(document.createElement("img"));
button.addEventListener("click", handler, false);
this.sidebarButtonsElement.appendChild(button);

var shortcutNames = [];
for (var i = 0; i < shortcuts.length; ++i) {
this.registerShortcut(shortcuts[i].key, handler);
shortcutNames.push(shortcuts[i].name);
}
var section = WebInspector.shortcutsHelp.section(WebInspector.UIString("Scripts Panel"));
section.addAlternateKeys(shortcutNames, shortcutDescription);

return button;
},

searchCanceled: function()
{
if (this._searchView)
this._searchView.searchCanceled();

delete this._searchView;
delete this._searchQuery;
},

performSearch: function(query)
{
WebInspector.searchController.updateSearchMatchesCount(0, this);

if (!this.visibleView)
return;


this.searchCanceled();

this._searchView = this.visibleView;
this._searchQuery = query;

function finishedCallback(view, searchMatches)
{
if (!searchMatches)
return;

WebInspector.searchController.updateSearchMatchesCount(searchMatches, this);
view.jumpToFirstSearchResult();
}

this._searchView.performSearch(query, finishedCallback.bind(this));
},

jumpToNextSearchResult: function()
{
if (!this._searchView)
return;

if (this._searchView !== this.visibleView) {
this.performSearch(this._searchQuery);
return;
}

if (this._searchView.showingLastSearchResult())
this._searchView.jumpToFirstSearchResult();
else
this._searchView.jumpToNextSearchResult();
},

jumpToPreviousSearchResult: function()
{
if (!this._searchView)
return;

if (this._searchView !== this.visibleView) {
this.performSearch(this._searchQuery);
if (this._searchView)
this._searchView.jumpToLastSearchResult();
return;
}

if (this._searchView.showingFirstSearchResult())
this._searchView.jumpToLastSearchResult();
else
this._searchView.jumpToPreviousSearchResult();
},

_toggleFormatSourceFiles: function()
{
WebInspector.panels.scripts.reset();
this._toggleFormatSourceFilesButton.toggled = !this._toggleFormatSourceFilesButton.toggled;
this._presentationModel.setFormatSourceFiles(this._toggleFormatSourceFilesButton.toggled);
}
}

WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype;


WebInspector.SourceFrameDelegateForScriptsPanel = function(model, sourceFileId, scriptName)
{
WebInspector.SourceFrameDelegate.call(this);
this._model = model;
this._sourceFileId = sourceFileId;
this._popoverObjectGroup = "popover";
this._scriptName = scriptName;
}

WebInspector.SourceFrameDelegateForScriptsPanel.prototype = {
requestContent: function(callback)
{
this._model.requestSourceFileContent(this._sourceFileId, callback);
},

debuggingSupported: function()
{
return true;
},

setBreakpoint: function(lineNumber, condition, enabled)
{
this._model.setBreakpoint(this._sourceFileId, lineNumber, condition, enabled);

if (!WebInspector.panels.scripts.breakpointsActivated)
WebInspector.panels.scripts.toggleBreakpointsClicked();
},

updateBreakpoint: function(lineNumber, condition, enabled)
{
this._model.updateBreakpoint(this._sourceFileId, lineNumber, condition, enabled);
},

removeBreakpoint: function(lineNumber)
{
this._model.removeBreakpoint(this._sourceFileId, lineNumber);
},

findBreakpoint: function(lineNumber)
{
return this._model.findBreakpoint(this._sourceFileId, lineNumber);
},

continueToLine: function(lineNumber)
{
this._model.continueToLine(this._sourceFileId, lineNumber);
},

canEditScriptSource: function()
{
return this._model.canEditScriptSource(this._sourceFileId);
},

editScriptSource: function(text, callback)
{
this._model.editScriptSource(this._sourceFileId, text, callback);
},

setScriptSourceIsBeingEdited: function(inEditMode)
{
WebInspector.panels.scripts.setScriptSourceIsBeingEdited(this._sourceFileId, inEditMode);
},

debuggerPaused: function()
{
return WebInspector.panels.scripts.paused;
},

evaluateInSelectedCallFrame: function(string, callback)
{
WebInspector.panels.scripts.evaluateInSelectedCallFrame(string, this._popoverObjectGroup, false, callback);
},

releaseEvaluationResult: function()
{
RuntimeAgent.releaseObjectGroup(this._popoverObjectGroup);
},

suggestedFileName: function()
{
return this._scriptName;
}
}

WebInspector.SourceFrameDelegateForScriptsPanel.prototype.__proto__ = WebInspector.SourceFrameDelegate.prototype;





WebInspector.ResourcesPanel = function(database)
{
WebInspector.Panel.call(this, "resources");

WebInspector.settings.installApplicationSetting("resourcesLastSelectedItem", {});

this.createSidebar();
this.sidebarElement.addStyleClass("outline-disclosure");
this.sidebarElement.addStyleClass("filter-all");
this.sidebarElement.addStyleClass("children");
this.sidebarElement.addStyleClass("small");
this.sidebarTreeElement.removeStyleClass("sidebar-tree");

this.resourcesListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Frames"), "Frames", ["frame-storage-tree-item"]);
this.sidebarTree.appendChild(this.resourcesListTreeElement);

this.databasesListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Databases"), "Databases", ["database-storage-tree-item"]);
this.sidebarTree.appendChild(this.databasesListTreeElement);

this.localStorageListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Local Storage"), "LocalStorage", ["domstorage-storage-tree-item", "local-storage"]);
this.sidebarTree.appendChild(this.localStorageListTreeElement);

this.sessionStorageListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Session Storage"), "SessionStorage", ["domstorage-storage-tree-item", "session-storage"]);
this.sidebarTree.appendChild(this.sessionStorageListTreeElement);

this.cookieListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Cookies"), "Cookies", ["cookie-storage-tree-item"]);
this.sidebarTree.appendChild(this.cookieListTreeElement);

this.applicationCacheListTreeElement = new WebInspector.StorageCategoryTreeElement(this, WebInspector.UIString("Application Cache"), "ApplicationCache", ["application-cache-storage-tree-item"]);
this.sidebarTree.appendChild(this.applicationCacheListTreeElement);

this.storageViews = document.createElement("div");
this.storageViews.id = "storage-views";
this.storageViews.className = "diff-container";
this.element.appendChild(this.storageViews);

this.storageViewStatusBarItemsContainer = document.createElement("div");
this.storageViewStatusBarItemsContainer.className = "status-bar-items";

this._databases = [];
this._domStorage = [];
this._cookieViews = {};
this._origins = {};
this._domains = {};

this.sidebarElement.addEventListener("mousemove", this._onmousemove.bind(this), false);
this.sidebarElement.addEventListener("mouseout", this._onmouseout.bind(this), false);

this.registerShortcuts();

WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceUpdated, this._refreshResource, this);

WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.OnLoad, this._onLoadEventFired, this);
}

WebInspector.ResourcesPanel.prototype = {
get toolbarItemLabel()
{
return WebInspector.UIString("Resources");
},

get statusBarItems()
{
return [this.storageViewStatusBarItemsContainer];
},

elementsToRestoreScrollPositionsFor: function()
{
return [this.sidebarElement];
},

show: function()
{
WebInspector.Panel.prototype.show.call(this);

this._populateResourceTree();

if (this.visibleView && this.visibleView.resource)
this._showResourceView(this.visibleView.resource);
},

_onLoadEventFired: function()
{
this._initDefaultSelection();
},

_initDefaultSelection: function()
{
var itemURL = WebInspector.settings.resourcesLastSelectedItem;
if (itemURL) {
for (var treeElement = this.sidebarTree.children[0]; treeElement; treeElement = treeElement.traverseNextTreeElement(false, this.sidebarTree, true)) {
if (treeElement.itemURL === itemURL) {
treeElement.select();
treeElement.reveal();
return;
}
}
}

if (WebInspector.mainResource && this.resourcesListTreeElement && this.resourcesListTreeElement.expanded)
this.showResource(WebInspector.mainResource);
},

reset: function()
{
delete this._initializedDefaultSelection;
this._origins = {};
this._domains = {};
for (var i = 0; i < this._databases.length; ++i) {
var database = this._databases[i];
delete database._tableViews;
delete database._queryView;
}
this._databases = [];

var domStorageLength = this._domStorage.length;
for (var i = 0; i < this._domStorage.length; ++i) {
var domStorage = this._domStorage[i];
delete domStorage._domStorageView;
}
this._domStorage = [];

this._cookieViews = {};

this._applicationCacheView = null;
delete this._cachedApplicationCacheViewStatus;

this.databasesListTreeElement.removeChildren();
this.localStorageListTreeElement.removeChildren();
this.sessionStorageListTreeElement.removeChildren();
this.cookieListTreeElement.removeChildren();
this.applicationCacheListTreeElement.removeChildren();
this.storageViews.removeChildren();

this.storageViewStatusBarItemsContainer.removeChildren();

if (this.sidebarTree.selectedTreeElement)
this.sidebarTree.selectedTreeElement.deselect();
},

_populateResourceTree: function()
{
if (this._treeElementForFrameId)
return;

this._treeElementForFrameId = {};
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, this._frameAdded, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this._frameDetached, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, this._resourceAdded, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded, this._cachedResourcesLoaded, this); 
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.WillLoadCachedResources, this._resetResourcesTree, this); 

function populateFrame(frameId)
{
var subframes = WebInspector.resourceTreeModel.subframes(frameId);
for (var i = 0; i < subframes.length; ++i) {
this._frameAdded({data:subframes[i]});
populateFrame.call(this, subframes[i].id);
}

var resources = WebInspector.resourceTreeModel.resources(frameId);
for (var i = 0; i < resources.length; ++i)
this._resourceAdded({data:resources[i]});
}
populateFrame.call(this, "");

this._initDefaultSelection();
},

_frameAdded: function(event)
{
var frame = event.data;
var parentFrameId = frame.parentId;

var parentTreeElement = parentFrameId ? this._treeElementForFrameId[parentFrameId] : this.resourcesListTreeElement;
if (!parentTreeElement) {
console.warn("No frame with id:" + parentFrameId + " to route " + frame.name + "/" + frame.url + " to.")
return;
}

var frameTreeElement = new WebInspector.FrameTreeElement(this, frame);
this._treeElementForFrameId[frame.id] = frameTreeElement;
parentTreeElement.appendChild(frameTreeElement);
},

_frameDetached: function(event)
{
var frameId = event.data;
var frameTreeElement = this._treeElementForFrameId[frameId];
if (!frameTreeElement)
return;

delete this._treeElementForFrameId[frameId];
if (frameTreeElement.parent)
frameTreeElement.parent.removeChild(frameTreeElement);
},

_resourceAdded: function(event)
{
var resource = event.data;
var frameId = resource.frameId;

if (resource.statusCode >= 301 && resource.statusCode <= 303)
return;

var frameTreeElement = this._treeElementForFrameId[frameId];
if (!frameTreeElement) {


return;
}

frameTreeElement.appendResource(resource);
},

_frameNavigated: function(event)
{
var frameId = event.data.frame.id;
var frameTreeElement = this._treeElementForFrameId[frameId];
if (frameTreeElement)
frameTreeElement.frameNavigated(event.data.frame);
},

_resetResourcesTree: function()
{
this.resourcesListTreeElement.removeChildren();
this._treeElementForFrameId = {};
this.reset();
},

_cachedResourcesLoaded: function()
{
this._initDefaultSelection();
},

_refreshResource: function(event)
{
var resource = event.data;

if (resource.type === WebInspector.Resource.Type.XHR) {
var resourceTreeElement = this._findTreeElementForResource(resource);
if (resourceTreeElement)
resourceTreeElement.parent.removeChild(resourceTreeElement);
}
},

addDatabase: function(database)
{
this._databases.push(database);

var databaseTreeElement = new WebInspector.DatabaseTreeElement(this, database);
database._databasesTreeElement = databaseTreeElement;
this.databasesListTreeElement.appendChild(databaseTreeElement);
},

addDocumentURL: function(url)
{
var parsedURL = url.asParsedURL();
if (!parsedURL)
return;

var domain = parsedURL.host;
if (!this._domains[domain]) {
this._domains[domain] = true;

var cookieDomainTreeElement = new WebInspector.CookieTreeElement(this, domain);
this.cookieListTreeElement.appendChild(cookieDomainTreeElement);

var applicationCacheTreeElement = new WebInspector.ApplicationCacheTreeElement(this, domain);
this.applicationCacheListTreeElement.appendChild(applicationCacheTreeElement);
}
},

addDOMStorage: function(domStorage)
{
this._domStorage.push(domStorage);
var domStorageTreeElement = new WebInspector.DOMStorageTreeElement(this, domStorage, (domStorage.isLocalStorage ? "local-storage" : "session-storage"));
domStorage._domStorageTreeElement = domStorageTreeElement;
if (domStorage.isLocalStorage)
this.localStorageListTreeElement.appendChild(domStorageTreeElement);
else
this.sessionStorageListTreeElement.appendChild(domStorageTreeElement);
},

selectDatabase: function(databaseId)
{
var database;
for (var i = 0, len = this._databases.length; i < len; ++i) {
database = this._databases[i];
if (database.id === databaseId) {
this.showDatabase(database);
database._databasesTreeElement.select();
return;
}
}
},

selectDOMStorage: function(storageId)
{
var domStorage = this._domStorageForId(storageId);
if (domStorage) {
this.showDOMStorage(domStorage);
domStorage._domStorageTreeElement.select();
}
},

canShowAnchorLocation: function(anchor)
{
return !!WebInspector.resourceForURL(anchor.href);
},

showAnchorLocation: function(anchor)
{
var resource = WebInspector.resourceForURL(anchor.href);
if (resource.type === WebInspector.Resource.Type.XHR) {

if (WebInspector.panels.network && WebInspector.panels.network.canShowAnchorLocation(anchor)) {
WebInspector.currentPanel = WebInspector.panels.network;
WebInspector.panels.network.showAnchorLocation(anchor);
}
return;
}
var lineNumber = parseInt(anchor.getAttribute("line_number"));
this.showResource(resource, lineNumber !== NaN ? lineNumber - 1 : undefined);
},

showResource: function(resource, line)
{
var resourceTreeElement = this._findTreeElementForResource(resource);
if (resourceTreeElement) {
resourceTreeElement.reveal();
resourceTreeElement.select();
}

if (line !== undefined) {
var view = this._resourceViewForResource(resource);
if (view.highlightLine)
view.highlightLine(line);
}
return true;
},

_showResourceView: function(resource)
{
var view = this._resourceViewForResource(resource);
if (!view) {
this.visibleView.hide();
return;
}
if (view.searchCanceled)
view.searchCanceled();
this._fetchAndApplyDiffMarkup(view, resource);
this._innerShowView(view);
},

_resourceViewForResource: function(resource)
{
if (WebInspector.ResourceView.hasTextContent(resource)) {
var treeElement = this._findTreeElementForResource(resource);
if (!treeElement)
return null;
return treeElement.sourceView();
}
return WebInspector.ResourceView.nonSourceViewForResource(resource);
},

_showRevisionView: function(revision)
{
var view = this._sourceViewForRevision(revision);
this._fetchAndApplyDiffMarkup(view, revision.resource, revision);
this._innerShowView(view);
},

_sourceViewForRevision: function(revision)
{
var treeElement = this._findTreeElementForRevision(revision);
return treeElement.sourceView();
},

_fetchAndApplyDiffMarkup: function(view, resource, revision)
{
var baseRevision = resource.history[0];
if (!baseRevision)
return;
if (!(view instanceof WebInspector.SourceFrame))
return;

baseRevision.requestContent(step1.bind(this));

function step1(baseContent)
{
(revision ? revision : resource).requestContent(step2.bind(this, baseContent));
}

function step2(baseContent, revisionContent)
{
this._applyDiffMarkup(view, baseContent, revisionContent);
}
},

_applyDiffMarkup: function(view, baseContent, newContent) {
var oldLines = baseContent.split(/\r?\n/);
var newLines = newContent.split(/\r?\n/);

var diff = Array.diff(oldLines, newLines);

var diffData = {};
diffData.added = [];
diffData.removed = [];
diffData.changed = [];

var offset = 0;
var right = diff.right;
for (var i = 0; i < right.length; ++i) {
if (typeof right[i] === "string") {
if (right.length > i + 1 && right[i + 1].row === i + 1 - offset)
diffData.changed.push(i);
else {
diffData.added.push(i);
offset++;
}
} else
offset = i - right[i].row;
}
view.markDiff(diffData);
},

showDatabase: function(database, tableName)
{
if (!database)
return;

var view;
if (tableName) {
if (!("_tableViews" in database))
database._tableViews = {};
view = database._tableViews[tableName];
if (!view) {
view = new WebInspector.DatabaseTableView(database, tableName);
database._tableViews[tableName] = view;
}
} else {
view = database._queryView;
if (!view) {
view = new WebInspector.DatabaseQueryView(database);
database._queryView = view;
}
}

this._innerShowView(view);
},

showDOMStorage: function(domStorage)
{
if (!domStorage)
return;

var view;
view = domStorage._domStorageView;
if (!view) {
view = new WebInspector.DOMStorageItemsView(domStorage);
domStorage._domStorageView = view;
}

this._innerShowView(view);
},

showCookies: function(treeElement, cookieDomain)
{
var view = this._cookieViews[cookieDomain];
if (!view) {
view = new WebInspector.CookieItemsView(treeElement, cookieDomain);
this._cookieViews[cookieDomain] = view;
}

this._innerShowView(view);
},

showApplicationCache: function(treeElement, appcacheDomain)
{
var view = this._applicationCacheView;
if (!view) {
view = new WebInspector.ApplicationCacheItemsView(treeElement, appcacheDomain);
this._applicationCacheView = view;
}

this._innerShowView(view);

if ("_cachedApplicationCacheViewStatus" in this)
this._applicationCacheView.updateStatus(this._cachedApplicationCacheViewStatus);
},

showCategoryView: function(categoryName)
{
if (!this._categoryView)
this._categoryView = new WebInspector.StorageCategoryView();
this._categoryView.setText(categoryName);
this._innerShowView(this._categoryView);
},

_innerShowView: function(view)
{
if (this.visibleView)
this.visibleView.hide();

view.show(this.storageViews);
this.visibleView = view;

this.storageViewStatusBarItemsContainer.removeChildren();
var statusBarItems = view.statusBarItems || [];
for (var i = 0; i < statusBarItems.length; ++i)
this.storageViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
},

closeVisibleView: function()
{
if (this.visibleView)
this.visibleView.hide();
delete this.visibleView;
},

updateDatabaseTables: function(database)
{
if (!database || !database._databasesTreeElement)
return;

database._databasesTreeElement.shouldRefreshChildren = true;

if (!("_tableViews" in database))
return;

var tableNamesHash = {};
var self = this;
function tableNamesCallback(tableNames)
{
var tableNamesLength = tableNames.length;
for (var i = 0; i < tableNamesLength; ++i)
tableNamesHash[tableNames[i]] = true;

for (var tableName in database._tableViews) {
if (!(tableName in tableNamesHash)) {
if (self.visibleView === database._tableViews[tableName])
self.closeVisibleView();
delete database._tableViews[tableName];
}
}
}
database.getTableNames(tableNamesCallback);
},

dataGridForResult: function(columnNames, values)
{
var numColumns = columnNames.length;
if (!numColumns)
return null;

var columns = {};

for (var i = 0; i < columnNames.length; ++i) {
var column = {};
column.width = columnNames[i].length;
column.title = columnNames[i];
column.sortable = true;

columns[columnNames[i]] = column;
}

var nodes = [];
for (var i = 0; i < values.length / numColumns; ++i) {
var data = {};
for (var j = 0; j < columnNames.length; ++j)
data[columnNames[j]] = values[numColumns * i + j];

var node = new WebInspector.DataGridNode(data, false);
node.selectable = false;
nodes.push(node);
}

var dataGrid = new WebInspector.DataGrid(columns);
var length = nodes.length;
for (var i = 0; i < length; ++i)
dataGrid.appendChild(nodes[i]);

dataGrid.addEventListener("sorting changed", this._sortDataGrid.bind(this, dataGrid), this);
return dataGrid;
},

_sortDataGrid: function(dataGrid)
{
var nodes = dataGrid.children.slice();
var sortColumnIdentifier = dataGrid.sortColumnIdentifier;
var sortDirection = dataGrid.sortOrder === "ascending" ? 1 : -1;
var columnIsNumeric = true;

for (var i = 0; i < nodes.length; i++) {
if (isNaN(Number(nodes[i].data[sortColumnIdentifier])))
columnIsNumeric = false;
}

function comparator(dataGridNode1, dataGridNode2)
{
var item1 = dataGridNode1.data[sortColumnIdentifier];
var item2 = dataGridNode2.data[sortColumnIdentifier];

var comparison;
if (columnIsNumeric) {

var number1 = parseFloat(item1);
var number2 = parseFloat(item2);
comparison = number1 < number2 ? -1 : (number1 > number2 ? 1 : 0);
} else
comparison = item1 < item2 ? -1 : (item1 > item2 ? 1 : 0);

return sortDirection * comparison;
}

nodes.sort(comparator);
dataGrid.removeChildren();
for (var i = 0; i < nodes.length; i++)
dataGrid.appendChild(nodes[i]);
},

updateDOMStorage: function(storageId)
{
var domStorage = this._domStorageForId(storageId);
if (!domStorage)
return;

var view = domStorage._domStorageView;
if (this.visibleView && view === this.visibleView)
domStorage._domStorageView.update();
},

updateApplicationCacheStatus: function(status)
{
this._cachedApplicationCacheViewStatus = status;
if (this._applicationCacheView && this._applicationCacheView === this.visibleView)
this._applicationCacheView.updateStatus(status);
},

updateNetworkState: function(isNowOnline)
{
if (this._applicationCacheView && this._applicationCacheView === this.visibleView)
this._applicationCacheView.updateNetworkState(isNowOnline);
},

updateManifest: function(manifest)
{
if (this._applicationCacheView && this._applicationCacheView === this.visibleView)
this._applicationCacheView.updateManifest(manifest);
},

_domStorageForId: function(storageId)
{
if (!this._domStorage)
return null;
var domStorageLength = this._domStorage.length;
for (var i = 0; i < domStorageLength; ++i) {
var domStorage = this._domStorage[i];
if (domStorage.id == storageId)
return domStorage;
}
return null;
},

updateMainViewWidth: function(width)
{
this.storageViews.style.left = width + "px";
this.storageViewStatusBarItemsContainer.style.left = width + "px";
this.resize();
},

performSearch: function(query) 
{
this._resetSearchResults();
var regex = WebInspector.SourceFrame.createSearchRegex(query);
var totalMatchesCount = 0;

function searchInEditedResource(treeElement)
{
var resource = treeElement.representedObject;
if (resource.history.length == 0)
return;
var matchesCount = countRegexMatches(regex, resource.content)
treeElement.searchMatchesFound(matchesCount);
totalMatchesCount += matchesCount;
}

function callback(error, result)
{
if (!error) {
for (var i = 0; i < result.length; i++) {
var searchResult = result[i];
var frameTreeElement = this._treeElementForFrameId[searchResult.frameId];
if (!frameTreeElement)
continue;
var resource = frameTreeElement.resourceByURL(searchResult.url);

if (resource.history.length > 0)
continue; 
this._findTreeElementForResource(resource).searchMatchesFound(searchResult.matchesCount);
totalMatchesCount += searchResult.matchesCount;
}
}

WebInspector.searchController.updateSearchMatchesCount(totalMatchesCount, this);
this._searchController = new WebInspector.ResourcesSearchController(this.resourcesListTreeElement);

if (this.sidebarTree.selectedTreeElement && this.sidebarTree.selectedTreeElement.searchMatchesCount)
this.jumpToNextSearchResult();
}

this._forAllResourceTreeElements(searchInEditedResource.bind(this));
PageAgent.searchInResources(regex.source, !regex.ignoreCase, true, callback.bind(this));            
},

_ensureViewSearchPerformed: function(callback)
{
function viewSearchPerformedCallback(searchId)
{
if (searchId !== this._lastViewSearchId)
return; 
this._viewSearchInProgress = false;
callback();
}

if (!this._viewSearchInProgress) {
if (!this.visibleView.hasSearchResults()) {

this._lastViewSearchId = this._lastViewSearchId ? this._lastViewSearchId + 1 : 0;
this._viewSearchInProgress = true;
this.visibleView.performSearch(this.currentQuery, viewSearchPerformedCallback.bind(this, this._lastViewSearchId));
} else
callback();
}
},

_showSearchResult: function(searchResult)
{
this._lastSearchResultIndex = searchResult.index;
this._lastSearchResultTreeElement = searchResult.treeElement;


if (searchResult.treeElement !== this.sidebarTree.selectedTreeElement) {
this.showResource(searchResult.treeElement.representedObject);
WebInspector.searchController.focusSearchField();
}

function callback(searchId)
{
if (this.sidebarTree.selectedTreeElement !== this._lastSearchResultTreeElement)
return; 
if (this._lastSearchResultIndex != -1)
this.visibleView.jumpToSearchResult(this._lastSearchResultIndex);
}


this._ensureViewSearchPerformed(callback.bind(this));
},

_resetSearchResults: function()
{
function callback(resourceTreeElement)
{
resourceTreeElement._resetSearchResults();
}

this._forAllResourceTreeElements(callback);
if (this.visibleView && this.visibleView.searchCanceled)
this.visibleView.searchCanceled();

this._lastSearchResultTreeElement = null;
this._lastSearchResultIndex = -1;
this._viewSearchInProgress = false;
},

searchCanceled: function()
{
function callback(resourceTreeElement)
{
resourceTreeElement._updateErrorsAndWarningsBubbles();
}

WebInspector.searchController.updateSearchMatchesCount(0, this);
this._resetSearchResults();
this._forAllResourceTreeElements(callback);
},

jumpToNextSearchResult: function()
{
if (!this.currentSearchMatches)
return;
var currentTreeElement = this.sidebarTree.selectedTreeElement;
var nextSearchResult = this._searchController.nextSearchResult(currentTreeElement);
this._showSearchResult(nextSearchResult);
},

jumpToPreviousSearchResult: function()
{
if (!this.currentSearchMatches)
return;
var currentTreeElement = this.sidebarTree.selectedTreeElement;
var previousSearchResult = this._searchController.previousSearchResult(currentTreeElement);
this._showSearchResult(previousSearchResult);
},

_forAllResourceTreeElements: function(callback)
{
var stop = false;
for (var treeElement = this.resourcesListTreeElement; !stop && treeElement; treeElement = treeElement.traverseNextTreeElement(false, this.resourcesListTreeElement, true)) {
if (treeElement instanceof WebInspector.FrameResourceTreeElement)
stop = callback(treeElement);
}
},

_findTreeElementForResource: function(resource)
{
function isAncestor(ancestor, object)
{

return false;
}

function getParent(object)
{

return null;
}

return this.sidebarTree.findTreeElement(resource, isAncestor, getParent);
},

_findTreeElementForRevision: function(revision)
{
function isAncestor(ancestor, object)
{
return false;
}

function getParent(object)
{
return null;
}

return this.sidebarTree.findTreeElement(revision, isAncestor, getParent);
},

showView: function(view)
{
if (view)
this.showResource(view.resource);
},

_onmousemove: function(event)
{
var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
if (!nodeUnderMouse)
return;

var listNode = nodeUnderMouse.enclosingNodeOrSelfWithNodeName("li");
if (!listNode)
return;

var element = listNode.treeElement;
if (this._previousHoveredElement === element)
return;

if (this._previousHoveredElement) {
this._previousHoveredElement.hovered = false;
delete this._previousHoveredElement;
}

if (element instanceof WebInspector.FrameTreeElement) {
this._previousHoveredElement = element;
element.hovered = true;
}
},

_onmouseout: function(event)
{
if (this._previousHoveredElement) {
this._previousHoveredElement.hovered = false;
delete this._previousHoveredElement;
}
}
}

WebInspector.ResourcesPanel.prototype.__proto__ = WebInspector.Panel.prototype;

WebInspector.BaseStorageTreeElement = function(storagePanel, representedObject, title, iconClasses, hasChildren, noIcon)
{
TreeElement.call(this, "", representedObject, hasChildren);
this._storagePanel = storagePanel;
this._titleText = title;
this._iconClasses = iconClasses;
this._noIcon = noIcon;
}

WebInspector.BaseStorageTreeElement.prototype = {
onattach: function()
{
this.listItemElement.removeChildren();
if (this._iconClasses) {
for (var i = 0; i < this._iconClasses.length; ++i)
this.listItemElement.addStyleClass(this._iconClasses[i]);
}

var selectionElement = document.createElement("div");
selectionElement.className = "selection";
this.listItemElement.appendChild(selectionElement);

if (!this._noIcon) {
this.imageElement = document.createElement("img");
this.imageElement.className = "icon";
this.listItemElement.appendChild(this.imageElement);
}

this.titleElement = document.createElement("div");
this.titleElement.className = "base-storage-tree-element-title";
this.titleElement.textContent = this._titleText;
this.listItemElement.appendChild(this.titleElement);
},

onselect: function()
{
var itemURL = this.itemURL;
if (itemURL)
WebInspector.settings.resourcesLastSelectedItem = itemURL;
},

onreveal: function()
{
if (this.listItemElement)
this.listItemElement.scrollIntoViewIfNeeded(false);
},

get titleText()
{
return this._titleText;
},

set titleText(titleText)
{
this._titleText = titleText;
if (this.titleElement)
this.titleElement.textContent = this._titleText;
},

isEventWithinDisclosureTriangle: function()
{



const paddingLeft = 14;
var left = this.listItemElement.totalOffsetLeft + paddingLeft;
return event.pageX >= left && event.pageX <= left + this.arrowToggleWidth && this.hasChildren;
}
}

WebInspector.BaseStorageTreeElement.prototype.__proto__ = TreeElement.prototype;

WebInspector.StorageCategoryTreeElement = function(storagePanel, categoryName, settingsKey, iconClasses, noIcon)
{
WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, categoryName, iconClasses, true, noIcon);
this._expandedSettingKey = "resources" + settingsKey + "Expanded";
WebInspector.settings.installApplicationSetting(this._expandedSettingKey, settingsKey === "Frames");
this._categoryName = categoryName;
}

WebInspector.StorageCategoryTreeElement.prototype = {
get itemURL()
{
return "category://" + this._categoryName;
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
this._storagePanel.showCategoryView(this._categoryName);
},

onattach: function()
{
WebInspector.BaseStorageTreeElement.prototype.onattach.call(this);
if (WebInspector.settings[this._expandedSettingKey])
this.expand();
},

onexpand: function()
{
WebInspector.settings[this._expandedSettingKey] = true;
},

oncollapse: function()
{
WebInspector.settings[this._expandedSettingKey] = false;
}
}

WebInspector.StorageCategoryTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;

WebInspector.FrameTreeElement = function(storagePanel, frame)
{
WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, "", ["frame-storage-tree-item"]);
this._frame = frame;
this.frameNavigated(frame);
}

WebInspector.FrameTreeElement.prototype = {
frameNavigated: function(frame)
{
this.removeChildren();
this._frameId = frame.id;

var title = frame.name;
var subtitle = new WebInspector.Resource(null, frame.url).displayName;
this.setTitles(title, subtitle);

this._categoryElements = {};
this._treeElementForResource = {};

this._storagePanel.addDocumentURL(frame.url);
},

get itemURL()
{
return "frame://" + encodeURI(this._displayName);
},

onattach: function()
{
WebInspector.BaseStorageTreeElement.prototype.onattach.call(this);
if (this._titleToSetOnAttach || this._subtitleToSetOnAttach) {
this.setTitles(this._titleToSetOnAttach, this._subtitleToSetOnAttach);
delete this._titleToSetOnAttach;
delete this._subtitleToSetOnAttach;
}
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
this._storagePanel.showCategoryView(this._displayName);

this.listItemElement.removeStyleClass("hovered");
DOMAgent.hideFrameHighlight();
},

get displayName()
{
return this._displayName;
},

setTitles: function(title, subtitle)
{
this._displayName = title || "";
if (subtitle)
this._displayName += " (" + subtitle + ")";

if (this.parent) {
this.titleElement.textContent = title || "";
if (subtitle) {
var subtitleElement = document.createElement("span");
subtitleElement.className = "base-storage-tree-element-subtitle";
subtitleElement.textContent = "(" + subtitle + ")";
this.titleElement.appendChild(subtitleElement);
}
} else {
this._titleToSetOnAttach = title;
this._subtitleToSetOnAttach = subtitle;
}
},

set hovered(hovered)
{
if (hovered) {
this.listItemElement.addStyleClass("hovered");
DOMAgent.highlightFrame(this._frameId);
} else {
this.listItemElement.removeStyleClass("hovered");
DOMAgent.hideFrameHighlight();
}
},

appendResource: function(resource)
{
if (this._treeElementForResource[resource.url])
return;

var categoryName = resource.category.name;
var categoryElement = resource.category === WebInspector.resourceCategories.documents ? this : this._categoryElements[categoryName];
if (!categoryElement) {
categoryElement = new WebInspector.StorageCategoryTreeElement(this._storagePanel, resource.category.title, categoryName, null, true);
this._categoryElements[resource.category.name] = categoryElement;
this._insertInPresentationOrder(this, categoryElement);
}
var resourceTreeElement = new WebInspector.FrameResourceTreeElement(this._storagePanel, resource);
this._insertInPresentationOrder(categoryElement, resourceTreeElement);
resourceTreeElement._populateRevisions();

this._treeElementForResource[resource.url] = resourceTreeElement;
},

resourceByURL: function(url)
{
return this._treeElementForResource[url].representedObject;
},

appendChild: function(treeElement)
{
this._insertInPresentationOrder(this, treeElement);
},

_insertInPresentationOrder: function(parentTreeElement, childTreeElement)
{

function typeWeight(treeElement)
{
if (treeElement instanceof WebInspector.StorageCategoryTreeElement)
return 2;
if (treeElement instanceof WebInspector.FrameTreeElement)
return 1;
return 3;
}

function compare(treeElement1, treeElement2)
{
var typeWeight1 = typeWeight(treeElement1);
var typeWeight2 = typeWeight(treeElement2);

var result;
if (typeWeight1 > typeWeight2)
result = 1;
else if (typeWeight1 < typeWeight2)
result = -1;
else {
var title1 = treeElement1.displayName || treeElement1.titleText;
var title2 = treeElement2.displayName || treeElement2.titleText;
result = title1.localeCompare(title2);
}
return result;            
}

var children = parentTreeElement.children;
var i;
for (i = 0; i < children.length; ++i) {
if (compare(childTreeElement, children[i]) < 0)
break;
}
parentTreeElement.insertChild(childTreeElement, i);
}
}

WebInspector.FrameTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;

WebInspector.FrameResourceTreeElement = function(storagePanel, resource)
{
WebInspector.BaseStorageTreeElement.call(this, storagePanel, resource, resource.displayName, ["resource-sidebar-tree-item", "resources-category-" + resource.category.name]);
this._resource = resource;
this._resource.addEventListener("errors-warnings-cleared", this._errorsWarningsCleared, this);
this._resource.addEventListener("errors-warnings-message-added", this._errorsWarningsMessageAdded, this);
this._resource.addEventListener(WebInspector.Resource.Events.RevisionAdded, this._revisionAdded, this);
this.tooltip = resource.url;
}

WebInspector.FrameResourceTreeElement.prototype = {
get itemURL()
{
return this._resource.url;
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
this._storagePanel._showResourceView(this._resource);
},

ondblclick: function(event)
{
PageAgent.open(this._resource.url, true);
},

onattach: function()
{
WebInspector.BaseStorageTreeElement.prototype.onattach.call(this);

if (this._resource.category === WebInspector.resourceCategories.images) {
var previewImage = document.createElement("img");
previewImage.className = "image-resource-icon-preview";
this._resource.populateImageSource(previewImage);

var iconElement = document.createElement("div");
iconElement.className = "icon";
iconElement.appendChild(previewImage);
this.listItemElement.replaceChild(iconElement, this.imageElement);
}

this._statusElement = document.createElement("div");
this._statusElement.className = "status";
this.listItemElement.insertBefore(this._statusElement, this.titleElement);

this.listItemElement.draggable = true;
this.listItemElement.addEventListener("dragstart", this._ondragstart.bind(this), false);
this.listItemElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), true);

this._updateErrorsAndWarningsBubbles();
},

_ondragstart: function(event)
{
event.dataTransfer.setData("text/plain", this._resource.content);
event.dataTransfer.effectAllowed = "copy";
return true;
},

_handleContextMenuEvent: function(event)
{
var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendItem(WebInspector.openLinkExternallyLabel(), WebInspector.openResource.bind(WebInspector, this._resource.url, false));
this._appendSaveAsAction(contextMenu, event);
contextMenu.show(event);
},

_appendSaveAsAction: function(contextMenu, event)
{
if (!Preferences.saveAsAvailable)
return;

if (this._resource.type !== WebInspector.Resource.Type.Document &&
this._resource.type !== WebInspector.Resource.Type.Stylesheet &&
this._resource.type !== WebInspector.Resource.Type.Script)
return;

function save()
{
var fileName = this._resource.displayName;
this._resource.requestContent(InspectorFrontendHost.saveAs.bind(InspectorFrontendHost, fileName));
}

contextMenu.appendSeparator();
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save as..." : "Save As..."), save.bind(this));
},

_setBubbleText: function(x)
{
if (!this._bubbleElement) {
this._bubbleElement = document.createElement("div");
this._bubbleElement.className = "bubble";
this._statusElement.appendChild(this._bubbleElement);
}

this._bubbleElement.textContent = x;
},

_resetBubble: function()
{
if (this._bubbleElement) {
this._bubbleElement.textContent = "";
this._bubbleElement.removeStyleClass("search-matches");
this._bubbleElement.removeStyleClass("warning");
this._bubbleElement.removeStyleClass("error");
}
},

_resetSearchResults: function()
{
this._resetBubble();
this._searchMatchesCount = 0;
},

get searchMatchesCount()
{
return this._searchMatchesCount;
},

searchMatchesFound: function(matchesCount)
{
this._resetSearchResults();

this._searchMatchesCount = matchesCount;
this._setBubbleText(matchesCount);
this._bubbleElement.addStyleClass("search-matches");


var currentAncestor = this.parent;
while (currentAncestor && !currentAncestor.root) {
if (!currentAncestor.expanded)
currentAncestor.expand();
currentAncestor = currentAncestor.parent;
}
},

_updateErrorsAndWarningsBubbles: function()
{
if (this._storagePanel.currentQuery)
return;

this._resetBubble();

if (this._resource.warnings || this._resource.errors)
this._setBubbleText(this._resource.warnings + this._resource.errors);

if (this._resource.warnings)
this._bubbleElement.addStyleClass("warning");

if (this._resource.errors)
this._bubbleElement.addStyleClass("error");
},

_errorsWarningsCleared: function()
{

if (this._sourceView)
this._sourceView.clearMessages();

this._updateErrorsAndWarningsBubbles();
},

_errorsWarningsMessageAdded: function(event)
{
var msg = event.data;

if (this._sourceView)
this._sourceView.addMessage(msg);

this._updateErrorsAndWarningsBubbles();
},

_populateRevisions: function()
{
for (var i = 0; i < this._resource.history.length; ++i)
this._appendRevision(this._resource.history[i]);
},

_revisionAdded: function(event)
{
this._appendRevision(event.data);
},

_appendRevision: function(revision)
{
this.insertChild(new WebInspector.ResourceRevisionTreeElement(this._storagePanel, revision), 0);
var oldView = this._sourceView;
if (oldView) {

var newView = this._recreateSourceView();
if (oldView === this._storagePanel.visibleView)
this._storagePanel._showResourceView(this._resource);
}
},

sourceView: function()
{
if (!this._sourceView) {
this._sourceView = this._createSourceView();
if (this._resource.messages) {
for (var i = 0; i < this._resource.messages.length; i++)
this._sourceView.addMessage(this._resource.messages[i]);
}
}
return this._sourceView;
},

_createSourceView: function()
{
return new WebInspector.EditableResourceSourceFrame(this._resource);
},

_recreateSourceView: function()
{
var oldView = this._sourceView;
var newView = this._createSourceView();

var oldViewParentNode = oldView.visible ? oldView.element.parentNode : null;
var scrollTop = oldView.scrollTop;

this._sourceView.detach();
this._sourceView = newView;

if (oldViewParentNode)
newView.show(oldViewParentNode);
if (scrollTop)
newView.scrollTop = scrollTop;

return newView;
}    
}

WebInspector.FrameResourceTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;

WebInspector.DatabaseTreeElement = function(storagePanel, database)
{
WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, database.name, ["database-storage-tree-item"], true);
this._database = database;
}

WebInspector.DatabaseTreeElement.prototype = {
get itemURL()
{
return "database://" + encodeURI(this._database.name);
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
this._storagePanel.showDatabase(this._database);
},

oncollapse: function()
{


this.shouldRefreshChildren = true;
},

onpopulate: function()
{
this.removeChildren();

function tableNamesCallback(tableNames)
{
var tableNamesLength = tableNames.length;
for (var i = 0; i < tableNamesLength; ++i)
this.appendChild(new WebInspector.DatabaseTableTreeElement(this._storagePanel, this._database, tableNames[i]));
}
this._database.getTableNames(tableNamesCallback.bind(this));
}
}

WebInspector.DatabaseTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;

WebInspector.DatabaseTableTreeElement = function(storagePanel, database, tableName)
{
WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, tableName, ["database-storage-tree-item"]);
this._database = database;
this._tableName = tableName;
}

WebInspector.DatabaseTableTreeElement.prototype = {
get itemURL()
{
return "database://" + encodeURI(this._database.name) + "/" + encodeURI(this._tableName);
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
this._storagePanel.showDatabase(this._database, this._tableName);
}
}
WebInspector.DatabaseTableTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;

WebInspector.DOMStorageTreeElement = function(storagePanel, domStorage, className)
{
WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, domStorage.domain ? domStorage.domain : WebInspector.UIString("Local Files"), ["domstorage-storage-tree-item", className]);
this._domStorage = domStorage;
}

WebInspector.DOMStorageTreeElement.prototype = {
get itemURL()
{
return "storage://" + this._domStorage.domain + "/" + (this._domStorage.isLocalStorage ? "local" : "session");
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
this._storagePanel.showDOMStorage(this._domStorage);
}
}
WebInspector.DOMStorageTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;

WebInspector.CookieTreeElement = function(storagePanel, cookieDomain)
{
WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, cookieDomain ? cookieDomain : WebInspector.UIString("Local Files"), ["cookie-storage-tree-item"]);
this._cookieDomain = cookieDomain;
}

WebInspector.CookieTreeElement.prototype = {
get itemURL()
{
return "cookies://" + this._cookieDomain;
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
this._storagePanel.showCookies(this, this._cookieDomain);
}
}
WebInspector.CookieTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;

WebInspector.ApplicationCacheTreeElement = function(storagePanel, appcacheDomain)
{
WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, appcacheDomain ? appcacheDomain : WebInspector.UIString("Local Files"), ["application-cache-storage-tree-item"]);
this._appcacheDomain = appcacheDomain;
}

WebInspector.ApplicationCacheTreeElement.prototype = {
get itemURL()
{
return "appcache://" + this._appcacheDomain;
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
this._storagePanel.showApplicationCache(this, this._appcacheDomain);
}
}
WebInspector.ApplicationCacheTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;

WebInspector.ResourceRevisionTreeElement = function(storagePanel, revision)
{
var title = revision.timestamp ? revision.timestamp.toLocaleTimeString() : WebInspector.UIString("(original)");
WebInspector.BaseStorageTreeElement.call(this, storagePanel, revision, title, ["resource-sidebar-tree-item", "resources-category-" + revision.resource.category.name]);
if (revision.timestamp)
this.tooltip = revision.timestamp.toLocaleString();
this._revision = revision;
}

WebInspector.ResourceRevisionTreeElement.prototype = {
get itemURL()
{
return this._revision.resource.url;
},

onattach: function()
{
WebInspector.BaseStorageTreeElement.prototype.onattach.call(this);
this.listItemElement.draggable = true;
this.listItemElement.addEventListener("dragstart", this._ondragstart.bind(this), false);
this.listItemElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), true);
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
this._storagePanel._showRevisionView(this._revision);
},

_ondragstart: function(event)
{
if (this._revision.content) {
event.dataTransfer.setData("text/plain", this._revision.content);
event.dataTransfer.effectAllowed = "copy";
return true;
}
},

_handleContextMenuEvent: function(event)
{
var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendItem(WebInspector.UIString("Revert to this revision"), this._revision.revertToThis.bind(this._revision));

if (Preferences.saveAsAvailable) {
function save()
{
var fileName = this._revision.resource.displayName;
this._revision.requestContent(InspectorFrontendHost.saveAs.bind(InspectorFrontendHost, fileName));
}
contextMenu.appendSeparator();
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save as..." : "Save As..."), save.bind(this));
}

contextMenu.show(event);
},

sourceView: function()
{
if (!this._sourceView)
this._sourceView = new WebInspector.ResourceRevisionSourceFrame(this._revision);
return this._sourceView;
}
}

WebInspector.ResourceRevisionTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;

WebInspector.StorageCategoryView = function()
{
WebInspector.View.call(this);

this.element.addStyleClass("storage-view");

this._emptyMsgElement = document.createElement("div");
this._emptyMsgElement.className = "storage-empty-view";
this.element.appendChild(this._emptyMsgElement);
}

WebInspector.StorageCategoryView.prototype = {
setText: function(text)
{
this._emptyMsgElement.textContent = text;
}
}

WebInspector.StorageCategoryView.prototype.__proto__ = WebInspector.View.prototype;

WebInspector.ResourcesSearchController = function(rootElement)
{
this._root = rootElement;
this._traverser = new WebInspector.SearchResultsTreeElementsTraverser(rootElement);
this._lastTreeElement = null;
this._lastIndex = -1;
}

WebInspector.ResourcesSearchController.prototype = {
nextSearchResult: function(currentTreeElement)
{
if (!currentTreeElement)
return this._searchResult(this._traverser.first(), 0);

if (!currentTreeElement.searchMatchesCount)
return this._searchResult(this._traverser.next(currentTreeElement), 0);

if (this._lastTreeElement !== currentTreeElement || this._lastIndex === -1)
return this._searchResult(currentTreeElement, 0);

if (this._lastIndex == currentTreeElement.searchMatchesCount - 1)
return this._searchResult(this._traverser.next(currentTreeElement), 0);

return this._searchResult(currentTreeElement, this._lastIndex + 1);
},

previousSearchResult: function(currentTreeElement)
{
if (!currentTreeElement) {
var treeElement = this._traverser.last();
return this._searchResult(treeElement, treeElement.searchMatchesCount - 1);            
}

if (currentTreeElement.searchMatchesCount && this._lastTreeElement === currentTreeElement && this._lastIndex > 0)
return this._searchResult(currentTreeElement, this._lastIndex - 1);

var treeElement = this._traverser.previous(currentTreeElement)
return this._searchResult(treeElement, treeElement.searchMatchesCount - 1);
},

_searchResult: function(treeElement, index)
{
this._lastTreeElement = treeElement;
this._lastIndex = index;
return {treeElement: treeElement, index: index};
}
}

WebInspector.SearchResultsTreeElementsTraverser = function(rootElement)
{
this._root = rootElement;
}

WebInspector.SearchResultsTreeElementsTraverser.prototype = {
first: function()
{
return this.next(this._root);
},

last: function(startTreeElement)
{
return this.previous(this._root);    
},

next: function(startTreeElement)
{
var treeElement = startTreeElement;
do {
treeElement = this._traverseNext(treeElement) || this._root;
} while (treeElement != startTreeElement && !this._elementHasSearchResults(treeElement));
return treeElement;
},

previous: function(startTreeElement)
{
var treeElement = startTreeElement;
do {
treeElement = this._traversePrevious(treeElement) || this._lastTreeElement();
} while (treeElement != startTreeElement && !this._elementHasSearchResults(treeElement));
return treeElement;
},

_traverseNext: function(treeElement)
{
return treeElement.traverseNextTreeElement(false, this._root, true);
},

_elementHasSearchResults: function(treeElement)
{
return treeElement instanceof WebInspector.FrameResourceTreeElement && treeElement.searchMatchesCount;
},

_traversePrevious: function(treeElement)
{
return treeElement.traversePreviousTreeElement(false, this._root, true);
},

_lastTreeElement: function()
{
var treeElement = this._root;
var nextTreeElement; 
while (nextTreeElement = this._traverseNext(treeElement))
treeElement = nextTreeElement;
return treeElement;        
}
}





const UserInitiatedProfileName = "org.webkit.profiles.user-initiated";

WebInspector.ProfileType = function(id, name)
{
this._id = id;
this._name = name;
}

WebInspector.ProfileType.URLRegExp = /webkit-profile:\/\/(.+)\/(.+)#([0-9]+)/;

WebInspector.ProfileType.prototype = {
get buttonTooltip()
{
return "";
},

get buttonStyle()
{
return undefined;
},

get buttonCaption()
{
return this.name;
},

get id()
{
return this._id;
},

get name()
{
return this._name;
},

buttonClicked: function()
{
},

viewForProfile: function(profile)
{
if (!profile._profileView)
profile._profileView = this.createView(profile);
return profile._profileView;
},

get welcomeMessage()
{
return "";
},


createView: function(profile)
{
throw new Error("Needs implemented.");
},


createSidebarTreeElementForProfile: function(profile)
{
throw new Error("Needs implemented.");
}
}

WebInspector.ProfilesPanel = function()
{
WebInspector.Panel.call(this, "profiles");

this.createSidebar();

this._profileTypesByIdMap = {};
this._profileTypeButtonsByIdMap = {};

var panelEnablerHeading = WebInspector.UIString("You need to enable profiling before you can use the Profiles panel.");
var panelEnablerDisclaimer = WebInspector.UIString("Enabling profiling will make scripts run slower.");
var panelEnablerButton = WebInspector.UIString("Enable Profiling");
this.panelEnablerView = new WebInspector.PanelEnablerView("profiles", panelEnablerHeading, panelEnablerDisclaimer, panelEnablerButton);
this.panelEnablerView.addEventListener("enable clicked", this._enableProfiling, this);

this.element.appendChild(this.panelEnablerView.element);

this.profileViews = document.createElement("div");
this.profileViews.id = "profile-views";
this.element.appendChild(this.profileViews);

this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
this.enableToggleButton.addEventListener("click", this._toggleProfiling.bind(this), false);

this.clearResultsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear all profiles."), "clear-status-bar-item");
this.clearResultsButton.addEventListener("click", this._clearProfiles.bind(this), false);

this.profileViewStatusBarItemsContainer = document.createElement("div");
this.profileViewStatusBarItemsContainer.className = "status-bar-items";

this.welcomeView = new WebInspector.WelcomeView("profiles", WebInspector.UIString("Welcome to the Profiles panel"));
this.element.appendChild(this.welcomeView.element);

this._profiles = [];
this._profilerEnabled = Preferences.profilerAlwaysEnabled;
this._reset();

this._registerProfileType(new WebInspector.CPUProfileType());
if (Preferences.heapProfilerPresent) {
if (!Preferences.detailedHeapProfiles)
this._registerProfileType(new WebInspector.HeapSnapshotProfileType());
else
this._registerProfileType(new WebInspector.DetailedHeapshotProfileType());
}

InspectorBackend.registerDomainDispatcher("Profiler", new WebInspector.ProfilerDispatcher(this));

if (Preferences.profilerAlwaysEnabled || WebInspector.settings.profilerEnabled)
ProfilerAgent.enable();
else {
function onProfilerEnebled(error, value) {
if (value)
this._profilerWasEnabled();
}
ProfilerAgent.isEnabled(onProfilerEnebled.bind(this));
}
}

WebInspector.ProfilesPanel.prototype = {
get toolbarItemLabel()
{
return WebInspector.UIString("Profiles");
},

get statusBarItems()
{
function clickHandler(profileType, buttonElement)
{
profileType.buttonClicked.call(profileType);
this.updateProfileTypeButtons();
}

var items = [this.enableToggleButton.element];

for (var typeId in this._profileTypesByIdMap) {
var profileType = this.getProfileType(typeId);
if (profileType.buttonStyle) {
var button = new WebInspector.StatusBarButton(profileType.buttonTooltip, profileType.buttonStyle, profileType.buttonCaption);
this._profileTypeButtonsByIdMap[typeId] = button.element;
button.element.addEventListener("click", clickHandler.bind(this, profileType, button.element), false);
items.push(button.element);
}
}
items.push(this.clearResultsButton.element, this.profileViewStatusBarItemsContainer);
return items;
},

show: function()
{
WebInspector.Panel.prototype.show.call(this);
this._populateProfiles();
},

_profilerWasEnabled: function()
{
if (this._profilerEnabled)
return;

this._profilerEnabled = true;

this._reset();
if (this.visible)
this._populateProfiles();
},

_profilerWasDisabled: function()
{
if (!this._profilerEnabled)
return;

this._profilerEnabled = false;
this._reset();
},

_reset: function()
{
WebInspector.Panel.prototype.reset.call(this);

for (var i = 0; i < this._profiles.length; ++i) {
var view = this._profiles[i]._profileView;
if (view && ("dispose" in view))
view.dispose();
delete this._profiles[i]._profileView;
}
delete this.visibleView;

delete this.currentQuery;
this.searchCanceled();

this._profiles = [];
this._profilesIdMap = {};
this._profileGroups = {};
this._profileGroupsForLinks = {};
this._profilesWereRequested = false;

this.sidebarTreeElement.removeStyleClass("some-expandable");

for (var typeId in this._profileTypesByIdMap)
this.getProfileType(typeId).treeElement.removeChildren();

this.profileViews.removeChildren();

this.profileViewStatusBarItemsContainer.removeChildren();

this.removeAllListeners();

this._updateInterface();
this.welcomeView.show();
},

_clearProfiles: function()
{
ProfilerAgent.clearProfiles();
this._reset();
},

_registerProfileType: function(profileType)
{
this._profileTypesByIdMap[profileType.id] = profileType;
profileType.treeElement = new WebInspector.SidebarSectionTreeElement(profileType.name, null, true);
this.sidebarTree.appendChild(profileType.treeElement);
profileType.treeElement.expand();
this._addWelcomeMessage(profileType);
},

_addWelcomeMessage: function(profileType)
{
var message = profileType.welcomeMessage;



var buttonPos = message.indexOf("%s");
if (buttonPos > -1) {
var container = document.createDocumentFragment();
var part1 = document.createElement("span");
part1.textContent = message.substr(0, buttonPos);
container.appendChild(part1);

var button = new WebInspector.StatusBarButton(profileType.buttonTooltip, profileType.buttonStyle, profileType.buttonCaption);
container.appendChild(button.element);

var part2 = document.createElement("span");
part2.textContent = message.substr(buttonPos + 2);
container.appendChild(part2);
this.welcomeView.addMessage(container);
} else
this.welcomeView.addMessage(message);
},

_makeKey: function(text, profileTypeId)
{
return escape(text) + '/' + escape(profileTypeId);
},

_addProfileHeader: function(profile)
{
if (this.hasTemporaryProfile(profile.typeId)) {
if (profile.typeId === WebInspector.CPUProfileType.TypeId)
this._removeProfileHeader(this._temporaryRecordingProfile);
else
this._removeProfileHeader(this._temporaryTakingSnapshot);
}

var typeId = profile.typeId;
var profileType = this.getProfileType(typeId);
var sidebarParent = profileType.treeElement;
var small = false;
var alternateTitle;

profile.__profilesPanelProfileType = profileType;
this._profiles.push(profile);
this._profilesIdMap[this._makeKey(profile.uid, typeId)] = profile;

if (profile.title.indexOf(UserInitiatedProfileName) !== 0) {
var profileTitleKey = this._makeKey(profile.title, typeId);
if (!(profileTitleKey in this._profileGroups))
this._profileGroups[profileTitleKey] = [];

var group = this._profileGroups[profileTitleKey];
group.push(profile);

if (group.length === 2) {

group._profilesTreeElement = new WebInspector.ProfileGroupSidebarTreeElement(profile.title);


var index = sidebarParent.children.indexOf(group[0]._profilesTreeElement);
sidebarParent.insertChild(group._profilesTreeElement, index);


var selected = group[0]._profilesTreeElement.selected;
sidebarParent.removeChild(group[0]._profilesTreeElement);
group._profilesTreeElement.appendChild(group[0]._profilesTreeElement);
if (selected) {
group[0]._profilesTreeElement.select();
group[0]._profilesTreeElement.reveal();
}

group[0]._profilesTreeElement.small = true;
group[0]._profilesTreeElement.mainTitle = WebInspector.UIString("Run %d", 1);

this.sidebarTreeElement.addStyleClass("some-expandable");
}

if (group.length >= 2) {
sidebarParent = group._profilesTreeElement;
alternateTitle = WebInspector.UIString("Run %d", group.length);
small = true;
}
}

var profileTreeElement = profileType.createSidebarTreeElementForProfile(profile);
profile.sideBarElement = profileTreeElement;
profileTreeElement.small = small;
if (alternateTitle)
profileTreeElement.mainTitle = alternateTitle;
profile._profilesTreeElement = profileTreeElement;

sidebarParent.appendChild(profileTreeElement);
if (!profile.isTemporary) {
this.welcomeView.hide();
if (!this.visibleView)
this.showProfile(profile);
this.dispatchEventToListeners("profile added");
}
},

_removeProfileHeader: function(profile)
{
var typeId = profile.typeId;
var profileType = this.getProfileType(typeId);
var sidebarParent = profileType.treeElement;

for (var i = 0; i < this._profiles.length; ++i) {
if (this._profiles[i].uid === profile.uid) {
profile = this._profiles[i];
this._profiles.splice(i, 1);
break;
}
}
delete this._profilesIdMap[this._makeKey(profile.uid, typeId)];

var profileTitleKey = this._makeKey(profile.title, typeId);
delete this._profileGroups[profileTitleKey];

sidebarParent.removeChild(profile._profilesTreeElement);

if (!profile.isTemporary)
ProfilerAgent.removeProfile(profile.typeId, profile.uid);



if (!this._profiles.length)
this.closeVisibleView();
},

showProfile: function(profile)
{
if (!profile || profile.isTemporary)
return;

this.closeVisibleView();

var view = profile.__profilesPanelProfileType.viewForProfile(profile);

view.show(this.profileViews);

profile._profilesTreeElement.select(true);
profile._profilesTreeElement.reveal();

this.visibleView = view;

this.profileViewStatusBarItemsContainer.removeChildren();

var statusBarItems = view.statusBarItems;
if (statusBarItems)
for (var i = 0; i < statusBarItems.length; ++i)
this.profileViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
},

getProfiles: function(typeId)
{
var result = [];
var profilesCount = this._profiles.length;
for (var i = 0; i < profilesCount; ++i) {
var profile = this._profiles[i];
if (!profile.isTemporary && profile.typeId === typeId)
result.push(profile);
}
return result;
},

hasTemporaryProfile: function(typeId)
{
var profilesCount = this._profiles.length;
for (var i = 0; i < profilesCount; ++i)
if (this._profiles[i].typeId === typeId && this._profiles[i].isTemporary)
return true;
return false;
},

hasProfile: function(profile)
{
return !!this._profilesIdMap[this._makeKey(profile.uid, profile.typeId)];
},

getProfile: function(typeId, uid)
{
return this._profilesIdMap[this._makeKey(uid, typeId)];
},

loadHeapSnapshot: function(uid, callback)
{
var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)];
if (!profile)
return;

if (!Preferences.detailedHeapProfiles) {
if (profile._loaded)
callback(profile);
else if (profile._is_loading)
profile._callbacks.push(callback);
else {
profile._is_loading = true;
profile._callbacks = [callback];
profile._json = "";
profile.sideBarElement.subtitle = WebInspector.UIString("Loading\u2026");
ProfilerAgent.getProfile(profile.typeId, profile.uid);
}
} else {
if (!profile.proxy)
profile.proxy = (new WebInspector.HeapSnapshotWorker()).createObject("WebInspector.HeapSnapshotLoader");
var proxy = profile.proxy;
if (proxy.startLoading(callback)) {
profile.sideBarElement.subtitle = WebInspector.UIString("Loading\u2026");
ProfilerAgent.getProfile(profile.typeId, profile.uid);
}
}
},

_addHeapSnapshotChunk: function(uid, chunk)
{
var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)];
if (!profile)
return;
if (!Preferences.detailedHeapProfiles) {
if (profile._loaded || !profile._is_loading)
return;
profile._json += chunk;
} else {
if (!profile.proxy)
return;
profile.proxy.pushJSONChunk(chunk);
}
},

_finishHeapSnapshot: function(uid)
{
var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)];
if (!profile)
return;
if (!Preferences.detailedHeapProfiles) {
if (profile._loaded || !profile._is_loading)
return;
profile.sideBarElement.subtitle = WebInspector.UIString("Parsing\u2026");
function doParse()
{
var loadedSnapshot = JSON.parse(profile._json);
var callbacks = profile._callbacks;
delete profile._callbacks;
delete profile._json;
delete profile._is_loading;
profile._loaded = true;
profile.sideBarElement.subtitle = "";

if (WebInspector.DetailedHeapshotView.prototype.isDetailedSnapshot(loadedSnapshot)) {
WebInspector.panels.profiles._enableDetailedHeapProfiles(false);
return;
}

WebInspector.HeapSnapshotView.prototype.processLoadedSnapshot(profile, loadedSnapshot);
for (var i = 0; i < callbacks.length; ++i)
callbacks[i](profile);
}
setTimeout(doParse, 0);
} else {
if (!profile.proxy)
return;
var proxy = profile.proxy;
function parsed(snapshotProxy)
{
profile.proxy = snapshotProxy;
profile.sideBarElement.subtitle = Number.bytesToString(snapshotProxy.totalSize);
}
if (proxy.finishLoading(parsed))
profile.sideBarElement.subtitle = WebInspector.UIString("Parsing\u2026");
}
},

showView: function(view)
{
this.showProfile(view.profile);
},

getProfileType: function(typeId)
{
return this._profileTypesByIdMap[typeId];
},

showProfileForURL: function(url)
{
var match = url.match(WebInspector.ProfileType.URLRegExp);
if (!match)
return;
this.showProfile(this._profilesIdMap[this._makeKey(match[3], match[1])]);
},

updateProfileTypeButtons: function()
{
for (var typeId in this._profileTypeButtonsByIdMap) {
var buttonElement = this._profileTypeButtonsByIdMap[typeId];
var profileType = this.getProfileType(typeId);
buttonElement.className = profileType.buttonStyle;
buttonElement.title = profileType.buttonTooltip;

}
},

closeVisibleView: function()
{
if (this.visibleView)
this.visibleView.hide();
delete this.visibleView;
},

displayTitleForProfileLink: function(title, typeId)
{
title = unescape(title);
if (title.indexOf(UserInitiatedProfileName) === 0) {
title = WebInspector.UIString("Profile %d", title.substring(UserInitiatedProfileName.length + 1));
} else {
var titleKey = this._makeKey(title, typeId);
if (!(titleKey in this._profileGroupsForLinks))
this._profileGroupsForLinks[titleKey] = 0;

var groupNumber = ++this._profileGroupsForLinks[titleKey];

if (groupNumber > 2)


title += " " + WebInspector.UIString("Run %d", (groupNumber + 1) / 2);
}

return title;
},

get searchableViews()
{
var views = [];

const visibleView = this.visibleView;
if (visibleView && visibleView.performSearch)
views.push(visibleView);

var profilesLength = this._profiles.length;
for (var i = 0; i < profilesLength; ++i) {
var profile = this._profiles[i];
var view = profile.__profilesPanelProfileType.viewForProfile(profile);
if (!view.performSearch || view === visibleView)
continue;
views.push(view);
}

return views;
},

searchMatchFound: function(view, matches)
{
view.profile._profilesTreeElement.searchMatches = matches;
},

searchCanceled: function(startingNewSearch)
{
WebInspector.Panel.prototype.searchCanceled.call(this, startingNewSearch);

if (!this._profiles)
return;

for (var i = 0; i < this._profiles.length; ++i) {
var profile = this._profiles[i];
profile._profilesTreeElement.searchMatches = 0;
}
},

_updateInterface: function()
{

if (this._profilerEnabled) {
this.enableToggleButton.title = WebInspector.UIString("Profiling enabled. Click to disable.");
this.enableToggleButton.toggled = true;
for (var typeId in this._profileTypeButtonsByIdMap)
this._profileTypeButtonsByIdMap[typeId].removeStyleClass("hidden");
this.profileViewStatusBarItemsContainer.removeStyleClass("hidden");
this.clearResultsButton.element.removeStyleClass("hidden");
this.panelEnablerView.visible = false;
} else {
this.enableToggleButton.title = WebInspector.UIString("Profiling disabled. Click to enable.");
this.enableToggleButton.toggled = false;
for (var typeId in this._profileTypeButtonsByIdMap)
this._profileTypeButtonsByIdMap[typeId].addStyleClass("hidden");
this.profileViewStatusBarItemsContainer.addStyleClass("hidden");
this.clearResultsButton.element.addStyleClass("hidden");
this.panelEnablerView.visible = true;
}
},

_enableProfiling: function()
{
if (this._profilerEnabled)
return;
this._toggleProfiling(this.panelEnablerView.alwaysEnabled);
},

_toggleProfiling: function(optionalAlways)
{
if (this._profilerEnabled) {
WebInspector.settings.profilerEnabled = false;
ProfilerAgent.disable();
} else {
WebInspector.settings.profilerEnabled = !!optionalAlways;
ProfilerAgent.enable();
}
},

_populateProfiles: function()
{
if (!this._profilerEnabled || this._profilesWereRequested)
return;

function populateCallback(error, profileHeaders) {
if (error)
return;
profileHeaders.sort(function(a, b) { return a.uid - b.uid; });
var profileHeadersLength = profileHeaders.length;
for (var i = 0; i < profileHeadersLength; ++i)
if (!this.hasProfile(profileHeaders[i]))
this._addProfileHeader(profileHeaders[i]);
}

ProfilerAgent.getProfileHeaders(populateCallback.bind(this));

this._profilesWereRequested = true;
},

updateMainViewWidth: function(width)
{
this.welcomeView.element.style.left = width + "px";
this.profileViews.style.left = width + "px";
this.profileViewStatusBarItemsContainer.style.left = Math.max(155, width) + "px";
this.resize();
},

_setRecordingProfile: function(isProfiling)
{
this.getProfileType(WebInspector.CPUProfileType.TypeId).setRecordingProfile(isProfiling);
if (this.hasTemporaryProfile(WebInspector.CPUProfileType.TypeId) !== isProfiling) {
if (!this._temporaryRecordingProfile) {
this._temporaryRecordingProfile = {
typeId: WebInspector.CPUProfileType.TypeId,
title: WebInspector.UIString("Recording…"),
uid: -1,
isTemporary: true
};
}
if (isProfiling)
this._addProfileHeader(this._temporaryRecordingProfile);
else
this._removeProfileHeader(this._temporaryRecordingProfile);
}
this.updateProfileTypeButtons();
},

takeHeapSnapshot: function(detailed)
{
if (!this.hasTemporaryProfile(WebInspector.HeapSnapshotProfileType.TypeId)) {
if (!this._temporaryTakingSnapshot) {
this._temporaryTakingSnapshot = {
typeId: WebInspector.HeapSnapshotProfileType.TypeId,
title: WebInspector.UIString("Snapshotting…"),
uid: -1,
isTemporary: true
};
}
this._addProfileHeader(this._temporaryTakingSnapshot);
}
ProfilerAgent.takeHeapSnapshot(detailed);
},

_reportHeapSnapshotProgress: function(done, total)
{
if (this.hasTemporaryProfile(WebInspector.HeapSnapshotProfileType.TypeId)) {
this._temporaryTakingSnapshot.sideBarElement.subtitle = WebInspector.UIString("%.2f%%", (done / total) * 100);
if (done >= total)
this._removeProfileHeader(this._temporaryTakingSnapshot);
}
},

_enableDetailedHeapProfiles: function(resetAgent)
{
if (resetAgent)
this._clearProfiles();
else
this._reset();
var oldProfileType = this._profileTypesByIdMap[WebInspector.HeapSnapshotProfileType.TypeId];
var profileType = new WebInspector.DetailedHeapshotProfileType();
profileType.treeElement = oldProfileType.treeElement;
this._profileTypesByIdMap[profileType.id] = profileType;
Preferences.detailedHeapProfiles = true;
this.hide();
this.show();
}
}

WebInspector.ProfilesPanel.prototype.__proto__ = WebInspector.Panel.prototype;


WebInspector.ProfilerDispatcher = function(profiler)
{
this._profiler = profiler;
}

WebInspector.ProfilerDispatcher.prototype = {
profilerWasEnabled: function()
{
this._profiler._profilerWasEnabled();
},

profilerWasDisabled: function()
{
this._profiler._profilerWasDisabled();
},

resetProfiles: function()
{
this._profiler._reset();
},

addProfileHeader: function(profile)
{
this._profiler._addProfileHeader(profile);
},

addHeapSnapshotChunk: function(uid, chunk)
{
this._profiler._addHeapSnapshotChunk(uid, chunk);
},

finishHeapSnapshot: function(uid)
{
this._profiler._finishHeapSnapshot(uid);
},

setRecordingProfile: function(isProfiling)
{
this._profiler._setRecordingProfile(isProfiling);
},

reportHeapSnapshotProgress: function(done, total)
{
this._profiler._reportHeapSnapshotProgress(done, total);
}
}

WebInspector.ProfileSidebarTreeElement = function(profile, titleFormat, className)
{
this.profile = profile;
this._titleFormat = titleFormat;

if (this.profile.title.indexOf(UserInitiatedProfileName) === 0)
this._profileNumber = this.profile.title.substring(UserInitiatedProfileName.length + 1);

WebInspector.SidebarTreeElement.call(this, className, "", "", profile, false);

this.refreshTitles();
}

WebInspector.ProfileSidebarTreeElement.prototype = {
onselect: function()
{
this.treeOutline.panel.showProfile(this.profile);
},

ondelete: function()
{
this.treeOutline.panel._removeProfileHeader(this.profile);
return true;
},

get mainTitle()
{
if (this._mainTitle)
return this._mainTitle;
if (this.profile.title.indexOf(UserInitiatedProfileName) === 0)
return WebInspector.UIString(this._titleFormat, this._profileNumber);
return this.profile.title;
},

set mainTitle(x)
{
this._mainTitle = x;
this.refreshTitles();
},

set searchMatches(matches)
{
if (!matches) {
if (!this.bubbleElement)
return;
this.bubbleElement.removeStyleClass("search-matches");
this.bubbleText = "";
return;
}

this.bubbleText = matches;
this.bubbleElement.addStyleClass("search-matches");
}
}

WebInspector.ProfileSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;

WebInspector.ProfileGroupSidebarTreeElement = function(title, subtitle)
{
WebInspector.SidebarTreeElement.call(this, "profile-group-sidebar-tree-item", title, subtitle, null, true);
}

WebInspector.ProfileGroupSidebarTreeElement.prototype = {
onselect: function()
{
if (this.children.length > 0)
WebInspector.panels.profiles.showProfile(this.children[this.children.length - 1].profile);
}
}

WebInspector.ProfileGroupSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;





WebInspector.ConsolePanel = function()
{
WebInspector.Panel.call(this, "console");
WebInspector.console.addEventListener(WebInspector.ConsoleView.Events.EntryAdded, this._consoleMessageAdded, this);
WebInspector.console.addEventListener(WebInspector.ConsoleView.Events.ConsoleCleared, this._consoleCleared, this);
}

WebInspector.ConsolePanel.prototype = {
get toolbarItemLabel()
{
return WebInspector.UIString("Console");
},

show: function()
{
WebInspector.Panel.prototype.show.call(this);

this._previousConsoleState = WebInspector.drawer.state;
WebInspector.drawer.enterPanelMode();
WebInspector.showConsole();


var scopeBar = document.getElementById("console-filter");
var consoleMessages = document.getElementById("console-messages");

scopeBar.parentNode.removeChild(scopeBar);
document.getElementById("console-view").insertBefore(scopeBar, consoleMessages);


scopeBar.addStyleClass("console-filter-top");
scopeBar.removeStyleClass("status-bar-item");

consoleMessages.addStyleClass("console-filter-top");
},

hide: function()
{
WebInspector.Panel.prototype.hide.call(this);

if (this._previousConsoleState === WebInspector.Drawer.State.Hidden)
WebInspector.drawer.immediatelyExitPanelMode();
else
WebInspector.drawer.exitPanelMode();
delete this._previousConsoleState;


var scopeBar = document.getElementById("console-filter");

scopeBar.parentNode.removeChild(scopeBar);
document.getElementById("other-drawer-status-bar-items").appendChild(scopeBar);


scopeBar.removeStyleClass("console-filter-top");
scopeBar.addStyleClass("status-bar-item");

document.getElementById("console-messages").removeStyleClass("console-filter-top");
},

searchCanceled: function()
{
this._clearCurrentSearchResultHighlight();
delete this._searchResults;
delete this._searchRegex;
},

performSearch: function(query)
{
WebInspector.searchController.updateSearchMatchesCount(0, this);
this.searchCanceled();
this._searchRegex = createSearchRegex(query, "g");

this._searchResults = [];
var messages = WebInspector.console.messages;
for (var i = 0; i < messages.length; i++) {
if (messages[i].matchesRegex(this._searchRegex)) {
this._searchResults.push(messages[i]);
this._searchRegex.lastIndex = 0;
}
}
WebInspector.searchController.updateSearchMatchesCount(this._searchResults.length, this);
this._currentSearchResultIndex = -1;
if (this._searchResults.length)
this._jumpToSearchResult(0);
},

jumpToNextSearchResult: function()
{
if (!this._searchResults || !this._searchResults.length)
return;
this._jumpToSearchResult((this._currentSearchResultIndex + 1) % this._searchResults.length);
},

jumpToPreviousSearchResult: function()
{
if (!this._searchResults || !this._searchResults.length)
return;
var index = this._currentSearchResultIndex - 1;
if (index === -1)
index = this._searchResults.length - 1;
this._jumpToSearchResult(index);
},

_clearCurrentSearchResultHighlight: function()
{
if (!this._searchResults)
return;
var highlightedMessage = this._searchResults[this._currentSearchResultIndex];
if (highlightedMessage)
highlightedMessage.clearHighlight();
this._currentSearchResultIndex = -1;
},

_jumpToSearchResult: function(index)
{
this._clearCurrentSearchResultHighlight();
this._currentSearchResultIndex = index;
this._searchResults[index].highlightSearchResults(this._searchRegex);
},

_consoleMessageAdded: function(event)
{
if (!this._searchRegex || !this.visible)
return;
var message = event.data;
this._searchRegex.lastIndex = 0;
if (message.matchesRegex(this._searchRegex)) {
this._searchResults.push(message);
WebInspector.searchController.updateSearchMatchesCount(this._searchResults.length, this);
}
},

_consoleCleared: function()
{
if (!this._searchResults)
return;
this._clearCurrentSearchResultHighlight();
this._searchResults.length = 0;
if (this.visible)
WebInspector.searchController.updateSearchMatchesCount(0, this);
}
}

WebInspector.ConsolePanel.prototype.__proto__ = WebInspector.Panel.prototype;





WebInspector.injectedExtensionAPI = function(InjectedScriptHost, inspectedWindow, injectedScriptId)
{







function EventSinkImpl(type, customDispatch)
{
this._type = type;
this._listeners = [];
this._customDispatch = customDispatch;
}

EventSinkImpl.prototype = {
addListener: function(callback)
{
if (typeof callback != "function")
throw new "addListener: callback is not a function";
if (this._listeners.length === 0)
extensionServer.sendRequest({ command: "subscribe", type: this._type });
this._listeners.push(callback);
extensionServer.registerHandler("notify-" + this._type, bind(this._dispatch, this));
},

removeListener: function(callback)
{
var listeners = this._listeners;

for (var i = 0; i < listeners.length; ++i) {
if (listeners[i] === callback) {
listeners.splice(i, 1);
break;
}
}
if (this._listeners.length === 0)
extensionServer.sendRequest({ command: "unsubscribe", type: this._type });
},

_fire: function()
{
var listeners = this._listeners.slice();
for (var i = 0; i < listeners.length; ++i)
listeners[i].apply(null, arguments);
},

_dispatch: function(request)
{
if (this._customDispatch)
this._customDispatch.call(this, request);
else
this._fire.apply(this, request.arguments);
}
}

function InspectorExtensionAPI()
{
this.audits = new Audits();
this.inspectedWindow = new InspectedWindow();
this.panels = new Panels();
this.resources = new Resources();
this.timeline = new Timeline();

this.onReset = new EventSink("reset");
}

InspectorExtensionAPI.prototype = {
log: function(message)
{
extensionServer.sendRequest({ command: "log", message: message });
}
}

function Resources()
{
function resourceDispatch(request)
{
var resource = request.arguments[1];
resource.__proto__ = new Resource(request.arguments[0]);
this._fire(resource);
}
this.onFinished = new EventSink("resource-finished", resourceDispatch);
this.onNavigated = new EventSink("inspectedURLChanged");
}

Resources.prototype = {
getHAR: function(callback)
{
function callbackWrapper(result)
{
var entries = (result && result.entries) || [];
for (var i = 0; i < entries.length; ++i) {
entries[i].__proto__ = new Resource(entries[i]._resourceId);
delete entries[i]._resourceId;
}
callback(result);
}
return extensionServer.sendRequest({ command: "getHAR" }, callback && callbackWrapper);
},

addRequestHeaders: function(headers)
{
return extensionServer.sendRequest({ command: "addRequestHeaders", headers: headers, extensionId: location.hostname });
}
}

function ResourceImpl(id)
{
this._id = id;
}

ResourceImpl.prototype = {
getContent: function(callback)
{
function callbackWrapper(response)
{
callback(response.content, response.encoding);
}
extensionServer.sendRequest({ command: "getResourceContent", id: this._id }, callback && callbackWrapper);
}
};

function Panels()
{
var panels = {
elements: new ElementsPanel()
};

function panelGetter(name)
{
return panels[name];
}
for (var panel in panels)
this.__defineGetter__(panel, bind(panelGetter, null, panel));
}

Panels.prototype = {
create: function(title, iconURL, pageURL, callback)
{
var id = "extension-panel-" + extensionServer.nextObjectId();
var request = {
command: "createPanel",
id: id,
title: title,
icon: expandURL(iconURL),
url: expandURL(pageURL)
};
extensionServer.sendRequest(request, callback && bind(callback, this, new ExtensionPanel(id)));
}
}

function PanelImpl(id)
{
this._id = id;
this.onShown = new EventSink("panel-shown-" + id);
this.onHidden = new EventSink("panel-hidden-" + id);
}

function PanelWithSidebarImpl(id)
{
PanelImpl.call(this, id);
}

PanelWithSidebarImpl.prototype = {
createSidebarPane: function(title, callback)
{
var id = "extension-sidebar-" + extensionServer.nextObjectId();
var request = {
command: "createSidebarPane",
panel: this._id,
id: id,
title: title
};
function callbackWrapper()
{
callback(new ExtensionSidebarPane(id));
}
extensionServer.sendRequest(request, callback && callbackWrapper);
}
}

PanelWithSidebarImpl.prototype.__proto__ = PanelImpl.prototype;

function ElementsPanel()
{
var id = "elements";
PanelWithSidebar.call(this, id);
this.onSelectionChanged = new EventSink("panel-objectSelected-" + id);
}

function ExtensionPanel(id)
{
Panel.call(this, id);
this.onSearch = new EventSink("panel-search-" + id);
}

function ExtensionSidebarPaneImpl(id)
{
this._id = id;
this.onUpdated = new EventSink("sidebar-updated-" + id);
}

ExtensionSidebarPaneImpl.prototype = {
setHeight: function(height)
{
extensionServer.sendRequest({ command: "setSidebarHeight", id: this._id, height: height });
},

setExpression: function(expression, rootTitle)
{
extensionServer.sendRequest({ command: "setSidebarContent", id: this._id, expression: expression, rootTitle: rootTitle, evaluateOnPage: true });
},

setObject: function(jsonObject, rootTitle)
{
extensionServer.sendRequest({ command: "setSidebarContent", id: this._id, expression: jsonObject, rootTitle: rootTitle });
},

setPage: function(url)
{
extensionServer.sendRequest({ command: "setSidebarPage", id: this._id, url: expandURL(url) });
}
}

function Audits()
{
}

Audits.prototype = {
addCategory: function(displayName, resultCount)
{
var id = "extension-audit-category-" + extensionServer.nextObjectId();
extensionServer.sendRequest({ command: "addAuditCategory", id: id, displayName: displayName, resultCount: resultCount });
return new AuditCategory(id);
}
}

function AuditCategoryImpl(id)
{
function auditResultDispatch(request)
{
var auditResult = new AuditResult(request.arguments[0]);
try {
this._fire(auditResult);
} catch (e) {
console.error("Uncaught exception in extension audit event handler: " + e);
auditResult.done();
}
}
this._id = id;
this.onAuditStarted = new EventSink("audit-started-" + id, auditResultDispatch);
}

function AuditResultImpl(id)
{
this._id = id;

var formatterTypes = [
"url",
"snippet",
"text"
];
for (var i = 0; i < formatterTypes.length; ++i)
this[formatterTypes[i]] = bind(this._nodeFactory, null, formatterTypes[i]);
}

AuditResultImpl.prototype = {
addResult: function(displayName, description, severity, details)
{

if (details && !(details instanceof AuditResultNode))
details = details instanceof Array ? this.createNode.apply(this, details) : this.createNode(details);

var request = {
command: "addAuditResult",
resultId: this._id,
displayName: displayName,
description: description,
severity: severity,
details: details
};
extensionServer.sendRequest(request);
},

createResult: function()
{
var node = new AuditResultNode();
node.contents = Array.prototype.slice.call(arguments);
return node;
},

done: function()
{
extensionServer.sendRequest({ command: "stopAuditCategoryRun", resultId: this._id });
},

get Severity()
{
return apiPrivate.audits.Severity;
},

_nodeFactory: function(type)
{
return {
type: type,
arguments: Array.prototype.slice.call(arguments, 1)
};
}
}

function AuditResultNode(contents)
{
this.contents = contents;
this.children = [];
this.expanded = false;
}

AuditResultNode.prototype = {
addChild: function()
{
var node = AuditResultImpl.prototype.createResult.apply(null, arguments);
this.children.push(node);
return node;
}
};

function InspectedWindow()
{
}

InspectedWindow.prototype = {
reload: function(userAgent)
{
return extensionServer.sendRequest({ command: "reload", userAgent: userAgent });
},

eval: function(expression, callback)
{
function callbackWrapper(result)
{
var value = result.value;
if (!result.isException)
value = value === "undefined" ? undefined : JSON.parse(value);
callback(value, result.isException);
}
return extensionServer.sendRequest({ command: "evaluateOnInspectedPage", expression: expression }, callback && callbackWrapper);
}
}

function TimelineImpl()
{
this.onEventRecorded = new EventSink("timeline-event-recorded");
}

function ExtensionServerClient()
{
this._callbacks = {};
this._handlers = {};
this._lastRequestId = 0;
this._lastObjectId = 0;

this.registerHandler("callback", bind(this._onCallback, this));

var channel = new MessageChannel();
this._port = channel.port1;
this._port.addEventListener("message", bind(this._onMessage, this), false);
this._port.start();

top.postMessage("registerExtension", [ channel.port2 ], "*");
}

ExtensionServerClient.prototype = {
sendRequest: function(message, callback)
{
if (typeof callback === "function")
message.requestId = this._registerCallback(callback);
return this._port.postMessage(message);
},

registerHandler: function(command, handler)
{
this._handlers[command] = handler;
},

nextObjectId: function()
{
return injectedScriptId + "_" + ++this._lastObjectId;
},

_registerCallback: function(callback)
{
var id = ++this._lastRequestId;
this._callbacks[id] = callback;
return id;
},

_onCallback: function(request)
{
if (request.requestId in this._callbacks) {
var callback = this._callbacks[request.requestId];
delete this._callbacks[request.requestId];
callback(request.result);
}
},

_onMessage: function(event)
{
var request = event.data;
var handler = this._handlers[request.command];
if (handler)
handler.call(this, request);
}
}

function expandURL(url)
{
if (!url)
return url;
if (/^[^/]+:/.exec(url)) // See if url has schema.
return url;
var baseURL = location.protocol + "//" + location.hostname + location.port;
if (/^\//.exec(url))
return baseURL + url;
return baseURL + location.pathname.replace(/\/[^/]*$/,"/") + url;
}

function bind(func, thisObject)
{
var args = Array.prototype.slice.call(arguments, 2);
return function() { return func.apply(thisObject, args.concat(Array.prototype.slice.call(arguments, 0))); };
}

function populateInterfaceClass(interface, implementation)
{
for (var member in implementation) {
if (member.charAt(0) === "_")
continue;
var value = implementation[member];
interface[member] = typeof value === "function" ? bind(value, implementation)
: interface[member] = implementation[member];
}
}

function declareInterfaceClass(implConstructor)
{
return function()
{
var impl = { __proto__: implConstructor.prototype };
implConstructor.apply(impl, arguments);
populateInterfaceClass(this, impl);
}
}

var AuditCategory = declareInterfaceClass(AuditCategoryImpl);
var AuditResult = declareInterfaceClass(AuditResultImpl);
var EventSink = declareInterfaceClass(EventSinkImpl);
var ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
var Panel = declareInterfaceClass(PanelImpl);
var PanelWithSidebar = declareInterfaceClass(PanelWithSidebarImpl);
var Resource = declareInterfaceClass(ResourceImpl);
var Timeline = declareInterfaceClass(TimelineImpl);

var extensionServer = new ExtensionServerClient();

webInspector = new InspectorExtensionAPI();
experimental = window.experimental || {};
experimental.webInspector = webInspector;

}





WebInspector.ExtensionAuditCategory = function(id, displayName, ruleCount)
{
this._id = id;
this._displayName = displayName;
this._ruleCount  = ruleCount;
}

WebInspector.ExtensionAuditCategory.prototype = {

get id()
{
return this._id;
},

get displayName()
{
return this._displayName;
},

get ruleCount()
{
return this._ruleCount;
},

run: function(resources, callback)
{
new WebInspector.ExtensionAuditCategoryResults(this, callback);
}
}

WebInspector.ExtensionAuditCategoryResults = function(category, callback)
{
this._category = category;
this._pendingRules = category.ruleCount;
this._ruleCompletionCallback = callback;

this.id = category.id + "-" + ++WebInspector.ExtensionAuditCategoryResults._lastId;
WebInspector.extensionServer.startAuditRun(category, this);
}

WebInspector.ExtensionAuditCategoryResults.prototype = {
get complete()
{
return !this._pendingRules;
},

cancel: function()
{
while (!this.complete)
this._addResult(null);
},

addResult: function(displayName, description, severity, details)
{
var result = new WebInspector.AuditRuleResult(displayName);
result.addChild(description);
result.severity = severity;
if (details)
this._addNode(result, details);
this._addResult(result);
},

_addNode: function(parent, node)
{
var addedNode = parent.addChild(node.contents, node.expanded);
if (node.children) {
for (var i = 0; i < node.children.length; ++i)
this._addNode(addedNode, node.children[i]);
}
},

_addResult: function(result)
{
this._ruleCompletionCallback(result);
this._pendingRules--;
if (!this._pendingRules)
WebInspector.extensionServer.stopAuditRun(this);
}
}

WebInspector.ExtensionAuditCategoryResults._lastId = 0;





WebInspector.commonExtensionSymbols = function(apiPrivate)
{

if (!apiPrivate.audits)
apiPrivate.audits = {};

apiPrivate.audits.Severity = {
Info: "info",
Warning: "warning",
Severe: "severe"
};
}

WebInspector.extensionAPI = {};

WebInspector.commonExtensionSymbols(WebInspector.extensionAPI);





WebInspector.ExtensionServer = function()
{
this._clientObjects = {};
this._handlers = {};
this._subscribers = {};
this._subscriptionStartHandlers = {};
this._subscriptionStopHandlers = {};
this._extraHeaders = {};
this._resources = {};
this._lastResourceId = 0;
this._status = new WebInspector.ExtensionStatus();

this._registerHandler("addRequestHeaders", this._onAddRequestHeaders.bind(this));
this._registerHandler("addAuditCategory", this._onAddAuditCategory.bind(this));
this._registerHandler("addAuditResult", this._onAddAuditResult.bind(this));
this._registerHandler("createPanel", this._onCreatePanel.bind(this));
this._registerHandler("createSidebarPane", this._onCreateSidebarPane.bind(this));
this._registerHandler("evaluateOnInspectedPage", this._onEvaluateOnInspectedPage.bind(this));
this._registerHandler("getHAR", this._onGetHAR.bind(this));
this._registerHandler("getResourceContent", this._onGetResourceContent.bind(this));
this._registerHandler("log", this._onLog.bind(this));
this._registerHandler("reload", this._onReload.bind(this));
this._registerHandler("setSidebarHeight", this._onSetSidebarHeight.bind(this));
this._registerHandler("setSidebarContent", this._onSetSidebarContent.bind(this));
this._registerHandler("setSidebarPage", this._onSetSidebarPage.bind(this));
this._registerHandler("stopAuditCategoryRun", this._onStopAuditCategoryRun.bind(this));
this._registerHandler("subscribe", this._onSubscribe.bind(this));
this._registerHandler("unsubscribe", this._onUnsubscribe.bind(this));

this._registerSubscriptionHandler("timeline-event-recorded", WebInspector.timelineManager.start.bind(WebInspector.timelineManager), WebInspector.timelineManager.stop.bind(WebInspector.timelineManager));

window.addEventListener("message", this._onWindowMessage.bind(this), false);

WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded, this._addRecordToTimeline, this);
}

WebInspector.ExtensionServer.prototype = {
_addRecordToTimeline: function(event)
{
this._postNotification("timeline-event-recorded", event.data);
},

notifyObjectSelected: function(panelId, objectId)
{
this._postNotification("panel-objectSelected-" + panelId, objectId);
},

notifySearchAction: function(panelId, action, searchString)
{
this._postNotification("panel-search-" + panelId, action, searchString);
},

notifyPanelShown: function(panelId)
{
this._postNotification("panel-shown-" + panelId);
},

notifyPanelHidden: function(panelId)
{
this._postNotification("panel-hidden-" + panelId);
},

_inspectedURLChanged: function(event)
{
var url = event.data;
this._postNotification("inspectedURLChanged", url);
},

notifyInspectorReset: function()
{
this._postNotification("reset");
},

notifyExtensionSidebarUpdated: function(id)
{
this._postNotification("sidebar-updated-" + id);
},

startAuditRun: function(category, auditRun)
{
this._clientObjects[auditRun.id] = auditRun;
this._postNotification("audit-started-" + category.id, auditRun.id);
},

stopAuditRun: function(auditRun)
{
delete this._clientObjects[auditRun.id];
},

resetResources: function()
{
this._resources = {};
},

_notifyResourceFinished: function(event)
{
var resource = event.data;
if (this._hasSubscribers("resource-finished"))
this._postNotification("resource-finished", this._resourceId(resource), (new WebInspector.HAREntry(resource)).build());
},

_hasSubscribers: function(type)
{
return !!this._subscribers[type];
},

_postNotification: function(type, details)
{
var subscribers = this._subscribers[type];
if (!subscribers)
return;
var message = {
command: "notify-" + type,
arguments: Array.prototype.slice.call(arguments, 1)
};
for (var i = 0; i < subscribers.length; ++i)
subscribers[i].postMessage(message);
},

_onSubscribe: function(message, port)
{
var subscribers = this._subscribers[message.type];
if (subscribers)
subscribers.push(port);
else {
this._subscribers[message.type] = [ port ];
if (this._subscriptionStartHandlers[message.type])
this._subscriptionStartHandlers[message.type]()
}
},

_onUnsubscribe: function(message, port)
{
var subscribers = this._subscribers[message.type];
if (!subscribers)
return;
subscribers.remove(port);
if (!subscribers.length) {
delete this._subscribers[message.type];
if (this._subscriptionStopHandlers[message.type])
this._subscriptionStopHandlers[message.type]()
}
},

_onAddRequestHeaders: function(message)
{
var id = message.extensionId;
if (typeof id !== "string")
return this._status.E_BADARGTYPE("extensionId", typeof id, "string");
var extensionHeaders = this._extraHeaders[id];
if (!extensionHeaders) {
extensionHeaders = {};
this._extraHeaders[id] = extensionHeaders;
}
for (name in message.headers)
extensionHeaders[name] = message.headers[name];
var allHeaders = {};
for (extension in this._extraHeaders) {
var headers = this._extraHeaders[extension];
for (name in headers) {
if (typeof headers[name] === "string")
allHeaders[name] = headers[name];
}
}
NetworkAgent.setExtraHeaders(allHeaders);
},

_onCreatePanel: function(message, port)
{
var id = message.id;


if (id in this._clientObjects || id in WebInspector.panels)
return this._status.E_EXISTS(id);

var panel = new WebInspector.ExtensionPanel(id, message.title, message.icon);
this._clientObjects[id] = panel;
WebInspector.panels[id] = panel;
WebInspector.addPanel(panel);

var iframe = this.createClientIframe(panel.element, message.url);
iframe.style.height = "100%";
return this._status.OK();
},

_onCreateSidebarPane: function(message, constructor)
{
var panel = WebInspector.panels[message.panel];
if (!panel)
return this._status.E_NOTFOUND(message.panel);
if (!panel.sidebarElement || !panel.sidebarPanes)
return this._status.E_NOTSUPPORTED();
var id = message.id;
var sidebar = new WebInspector.ExtensionSidebarPane(message.title, message.id);
this._clientObjects[id] = sidebar;
panel.sidebarPanes[id] = sidebar;
panel.sidebarElement.appendChild(sidebar.element);

return this._status.OK();
},

createClientIframe: function(parent, url)
{
var iframe = document.createElement("iframe");
iframe.src = url;
iframe.style.width = "100%";
parent.appendChild(iframe);
return iframe;
},

_onSetSidebarHeight: function(message)
{
var sidebar = this._clientObjects[message.id];
if (!sidebar)
return this._status.E_NOTFOUND(message.id);
sidebar.bodyElement.firstChild.style.height = message.height;
},

_onSetSidebarContent: function(message)
{
var sidebar = this._clientObjects[message.id];
if (!sidebar)
return this._status.E_NOTFOUND(message.id);
if (message.evaluateOnPage)
sidebar.setExpression(message.expression, message.rootTitle);
else
sidebar.setObject(message.expression, message.rootTitle);
},

_onSetSidebarPage: function(message)
{
var sidebar = this._clientObjects[message.id];
if (!sidebar)
return this._status.E_NOTFOUND(message.id);
sidebar.setPage(message.url);
},

_onLog: function(message)
{
WebInspector.log(message.message);
},

_onReload: function(message)
{
if (typeof message.userAgent === "string")
PageAgent.setUserAgentOverride(message.userAgent);

PageAgent.reload(false);
return this._status.OK();
},

_onEvaluateOnInspectedPage: function(message, port)
{
function callback(error, resultPayload, wasThrown)
{
if (error)
return;
var resultObject = WebInspector.RemoteObject.fromPayload(resultPayload);
var result = {};
if (wasThrown)
result.isException = true;
result.value = resultObject.description;
this._dispatchCallback(message.requestId, port, result);
}
var evalExpression = "JSON.stringify(eval(unescape('" + escape(message.expression) + "')));";
RuntimeAgent.evaluate(evalExpression, "", true, callback.bind(this));
},

_onRevealAndSelect: function(message)
{
if (message.panelId === "resources" && type === "resource")
return this._onRevealAndSelectResource(message);
else
return this._status.E_NOTSUPPORTED(message.panelId, message.type);
},

_onRevealAndSelectResource: function(message)
{
var id = message.id;
var resource = null;

resource = this._resourceById(id) || WebInspector.resourceForURL(id);
if (!resource)
return this._status.E_NOTFOUND(typeof id + ": " + id);

WebInspector.panels.resources.showResource(resource, message.line);
WebInspector.showPanel("resources");
},

_dispatchCallback: function(requestId, port, result)
{
port.postMessage({ command: "callback", requestId: requestId, result: result });
},

_onGetHAR: function(request)
{
var harLog = (new WebInspector.HARLog()).build();
for (var i = 0; i < harLog.entries.length; ++i)
harLog.entries[i]._resourceId = this._resourceId(WebInspector.networkResources[i]);
return harLog;
},

_onGetResourceContent: function(message, port)
{
function onContentAvailable(content, encoded)
{
var response = {
encoding: encoded ? "base64" : "",
content: content
};
this._dispatchCallback(message.requestId, port, response);
}
var resource = this._resourceById(message.id);
if (!resource)
return this._status.E_NOTFOUND(message.id);
resource.requestContent(onContentAvailable.bind(this));
},

_resourceId: function(resource)
{
if (!resource._extensionResourceId) {
resource._extensionResourceId = ++this._lastResourceId;
this._resources[resource._extensionResourceId] = resource;
}
return resource._extensionResourceId;
},

_resourceById: function(id)
{
return this._resources[id];
},

_onAddAuditCategory: function(request)
{
var category = new WebInspector.ExtensionAuditCategory(request.id, request.displayName, request.resultCount);
if (WebInspector.panels.audits.getCategory(category.id))
return this._status.E_EXISTS(category.id);
this._clientObjects[request.id] = category;
WebInspector.panels.audits.addCategory(category);
},

_onAddAuditResult: function(request)
{
var auditResult = this._clientObjects[request.resultId];
if (!auditResult)
return this._status.E_NOTFOUND(request.resultId);
try {
auditResult.addResult(request.displayName, request.description, request.severity, request.details);
} catch (e) {
return e;
}
return this._status.OK();
},

_onStopAuditCategoryRun: function(request)
{
var auditRun = this._clientObjects[request.resultId];
if (!auditRun)
return this._status.E_NOTFOUND(request.resultId);
auditRun.cancel();
},

initExtensions: function()
{

WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._notifyResourceFinished, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, this._inspectedURLChanged, this);

InspectorExtensionRegistry.getExtensionsAsync();
},

_addExtensions: function(extensions)
{

InspectorFrontendHost.setExtensionAPI(this._buildExtensionAPIInjectedScript());
for (var i = 0; i < extensions.length; ++i) {
var extension = extensions[i];
try {
if (!extension.startPage)
return;
var iframe = document.createElement("iframe");
iframe.src = extension.startPage;
iframe.style.display = "none";
document.body.appendChild(iframe);
} catch (e) {
console.error("Failed to initialize extension " + extension.startPage + ":" + e);
}
}
},

_buildExtensionAPIInjectedScript: function()
{
var resourceTypes = {};
var resourceTypeProperties = Object.getOwnPropertyNames(WebInspector.Resource.Type);
for (var i = 0; i < resourceTypeProperties.length; ++i) {
var propName = resourceTypeProperties[i];
var propValue = WebInspector.Resource.Type[propName];
if (typeof propValue === "number")
resourceTypes[propName] = WebInspector.Resource.Type.toString(propValue);
}
var platformAPI = WebInspector.buildPlatformExtensionAPI ? WebInspector.buildPlatformExtensionAPI() : "";
return "(function(){ " +
"var apiPrivate = {};" +
"(" + WebInspector.commonExtensionSymbols.toString() + ")(apiPrivate);" +
"(" + WebInspector.injectedExtensionAPI.toString() + ").apply(this, arguments);" +
platformAPI +
"})";
},

_onWindowMessage: function(event)
{
if (event.data !== "registerExtension")
return;
var port = event.ports[0];
port.addEventListener("message", this._onmessage.bind(this), false);
port.start();
},

_onmessage: function(event)
{
var request = event.data;
var result;

if (request.command in this._handlers)
result = this._handlers[request.command](request, event.target);
else
result = this._status.E_NOTSUPPORTED(request.command);

if (result && request.requestId)
this._dispatchCallback(request.requestId, event.target, result);
},

_registerHandler: function(command, callback)
{
this._handlers[command] = callback;
},

_registerSubscriptionHandler: function(eventTopic, onSubscribeFirst, onUnsubscribeLast)
{
this._subscriptionStartHandlers[eventTopic] =  onSubscribeFirst;
this._subscriptionStopHandlers[eventTopic] =  onUnsubscribeLast;
}
}

WebInspector.ExtensionServer._statuses =
{
OK: "",
E_EXISTS: "Object already exists: %s",
E_BADARG: "Invalid argument %s: %s",
E_BADARGTYPE: "Invalid type for argument %s: got %s, expected %s",
E_NOTFOUND: "Object not found: %s",
E_NOTSUPPORTED: "Object does not support requested operation: %s",
}

WebInspector.ExtensionStatus = function()
{
function makeStatus(code)
{
var description = WebInspector.ExtensionServer._statuses[code] || code;
var details = Array.prototype.slice.call(arguments, 1);
var status = { code: code, description: description, details: details };
if (code !== "OK") {
status.isError = true;
console.log("Extension server error: " + String.vsprintf(description, details));
}
return status;
}
for (status in WebInspector.ExtensionServer._statuses)
this[status] = makeStatus.bind(null, status);
}

WebInspector.addExtensions = function(extensions)
{
WebInspector.extensionServer._addExtensions(extensions);
}

WebInspector.extensionServer = new WebInspector.ExtensionServer();





WebInspector.ExtensionPanel = function(id, label, iconURL, options)
{
this.toolbarItemLabel = label;
this._addStyleRule(".toolbar-item." + id + " .toolbar-icon", "background-image: url(" + iconURL + ");");
WebInspector.Panel.call(this, id);
}

WebInspector.ExtensionPanel.prototype = {
get defaultFocusedElement()
{
return this.sidebarTreeElement || this.element;
},

updateMainViewWidth: function(width)
{
this.bodyElement.style.left = width + "px";
this.resize();
},

searchCanceled: function(startingNewSearch)
{
WebInspector.extensionServer.notifySearchAction(this._id, "cancelSearch");
WebInspector.Panel.prototype.searchCanceled.apply(this, arguments);
},

performSearch: function(query)
{
WebInspector.extensionServer.notifySearchAction(this._id, "performSearch", query);
WebInspector.Panel.prototype.performSearch.apply(this, arguments);
},

jumpToNextSearchResult: function()
{
WebInspector.extensionServer.notifySearchAction(this._id, "nextSearchResult");
WebInspector.Panel.prototype.jumpToNextSearchResult.call(this);
},

jumpToPreviousSearchResult: function()
{
WebInspector.extensionServer.notifySearchAction(this._id, "previousSearchResult");
WebInspector.Panel.prototype.jumpToPreviousSearchResult.call(this);
},

_addStyleRule: function(selector, body)
{
var style = document.createElement("style");
style.textContent = selector + " { " + body + " }";
document.head.appendChild(style);
}
}

WebInspector.ExtensionPanel.prototype.__proto__ = WebInspector.Panel.prototype;

WebInspector.ExtensionSidebarPane = function(title, id)
{
WebInspector.SidebarPane.call(this, title);
this._id = id;
}

WebInspector.ExtensionSidebarPane.prototype = {
setObject: function(object, title)
{
this._setObject(WebInspector.RemoteObject.fromLocalObject(object), title);
},

setExpression: function(expression, title)
{
RuntimeAgent.evaluate(expression, "extension-watch", true, this._onEvaluate.bind(this, title));
},

setPage: function(url)
{
this.bodyElement.removeChildren();
WebInspector.extensionServer.createClientIframe(this.bodyElement, url);

WebInspector.extensionServer.notifyExtensionSidebarUpdated(this._id);
},

_onEvaluate: function(title, error, result, wasThrown)
{
if (!error)
this._setObject(WebInspector.RemoteObject.fromPayload(result), title);
},

_setObject: function(object, title)
{
this.bodyElement.removeChildren();
var section = new WebInspector.ObjectPropertiesSection(object, title);
if (!title)
section.headerElement.addStyleClass("hidden");
section.expanded = true;
section.editable = false;
this.bodyElement.appendChild(section.element);
WebInspector.extensionServer.notifyExtensionSidebarUpdated(this._id);
}
}

WebInspector.ExtensionSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;





WebInspector.AuditsPanel = function()
{
WebInspector.Panel.call(this, "audits");

this.createSidebar();
this.auditsTreeElement = new WebInspector.SidebarSectionTreeElement("", {}, true);
this.sidebarTree.appendChild(this.auditsTreeElement);
this.auditsTreeElement.listItemElement.addStyleClass("hidden");
this.auditsTreeElement.expand();

this.auditsItemTreeElement = new WebInspector.AuditsSidebarTreeElement();
this.auditsTreeElement.appendChild(this.auditsItemTreeElement);

this.auditResultsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("RESULTS"), {}, true);
this.sidebarTree.appendChild(this.auditResultsTreeElement);
this.auditResultsTreeElement.expand();

this.clearResultsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear audit results."), "clear-status-bar-item");
this.clearResultsButton.addEventListener("click", this._clearButtonClicked.bind(this), false);

this.viewsContainerElement = document.createElement("div");
this.viewsContainerElement.id = "audit-views";
this.element.appendChild(this.viewsContainerElement);

this._constructCategories();

this._launcherView = new WebInspector.AuditLauncherView(this.initiateAudit.bind(this));
for (id in this.categoriesById)
this._launcherView.addCategory(this.categoriesById[id]);

WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.OnLoad, this._onLoadEventFired, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, this._domContentLoadedEventFired, this);
}

WebInspector.AuditsPanel.prototype = {
get toolbarItemLabel()
{
return WebInspector.UIString("Audits");
},

get statusBarItems()
{
return [this.clearResultsButton.element];
},

get mainResourceLoadTime()
{
return this._mainResourceLoadTime;
},

_onLoadEventFired: function(event)
{
this._mainResourceLoadTime = event.data;
this._didMainResourceLoad();
},

get mainResourceDOMContentTime()
{
return this._mainResourceDOMContentTime;
},

_domContentLoadedEventFired: function(event)
{
this._mainResourceDOMContentTime = event.data;
},

get categoriesById()
{
return this._auditCategoriesById;
},

addCategory: function(category)
{
this.categoriesById[category.id] = category;
this._launcherView.addCategory(category);
},

getCategory: function(id)
{
return this.categoriesById[id];
},

_constructCategories: function()
{
this._auditCategoriesById = {};
for (var categoryCtorID in WebInspector.AuditCategories) {
var auditCategory = new WebInspector.AuditCategories[categoryCtorID]();
auditCategory._id = categoryCtorID;
this.categoriesById[categoryCtorID] = auditCategory;
}
},

_executeAudit: function(categories, resultCallback)
{
var resources = WebInspector.networkResources;

var rulesRemaining = 0;
for (var i = 0; i < categories.length; ++i)
rulesRemaining += categories[i].ruleCount;

var results = [];
var mainResourceURL = WebInspector.mainResource.url;

function ruleResultReadyCallback(categoryResult, ruleResult)
{
if (ruleResult && ruleResult.children)
categoryResult.addRuleResult(ruleResult);

--rulesRemaining;

if (!rulesRemaining && resultCallback)
resultCallback(mainResourceURL, results);
}

if (!rulesRemaining) {
resultCallback(mainResourceURL, results);
return;
}

for (var i = 0; i < categories.length; ++i) {
var category = categories[i];
var result = new WebInspector.AuditCategoryResult(category);
results.push(result);
category.run(resources, ruleResultReadyCallback.bind(null, result));
}
},

_auditFinishedCallback: function(launcherCallback, mainResourceURL, results)
{
var children = this.auditResultsTreeElement.children;
var ordinal = 1;
for (var i = 0; i < children.length; ++i) {
if (children[i].mainResourceURL === mainResourceURL)
ordinal++;
}

var resultTreeElement = new WebInspector.AuditResultSidebarTreeElement(results, mainResourceURL, ordinal);
this.auditResultsTreeElement.appendChild(resultTreeElement);
resultTreeElement.reveal();
resultTreeElement.select();
if (launcherCallback)
launcherCallback();
},

initiateAudit: function(categoryIds, runImmediately, launcherCallback)
{
if (!categoryIds || !categoryIds.length)
return;

var categories = [];
for (var i = 0; i < categoryIds.length; ++i)
categories.push(this.categoriesById[categoryIds[i]]);

function initiateAuditCallback(categories, launcherCallback)
{
this._executeAudit(categories, this._auditFinishedCallback.bind(this, launcherCallback));
}

if (runImmediately)
initiateAuditCallback.call(this, categories, launcherCallback);
else
this._reloadResources(initiateAuditCallback.bind(this, categories, launcherCallback));
},

_reloadResources: function(callback)
{
this._pageReloadCallback = callback;
PageAgent.reload(false);
},

_didMainResourceLoad: function()
{
if (this._pageReloadCallback) {
var callback = this._pageReloadCallback;
delete this._pageReloadCallback;
callback();
}
},

showResults: function(categoryResults)
{
if (!categoryResults._resultView)
categoryResults._resultView = new WebInspector.AuditResultView(categoryResults);

this.visibleView = categoryResults._resultView;
},

showLauncherView: function()
{
this.visibleView = this._launcherView;
},

get visibleView()
{
return this._visibleView;
},

set visibleView(x)
{
if (this._visibleView === x)
return;

if (this._visibleView)
this._visibleView.hide();

this._visibleView = x;

if (x)
x.show(this.viewsContainerElement);
},

attach: function()
{
WebInspector.Panel.prototype.attach.call(this);

this.auditsItemTreeElement.select();
},

updateMainViewWidth: function(width)
{
this.viewsContainerElement.style.left = width + "px";
},

_clearButtonClicked: function()
{
this.auditsItemTreeElement.reveal();
this.auditsItemTreeElement.select();
this.auditResultsTreeElement.removeChildren();
}
}

WebInspector.AuditsPanel.prototype.__proto__ = WebInspector.Panel.prototype;



WebInspector.AuditCategory = function(displayName)
{
this._displayName = displayName;
this._rules = [];
}

WebInspector.AuditCategory.prototype = {
get id()
{

return this._id;
},

get displayName()
{
return this._displayName;
},

get ruleCount()
{
this._ensureInitialized();
return this._rules.length;
},

addRule: function(rule, severity)
{
rule.severity = severity;
this._rules.push(rule);
},

run: function(resources, callback)
{
this._ensureInitialized();
for (var i = 0; i < this._rules.length; ++i)
this._rules[i].run(resources, callback);
},

_ensureInitialized: function()
{
if (!this._initialized) {
if ("initialize" in this)
this.initialize();
this._initialized = true;
}
}
}


WebInspector.AuditRule = function(id, displayName)
{
this._id = id;
this._displayName = displayName;
}

WebInspector.AuditRule.Severity = {
Info: "info",
Warning: "warning",
Severe: "severe"
}

WebInspector.AuditRule.SeverityOrder = {
"info": 3,
"warning": 2,
"severe": 1
}

WebInspector.AuditRule.prototype = {
get id()
{
return this._id;
},

get displayName()
{
return this._displayName;
},

set severity(severity)
{
this._severity = severity;
},

run: function(resources, callback)
{
var result = new WebInspector.AuditRuleResult(this.displayName);
result.severity = this._severity;
this.doRun(resources, result, callback);
},

doRun: function(resources, result, callback)
{
throw new Error("doRun() not implemented");
}
}

WebInspector.AuditCategoryResult = function(category)
{
this.title = category.displayName;
this.ruleResults = [];
}

WebInspector.AuditCategoryResult.prototype = {
addRuleResult: function(ruleResult)
{
this.ruleResults.push(ruleResult);
}
}

WebInspector.AuditRuleResult = function(value, expanded, className)
{
this.value = value;
this.className = className;
this.expanded = expanded;
this.violationCount = 0;
}

WebInspector.AuditRuleResult.linkifyDisplayName = function(url)
{
return WebInspector.linkifyURL(url, WebInspector.displayNameForURL(url));
}

WebInspector.AuditRuleResult.resourceDomain = function(domain)
{
return domain || WebInspector.UIString("[empty domain]");
}

WebInspector.AuditRuleResult.prototype = {
addChild: function(value, expanded, className)
{
if (!this.children)
this.children = [];
var entry = new WebInspector.AuditRuleResult(value, expanded, className);
this.children.push(entry);
return entry;
},

addURL: function(url)
{
return this.addChild(WebInspector.AuditRuleResult.linkifyDisplayName(url));
},

addURLs: function(urls)
{
for (var i = 0; i < urls.length; ++i)
this.addURL(urls[i]);
},

addSnippet: function(snippet)
{
return this.addChild(snippet, false, "source-code");
}
}

WebInspector.AuditsSidebarTreeElement = function()
{
this.small = false;

WebInspector.SidebarTreeElement.call(this, "audits-sidebar-tree-item", WebInspector.UIString("Audits"), "", null, false);
}

WebInspector.AuditsSidebarTreeElement.prototype = {
onattach: function()
{
WebInspector.SidebarTreeElement.prototype.onattach.call(this);
},

onselect: function()
{
WebInspector.panels.audits.showLauncherView();
},

get selectable()
{
return true;
},

refresh: function()
{
this.refreshTitles();
}
}

WebInspector.AuditsSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;


WebInspector.AuditResultSidebarTreeElement = function(results, mainResourceURL, ordinal)
{
this.results = results;
this.mainResourceURL = mainResourceURL;

WebInspector.SidebarTreeElement.call(this, "audit-result-sidebar-tree-item", String.sprintf("%s (%d)", mainResourceURL, ordinal), "", {}, false);
}

WebInspector.AuditResultSidebarTreeElement.prototype = {
onselect: function()
{
WebInspector.panels.audits.showResults(this.results);
},

get selectable()
{
return true;
}
}

WebInspector.AuditResultSidebarTreeElement.prototype.__proto__ = WebInspector.SidebarTreeElement.prototype;


WebInspector.AuditRules = {};


WebInspector.AuditCategories = {};





WebInspector.AuditResultView = function(categoryResults)
{
WebInspector.View.call(this);
this.element.className = "audit-result-view";

function categorySorter(a, b) {
return (a.title || "").localeCompare(b.title || "");
}
categoryResults.sort(categorySorter);
for (var i = 0; i < categoryResults.length; ++i)
this.element.appendChild(new WebInspector.AuditCategoryResultPane(categoryResults[i]).element);
}

WebInspector.AuditResultView.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.AuditCategoryResultPane = function(categoryResult)
{
WebInspector.SidebarPane.call(this, categoryResult.title);
var treeOutlineElement = document.createElement("ol");
this.bodyElement.addStyleClass("audit-result-tree");
this.bodyElement.appendChild(treeOutlineElement);

this._treeOutline = new TreeOutline(treeOutlineElement);
this._treeOutline.expandTreeElementsWhenArrowing = true;

function ruleSorter(a, b)
{
var result = WebInspector.AuditRule.SeverityOrder[a.severity || 0] - WebInspector.AuditRule.SeverityOrder[b.severity || 0];
if (!result)
result = (a.value || "").localeCompare(b.value || "");
return result;
}

categoryResult.ruleResults.sort(ruleSorter);

for (var i = 0; i < categoryResult.ruleResults.length; ++i) {
var ruleResult = categoryResult.ruleResults[i];
var treeElement = this._appendResult(this._treeOutline, ruleResult);
treeElement.listItemElement.addStyleClass("audit-result");

if (ruleResult.severity) {
var severityElement = document.createElement("img");
severityElement.className = "severity-" + ruleResult.severity;
treeElement.listItemElement.appendChild(severityElement);
}
}
this.expand();
}

WebInspector.AuditCategoryResultPane.prototype = {
_appendResult: function(parentTreeElement, result)
{
var title = "";

if (typeof result.value === "string") {
title = result.value;
if (result.violationCount)
title = String.sprintf("%s (%d)", title, result.violationCount);
}

var treeElement = new TreeElement(null, null, !!result.children);
treeElement.titleHTML = title;
parentTreeElement.appendChild(treeElement);

if (result.className)
treeElement.listItemElement.addStyleClass(result.className);
if (typeof result.value !== "string")
treeElement.listItemElement.appendChild(WebInspector.applyFormatters(result.value));

if (result.children) {
for (var i = 0; i < result.children.length; ++i)
this._appendResult(treeElement, result.children[i]);
}
if (result.expanded) {
treeElement.listItemElement.removeStyleClass("parent");
treeElement.listItemElement.addStyleClass("parent-expanded");
treeElement.expand();
}
return treeElement;
}
}

WebInspector.AuditCategoryResultPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;





WebInspector.AuditLauncherView = function(runnerCallback)
{
WebInspector.View.call(this);
this._runnerCallback = runnerCallback;
this._categoryIdPrefix = "audit-category-item-";
this._auditRunning = false;

this.element.addStyleClass("audit-launcher-view");

this._contentElement = document.createElement("div");
this._contentElement.className = "audit-launcher-view-content";
this.element.appendChild(this._contentElement);
this._boundCategoryClickListener = this._categoryClicked.bind(this);

this._resetResourceCount();

this._sortedCategories = [];

this._headerElement = document.createElement("h1");
this._headerElement.className = "no-audits";
this._headerElement.textContent = WebInspector.UIString("No audits to run");
this._contentElement.appendChild(this._headerElement);

WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceStarted, this._onResourceStarted, this);
WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._onResourceFinished, this);
}

WebInspector.AuditLauncherView.prototype = {
_resetResourceCount: function()
{
this._loadedResources = 0;
this._totalResources = 0;
},

_onResourceStarted: function(event)
{
var resource = event.data;

if (resource.type === WebInspector.Resource.Type.WebSocket)
return;
++this._totalResources;
this._updateResourceProgress();
},

_onResourceFinished: function(event)
{
var resource = event.data;

if (resource.type === WebInspector.Resource.Type.WebSocket)
return;
++this._loadedResources;
this._updateResourceProgress();
},

addCategory: function(category)
{
if (!this._sortedCategories.length)
this._createLauncherUI();

var categoryElement = this._createCategoryElement(category.displayName, category.id);
category._checkboxElement = categoryElement.firstChild;
if (this._selectAllCheckboxElement.checked) {
category._checkboxElement.checked = true;
++this._currentCategoriesCount;
}

function compareCategories(a, b)
{
var aTitle = a.displayName || "";
var bTitle = b.displayName || "";
return aTitle.localeCompare(bTitle);
}
var insertBefore = insertionIndexForObjectInListSortedByFunction(category, this._sortedCategories, compareCategories);
this._categoriesElement.insertBefore(categoryElement, this._categoriesElement.children[insertBefore]);
this._sortedCategories.splice(insertBefore, 0, category);
this._updateButton();
},

_setAuditRunning: function(auditRunning)
{
if (this._auditRunning === auditRunning)
return;
this._auditRunning = auditRunning;
this._updateButton();
this._updateResourceProgress();
},

_launchButtonClicked: function(event)
{
var catIds = [];
var childNodes = this._categoriesElement.childNodes;
for (var category = 0; category < this._sortedCategories.length; ++category) {
if (this._sortedCategories[category]._checkboxElement.checked)
catIds.push(this._sortedCategories[category].id);
}

this._setAuditRunning(true);
this._runnerCallback(catIds, this._auditPresentStateElement.checked, this._setAuditRunning.bind(this, false));
},

_selectAllClicked: function(checkCategories)
{
var childNodes = this._categoriesElement.childNodes;
for (var i = 0, length = childNodes.length; i < length; ++i)
childNodes[i].firstChild.checked = checkCategories;
this._currentCategoriesCount = checkCategories ? this._sortedCategories.length : 0;
this._updateButton();
},

_categoryClicked: function(event)
{
this._currentCategoriesCount += event.target.checked ? 1 : -1;
this._selectAllCheckboxElement.checked = this._currentCategoriesCount === this._sortedCategories.length;
this._updateButton();
},

_createCategoryElement: function(title, id)
{
var labelElement = document.createElement("label");
labelElement.id = this._categoryIdPrefix + id;

var element = document.createElement("input");
element.type = "checkbox";
if (id !== "")
element.addEventListener("click", this._boundCategoryClickListener, false);
labelElement.appendChild(element);
labelElement.appendChild(document.createTextNode(title));

return labelElement;
},

_createLauncherUI: function()
{
this._headerElement = document.createElement("h1");
this._headerElement.textContent = WebInspector.UIString("Select audits to run");

for (var child = 0; child < this._contentElement.children.length; ++child)
this._contentElement.removeChild(this._contentElement.children[child]);

this._contentElement.appendChild(this._headerElement);

function handleSelectAllClick(event)
{
this._selectAllClicked(event.target.checked);
}
var categoryElement = this._createCategoryElement(WebInspector.UIString("Select All"), "");
categoryElement.id = "audit-launcher-selectall";
this._selectAllCheckboxElement = categoryElement.firstChild;
this._selectAllCheckboxElement.checked = true;
this._selectAllCheckboxElement.addEventListener("click", handleSelectAllClick.bind(this), false);
this._contentElement.appendChild(categoryElement);

this._categoriesElement = document.createElement("div");
this._categoriesElement.className = "audit-categories-container";
this._contentElement.appendChild(this._categoriesElement);

this._currentCategoriesCount = 0;

var flexibleSpaceElement = document.createElement("div");
flexibleSpaceElement.className = "flexible-space";
this._contentElement.appendChild(flexibleSpaceElement);

this._buttonContainerElement = document.createElement("div");
this._buttonContainerElement.className = "button-container";

var labelElement = document.createElement("label");
this._auditPresentStateElement = document.createElement("input");
this._auditPresentStateElement.name = "audit-mode";
this._auditPresentStateElement.type = "radio";
this._auditPresentStateElement.checked = true;
this._auditPresentStateLabelElement = document.createTextNode(WebInspector.UIString("Audit Present State"));
labelElement.appendChild(this._auditPresentStateElement);
labelElement.appendChild(this._auditPresentStateLabelElement);
this._buttonContainerElement.appendChild(labelElement);

labelElement = document.createElement("label");
this.auditReloadedStateElement = document.createElement("input");
this.auditReloadedStateElement.name = "audit-mode";
this.auditReloadedStateElement.type = "radio";
labelElement.appendChild(this.auditReloadedStateElement);
labelElement.appendChild(document.createTextNode("Reload Page and Audit on Load"));
this._buttonContainerElement.appendChild(labelElement);

this._launchButton = document.createElement("button");
this._launchButton.type = "button";
this._launchButton.textContent = WebInspector.UIString("Run");
this._launchButton.addEventListener("click", this._launchButtonClicked.bind(this), false);
this._buttonContainerElement.appendChild(this._launchButton);

this._resourceProgressContainer = document.createElement("span");
this._resourceProgressContainer.className = "resource-progress";
var resourceProgressImage = document.createElement("img");
this._resourceProgressContainer.appendChild(resourceProgressImage);
this._resourceProgressTextElement = document.createElement("span");
this._resourceProgressContainer.appendChild(this._resourceProgressTextElement);
this._buttonContainerElement.appendChild(this._resourceProgressContainer);

this._contentElement.appendChild(this._buttonContainerElement);

this._selectAllClicked(this._selectAllCheckboxElement.checked);
this._updateButton();
this._updateResourceProgress();
},

_updateResourceProgress: function()
{
if (!this._resourceProgressContainer)
return;

if (!this._auditRunning) {
this._resetResourceCount();
this._resourceProgressContainer.addStyleClass("hidden");
} else
this._resourceProgressContainer.removeStyleClass("hidden");
this._resourceProgressTextElement.textContent = WebInspector.UIString("Loading (%d of %d)", this._loadedResources, this._totalResources);
},

_updateButton: function()
{
this._launchButton.disabled = !this._currentCategoriesCount || this._auditRunning;
}
}

WebInspector.AuditLauncherView.prototype.__proto__ = WebInspector.View.prototype;





WebInspector.AuditRules.IPAddressRegexp = /^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}$/;

WebInspector.AuditRules.CacheableResponseCodes =
{
200: true,
203: true,
206: true,
300: true,
301: true,
410: true,

304: true 
}

WebInspector.AuditRules.getDomainToResourcesMap = function(resources, types, needFullResources)
{
var domainToResourcesMap = {};
for (var i = 0, size = resources.length; i < size; ++i) {
var resource = resources[i];
if (types && types.indexOf(resource.type) === -1)
continue;
var parsedURL = resource.url.asParsedURL();
if (!parsedURL)
continue;
var domain = parsedURL.host;
var domainResources = domainToResourcesMap[domain];
if (domainResources === undefined) {
domainResources = [];
domainToResourcesMap[domain] = domainResources;
}
domainResources.push(needFullResources ? resource : resource.url);
}
return domainToResourcesMap;
}

WebInspector.AuditRules.GzipRule = function()
{
WebInspector.AuditRule.call(this, "network-gzip", "Enable gzip compression");
}

WebInspector.AuditRules.GzipRule.prototype = {
doRun: function(resources, result, callback)
{
var totalSavings = 0;
var compressedSize = 0;
var candidateSize = 0;
var summary = result.addChild("", true);
for (var i = 0, length = resources.length; i < length; ++i) {
var resource = resources[i];
if (resource.statusCode === 304)
continue; 
if (this._shouldCompress(resource)) {
var size = resource.resourceSize;
candidateSize += size;
if (this._isCompressed(resource)) {
compressedSize += size;
continue;
}
var savings = 2 * size / 3;
totalSavings += savings;
summary.addChild(String.sprintf("%s could save ~%s", WebInspector.AuditRuleResult.linkifyDisplayName(resource.url), Number.bytesToString(savings)));
result.violationCount++;
}
}
if (!totalSavings)
return callback(null);
summary.value = String.sprintf("Compressing the following resources with gzip could reduce their transfer size by about two thirds (~%s):", Number.bytesToString(totalSavings));
callback(result);
},

_isCompressed: function(resource)
{
var encodingHeader = resource.responseHeaders["Content-Encoding"];
if (!encodingHeader)
return false;

return /\b(?:gzip|deflate)\b/.test(encodingHeader);
},

_shouldCompress: function(resource)
{
return WebInspector.Resource.Type.isTextType(resource.type) && resource.domain && resource.resourceSize !== undefined && resource.resourceSize > 150;
}
}

WebInspector.AuditRules.GzipRule.prototype.__proto__ = WebInspector.AuditRule.prototype;


WebInspector.AuditRules.CombineExternalResourcesRule = function(id, name, type, resourceTypeName, allowedPerDomain)
{
WebInspector.AuditRule.call(this, id, name);
this._type = type;
this._resourceTypeName = resourceTypeName;
this._allowedPerDomain = allowedPerDomain;
}

WebInspector.AuditRules.CombineExternalResourcesRule.prototype = {
doRun: function(resources, result, callback)
{
var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources, [this._type]);
var penalizedResourceCount = 0;

var summary = result.addChild("", true);
for (var domain in domainToResourcesMap) {
var domainResources = domainToResourcesMap[domain];
var extraResourceCount = domainResources.length - this._allowedPerDomain;
if (extraResourceCount <= 0)
continue;
penalizedResourceCount += extraResourceCount - 1;
summary.addChild(String.sprintf("%d %s resources served from %s.", domainResources.length, this._resourceTypeName, WebInspector.AuditRuleResult.resourceDomain(domain)));
result.violationCount += domainResources.length;
}
if (!penalizedResourceCount)
return callback(null);

summary.value = "There are multiple resources served from same domain. Consider combining them into as few files as possible.";
callback(result);
}
}

WebInspector.AuditRules.CombineExternalResourcesRule.prototype.__proto__ = WebInspector.AuditRule.prototype;


WebInspector.AuditRules.CombineJsResourcesRule = function(allowedPerDomain) {
WebInspector.AuditRules.CombineExternalResourcesRule.call(this, "page-externaljs", "Combine external JavaScript", WebInspector.Resource.Type.Script, "JavaScript", allowedPerDomain);
}

WebInspector.AuditRules.CombineJsResourcesRule.prototype.__proto__ = WebInspector.AuditRules.CombineExternalResourcesRule.prototype;


WebInspector.AuditRules.CombineCssResourcesRule = function(allowedPerDomain) {
WebInspector.AuditRules.CombineExternalResourcesRule.call(this, "page-externalcss", "Combine external CSS", WebInspector.Resource.Type.Stylesheet, "CSS", allowedPerDomain);
}

WebInspector.AuditRules.CombineCssResourcesRule.prototype.__proto__ = WebInspector.AuditRules.CombineExternalResourcesRule.prototype;


WebInspector.AuditRules.MinimizeDnsLookupsRule = function(hostCountThreshold) {
WebInspector.AuditRule.call(this, "network-minimizelookups", "Minimize DNS lookups");
this._hostCountThreshold = hostCountThreshold;
}

WebInspector.AuditRules.MinimizeDnsLookupsRule.prototype = {
doRun: function(resources, result, callback)
{
var summary = result.addChild("");
var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources, undefined);
for (var domain in domainToResourcesMap) {
if (domainToResourcesMap[domain].length > 1)
continue;
var parsedURL = domain.asParsedURL();
if (!parsedURL)
continue;
if (!parsedURL.host.search(WebInspector.AuditRules.IPAddressRegexp))
continue; 
summary.addSnippet(match[2]);
result.violationCount++;
}
if (!summary.children || summary.children.length <= this._hostCountThreshold)
return callback(null);

summary.value = "The following domains only serve one resource each. If possible, avoid the extra DNS lookups by serving these resources from existing domains.";
callback(result);
}
}

WebInspector.AuditRules.MinimizeDnsLookupsRule.prototype.__proto__ = WebInspector.AuditRule.prototype;


WebInspector.AuditRules.ParallelizeDownloadRule = function(optimalHostnameCount, minRequestThreshold, minBalanceThreshold)
{
WebInspector.AuditRule.call(this, "network-parallelizehosts", "Parallelize downloads across hostnames");
this._optimalHostnameCount = optimalHostnameCount;
this._minRequestThreshold = minRequestThreshold;
this._minBalanceThreshold = minBalanceThreshold;
}


WebInspector.AuditRules.ParallelizeDownloadRule.prototype = {
doRun: function(resources, result, callback)
{
function hostSorter(a, b)
{
var aCount = domainToResourcesMap[a].length;
var bCount = domainToResourcesMap[b].length;
return (aCount < bCount) ? 1 : (aCount == bCount) ? 0 : -1;
}

var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(
resources,
[WebInspector.Resource.Type.Stylesheet, WebInspector.Resource.Type.Image],
true);

var hosts = [];
for (var url in domainToResourcesMap)
hosts.push(url);

if (!hosts.length)
return callback(null); 

hosts.sort(hostSorter);

var optimalHostnameCount = this._optimalHostnameCount;
if (hosts.length > optimalHostnameCount)
hosts.splice(optimalHostnameCount);

var busiestHostResourceCount = domainToResourcesMap[hosts[0]].length;
var resourceCountAboveThreshold = busiestHostResourceCount - this._minRequestThreshold;
if (resourceCountAboveThreshold <= 0)
return callback(null);

var avgResourcesPerHost = 0;
for (var i = 0, size = hosts.length; i < size; ++i)
avgResourcesPerHost += domainToResourcesMap[hosts[i]].length;


avgResourcesPerHost /= optimalHostnameCount;
avgResourcesPerHost = Math.max(avgResourcesPerHost, 1);

var pctAboveAvg = (resourceCountAboveThreshold / avgResourcesPerHost) - 1.0;
var minBalanceThreshold = this._minBalanceThreshold;
if (pctAboveAvg < minBalanceThreshold)
return callback(null);

var resourcesOnBusiestHost = domainToResourcesMap[hosts[0]];
var entry = result.addChild(String.sprintf("This page makes %d parallelizable requests to %s. Increase download parallelization by distributing the following requests across multiple hostnames.", busiestHostResourceCount, hosts[0]), true);
for (var i = 0; i < resourcesOnBusiestHost.length; ++i)
entry.addURL(resourcesOnBusiestHost[i].url);

result.violationCount = resourcesOnBusiestHost.length;
callback(result);
}
}

WebInspector.AuditRules.ParallelizeDownloadRule.prototype.__proto__ = WebInspector.AuditRule.prototype;




WebInspector.AuditRules.UnusedCssRule = function()
{
WebInspector.AuditRule.call(this, "page-unusedcss", "Remove unused CSS rules");
}

WebInspector.AuditRules.UnusedCssRule.prototype = {
doRun: function(resources, result, callback)
{
var self = this;

function evalCallback(styleSheets) {
if (!styleSheets.length)
return callback(null);

var pseudoSelectorRegexp = /:hover|:link|:active|:visited|:focus|:before|:after/;
var selectors = [];
var testedSelectors = {};
for (var i = 0; i < styleSheets.length; ++i) {
var styleSheet = styleSheets[i];
for (var curRule = 0; curRule < styleSheet.rules.length; ++curRule) {
var selectorText = styleSheet.rules[curRule].selectorText;
if (selectorText.match(pseudoSelectorRegexp) || testedSelectors[selectorText])
continue;
selectors.push(selectorText);
testedSelectors[selectorText] = 1;
}
}

function selectorsCallback(callback, styleSheets, testedSelectors, foundSelectors)
{
var inlineBlockOrdinal = 0;
var totalStylesheetSize = 0;
var totalUnusedStylesheetSize = 0;
var summary;

for (var i = 0; i < styleSheets.length; ++i) {
var styleSheet = styleSheets[i];
var stylesheetSize = 0;
var unusedStylesheetSize = 0;
var unusedRules = [];
for (var curRule = 0; curRule < styleSheet.rules.length; ++curRule) {
var rule = styleSheet.rules[curRule];

var textLength = (rule.selectorRange && rule.style.range && rule.style.range.end) ? rule.style.range.end - rule.selectorRange.start + 1 : 0;
if (!textLength && rule.style.cssText)
textLength = rule.style.cssText.length + rule.selectorText.length;
stylesheetSize += textLength;
if (!testedSelectors[rule.selectorText] || foundSelectors[rule.selectorText])
continue;
unusedStylesheetSize += textLength;
unusedRules.push(rule.selectorText);
}
totalStylesheetSize += stylesheetSize;
totalUnusedStylesheetSize += unusedStylesheetSize;

if (!unusedRules.length)
continue;

var resource = WebInspector.resourceForURL(styleSheet.sourceURL);
var isInlineBlock = resource && resource.type == WebInspector.Resource.Type.Document;
var url = !isInlineBlock ? WebInspector.AuditRuleResult.linkifyDisplayName(styleSheet.sourceURL) : String.sprintf("Inline block #%d", ++inlineBlockOrdinal);
var pctUnused = Math.round(100 * unusedStylesheetSize / stylesheetSize);
if (!summary)
summary = result.addChild("", true);
var entry = summary.addChild(String.sprintf("%s: %s (%d%%) is not used by the current page.", url, Number.bytesToString(unusedStylesheetSize), pctUnused));

for (var j = 0; j < unusedRules.length; ++j)
entry.addSnippet(unusedRules[j]);

result.violationCount += unusedRules.length;
}

if (!totalUnusedStylesheetSize)
return callback(null);

var totalUnusedPercent = Math.round(100 * totalUnusedStylesheetSize / totalStylesheetSize);
summary.value = String.sprintf("%s (%d%%) of CSS is not used by the current page.", Number.bytesToString(totalUnusedStylesheetSize), totalUnusedPercent);

callback(result);
}

var foundSelectors = {};
function queryCallback(boundSelectorsCallback, selector, styleSheets, testedSelectors, nodeId)
{
if (nodeId)
foundSelectors[selector] = true;
if (boundSelectorsCallback)
boundSelectorsCallback(foundSelectors);
}

function documentLoaded(selectors, document) {
for (var i = 0; i < selectors.length; ++i)
WebInspector.domAgent.querySelector(document.id, selectors[i], queryCallback.bind(null, i === selectors.length - 1 ? selectorsCallback.bind(null, callback, styleSheets, testedSelectors) : null, selectors[i], styleSheets, testedSelectors));
}

WebInspector.domAgent.requestDocument(documentLoaded.bind(null, selectors));
}

function styleSheetCallback(styleSheets, sourceURL, continuation, styleSheet)
{
if (styleSheet) {
styleSheet.sourceURL = sourceURL;
styleSheets.push(styleSheet);
}
if (continuation)
continuation(styleSheets);
}

function allStylesCallback(error, styleSheetInfos)
{
if (error || !styleSheetInfos || !styleSheetInfos.length)
return evalCallback([]);
var styleSheets = [];
for (var i = 0; i < styleSheetInfos.length; ++i) {
var info = styleSheetInfos[i];
WebInspector.CSSStyleSheet.createForId(info.styleSheetId, styleSheetCallback.bind(null, styleSheets, info.sourceURL, i == styleSheetInfos.length - 1 ? evalCallback : null));
}
}

CSSAgent.getAllStyleSheets(allStylesCallback);
}
}

WebInspector.AuditRules.UnusedCssRule.prototype.__proto__ = WebInspector.AuditRule.prototype;


WebInspector.AuditRules.CacheControlRule = function(id, name)
{
WebInspector.AuditRule.call(this, id, name);
}

WebInspector.AuditRules.CacheControlRule.MillisPerMonth = 1000 * 60 * 60 * 24 * 30;

WebInspector.AuditRules.CacheControlRule.prototype = {

doRun: function(resources, result, callback)
{
var cacheableAndNonCacheableResources = this._cacheableAndNonCacheableResources(resources);
if (cacheableAndNonCacheableResources[0].length)
this.runChecks(cacheableAndNonCacheableResources[0], result);
this.handleNonCacheableResources(cacheableAndNonCacheableResources[1], result);

callback(result);
},

handleNonCacheableResources: function()
{
},

_cacheableAndNonCacheableResources: function(resources)
{
var processedResources = [[], []];
for (var i = 0; i < resources.length; ++i) {
var resource = resources[i];
if (!this.isCacheableResource(resource))
continue;
if (this._isExplicitlyNonCacheable(resource))
processedResources[1].push(resource);
else
processedResources[0].push(resource);
}
return processedResources;
},

execCheck: function(messageText, resourceCheckFunction, resources, result)
{
var resourceCount = resources.length;
var urls = [];
for (var i = 0; i < resourceCount; ++i) {
if (resourceCheckFunction.call(this, resources[i]))
urls.push(resources[i].url);
}
if (urls.length) {
var entry = result.addChild(messageText, true);
entry.addURLs(urls);
result.violationCount += urls.length;
}
},

freshnessLifetimeGreaterThan: function(resource, timeMs)
{
var dateHeader = this.responseHeader(resource, "Date");
if (!dateHeader)
return false;

var dateHeaderMs = Date.parse(dateHeader);
if (isNaN(dateHeaderMs))
return false;

var freshnessLifetimeMs;
var maxAgeMatch = this.responseHeaderMatch(resource, "Cache-Control", "max-age=(\\d+)");

if (maxAgeMatch)
freshnessLifetimeMs = (maxAgeMatch[1]) ? 1000 * maxAgeMatch[1] : 0;
else {
var expiresHeader = this.responseHeader(resource, "Expires");
if (expiresHeader) {
var expDate = Date.parse(expiresHeader);
if (!isNaN(expDate))
freshnessLifetimeMs = expDate - dateHeaderMs;
}
}

return (isNaN(freshnessLifetimeMs)) ? false : freshnessLifetimeMs > timeMs;
},

responseHeader: function(resource, header)
{
return resource.responseHeaders[header];
},

hasResponseHeader: function(resource, header)
{
return resource.responseHeaders[header] !== undefined;
},

isCompressible: function(resource)
{
return WebInspector.Resource.Type.isTextType(resource.type);
},

isPubliclyCacheable: function(resource)
{
if (this._isExplicitlyNonCacheable(resource))
return false;

if (this.responseHeaderMatch(resource, "Cache-Control", "public"))
return true;

return resource.url.indexOf("?") == -1 && !this.responseHeaderMatch(resource, "Cache-Control", "private");
},

responseHeaderMatch: function(resource, header, regexp)
{
return resource.responseHeaders[header]
? resource.responseHeaders[header].match(new RegExp(regexp, "im"))
: undefined;
},

hasExplicitExpiration: function(resource)
{
return this.hasResponseHeader(resource, "Date") &&
(this.hasResponseHeader(resource, "Expires") || this.responseHeaderMatch(resource, "Cache-Control", "max-age"));
},

_isExplicitlyNonCacheable: function(resource)
{
var hasExplicitExp = this.hasExplicitExpiration(resource);
return this.responseHeaderMatch(resource, "Cache-Control", "(no-cache|no-store|must-revalidate)") ||
this.responseHeaderMatch(resource, "Pragma", "no-cache") ||
(hasExplicitExp && !this.freshnessLifetimeGreaterThan(resource, 0)) ||
(!hasExplicitExp && resource.url && resource.url.indexOf("?") >= 0) ||
(!hasExplicitExp && !this.isCacheableResource(resource));
},

isCacheableResource: function(resource)
{
return resource.statusCode !== undefined && WebInspector.AuditRules.CacheableResponseCodes[resource.statusCode];
}
}

WebInspector.AuditRules.CacheControlRule.prototype.__proto__ = WebInspector.AuditRule.prototype;


WebInspector.AuditRules.BrowserCacheControlRule = function()
{
WebInspector.AuditRules.CacheControlRule.call(this, "http-browsercache", "Leverage browser caching");
}

WebInspector.AuditRules.BrowserCacheControlRule.prototype = {
handleNonCacheableResources: function(resources, result)
{
if (resources.length) {
var entry = result.addChild("The following resources are explicitly non-cacheable. Consider making them cacheable if possible:", true);
result.violationCount += resources.length;
for (var i = 0; i < resources.length; ++i)
entry.addURL(resources[i].url);
}
},

runChecks: function(resources, result, callback)
{
this.execCheck("The following resources are missing a cache expiration. Resources that do not specify an expiration may not be cached by browsers:",
this._missingExpirationCheck, resources, result);
this.execCheck("The following resources specify a \"Vary\" header that disables caching in most versions of Internet Explorer:",
this._varyCheck, resources, result);
this.execCheck("The following cacheable resources have a short freshness lifetime:",
this._oneMonthExpirationCheck, resources, result);


this.execCheck("To further improve cache hit rate, specify an expiration one year in the future for the following cacheable resources:",
this._oneYearExpirationCheck, resources, result);
},

_missingExpirationCheck: function(resource)
{
return this.isCacheableResource(resource) && !this.hasResponseHeader(resource, "Set-Cookie") && !this.hasExplicitExpiration(resource);
},

_varyCheck: function(resource)
{
var varyHeader = this.responseHeader(resource, "Vary");
if (varyHeader) {
varyHeader = varyHeader.replace(/User-Agent/gi, "");
varyHeader = varyHeader.replace(/Accept-Encoding/gi, "");
varyHeader = varyHeader.replace(/[, ]*/g, "");
}
return varyHeader && varyHeader.length && this.isCacheableResource(resource) && this.freshnessLifetimeGreaterThan(resource, 0);
},

_oneMonthExpirationCheck: function(resource)
{
return this.isCacheableResource(resource) &&
!this.hasResponseHeader(resource, "Set-Cookie") &&
!this.freshnessLifetimeGreaterThan(resource, WebInspector.AuditRules.CacheControlRule.MillisPerMonth) &&
this.freshnessLifetimeGreaterThan(resource, 0);
},

_oneYearExpirationCheck: function(resource)
{
return this.isCacheableResource(resource) &&
!this.hasResponseHeader(resource, "Set-Cookie") &&
!this.freshnessLifetimeGreaterThan(resource, 11 * WebInspector.AuditRules.CacheControlRule.MillisPerMonth) &&
this.freshnessLifetimeGreaterThan(resource, WebInspector.AuditRules.CacheControlRule.MillisPerMonth);
}
}

WebInspector.AuditRules.BrowserCacheControlRule.prototype.__proto__ = WebInspector.AuditRules.CacheControlRule.prototype;


WebInspector.AuditRules.ProxyCacheControlRule = function() {
WebInspector.AuditRules.CacheControlRule.call(this, "http-proxycache", "Leverage proxy caching");
}

WebInspector.AuditRules.ProxyCacheControlRule.prototype = {
runChecks: function(resources, result, callback)
{
this.execCheck("Resources with a \"?\" in the URL are not cached by most proxy caching servers:",
this._questionMarkCheck, resources, result);
this.execCheck("Consider adding a \"Cache-Control: public\" header to the following resources:",
this._publicCachingCheck, resources, result);
this.execCheck("The following publicly cacheable resources contain a Set-Cookie header. This security vulnerability can cause cookies to be shared by multiple users.",
this._setCookieCacheableCheck, resources, result);
},

_questionMarkCheck: function(resource)
{
return resource.url.indexOf("?") >= 0 && !this.hasResponseHeader(resource, "Set-Cookie") && this.isPubliclyCacheable(resource);
},

_publicCachingCheck: function(resource)
{
return this.isCacheableResource(resource) &&
!this.isCompressible(resource) &&
!this.responseHeaderMatch(resource, "Cache-Control", "public") &&
!this.hasResponseHeader(resource, "Set-Cookie");
},

_setCookieCacheableCheck: function(resource)
{
return this.hasResponseHeader(resource, "Set-Cookie") && this.isPubliclyCacheable(resource);
}
}

WebInspector.AuditRules.ProxyCacheControlRule.prototype.__proto__ = WebInspector.AuditRules.CacheControlRule.prototype;


WebInspector.AuditRules.ImageDimensionsRule = function()
{
WebInspector.AuditRule.call(this, "page-imagedims", "Specify image dimensions");
}

WebInspector.AuditRules.ImageDimensionsRule.prototype = {
doRun: function(resources, result, callback)
{
var urlToNoDimensionCount = {};

function doneCallback()
{
for (var url in urlToNoDimensionCount) {
var entry = entry || result.addChild("A width and height should be specified for all images in order to speed up page display. The following image(s) are missing a width and/or height:", true);
var value = WebInspector.AuditRuleResult.linkifyDisplayName(url);
if (urlToNoDimensionCount[url] > 1)
value += String.sprintf(" (%d uses)", urlToNoDimensionCount[url]);
entry.addChild(value);
result.violationCount++;
}
callback(entry ? result : null);
}

function imageStylesReady(imageId, lastCall, styles)
{
const node = WebInspector.domAgent.nodeForId(imageId);
var src = node.getAttribute("src");
if (!src.asParsedURL()) {
for (var frameOwnerCandidate = node; frameOwnerCandidate; frameOwnerCandidate = frameOwnerCandidate.parentNode) {
if (frameOwnerCandidate.documentURL) {
var completeSrc = WebInspector.completeURL(frameOwnerCandidate.documentURL, src);
break;
}
}
}
if (completeSrc)
src = completeSrc;

const computedStyle = styles.computedStyle;
if (computedStyle.getPropertyValue("position") === "absolute") {
if (lastCall)
doneCallback();
return;
}

var widthFound = "width" in styles.styleAttributes;
var heightFound = "height" in styles.styleAttributes;

var inlineStyle = styles.inlineStyle;
if (inlineStyle) {
if (inlineStyle.getPropertyValue("width") !== "")
widthFound = true;
if (inlineStyle.getPropertyValue("height") !== "")
heightFound = true;
}

for (var i = styles.matchedCSSRules.length - 1; i >= 0 && !(widthFound && heightFound); --i) {
var style = styles.matchedCSSRules[i].style;
if (style.getPropertyValue("width") !== "")
widthFound = true;
if (style.getPropertyValue("height") !== "")
heightFound = true;
}

if (!widthFound || !heightFound) {
if (src in urlToNoDimensionCount)
++urlToNoDimensionCount[src];
else
urlToNoDimensionCount[src] = 1;
}

if (lastCall)
doneCallback();
}

function getStyles(nodeIds)
{
for (var i = 0; nodeIds && i < nodeIds.length; ++i)
WebInspector.cssModel.getStylesAsync(nodeIds[i], imageStylesReady.bind(this, nodeIds[i], i === nodeIds.length - 1));
}

function onDocumentAvailable(root)
{
WebInspector.domAgent.querySelectorAll(root.id, "img[src]", getStyles);
}

WebInspector.domAgent.requestDocument(onDocumentAvailable);
}
}

WebInspector.AuditRules.ImageDimensionsRule.prototype.__proto__ = WebInspector.AuditRule.prototype;


WebInspector.AuditRules.CssInHeadRule = function()
{
WebInspector.AuditRule.call(this, "page-cssinhead", "Put CSS in the document head");
}

WebInspector.AuditRules.CssInHeadRule.prototype = {
doRun: function(resources, result, callback)
{
function evalCallback(evalResult)
{
if (!evalResult)
return callback(null);

var summary = result.addChild("");

var outputMessages = [];
for (var url in evalResult) {
var urlViolations = evalResult[url];
if (urlViolations[0]) {
result.addChild(String.sprintf("%s style block(s) in the %s body should be moved to the document head.", urlViolations[0], WebInspector.AuditRuleResult.linkifyDisplayName(url)));
result.violationCount += urlViolations[0];
}
for (var i = 0; i < urlViolations[1].length; ++i)
result.addChild(String.sprintf("Link node %s should be moved to the document head in %s", WebInspector.AuditRuleResult.linkifyDisplayName(urlViolations[1][i]), WebInspector.AuditRuleResult.linkifyDisplayName(url)));
result.violationCount += urlViolations[1].length;
}
summary.value = String.sprintf("CSS in the document body adversely impacts rendering performance.");
callback(result);
}

function externalStylesheetsReceived(root, inlineStyleNodeIds, nodeIds)
{
if (!nodeIds)
return;
var externalStylesheetNodeIds = nodeIds;
var result = null;
if (inlineStyleNodeIds.length || externalStylesheetNodeIds.length) {
var urlToViolationsArray = {};
var externalStylesheetHrefs = [];
for (var j = 0; j < externalStylesheetNodeIds.length; ++j) {
var linkNode = WebInspector.domAgent.nodeForId(externalStylesheetNodeIds[j]);
var completeHref = WebInspector.completeURL(linkNode.ownerDocument.documentURL, linkNode.getAttribute("href"));
externalStylesheetHrefs.push(completeHref || "<empty>");
}
urlToViolationsArray[root.documentURL] = [inlineStyleNodeIds.length, externalStylesheetHrefs];
result = urlToViolationsArray;
}
evalCallback(result);
}

function inlineStylesReceived(root, nodeIds)
{
if (!nodeIds)
return;
WebInspector.domAgent.querySelectorAll(root.id, "body link[rel~='stylesheet'][href]", externalStylesheetsReceived.bind(null, root, nodeIds));
}

function onDocumentAvailable(root)
{
WebInspector.domAgent.querySelectorAll(root.id, "body style", inlineStylesReceived.bind(null, root));
}

WebInspector.domAgent.requestDocument(onDocumentAvailable);
}
}

WebInspector.AuditRules.CssInHeadRule.prototype.__proto__ = WebInspector.AuditRule.prototype;


WebInspector.AuditRules.StylesScriptsOrderRule = function()
{
WebInspector.AuditRule.call(this, "page-stylescriptorder", "Optimize the order of styles and scripts");
}

WebInspector.AuditRules.StylesScriptsOrderRule.prototype = {
doRun: function(resources, result, callback)
{
function evalCallback(resultValue)
{
if (!resultValue)
return callback(null);

var lateCssUrls = resultValue[0];
var cssBeforeInlineCount = resultValue[1];

var entry = result.addChild("The following external CSS files were included after an external JavaScript file in the document head. To ensure CSS files are downloaded in parallel, always include external CSS before external JavaScript.", true);
entry.addURLs(lateCssUrls);
result.violationCount += lateCssUrls.length;

if (cssBeforeInlineCount) {
result.addChild(String.sprintf(" %d inline script block%s found in the head between an external CSS file and another resource. To allow parallel downloading, move the inline script before the external CSS file, or after the next resource.", cssBeforeInlineCount, cssBeforeInlineCount > 1 ? "s were" : " was"));
result.violationCount += cssBeforeInlineCount;
}
callback(result);
}

function cssBeforeInlineReceived(lateStyleIds, nodeIds)
{
if (!nodeIds)
return;

var cssBeforeInlineCount = nodeIds.length;
var result = null;
if (lateStyleIds.length || cssBeforeInlineCount) {
var lateStyleUrls = [];
for (var i = 0; i < lateStyleIds.length; ++i) {
var lateStyleNode = WebInspector.domAgent.nodeForId(lateStyleIds[i]);
var completeHref = WebInspector.completeURL(lateStyleNode.ownerDocument.documentURL, lateStyleNode.getAttribute("href"));
lateStyleUrls.push(completeHref || "<empty>");
}
result = [ lateStyleUrls, cssBeforeInlineCount ];
}

evalCallback(result);
}

function lateStylesReceived(root, nodeIds)
{
if (!nodeIds)
return;

WebInspector.domAgent.querySelectorAll(root.id, "head link[rel~='stylesheet'][href] ~ script:not([src])", cssBeforeInlineReceived.bind(null, nodeIds));
}

function onDocumentAvailable(root)
{
WebInspector.domAgent.querySelectorAll(root.id, "head script[src] ~ link[rel~='stylesheet'][href]", lateStylesReceived.bind(null, root));
}

WebInspector.domAgent.requestDocument(onDocumentAvailable);
}
}

WebInspector.AuditRules.StylesScriptsOrderRule.prototype.__proto__ = WebInspector.AuditRule.prototype;


WebInspector.AuditRules.CookieRuleBase = function(id, name)
{
WebInspector.AuditRule.call(this, id, name);
}

WebInspector.AuditRules.CookieRuleBase.prototype = {
doRun: function(resources, result, callback)
{
var self = this;
function resultCallback(receivedCookies, isAdvanced) {
self.processCookies(isAdvanced ? receivedCookies : [], resources, result);
callback(result);
}
WebInspector.Cookies.getCookiesAsync(resultCallback);
},

mapResourceCookies: function(resourcesByDomain, allCookies, callback)
{
for (var i = 0; i < allCookies.length; ++i) {
for (var resourceDomain in resourcesByDomain) {
if (WebInspector.Cookies.cookieDomainMatchesResourceDomain(allCookies[i].domain, resourceDomain))
this._callbackForResourceCookiePairs(resourcesByDomain[resourceDomain], allCookies[i], callback);
}
}
},

_callbackForResourceCookiePairs: function(resources, cookie, callback)
{
if (!resources)
return;
for (var i = 0; i < resources.length; ++i) {
if (WebInspector.Cookies.cookieMatchesResourceURL(cookie, resources[i].url))
callback(resources[i], cookie);
}
}
}

WebInspector.AuditRules.CookieRuleBase.prototype.__proto__ = WebInspector.AuditRule.prototype;


WebInspector.AuditRules.CookieSizeRule = function(avgBytesThreshold)
{
WebInspector.AuditRules.CookieRuleBase.call(this, "http-cookiesize", "Minimize cookie size");
this._avgBytesThreshold = avgBytesThreshold;
this._maxBytesThreshold = 1000;
}

WebInspector.AuditRules.CookieSizeRule.prototype = {
_average: function(cookieArray)
{
var total = 0;
for (var i = 0; i < cookieArray.length; ++i)
total += cookieArray[i].size;
return cookieArray.length ? Math.round(total / cookieArray.length) : 0;
},

_max: function(cookieArray)
{
var result = 0;
for (var i = 0; i < cookieArray.length; ++i)
result = Math.max(cookieArray[i].size, result);
return result;
},

processCookies: function(allCookies, resources, result)
{
function maxSizeSorter(a, b)
{
return b.maxCookieSize - a.maxCookieSize;
}

function avgSizeSorter(a, b)
{
return b.avgCookieSize - a.avgCookieSize;
}

var cookiesPerResourceDomain = {};

function collectorCallback(resource, cookie)
{
var cookies = cookiesPerResourceDomain[resource.domain];
if (!cookies) {
cookies = [];
cookiesPerResourceDomain[resource.domain] = cookies;
}
cookies.push(cookie);
}

if (!allCookies.length)
return;

var sortedCookieSizes = [];

var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources,
null,
true);
var matchingResourceData = {};
this.mapResourceCookies(domainToResourcesMap, allCookies, collectorCallback.bind(this));

for (var resourceDomain in cookiesPerResourceDomain) {
var cookies = cookiesPerResourceDomain[resourceDomain];
sortedCookieSizes.push({
domain: resourceDomain,
avgCookieSize: this._average(cookies),
maxCookieSize: this._max(cookies)
});
}
var avgAllCookiesSize = this._average(allCookies);

var hugeCookieDomains = [];
sortedCookieSizes.sort(maxSizeSorter);

for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) {
var maxCookieSize = sortedCookieSizes[i].maxCookieSize;
if (maxCookieSize > this._maxBytesThreshold)
hugeCookieDomains.push(WebInspector.AuditRuleResult.resourceDomain(sortedCookieSizes[i].domain) + ": " + Number.bytesToString(maxCookieSize));
}

var bigAvgCookieDomains = [];
sortedCookieSizes.sort(avgSizeSorter);
for (var i = 0, len = sortedCookieSizes.length; i < len; ++i) {
var domain = sortedCookieSizes[i].domain;
var avgCookieSize = sortedCookieSizes[i].avgCookieSize;
if (avgCookieSize > this._avgBytesThreshold && avgCookieSize < this._maxBytesThreshold)
bigAvgCookieDomains.push(WebInspector.AuditRuleResult.resourceDomain(domain) + ": " + Number.bytesToString(avgCookieSize));
}
result.addChild(String.sprintf("The average cookie size for all requests on this page is %s", Number.bytesToString(avgAllCookiesSize)));

var message;
if (hugeCookieDomains.length) {
var entry = result.addChild("The following domains have a cookie size in excess of 1KB. This is harmful because requests with cookies larger than 1KB typically cannot fit into a single network packet.", true);
entry.addURLs(hugeCookieDomains);
result.violationCount += hugeCookieDomains.length;
}

if (bigAvgCookieDomains.length) {
var entry = result.addChild(String.sprintf("The following domains have an average cookie size in excess of %d bytes. Reducing the size of cookies for these domains can reduce the time it takes to send requests.", this._avgBytesThreshold), true);
entry.addURLs(bigAvgCookieDomains);
result.violationCount += bigAvgCookieDomains.length;
}
}
}

WebInspector.AuditRules.CookieSizeRule.prototype.__proto__ = WebInspector.AuditRules.CookieRuleBase.prototype;


WebInspector.AuditRules.StaticCookielessRule = function(minResources)
{
WebInspector.AuditRules.CookieRuleBase.call(this, "http-staticcookieless", "Serve static content from a cookieless domain");
this._minResources = minResources;
}

WebInspector.AuditRules.StaticCookielessRule.prototype = {
processCookies: function(allCookies, resources, result)
{
var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(resources,
[WebInspector.Resource.Type.Stylesheet,
WebInspector.Resource.Type.Image],
true);
var totalStaticResources = 0;
for (var domain in domainToResourcesMap)
totalStaticResources += domainToResourcesMap[domain].length;
if (totalStaticResources < this._minResources)
return;
var matchingResourceData = {};
this.mapResourceCookies(domainToResourcesMap, allCookies, this._collectorCallback.bind(this, matchingResourceData));

var badUrls = [];
var cookieBytes = 0;
for (var url in matchingResourceData) {
badUrls.push(url);
cookieBytes += matchingResourceData[url]
}
if (badUrls.length < this._minResources)
return;

var entry = result.addChild(String.sprintf("%s of cookies were sent with the following static resources. Serve these static resources from a domain that does not set cookies:", Number.bytesToString(cookieBytes)), true);
entry.addURLs(badUrls);
result.violationCount = badUrls.length;
},

_collectorCallback: function(matchingResourceData, resource, cookie)
{
matchingResourceData[resource.url] = (matchingResourceData[resource.url] || 0) + cookie.size;
}
}

WebInspector.AuditRules.StaticCookielessRule.prototype.__proto__ = WebInspector.AuditRules.CookieRuleBase.prototype;





WebInspector.AuditCategories.PagePerformance = function() {
WebInspector.AuditCategory.call(this, WebInspector.AuditCategories.PagePerformance.AuditCategoryName);
}

WebInspector.AuditCategories.PagePerformance.AuditCategoryName = "Web Page Performance";

WebInspector.AuditCategories.PagePerformance.prototype = {
initialize: function()
{
this.addRule(new WebInspector.AuditRules.UnusedCssRule(), WebInspector.AuditRule.Severity.Warning);
this.addRule(new WebInspector.AuditRules.CssInHeadRule(), WebInspector.AuditRule.Severity.Severe);
this.addRule(new WebInspector.AuditRules.StylesScriptsOrderRule(), WebInspector.AuditRule.Severity.Severe);
}
}

WebInspector.AuditCategories.PagePerformance.prototype.__proto__ = WebInspector.AuditCategory.prototype;

WebInspector.AuditCategories.NetworkUtilization = function() {
WebInspector.AuditCategory.call(this, WebInspector.AuditCategories.NetworkUtilization.AuditCategoryName);
}

WebInspector.AuditCategories.NetworkUtilization.AuditCategoryName = "Network Utilization";

WebInspector.AuditCategories.NetworkUtilization.prototype = {
initialize: function()
{
this.addRule(new WebInspector.AuditRules.GzipRule(), WebInspector.AuditRule.Severity.Severe);
this.addRule(new WebInspector.AuditRules.ImageDimensionsRule(), WebInspector.AuditRule.Severity.Warning);
this.addRule(new WebInspector.AuditRules.CookieSizeRule(400), WebInspector.AuditRule.Severity.Warning);
this.addRule(new WebInspector.AuditRules.StaticCookielessRule(5), WebInspector.AuditRule.Severity.Warning);
this.addRule(new WebInspector.AuditRules.CombineJsResourcesRule(2), WebInspector.AuditRule.Severity.Severe);
this.addRule(new WebInspector.AuditRules.CombineCssResourcesRule(2), WebInspector.AuditRule.Severity.Severe);
this.addRule(new WebInspector.AuditRules.MinimizeDnsLookupsRule(4), WebInspector.AuditRule.Severity.Warning);
this.addRule(new WebInspector.AuditRules.ParallelizeDownloadRule(4, 10, 0.5), WebInspector.AuditRule.Severity.Warning);
this.addRule(new WebInspector.AuditRules.BrowserCacheControlRule(), WebInspector.AuditRule.Severity.Severe);
this.addRule(new WebInspector.AuditRules.ProxyCacheControlRule(), WebInspector.AuditRule.Severity.Warning);
}
}

WebInspector.AuditCategories.NetworkUtilization.prototype.__proto__ = WebInspector.AuditCategory.prototype;





WebInspector.applyFormatters = function(value)
{
var formatter;
var type = typeof value;
var args;

switch (type) {
case "string":
case "boolean":
case "number":
formatter = WebInspector.AuditFormatters.text;
args = [ value.toString() ];
break;

case "object":
if (value instanceof Array) {
formatter = WebInspector.AuditFormatters.concat;
args = value;
} else if (value.type && value.arguments) {
formatter = WebInspector.AuditFormatters[value.type];
args = value.arguments;
}
}
if (!formatter)
throw "Invalid value or formatter: " + type + JSON.stringify(value);

return formatter.apply(null, args);
}

WebInspector.AuditFormatters = {
text: function(text)
{
return document.createTextNode(text);
},

snippet: function(snippetText)
{
var div = document.createElement("div");
div.textContent = snippetText;
div.className = "source-code";
return div;
},

concat: function()
{
var parent = document.createElement("span");
for (var arg = 0; arg < arguments.length; ++arg)
parent.appendChild(WebInspector.applyFormatters(arguments[arg]));
return parent;
},

url: function(url, displayText, allowExternalNavigation)
{
var a = document.createElement("a");
a.href = url;
a.title = url;
a.textContent = displayText || url;
if (allowExternalNavigation)
a.target = "_blank";
return a;
}
};





WebInspector.ResourceHeadersView = function(resource)
{
WebInspector.View.call(this);
this.element.addStyleClass("resource-headers-view");

this._resource = resource;

this._headersListElement = document.createElement("ol");
this._headersListElement.className = "outline-disclosure";
this.element.appendChild(this._headersListElement);

this._headersTreeOutline = new TreeOutline(this._headersListElement);
this._headersTreeOutline.expandTreeElementsWhenArrowing = true;

this._urlTreeElement = new TreeElement("", null, false);
this._urlTreeElement.selectable = false;
this._headersTreeOutline.appendChild(this._urlTreeElement);

this._requestMethodTreeElement = new TreeElement("", null, false);
this._requestMethodTreeElement.selectable = false;
this._headersTreeOutline.appendChild(this._requestMethodTreeElement);

this._statusCodeTreeElement = new TreeElement("", null, false);
this._statusCodeTreeElement.selectable = false;
this._headersTreeOutline.appendChild(this._statusCodeTreeElement);

this._requestHeadersTreeElement = new TreeElement("", null, true);
this._requestHeadersTreeElement.expanded = true;
this._requestHeadersTreeElement.selectable = false;
this._headersTreeOutline.appendChild(this._requestHeadersTreeElement);

this._decodeRequestParameters = true;

this._showRequestHeadersText = false;
this._showResponseHeadersText = false;

this._queryStringTreeElement = new TreeElement("", null, true);
this._queryStringTreeElement.expanded = true;
this._queryStringTreeElement.selectable = false;
this._queryStringTreeElement.hidden = true;
this._headersTreeOutline.appendChild(this._queryStringTreeElement);

this._formDataTreeElement = new TreeElement("", null, true);
this._formDataTreeElement.expanded = true;
this._formDataTreeElement.selectable = false;
this._formDataTreeElement.hidden = true;
this._headersTreeOutline.appendChild(this._formDataTreeElement);

this._requestPayloadTreeElement = new TreeElement(WebInspector.UIString("Request Payload"), null, true);
this._requestPayloadTreeElement.expanded = true;
this._requestPayloadTreeElement.selectable = false;
this._requestPayloadTreeElement.hidden = true;
this._headersTreeOutline.appendChild(this._requestPayloadTreeElement);

this._responseHeadersTreeElement = new TreeElement("", null, true);
this._responseHeadersTreeElement.expanded = true;
this._responseHeadersTreeElement.selectable = false;
this._headersTreeOutline.appendChild(this._responseHeadersTreeElement);

resource.addEventListener("requestHeaders changed", this._refreshRequestHeaders, this);
resource.addEventListener("responseHeaders changed", this._refreshResponseHeaders, this);
resource.addEventListener("finished", this._refreshHTTPInformation, this);

this._refreshURL();
this._refreshQueryString();
this._refreshRequestHeaders();
this._refreshResponseHeaders();
this._refreshHTTPInformation();
}

WebInspector.ResourceHeadersView.prototype = {

_refreshURL: function()
{
this._urlTreeElement.titleHTML = "<div class=\"header-name\">" + WebInspector.UIString("Request URL") + ":</div>" +
"<div class=\"header-value source-code\">" + this._resource.url.escapeHTML() + "</div>";
},

_refreshQueryString: function()
{
var queryParameters = this._resource.queryParameters;
this._queryStringTreeElement.hidden = !queryParameters;
if (queryParameters)
this._refreshParms(WebInspector.UIString("Query String Parameters"), queryParameters, this._queryStringTreeElement);
},

_refreshFormData: function()
{
this._formDataTreeElement.hidden = true;
this._requestPayloadTreeElement.hidden = true;

var formData = this._resource.requestFormData;
if (!formData)
return;

var formParameters = this._resource.formParameters;
if (formParameters) {
this._formDataTreeElement.hidden = false;
this._refreshParms(WebInspector.UIString("Form Data"), formParameters, this._formDataTreeElement);
} else {
this._requestPayloadTreeElement.hidden = false;
this._refreshRequestPayload(formData);
}
},

_refreshRequestPayload: function(formData)
{
this._requestPayloadTreeElement.removeChildren();

var title = "<div class=\"raw-form-data header-value source-code\">" + formData.escapeHTML() + "</div>";
var parmTreeElement = new TreeElement(null, null, false);
parmTreeElement.titleHTML = title;
parmTreeElement.selectable = false;
this._requestPayloadTreeElement.appendChild(parmTreeElement);
},

_refreshParms: function(title, parms, parmsTreeElement)
{
parmsTreeElement.removeChildren();

parmsTreeElement.listItemElement.removeChildren();
parmsTreeElement.listItemElement.appendChild(document.createTextNode(title));

var headerCount = document.createElement("span");
headerCount.addStyleClass("header-count");
headerCount.textContent = WebInspector.UIString(" (%d)", parms.length);
parmsTreeElement.listItemElement.appendChild(headerCount);

var toggleTitle = this._decodeRequestParameters ? WebInspector.UIString("view URL encoded") : WebInspector.UIString("view decoded");
var toggleButton = this._createToggleButton(toggleTitle);
toggleButton.addEventListener("click", this._toggleURLdecoding.bind(this));
parmsTreeElement.listItemElement.appendChild(toggleButton);


for (var i = 0; i < parms.length; ++i) {
var name = parms[i].name;
var value = parms[i].value;

var errorDecoding = false;
if (this._decodeRequestParameters) {
if (value.indexOf("%") >= 0) {
try {
value = decodeURIComponent(value);
} catch(e) {
errorDecoding = true;
}
}

value = value.replace(/\+/g, " ");
}

valueEscaped = value.escapeHTML();
if (errorDecoding)
valueEscaped += " <span class=\"error-message\">" + WebInspector.UIString("(unable to decode value)").escapeHTML() + "</span>";

var title = "<div class=\"header-name\">" + name.escapeHTML() + ":</div>";
title += "<div class=\"header-value source-code\">" + valueEscaped + "</div>";

var parmTreeElement = new TreeElement(null, null, false);
parmTreeElement.titleHTML = title;
parmTreeElement.selectable = false;
parmsTreeElement.appendChild(parmTreeElement);
}
},

_toggleURLdecoding: function(event)
{
this._decodeRequestParameters = !this._decodeRequestParameters;
this._refreshQueryString();
this._refreshFormData();
},

_getHeaderValue: function(headers, key)
{
var lowerKey = key.toLowerCase();
for (var testKey in headers) {
if (testKey.toLowerCase() === lowerKey)
return headers[testKey];
}
},

_refreshRequestHeaders: function()
{
var additionalRow = null;
if (typeof this._resource.webSocketRequestKey3 !== "undefined")
additionalRow = {header: "(Key3)", value: this._resource.webSocketRequestKey3};
if (this._showRequestHeadersText)
this._refreshHeadersText(WebInspector.UIString("Request Headers"), this._resource.requestHeadersText, this._requestHeadersTreeElement);
else 
this._refreshHeaders(WebInspector.UIString("Request Headers"), this._resource.sortedRequestHeaders, additionalRow, this._requestHeadersTreeElement);

if (this._resource.requestHeadersText) { 
var toggleButton = this._createHeadersToggleButton(this._showRequestHeadersText);
toggleButton.addEventListener("click", this._toggleRequestHeadersText.bind(this));
this._requestHeadersTreeElement.listItemElement.appendChild(toggleButton);
}

this._refreshFormData();
},

_refreshResponseHeaders: function()
{
var additionalRow = null;
if (typeof this._resource.webSocketChallengeResponse !== "undefined")
additionalRow = {header: "(Challenge Response)", value: this._resource.webSocketChallengeResponse};
if (this._showResponseHeadersText)
this._refreshHeadersText(WebInspector.UIString("Response Headers"), this._resource.responseHeadersText, this._responseHeadersTreeElement);
else
this._refreshHeaders(WebInspector.UIString("Response Headers"), this._resource.sortedResponseHeaders, additionalRow, this._responseHeadersTreeElement);

if (this._resource.responseHeadersText) {
var toggleButton = this._createHeadersToggleButton(this._showResponseHeadersText);
toggleButton.addEventListener("click", this._toggleResponseHeadersText.bind(this));
this._responseHeadersTreeElement.listItemElement.appendChild(toggleButton);
}
},

_refreshHTTPInformation: function()
{
var requestMethodElement = this._requestMethodTreeElement;
requestMethodElement.hidden = !this._resource.statusCode;
var statusCodeElement = this._statusCodeTreeElement;
statusCodeElement.hidden = !this._resource.statusCode;
var statusCodeImage = "";

if (this._resource.statusCode) {
var statusImageSource = "";
if (this._resource.statusCode < 300 || this._resource.statusCode === 304)
statusImageSource = "Images/successGreenDot.png";
else if (this._resource.statusCode < 400)
statusImageSource = "Images/warningOrangeDot.png";
else
statusImageSource = "Images/errorRedDot.png";

var statusTextEscaped = this._resource.statusCode + " " + this._resource.statusText.escapeHTML();
statusCodeImage = "<img class=\"resource-status-image\" src=\"" + statusImageSource + "\" title=\"" + statusTextEscaped + "\">";

requestMethodElement.titleHTML = "<div class=\"header-name\">" + WebInspector.UIString("Request Method") + ":</div>" +
"<div class=\"header-value source-code\">" + this._resource.requestMethod + "</div>";

statusCodeElement.titleHTML = "<div class=\"header-name\">" + WebInspector.UIString("Status Code") + ":</div>" +
statusCodeImage + "<div class=\"header-value source-code\">" + statusTextEscaped + "</div>";
}
},

_refreshHeadersTitle: function(title, headersTreeElement, isHeadersTextShown, headersLength)
{
headersTreeElement.listItemElement.removeChildren();
headersTreeElement.listItemElement.appendChild(document.createTextNode(title));

if (!isHeadersTextShown) {
var headerCount = document.createElement("span");
headerCount.addStyleClass("header-count");
headerCount.textContent = WebInspector.UIString(" (%d)", headersLength);
headersTreeElement.listItemElement.appendChild(headerCount);
}
},

_refreshHeaders: function(title, headers, additionalRow, headersTreeElement)
{
headersTreeElement.removeChildren();

var length = headers.length;
this._refreshHeadersTitle(title, headersTreeElement, false, length);
headersTreeElement.hidden = !length;
for (var i = 0; i < length; ++i) {
var title = "<div class=\"header-name\">" + headers[i].header.escapeHTML() + ":</div>";
title += "<div class=\"header-value source-code\">" + headers[i].value.escapeHTML() + "</div>"

var headerTreeElement = new TreeElement(null, null, false);
headerTreeElement.titleHTML = title;
headerTreeElement.selectable = false;
headersTreeElement.appendChild(headerTreeElement);
}

if (additionalRow) {
var title = "<div class=\"header-name\">" + additionalRow.header.escapeHTML() + ":</div>";
title += "<div class=\"header-value source-code\">" + additionalRow.value.escapeHTML() + "</div>"

var headerTreeElement = new TreeElement(null, null, false);
headerTreeElement.titleHTML = title;
headerTreeElement.selectable = false;
headersTreeElement.appendChild(headerTreeElement);
}
},

_refreshHeadersText: function(title, headersText, headersTreeElement)
{
headersTreeElement.removeChildren();

this._refreshHeadersTitle(title, headersTreeElement, true);
var headerTreeElement = new TreeElement(null, null, false);
headerTreeElement.selectable = false;
headersTreeElement.appendChild(headerTreeElement);
headerTreeElement.listItemElement.addStyleClass("headers-text");

var headersTextElement = document.createElement("span");
headersTextElement.addStyleClass("header-value");
headersTextElement.addStyleClass("source-code");
headersTextElement.textContent = String(headersText).trim();
headerTreeElement.listItemElement.appendChild(headersTextElement);
},

_toggleRequestHeadersText: function(event)
{
this._showRequestHeadersText = !this._showRequestHeadersText;
this._refreshRequestHeaders();
},

_toggleResponseHeadersText: function(event)
{
this._showResponseHeadersText = !this._showResponseHeadersText;
this._refreshResponseHeaders();
},

_createToggleButton: function(title)
{
var button = document.createElement("span");
button.addStyleClass("header-toggle");
button.textContent = title;
return button;
},

_createHeadersToggleButton: function(isHeadersTextShown)
{
var toggleTitle = isHeadersTextShown ? WebInspector.UIString("view parsed") : WebInspector.UIString("view source");
return this._createToggleButton(toggleTitle);
}
}

WebInspector.ResourceHeadersView.prototype.__proto__ = WebInspector.View.prototype;





WebInspector.ResourceCookiesView = function(resource)
{
WebInspector.View.call(this);
this.element.addStyleClass("resource-cookies-view");

this._resource = resource;

resource.addEventListener("requestHeaders changed", this._refreshCookies, this);
resource.addEventListener("responseHeaders changed", this._refreshCookies, this);
}

WebInspector.ResourceCookiesView.prototype = {
show: function(parentElement)
{
if (!this._gotCookies) {
if (!this._emptyMsgElement) {
this._emptyMsgElement = document.createElement("div");
this._emptyMsgElement.className = "storage-empty-view";
this._emptyMsgElement.textContent = WebInspector.UIString("This request has no cookies.");
this.element.appendChild(this._emptyMsgElement);
}
WebInspector.View.prototype.show.call(this, parentElement);
return;
}

if (!this._cookiesTable)
this._buildCookiesTable();
WebInspector.View.prototype.show.call(this, parentElement);
this._cookiesTable.updateWidths();
},

get _gotCookies()
{
return !!(this._resource.requestCookies || this._resource.responseCookies);
},

_buildCookiesTable: function()
{
this.element.removeChildren();

this._cookiesTable = new WebInspector.CookiesTable(null, true, true);
this._cookiesTable.addCookiesFolder(WebInspector.UIString("Request Cookies"), this._resource.requestCookies);
this._cookiesTable.addCookiesFolder(WebInspector.UIString("Response Cookies"), this._resource.responseCookies);
this.element.appendChild(this._cookiesTable.element);
},

_refreshCookies: function()
{
delete this._cookiesTable;
if (!this._gotCookies || !this.visible)
return;
this._buildCookiesTable();
this._cookiesTable.updateWidths();
}
}

WebInspector.ResourceCookiesView.prototype.__proto__ = WebInspector.View.prototype;





WebInspector.ResourceTimingView = function(resource)
{
WebInspector.View.call(this);
this.element.addStyleClass("resource-timing-view");

this._resource = resource;

resource.addEventListener("timing changed", this._refresh, this);
}

WebInspector.ResourceTimingView.prototype = {
show: function(parentElement)
{
if (!this._resource.timing) {
if (!this._emptyMsgElement) {
this._emptyMsgElement = document.createElement("div");
this._emptyMsgElement.className = "storage-empty-view";
this._emptyMsgElement.textContent = WebInspector.UIString("This request has no detailed timing info.");
this.element.appendChild(this._emptyMsgElement);
}
WebInspector.View.prototype.show.call(this, parentElement);
return;
}

if (this._emptyMsgElement)
this._emptyMsgElement.parentElement.removeChild(this._emptyMsgElement);

this._refresh();
WebInspector.View.prototype.show.call(this, parentElement);
},

_refresh: function()
{
if (this._tableElement)
this._tableElement.parentElement.removeChild(this._tableElement);

this._tableElement = WebInspector.ResourceTimingView.createTimingTable(this._resource);
this.element.appendChild(this._tableElement);
}
}

WebInspector.ResourceTimingView.createTimingTable = function(resource)
{
var tableElement = document.createElement("table");
var rows = [];

function addRow(title, className, start, end, color)
{
var row = {};
row.title = title;
row.className = className;
row.start = start;
row.end = end;
rows.push(row);
}

if (resource.timing.proxyStart !== -1)
addRow(WebInspector.UIString("Proxy"), "proxy", resource.timing.proxyStart, resource.timing.proxyEnd);

if (resource.timing.dnsStart !== -1)
addRow(WebInspector.UIString("DNS Lookup"), "dns", resource.timing.dnsStart, resource.timing.dnsEnd);

if (resource.timing.connectStart !== -1) {
if (resource.connectionReused)
addRow(WebInspector.UIString("Blocking"), "connecting", resource.timing.connectStart, resource.timing.connectEnd);
else {
var connectStart = resource.timing.connectStart;

if (resource.timing.dnsStart !== -1)
connectStart += resource.timing.dnsEnd - resource.timing.dnsStart;
addRow(WebInspector.UIString("Connecting"), "connecting", connectStart, resource.timing.connectEnd);
}
}

if (resource.timing.sslStart !== -1)
addRow(WebInspector.UIString("SSL"), "ssl", resource.timing.sslStart, resource.timing.sslEnd);

var sendStart = resource.timing.sendStart;
if (resource.timing.sslStart !== -1)
sendStart += resource.timing.sslEnd - resource.timing.sslStart;

addRow(WebInspector.UIString("Sending"), "sending", resource.timing.sendStart, resource.timing.sendEnd);
addRow(WebInspector.UIString("Waiting"), "waiting", resource.timing.sendEnd, resource.timing.receiveHeadersEnd);
addRow(WebInspector.UIString("Receiving"), "receiving", (resource.responseReceivedTime - resource.timing.requestTime) * 1000, (resource.endTime - resource.timing.requestTime) * 1000);

const chartWidth = 200;
var total = (resource.endTime - resource.timing.requestTime) * 1000;
var scale = chartWidth / total;

for (var i = 0; i < rows.length; ++i) {
var tr = document.createElement("tr");
tableElement.appendChild(tr);

var td = document.createElement("td");
td.textContent = rows[i].title;
tr.appendChild(td);

td = document.createElement("td");
td.width = chartWidth + "px";

var row = document.createElement("div");
row.className = "network-timing-row";
td.appendChild(row);

var bar = document.createElement("span");
bar.className = "network-timing-bar " + rows[i].className;
bar.style.left = scale * rows[i].start + "px";
bar.style.right = scale * (total - rows[i].end) + "px";
bar.style.backgroundColor = rows[i].color;
bar.textContent = "\u200B"; 
row.appendChild(bar);

var title = document.createElement("span");
title.className = "network-timing-bar-title";
if (total - rows[i].end < rows[i].start)
title.style.right = (scale * (total - rows[i].end) + 3) + "px";
else
title.style.left = (scale * rows[i].start + 3) + "px";
title.textContent = Number.millisToString(rows[i].end - rows[i].start);
row.appendChild(title);

tr.appendChild(td);
}
return tableElement;
}

WebInspector.ResourceTimingView.prototype.__proto__ = WebInspector.View.prototype;





WebInspector.ResourceJSONView = function(resource, parsedJSON)
{
WebInspector.ResourceView.call(this, resource);
this._parsedJSON = parsedJSON;
this.element.addStyleClass("json");
}

WebInspector.ResourceJSONView.parseJSON = function(text)
{

var start = /[{[]/.exec(text);
if (start && start.index)
text = text.substring(start.index);

try {
return JSON.parse(text);
} catch (e) {
return;
}
}

WebInspector.ResourceJSONView.prototype = {
hasContent: function()
{
return true;
},

show: function(parentElement)
{
WebInspector.ResourceView.prototype.show.call(this, parentElement);
this._initialize();
},

_initialize: function()
{
if (this._initialized)
return;
this._initialized = true;

var obj = WebInspector.RemoteObject.fromLocalObject(this._parsedJSON);
this.element.appendChild(new WebInspector.ObjectPropertiesSection(obj, obj.description).element);
}
}

WebInspector.ResourceJSONView.prototype.__proto__ = WebInspector.ResourceView.prototype;





WebInspector.NetworkItemView = function(resource)
{
WebInspector.View.call(this);

this.element.addStyleClass("network-item-view");

this._headersView = new WebInspector.ResourceHeadersView(resource);
this._tabbedPane = new WebInspector.TabbedPane(this.element);
this._tabbedPane.appendTab("headers", WebInspector.UIString("Headers"), this._headersView);

var contentView = WebInspector.NetworkItemView._contentViewForResource(resource);
if (contentView.hasContent())
this._tabbedPane.appendTab("content", WebInspector.UIString("Content"), contentView);

if (resource.type === WebInspector.Resource.Type.XHR && resource.content) {
var parsedJSON = WebInspector.ResourceJSONView.parseJSON(resource.content);
if (parsedJSON) {
var jsonView = new WebInspector.ResourceJSONView(resource, parsedJSON);
this._tabbedPane.appendTab("json", WebInspector.UIString("JSON"), jsonView);
}
}

if (Preferences.showCookiesTab) {
this._cookiesView = new WebInspector.ResourceCookiesView(resource);
this._tabbedPane.appendTab("cookies", WebInspector.UIString("Cookies"), this._cookiesView);
}

if (Preferences.showTimingTab) {
var timingView = new WebInspector.ResourceTimingView(resource);
this._tabbedPane.appendTab("timing", WebInspector.UIString("Timing"), timingView);
}

this._tabbedPane.addEventListener("tab-selected", this._tabSelected, this);
}

WebInspector.NetworkItemView._contentViewForResource = function(resource)
{
if (WebInspector.ResourceView.hasTextContent(resource))
return new WebInspector.ResourceSourceFrame(resource)
return WebInspector.ResourceView.nonSourceViewForResource(resource);
}

WebInspector.NetworkItemView.prototype = {
show: function(parentElement)
{
WebInspector.View.prototype.show.call(this, parentElement);
this._selectTab();
},

_selectTab: function(tabId)
{
if (!tabId)
tabId = WebInspector.settings.resourceViewTab;

if (!this._tabbedPane.selectTab(tabId)) {
this._isInFallbackSelection = true;
this._tabbedPane.selectTab("headers");
delete this._isInFallbackSelection;
}
},

_tabSelected: function(event)
{
if (event.data.isUserGesture)
WebInspector.settings.resourceViewTab = event.data.tabId;
this._installHighlightSupport(event.data.view);
},

_installHighlightSupport: function(view)
{
if (typeof view.highlightLine === "function")
this.highlightLine = view.highlightLine.bind(view);
else
delete this.highlightLine;
},

resize: function()
{
if (this._cookiesView && this._cookiesView.visible)
this._cookiesView.resize();
}
}

WebInspector.NetworkItemView.prototype.__proto__ = WebInspector.View.prototype;





WebInspector.ScriptFormatter = function()
{
this._worker = new Worker("ScriptFormatterWorker.js");
this._worker.onmessage = this._didFormatContent.bind(this);
this._tasks = [];
}

WebInspector.ScriptFormatter.locationToPosition = function(lineEndings, location)
{
var position = location.lineNumber ? lineEndings[location.lineNumber - 1] + 1 : 0;
return position + location.columnNumber;
}

WebInspector.ScriptFormatter.positionToLocation = function(lineEndings, position)
{
var location = {};
location.lineNumber = lineEndings.upperBound(position - 1);
if (!location.lineNumber)
location.columnNumber = position;
else
location.columnNumber = position - lineEndings[location.lineNumber - 1] - 1;
return location;
}

WebInspector.ScriptFormatter.prototype = {
formatContent: function(mimeType, content, callback)
{
content = content.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '');
var data = { mimeType: mimeType, content: content };
this._tasks.push({ data: data, callback: callback });
this._worker.postMessage(data);
},

_didFormatContent: function(event)
{
var task = this._tasks.shift();
var originalContent = task.data.content;
var formattedContent = event.data.content;
var sourceMapping = new WebInspector.FormattedSourceMapping(originalContent.lineEndings(), formattedContent.lineEndings(), event.data.mapping);
task.callback(formattedContent, sourceMapping);
}
}

WebInspector.FormattedSourceMapping = function(originalLineEndings, formattedLineEndings, mapping)
{
this._originalLineEndings = originalLineEndings;
this._formattedLineEndings = formattedLineEndings;
this._mapping = mapping;
}

WebInspector.FormattedSourceMapping.prototype = {
originalToFormatted: function(location)
{
var originalPosition = WebInspector.ScriptFormatter.locationToPosition(this._originalLineEndings, location);
var formattedPosition = this._convertPosition(this._mapping.original, this._mapping.formatted, originalPosition);
return WebInspector.ScriptFormatter.positionToLocation(this._formattedLineEndings, formattedPosition);
},

formattedToOriginal: function(location)
{
var formattedPosition = WebInspector.ScriptFormatter.locationToPosition(this._formattedLineEndings, location);
var originalPosition = this._convertPosition(this._mapping.formatted, this._mapping.original, formattedPosition);
return WebInspector.ScriptFormatter.positionToLocation(this._originalLineEndings, originalPosition);
},

_convertPosition: function(positions1, positions2, position)
{
var index = positions1.upperBound(position) - 1;
var convertedPosition = positions2[index] + position - positions1[index];
if (index < positions2.length - 1 && convertedPosition > positions2[index + 1])
convertedPosition = positions2[index + 1];
return convertedPosition;
}
}





WebInspector.DOMSyntaxHighlighter = function(mimeType, stripExtraWhitespace)
{
this._tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(mimeType);
this._stripExtraWhitespace = stripExtraWhitespace;
}

WebInspector.DOMSyntaxHighlighter.prototype = {
createSpan: function(content, className)
{
var span = document.createElement("span");
span.className = "webkit-" + className;
if (this._stripExtraWhitespace)
content = content.replace(/^[\n\r]*/, "").replace(/\s*$/, "");
span.appendChild(document.createTextNode(content));
return span;
},

syntaxHighlightNode: function(node)
{
this._tokenizer.condition = this._tokenizer.createInitialCondition();
var lines = node.textContent.split("\n");
node.removeChildren();

for (var i = lines[0].length ? 0 : 1; i < lines.length; ++i) {
var line = lines[i];
var plainTextStart = 0;
this._tokenizer.line = line;
var column = 0;
do {
var newColumn = this._tokenizer.nextToken(column);
var tokenType = this._tokenizer.tokenType;
if (tokenType) {
if (column > plainTextStart) {
var plainText = line.substring(plainTextStart, column);
node.appendChild(document.createTextNode(plainText));
}
var token = line.substring(column, newColumn);
node.appendChild(this.createSpan(token, tokenType));
plainTextStart = newColumn;
}
column = newColumn;
} while (column < line.length)

if (plainTextStart < line.length) {
var plainText = line.substring(plainTextStart, line.length);
node.appendChild(document.createTextNode(plainText));
}
if (i < lines.length - 1)
node.appendChild(document.createElement("br"));
}
}
}





WebInspector.TextRange = function(startLine, startColumn, endLine, endColumn)
{
this.startLine = startLine;
this.startColumn = startColumn;
this.endLine = endLine;
this.endColumn = endColumn;
}

WebInspector.TextRange.prototype = {
isEmpty: function()
{
return this.startLine === this.endLine && this.startColumn === this.endColumn;
},

get linesCount()
{
return this.endLine - this.startLine;
},

clone: function()
{
return new WebInspector.TextRange(this.startLine, this.startColumn, this.endLine, this.endColumn); 
}
}

WebInspector.TextEditorModel = function()
{
this._lines = [""];
this._attributes = [];
this._undoStack = [];
this._noPunctuationRegex = /[^ !%&()*+,-.:;<=>?\[\]\^{|}~]+/;
this._lineBreak = "\n";
}

WebInspector.TextEditorModel.prototype = {
set changeListener(changeListener)
{
this._changeListener = changeListener;
},

get linesCount()
{
return this._lines.length;
},

get text()
{
return this._lines.join(this._lineBreak);
},

line: function(lineNumber)
{
if (lineNumber >= this._lines.length)
throw "Out of bounds:" + lineNumber;
return this._lines[lineNumber];
},

lineLength: function(lineNumber)
{
return this._lines[lineNumber].length;
},

setText: function(range, text)
{
text = text || "";
if (!range) {
range = new WebInspector.TextRange(0, 0, this._lines.length - 1, this._lines[this._lines.length - 1].length);
this._lineBreak = /\r\n/.test(text) ? "\r\n" : "\n";
}
var command = this._pushUndoableCommand(range);
var newRange = this._innerSetText(range, text);
command.range = newRange.clone();

if (this._changeListener)
this._changeListener(range, newRange, command.text, text);
return newRange;
},

set replaceTabsWithSpaces(replaceTabsWithSpaces)
{
this._replaceTabsWithSpaces = replaceTabsWithSpaces;
},

_innerSetText: function(range, text)
{
this._eraseRange(range);
if (text === "")
return new WebInspector.TextRange(range.startLine, range.startColumn, range.startLine, range.startColumn);

var newLines = text.split(/\r?\n/);
this._replaceTabsIfNeeded(newLines);

var prefix = this._lines[range.startLine].substring(0, range.startColumn);
var suffix = this._lines[range.startLine].substring(range.startColumn);

var postCaret = prefix.length;

if (newLines.length === 1) {
this._setLine(range.startLine, prefix + newLines[0] + suffix);
postCaret += newLines[0].length;
} else {
this._setLine(range.startLine, prefix + newLines[0]);
for (var i = 1; i < newLines.length; ++i)
this._insertLine(range.startLine + i, newLines[i]);
this._setLine(range.startLine + newLines.length - 1, newLines[newLines.length - 1] + suffix);
postCaret = newLines[newLines.length - 1].length;
}
return new WebInspector.TextRange(range.startLine, range.startColumn,
range.startLine + newLines.length - 1, postCaret);
},

_replaceTabsIfNeeded: function(lines)
{
if (!this._replaceTabsWithSpaces)
return;
var spaces = [ "    ", "   ", "  ", " "];
for (var i = 0; i < lines.length; ++i) {
var line = lines[i];
var index = line.indexOf("\t");
while (index !== -1) {
line = line.substring(0, index) + spaces[index % 4] + line.substring(index + 1);
index = line.indexOf("\t", index + 1);
}
lines[i] = line;
}
},

_eraseRange: function(range)
{
if (range.isEmpty())
return;

var prefix = this._lines[range.startLine].substring(0, range.startColumn);
var suffix = this._lines[range.endLine].substring(range.endColumn);

if (range.endLine > range.startLine)
this._removeLines(range.startLine + 1, range.endLine - range.startLine);
this._setLine(range.startLine, prefix + suffix);
},

_setLine: function(lineNumber, text)
{
this._lines[lineNumber] = text;
},

_removeLines: function(fromLine, count)
{
this._lines.splice(fromLine, count);
this._attributes.splice(fromLine, count);
},

_insertLine: function(lineNumber, text)
{
this._lines.splice(lineNumber, 0, text);
this._attributes.splice(lineNumber, 0, {});
},

wordRange: function(lineNumber, column)
{
return new WebInspector.TextRange(lineNumber, this.wordStart(lineNumber, column, true), lineNumber, this.wordEnd(lineNumber, column, true));
},

wordStart: function(lineNumber, column, gapless)
{
var line = this._lines[lineNumber];
var prefix = line.substring(0, column).split("").reverse().join("");
var prefixMatch = this._noPunctuationRegex.exec(prefix);
return prefixMatch && (!gapless || prefixMatch.index === 0) ? column - prefixMatch.index - prefixMatch[0].length : column;
},

wordEnd: function(lineNumber, column, gapless)
{
var line = this._lines[lineNumber];
var suffix = line.substring(column);
var suffixMatch = this._noPunctuationRegex.exec(suffix);
return suffixMatch && (!gapless || suffixMatch.index === 0) ? column + suffixMatch.index + suffixMatch[0].length : column;
},

copyRange: function(range)
{
if (!range)
range = new WebInspector.TextRange(0, 0, this._lines.length - 1, this._lines[this._lines.length - 1].length);

var clip = [];
if (range.startLine === range.endLine) {
clip.push(this._lines[range.startLine].substring(range.startColumn, range.endColumn));
return clip.join(this._lineBreak);
}
clip.push(this._lines[range.startLine].substring(range.startColumn));
for (var i = range.startLine + 1; i < range.endLine; ++i)
clip.push(this._lines[i]);
clip.push(this._lines[range.endLine].substring(0, range.endColumn));
return clip.join(this._lineBreak);
},

setAttribute: function(line, name, value)
{
var attrs = this._attributes[line];
if (!attrs) {
attrs = {};
this._attributes[line] = attrs;
}
attrs[name] = value;
},

getAttribute: function(line, name)
{
var attrs = this._attributes[line];
return attrs ? attrs[name] : null;
},

removeAttribute: function(line, name)
{
var attrs = this._attributes[line];
if (attrs)
delete attrs[name];
},

_pushUndoableCommand: function(range)
{
var command = {
text: this.copyRange(range),
startLine: range.startLine,
startColumn: range.startColumn,
endLine: range.startLine,
endColumn: range.startColumn
};
if (this._inUndo)
this._redoStack.push(command);
else {
if (!this._inRedo)
this._redoStack = [];
this._undoStack.push(command);
}
return command;
},

undo: function(callback)
{
this._markRedoableState();

this._inUndo = true;
var range = this._doUndo(this._undoStack, callback);
delete this._inUndo;

return range;
},

redo: function(callback)
{
this.markUndoableState();

this._inRedo = true;
var range = this._doUndo(this._redoStack, callback);
delete this._inRedo;

return range;
},

_doUndo: function(stack, callback)
{
var range = null;
for (var i = stack.length - 1; i >= 0; --i) {
var command = stack[i];
stack.length = i;

range = this.setText(command.range, command.text);
if (callback)
callback(command.range, range);
if (i > 0 && stack[i - 1].explicit)
return range;
}
return range;
},

markUndoableState: function()
{
if (this._undoStack.length)
this._undoStack[this._undoStack.length - 1].explicit = true;
},

_markRedoableState: function()
{
if (this._redoStack.length)
this._redoStack[this._redoStack.length - 1].explicit = true;
},

resetUndoStack: function()
{
this._undoStack = [];
}
}





WebInspector.TextEditorHighlighter = function(textModel, damageCallback)
{
this._textModel = textModel;
this._tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/html");
this._damageCallback = damageCallback;
this._highlightChunkLimit = 1000;
}

WebInspector.TextEditorHighlighter.prototype = {
set mimeType(mimeType)
{
var tokenizer = WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer(mimeType);
if (tokenizer)
this._tokenizer = tokenizer;
},

set highlightChunkLimit(highlightChunkLimit)
{
this._highlightChunkLimit = highlightChunkLimit;
},

highlight: function(endLine, opt_forceRun)
{

var state = this._textModel.getAttribute(endLine - 1, "highlight");
if (state && state.postConditionStringified) {

return;
}

this._requestedEndLine = endLine;

if (this._highlightTimer && !opt_forceRun) {

return;
}


var startLine = endLine;
while (startLine > 0) {
var state = this._textModel.getAttribute(startLine - 1, "highlight");
if (state && state.postConditionStringified)
break;
startLine--;
}


this._highlightInChunks(startLine, endLine);
},

updateHighlight: function(startLine, endLine)
{

this._clearHighlightState(startLine);

if (startLine) {
var state = this._textModel.getAttribute(startLine - 1, "highlight");
if (!state || !state.postConditionStringified) {

return false;
}
}

var restored = this._highlightLines(startLine, endLine);
if (!restored) {
for (var i = this._lastHighlightedLine; i < this._textModel.linesCount; ++i) {
var state = this._textModel.getAttribute(i, "highlight");
if (!state && i > endLine)
break;
this._textModel.setAttribute(i, "highlight-outdated", state);
this._textModel.removeAttribute(i, "highlight");
}

if (this._highlightTimer) {
clearTimeout(this._highlightTimer);
this._requestedEndLine = endLine;
this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, this._lastHighlightedLine, this._requestedEndLine), 10);
}
}
return restored;
},

_highlightInChunks: function(startLine, endLine)
{
delete this._highlightTimer;


var state = this._textModel.getAttribute(this._requestedEndLine - 1, "highlight");
if (state && state.postConditionStringified)
return;

if (this._requestedEndLine !== endLine) {

this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, startLine, this._requestedEndLine), 100);
return;
}


if (this._requestedEndLine > this._textModel.linesCount)
this._requestedEndLine = this._textModel.linesCount;

this._highlightLines(startLine, this._requestedEndLine);


if (this._lastHighlightedLine < this._requestedEndLine)
this._highlightTimer = setTimeout(this._highlightInChunks.bind(this, this._lastHighlightedLine, this._requestedEndLine), 10);
},

_highlightLines: function(startLine, endLine)
{

var state = this._textModel.getAttribute(startLine - 1, "highlight");
var postConditionStringified = state ? state.postConditionStringified : JSON.stringify(this._tokenizer.createInitialCondition());

var tokensCount = 0;
for (var lineNumber = startLine; lineNumber < endLine; ++lineNumber) {
var state = this._selectHighlightState(lineNumber, postConditionStringified);
if (state.postConditionStringified) {

postConditionStringified = state.postConditionStringified;
} else {
var lastHighlightedColumn = 0;
if (state.midConditionStringified) {
lastHighlightedColumn = state.lastHighlightedColumn;
postConditionStringified = state.midConditionStringified;
}

var line = this._textModel.line(lineNumber);
this._tokenizer.line = line;
this._tokenizer.condition = JSON.parse(postConditionStringified);


do {
var newColumn = this._tokenizer.nextToken(lastHighlightedColumn);
var tokenType = this._tokenizer.tokenType;
if (tokenType)
state[lastHighlightedColumn] = { length: newColumn - lastHighlightedColumn, tokenType: tokenType };
lastHighlightedColumn = newColumn;
if (++tokensCount > this._highlightChunkLimit)
break;
} while (lastHighlightedColumn < line.length);

postConditionStringified = JSON.stringify(this._tokenizer.condition);

if (lastHighlightedColumn < line.length) {

state.lastHighlightedColumn = lastHighlightedColumn;
state.midConditionStringified = postConditionStringified;
break;
} else {
delete state.lastHighlightedColumn;
delete state.midConditionStringified;
state.postConditionStringified = postConditionStringified;
}
}

var nextLineState = this._textModel.getAttribute(lineNumber + 1, "highlight");
if (nextLineState && nextLineState.preConditionStringified === state.postConditionStringified) {

++lineNumber;
this._damageCallback(startLine, lineNumber);


for (; lineNumber < endLine; ++lineNumber) {
var state = this._textModel.getAttribute(lineNumber, "highlight");
if (!state || !state.postConditionStringified)
break;
}
this._lastHighlightedLine = lineNumber;
return true;
}
}

this._damageCallback(startLine, lineNumber);
this._lastHighlightedLine = lineNumber;
return false;
},

_selectHighlightState: function(lineNumber, preConditionStringified)
{
var state = this._textModel.getAttribute(lineNumber, "highlight");
if (state && state.preConditionStringified === preConditionStringified)
return state;

var outdatedState = this._textModel.getAttribute(lineNumber, "highlight-outdated");
if (outdatedState && outdatedState.preConditionStringified === preConditionStringified) {

this._textModel.setAttribute(lineNumber, "highlight", outdatedState);
this._textModel.setAttribute(lineNumber, "highlight-outdated", state);
return outdatedState;
}

if (state)
this._textModel.setAttribute(lineNumber, "highlight-outdated", state);

state = {};
state.preConditionStringified = preConditionStringified;
this._textModel.setAttribute(lineNumber, "highlight", state);
return state;
},

_clearHighlightState: function(lineNumber)
{
this._textModel.removeAttribute(lineNumber, "highlight");
this._textModel.removeAttribute(lineNumber, "highlight-outdated");
}
}






WebInspector.SourceTokenizer = function()
{
}

WebInspector.SourceTokenizer.prototype = {
set line(line) {
this._line = line;
},

set condition(condition)
{
this._condition = condition;
},

get condition()
{
return this._condition;
},

getLexCondition: function()
{
return this.condition.lexCondition;
},

setLexCondition: function(lexCondition)
{
this.condition.lexCondition = lexCondition;
},

_charAt: function(cursor)
{
return cursor < this._line.length ? this._line.charAt(cursor) : "\n";
}
}


WebInspector.SourceTokenizer.Registry = function() {
this._tokenizers = {};
this._tokenizerConstructors = {
"text/css": "SourceCSSTokenizer",
"text/html": "SourceHTMLTokenizer",
"text/javascript": "SourceJavaScriptTokenizer"
};
}

WebInspector.SourceTokenizer.Registry.getInstance = function()
{
if (!WebInspector.SourceTokenizer.Registry._instance)
WebInspector.SourceTokenizer.Registry._instance = new WebInspector.SourceTokenizer.Registry();
return WebInspector.SourceTokenizer.Registry._instance;
}

WebInspector.SourceTokenizer.Registry.prototype = {
getTokenizer: function(mimeType)
{
if (!this._tokenizerConstructors[mimeType])
return null;
var tokenizerClass = this._tokenizerConstructors[mimeType];
var tokenizer = this._tokenizers[tokenizerClass];
if (!tokenizer) {
tokenizer = new WebInspector[tokenizerClass]();
this._tokenizers[tokenizerClass] = tokenizer;
}
return tokenizer;
}
}


















WebInspector.SourceCSSTokenizer = function()
{
WebInspector.SourceTokenizer.call(this);

this._propertyKeywords = WebInspector.cssNameCompletions.keySet();

this._valueKeywords = [
"above", "absolute", "activeborder", "activecaption", "afar", "after-white-space", "ahead", "alias", "all", "all-scroll",
"alternate", "always","amharic", "amharic-abegede", "antialiased", "appworkspace", "aqua", "arabic-indic", "armenian", "asterisks",
"auto", "avoid", "background", "backwards", "baseline", "below", "bidi-override", "binary", "bengali", "black", "blink",
"block", "block-axis", "blue", "bold", "bolder", "border", "border-box", "both", "bottom", "break-all", "break-word", "button",
"button-bevel", "buttonface", "buttonhighlight", "buttonshadow", "buttontext", "cambodian", "capitalize", "caps-lock-indicator",
"caption", "captiontext", "caret", "cell", "center", "checkbox", "circle", "cjk-earthly-branch", "cjk-heavenly-stem", "cjk-ideographic",
"clear", "clip", "close-quote", "col-resize", "collapse", "compact", "condensed", "contain", "content", "content-box", "context-menu",
"continuous", "copy", "cover", "crop", "cross", "crosshair", "currentcolor", "cursive", "dashed", "decimal", "decimal-leading-zero", "default",
"default-button", "destination-atop", "destination-in", "destination-out", "destination-over", "devanagari", "disc", "discard", "document",
"dot-dash", "dot-dot-dash", "dotted", "double", "down", "e-resize", "ease", "ease-in", "ease-in-out", "ease-out", "element",
"ellipsis", "embed", "end", "ethiopic", "ethiopic-abegede", "ethiopic-abegede-am-et", "ethiopic-abegede-gez",
"ethiopic-abegede-ti-er", "ethiopic-abegede-ti-et", "ethiopic-halehame-aa-er", "ethiopic-halehame-aa-et",
"ethiopic-halehame-am-et", "ethiopic-halehame-gez", "ethiopic-halehame-om-et", "ethiopic-halehame-sid-et",
"ethiopic-halehame-so-et", "ethiopic-halehame-ti-er", "ethiopic-halehame-ti-et", "ethiopic-halehame-tig", "ew-resize", "expanded",
"extra-condensed", "extra-expanded", "fantasy", "fast", "fill", "fixed", "flat", "footnotes", "forwards", "from", "fuchsia", "geometricPrecision",
"georgian", "gray", "graytext", "green", "grey", "groove", "gujarati", "gurmukhi", "hand", "hangul", "hangul-consonant", "hebrew", "help",
"hidden", "hide", "higher", "highlight", "highlighttext", "hiragana", "hiragana-iroha", "horizontal", "hsl", "hsla", "icon", "ignore",
"inactiveborder", "inactivecaption", "inactivecaptiontext", "infinite", "infobackground", "infotext", "inherit", "initial", "inline",
"inline-axis", "inline-block", "inline-table", "inset", "inside", "intrinsic", "invert", "italic", "justify", "kannada", "katakana",
"katakana-iroha", "khmer", "landscape", "lao", "large", "larger", "left", "level", "lighter", "lime", "line-through", "linear", "lines",
"list-button", "list-item", "listbox", "listitem", "local", "logical", "loud", "lower", "lower-alpha", "lower-armenian", "lower-greek",
"lower-hexadecimal", "lower-latin", "lower-norwegian", "lower-roman", "lowercase", "ltr", "malayalam", "maroon", "match", "media-controls-background",
"media-current-time-display", "media-fullscreen-button", "media-mute-button", "media-play-button", "media-return-to-realtime-button",
"media-rewind-button", "media-seek-back-button", "media-seek-forward-button", "media-slider", "media-sliderthumb", "media-time-remaining-display",
"media-volume-slider", "media-volume-slider-container", "media-volume-sliderthumb", "medium", "menu", "menulist", "menulist-button",
"menulist-text", "menulist-textfield", "menutext", "message-box", "middle", "min-intrinsic", "mix", "mongolian", "monospace", "move", "multiple",
"myanmar", "n-resize", "narrower", "navy", "ne-resize", "nesw-resize", "no-close-quote", "no-drop", "no-open-quote", "no-repeat", "none",
"normal", "not-allowed", "nowrap", "ns-resize", "nw-resize", "nwse-resize", "oblique", "octal", "olive", "open-quote", "optimizeLegibility",
"optimizeSpeed", "orange", "oriya", "oromo", "outset", "outside", "overlay", "overline", "padding", "padding-box", "painted", "paused",
"persian", "plus-darker", "plus-lighter", "pointer", "portrait", "pre", "pre-line", "pre-wrap", "preserve-3d", "progress", "purple",
"push-button", "radio", "read-only", "read-write", "read-write-plaintext-only", "red", "relative", "repeat", "repeat-x",
"repeat-y", "reset", "reverse", "rgb", "rgba", "ridge", "right", "round", "row-resize", "rtl", "run-in", "running", "s-resize", "sans-serif",
"scroll", "scrollbar", "se-resize", "searchfield", "searchfield-cancel-button", "searchfield-decoration", "searchfield-results-button",
"searchfield-results-decoration", "semi-condensed", "semi-expanded", "separate", "serif", "show", "sidama", "silver", "single",
"skip-white-space", "slide", "slider-horizontal", "slider-vertical", "sliderthumb-horizontal", "sliderthumb-vertical", "slow",
"small", "small-caps", "small-caption", "smaller", "solid", "somali", "source-atop", "source-in", "source-out", "source-over",
"space", "square", "square-button", "start", "static", "status-bar", "stretch", "stroke", "sub", "subpixel-antialiased", "super",
"sw-resize", "table", "table-caption", "table-cell", "table-column", "table-column-group", "table-footer-group", "table-header-group",
"table-row", "table-row-group", "teal", "telugu", "text", "text-bottom", "text-top", "textarea", "textfield", "thai", "thick", "thin",
"threeddarkshadow", "threedface", "threedhighlight", "threedlightshadow", "threedshadow", "tibetan", "tigre", "tigrinya-er", "tigrinya-er-abegede",
"tigrinya-et", "tigrinya-et-abegede", "to", "top", "transparent", "ultra-condensed", "ultra-expanded", "underline", "up", "upper-alpha", "upper-armenian",
"upper-greek", "upper-hexadecimal", "upper-latin", "upper-norwegian", "upper-roman", "uppercase", "urdu", "url", "vertical", "vertical-text", "visible",
"visibleFill", "visiblePainted", "visibleStroke", "visual", "w-resize", "wait", "wave", "white", "wider", "window", "windowframe", "windowtext",
"x-large", "x-small", "xor", "xx-large", "xx-small", "yellow", "-wap-marquee", "-webkit-activelink", "-webkit-auto", "-webkit-baseline-middle",
"-webkit-body", "-webkit-box", "-webkit-center", "-webkit-control", "-webkit-focus-ring-color", "-webkit-grab", "-webkit-grabbing",
"-webkit-gradient", "-webkit-inline-box", "-webkit-left", "-webkit-link", "-webkit-marquee", "-webkit-mini-control", "-webkit-nowrap", "-webkit-right",
"-webkit-small-control", "-webkit-text", "-webkit-xxx-large", "-webkit-zoom-in", "-webkit-zoom-out",
].keySet();

this._mediaTypes = ["all", "aural", "braille", "embossed", "handheld", "import", "print", "projection", "screen", "tty", "tv"].keySet();

this._lexConditions = {
INITIAL: 0,
COMMENT: 1,
DSTRING: 2,
SSTRING: 3
};

this._parseConditions = {
INITIAL: 0,
PROPERTY: 1,
PROPERTY_VALUE: 2,
AT_RULE: 3
};

this.case_INITIAL = 1000;
this.case_COMMENT = 1002;
this.case_DSTRING = 1003;
this.case_SSTRING = 1004;

this.condition = this.createInitialCondition();
}

WebInspector.SourceCSSTokenizer.prototype = {
createInitialCondition: function()
{
return { lexCondition: this._lexConditions.INITIAL, parseCondition: this._parseConditions.INITIAL };
},

_stringToken: function(cursor, stringEnds)
{
if (this._isPropertyValue())
this.tokenType = "css-string";
else
this.tokenType = null;
return cursor;
},

_isPropertyValue: function()
{
return this._condition.parseCondition === this._parseConditions.PROPERTY_VALUE || this._condition.parseCondition === this._parseConditions.AT_RULE;
},

nextToken: function(cursor)
{
var cursorOnEnter = cursor;
var gotoCase = 1;
while (1) {
switch (gotoCase)


{
case 1: var yych;
var yyaccept = 0;
if (this.getLexCondition() < 2) {
if (this.getLexCondition() < 1) {
{ gotoCase = this.case_INITIAL; continue; };
} else {
{ gotoCase = this.case_COMMENT; continue; };
}
} else {
if (this.getLexCondition() < 3) {
{ gotoCase = this.case_DSTRING; continue; };
} else {
{ gotoCase = this.case_SSTRING; continue; };
}
}

case this.case_COMMENT:

yych = this._charAt(cursor);
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 4; continue; };
{ gotoCase = 3; continue; };
} else {
if (yych <= '\r') { gotoCase = 4; continue; };
if (yych == '*') { gotoCase = 6; continue; };
{ gotoCase = 3; continue; };
}
case 2:
{ this.tokenType = "css-comment"; return cursor; }
case 3:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
{ gotoCase = 12; continue; };
case 4:
++cursor;
{ this.tokenType = null; return cursor; }
case 6:
yyaccept = 1;
yych = this._charAt(YYMARKER = ++cursor);
if (yych == '*') { gotoCase = 9; continue; };
if (yych != '/') { gotoCase = 11; continue; };
case 7:
++cursor;
this.setLexCondition(this._lexConditions.INITIAL);
{ this.tokenType = "css-comment"; return cursor; }
case 9:
++cursor;
yych = this._charAt(cursor);
if (yych == '*') { gotoCase = 9; continue; };
if (yych == '/') { gotoCase = 7; continue; };
case 11:
yyaccept = 0;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
case 12:
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 2; continue; };
{ gotoCase = 11; continue; };
} else {
if (yych <= '\r') { gotoCase = 2; continue; };
if (yych == '*') { gotoCase = 9; continue; };
{ gotoCase = 11; continue; };
}

case this.case_DSTRING:
yych = this._charAt(cursor);
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 17; continue; };
if (yych <= '\f') { gotoCase = 16; continue; };
{ gotoCase = 17; continue; };
} else {
if (yych <= '"') {
if (yych <= '!') { gotoCase = 16; continue; };
{ gotoCase = 19; continue; };
} else {
if (yych == '\\') { gotoCase = 21; continue; };
{ gotoCase = 16; continue; };
}
}
case 15:
{ return this._stringToken(cursor); }
case 16:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
{ gotoCase = 23; continue; };
case 17:
++cursor;
case 18:
{ this.tokenType = null; return cursor; }
case 19:
++cursor;
case 20:
this.setLexCondition(this._lexConditions.INITIAL);
{ return this._stringToken(cursor, true); }
case 21:
yych = this._charAt(++cursor);
if (yych <= 'e') {
if (yych <= '\'') {
if (yych == '"') { gotoCase = 22; continue; };
if (yych <= '&') { gotoCase = 18; continue; };
} else {
if (yych <= '\\') {
if (yych <= '[') { gotoCase = 18; continue; };
} else {
if (yych != 'b') { gotoCase = 18; continue; };
}
}
} else {
if (yych <= 'r') {
if (yych <= 'm') {
if (yych >= 'g') { gotoCase = 18; continue; };
} else {
if (yych <= 'n') { gotoCase = 22; continue; };
if (yych <= 'q') { gotoCase = 18; continue; };
}
} else {
if (yych <= 't') {
if (yych <= 's') { gotoCase = 18; continue; };
} else {
if (yych != 'v') { gotoCase = 18; continue; };
}
}
}
case 22:
yyaccept = 0;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
case 23:
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 15; continue; };
if (yych <= '\f') { gotoCase = 22; continue; };
{ gotoCase = 15; continue; };
} else {
if (yych <= '"') {
if (yych <= '!') { gotoCase = 22; continue; };
{ gotoCase = 26; continue; };
} else {
if (yych != '\\') { gotoCase = 22; continue; };
}
}
++cursor;
yych = this._charAt(cursor);
if (yych <= 'e') {
if (yych <= '\'') {
if (yych == '"') { gotoCase = 22; continue; };
if (yych >= '\'') { gotoCase = 22; continue; };
} else {
if (yych <= '\\') {
if (yych >= '\\') { gotoCase = 22; continue; };
} else {
if (yych == 'b') { gotoCase = 22; continue; };
}
}
} else {
if (yych <= 'r') {
if (yych <= 'm') {
if (yych <= 'f') { gotoCase = 22; continue; };
} else {
if (yych <= 'n') { gotoCase = 22; continue; };
if (yych >= 'r') { gotoCase = 22; continue; };
}
} else {
if (yych <= 't') {
if (yych >= 't') { gotoCase = 22; continue; };
} else {
if (yych == 'v') { gotoCase = 22; continue; };
}
}
}
cursor = YYMARKER;
{ gotoCase = 15; continue; };
case 26:
++cursor;
yych = this._charAt(cursor);
{ gotoCase = 20; continue; };

case this.case_INITIAL:
yych = this._charAt(cursor);
if (yych <= ';') {
if (yych <= '\'') {
if (yych <= '"') {
if (yych <= ' ') { gotoCase = 29; continue; };
if (yych <= '!') { gotoCase = 31; continue; };
{ gotoCase = 33; continue; };
} else {
if (yych == '$') { gotoCase = 31; continue; };
if (yych >= '\'') { gotoCase = 34; continue; };
}
} else {
if (yych <= '.') {
if (yych <= ',') { gotoCase = 29; continue; };
if (yych <= '-') { gotoCase = 35; continue; };
{ gotoCase = 36; continue; };
} else {
if (yych <= '/') { gotoCase = 37; continue; };
if (yych <= '9') { gotoCase = 38; continue; };
if (yych <= ':') { gotoCase = 40; continue; };
{ gotoCase = 42; continue; };
}
}
} else {
if (yych <= '^') {
if (yych <= '?') {
if (yych == '=') { gotoCase = 31; continue; };
} else {
if (yych == '\\') { gotoCase = 29; continue; };
if (yych <= ']') { gotoCase = 31; continue; };
}
} else {
if (yych <= 'z') {
if (yych != '`') { gotoCase = 31; continue; };
} else {
if (yych <= '{') { gotoCase = 44; continue; };
if (yych == '}') { gotoCase = 46; continue; };
}
}
}
case 29:
++cursor;
case 30:
{ this.tokenType = null; return cursor; }
case 31:
++cursor;
yych = this._charAt(cursor);
{ gotoCase = 49; continue; };
case 32:
{
var token = this._line.substring(cursorOnEnter, cursor);
if (this._condition.parseCondition === this._parseConditions.INITIAL) {
if (token === "@import" || token === "@media") {
this.tokenType = "css-at-rule";
this._condition.parseCondition = this._parseConditions.AT_RULE;
} else if (token.indexOf("@") === 0)
this.tokenType = "css-at-rule";
else
this.tokenType = "css-selector";
}
else if (this._condition.parseCondition === this._parseConditions.AT_RULE && token in this._mediaTypes)
this.tokenType = "css-keyword";
else if (this._condition.parseCondition === this._parseConditions.PROPERTY && token in this._propertyKeywords)
this.tokenType = "css-property";
else if (this._isPropertyValue() && token in this._valueKeywords)
this.tokenType = "css-keyword";
else if (token === "!important")
this.tokenType = "css-important";
else
this.tokenType = null;
return cursor;
}
case 33:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych <= '-') {
if (yych <= '!') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 32; continue; };
{ gotoCase = 124; continue; };
} else {
if (yych <= '\r') { gotoCase = 32; continue; };
if (yych <= ' ') { gotoCase = 124; continue; };
{ gotoCase = 122; continue; };
}
} else {
if (yych <= '$') {
if (yych <= '"') { gotoCase = 114; continue; };
if (yych <= '#') { gotoCase = 124; continue; };
{ gotoCase = 122; continue; };
} else {
if (yych == '\'') { gotoCase = 122; continue; };
if (yych <= ',') { gotoCase = 124; continue; };
{ gotoCase = 122; continue; };
}
}
} else {
if (yych <= '[') {
if (yych <= '<') {
if (yych <= '.') { gotoCase = 124; continue; };
if (yych <= '9') { gotoCase = 122; continue; };
{ gotoCase = 124; continue; };
} else {
if (yych <= '=') { gotoCase = 122; continue; };
if (yych <= '?') { gotoCase = 124; continue; };
{ gotoCase = 122; continue; };
}
} else {
if (yych <= '^') {
if (yych <= '\\') { gotoCase = 126; continue; };
if (yych <= ']') { gotoCase = 122; continue; };
{ gotoCase = 124; continue; };
} else {
if (yych == '`') { gotoCase = 124; continue; };
if (yych <= 'z') { gotoCase = 122; continue; };
{ gotoCase = 124; continue; };
}
}
}
case 34:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych <= '-') {
if (yych <= '"') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 32; continue; };
{ gotoCase = 116; continue; };
} else {
if (yych <= '\r') { gotoCase = 32; continue; };
if (yych <= ' ') { gotoCase = 116; continue; };
{ gotoCase = 112; continue; };
}
} else {
if (yych <= '&') {
if (yych == '$') { gotoCase = 112; continue; };
{ gotoCase = 116; continue; };
} else {
if (yych <= '\'') { gotoCase = 114; continue; };
if (yych <= ',') { gotoCase = 116; continue; };
{ gotoCase = 112; continue; };
}
}
} else {
if (yych <= '[') {
if (yych <= '<') {
if (yych <= '.') { gotoCase = 116; continue; };
if (yych <= '9') { gotoCase = 112; continue; };
{ gotoCase = 116; continue; };
} else {
if (yych <= '=') { gotoCase = 112; continue; };
if (yych <= '?') { gotoCase = 116; continue; };
{ gotoCase = 112; continue; };
}
} else {
if (yych <= '^') {
if (yych <= '\\') { gotoCase = 118; continue; };
if (yych <= ']') { gotoCase = 112; continue; };
{ gotoCase = 116; continue; };
} else {
if (yych == '`') { gotoCase = 116; continue; };
if (yych <= 'z') { gotoCase = 112; continue; };
{ gotoCase = 116; continue; };
}
}
}
case 35:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych == '.') { gotoCase = 65; continue; };
if (yych <= '/') { gotoCase = 49; continue; };
if (yych <= '9') { gotoCase = 50; continue; };
{ gotoCase = 49; continue; };
case 36:
yych = this._charAt(++cursor);
if (yych <= '/') { gotoCase = 30; continue; };
if (yych <= '9') { gotoCase = 68; continue; };
{ gotoCase = 30; continue; };
case 37:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych == '*') { gotoCase = 104; continue; };
{ gotoCase = 49; continue; };
case 38:
yyaccept = 1;
yych = this._charAt(YYMARKER = ++cursor);
switch (yych) {
case '!':
case '"':
case '$':
case '\'':
case '-':
case '/':
case '=':
case '@':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
case '[':
case ']':
case 'a':
case 'b':
case 'f':
case 'h':
case 'j':
case 'l':
case 'n':
case 'o':
case 'q':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':    { gotoCase = 48; continue; };
case '%':    { gotoCase = 67; continue; };
case '.':    { gotoCase = 65; continue; };
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':    { gotoCase = 50; continue; };
case 'H':    { gotoCase = 52; continue; };
case '_':    { gotoCase = 53; continue; };
case 'c':    { gotoCase = 54; continue; };
case 'd':    { gotoCase = 55; continue; };
case 'e':    { gotoCase = 56; continue; };
case 'g':    { gotoCase = 57; continue; };
case 'i':    { gotoCase = 58; continue; };
case 'k':    { gotoCase = 59; continue; };
case 'm':    { gotoCase = 60; continue; };
case 'p':    { gotoCase = 61; continue; };
case 'r':    { gotoCase = 62; continue; };
case 's':    { gotoCase = 63; continue; };
case 't':    { gotoCase = 64; continue; };
default:    { gotoCase = 39; continue; };
}
case 39:
{
if (this._isPropertyValue())
this.tokenType = "css-number";
else
this.tokenType = null;
return cursor;
}
case 40:
++cursor;
{
this.tokenType = null;
if (this._condition.parseCondition === this._parseConditions.PROPERTY)
this._condition.parseCondition = this._parseConditions.PROPERTY_VALUE;
return cursor;
}
case 42:
++cursor;
{
this.tokenType = null;
if (this._condition.parseCondition === this._parseConditions.AT_RULE)
this._condition.parseCondition = this._parseConditions.INITIAL;
else
this._condition.parseCondition = this._parseConditions.PROPERTY;
return cursor;
}
case 44:
++cursor;
{
this.tokenType = null;
if (this._condition.parseCondition === this._parseConditions.AT_RULE)
this._condition.parseCondition = this._parseConditions.INITIAL;
else
this._condition.parseCondition = this._parseConditions.PROPERTY;
return cursor;
}
case 46:
++cursor;
{
this.tokenType = null;
this._condition.parseCondition = this._parseConditions.INITIAL;
return cursor;
}
case 48:
++cursor;
yych = this._charAt(cursor);
case 49:
if (yych <= '9') {
if (yych <= '&') {
if (yych <= '"') {
if (yych <= ' ') { gotoCase = 32; continue; };
{ gotoCase = 48; continue; };
} else {
if (yych == '$') { gotoCase = 48; continue; };
{ gotoCase = 32; continue; };
}
} else {
if (yych <= ',') {
if (yych <= '\'') { gotoCase = 48; continue; };
{ gotoCase = 32; continue; };
} else {
if (yych == '.') { gotoCase = 32; continue; };
{ gotoCase = 48; continue; };
}
}
} else {
if (yych <= '\\') {
if (yych <= '=') {
if (yych <= '<') { gotoCase = 32; continue; };
{ gotoCase = 48; continue; };
} else {
if (yych <= '?') { gotoCase = 32; continue; };
if (yych <= '[') { gotoCase = 48; continue; };
{ gotoCase = 32; continue; };
}
} else {
if (yych <= '_') {
if (yych == '^') { gotoCase = 32; continue; };
{ gotoCase = 48; continue; };
} else {
if (yych <= '`') { gotoCase = 32; continue; };
if (yych <= 'z') { gotoCase = 48; continue; };
{ gotoCase = 32; continue; };
}
}
}
case 50:
yyaccept = 1;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
switch (yych) {
case '!':
case '"':
case '$':
case '\'':
case '-':
case '/':
case '=':
case '@':
case 'A':
case 'B':
case 'C':
case 'D':
case 'E':
case 'F':
case 'G':
case 'I':
case 'J':
case 'K':
case 'L':
case 'M':
case 'N':
case 'O':
case 'P':
case 'Q':
case 'R':
case 'S':
case 'T':
case 'U':
case 'V':
case 'W':
case 'X':
case 'Y':
case 'Z':
case '[':
case ']':
case 'a':
case 'b':
case 'f':
case 'h':
case 'j':
case 'l':
case 'n':
case 'o':
case 'q':
case 'u':
case 'v':
case 'w':
case 'x':
case 'y':
case 'z':    { gotoCase = 48; continue; };
case '%':    { gotoCase = 67; continue; };
case '.':    { gotoCase = 65; continue; };
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':    { gotoCase = 50; continue; };
case 'H':    { gotoCase = 52; continue; };
case '_':    { gotoCase = 53; continue; };
case 'c':    { gotoCase = 54; continue; };
case 'd':    { gotoCase = 55; continue; };
case 'e':    { gotoCase = 56; continue; };
case 'g':    { gotoCase = 57; continue; };
case 'i':    { gotoCase = 58; continue; };
case 'k':    { gotoCase = 59; continue; };
case 'm':    { gotoCase = 60; continue; };
case 'p':    { gotoCase = 61; continue; };
case 'r':    { gotoCase = 62; continue; };
case 's':    { gotoCase = 63; continue; };
case 't':    { gotoCase = 64; continue; };
default:    { gotoCase = 39; continue; };
}
case 52:
yych = this._charAt(++cursor);
if (yych == 'z') { gotoCase = 63; continue; };
{ gotoCase = 49; continue; };
case 53:
yych = this._charAt(++cursor);
if (yych == '_') { gotoCase = 101; continue; };
{ gotoCase = 49; continue; };
case 54:
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 63; continue; };
{ gotoCase = 49; continue; };
case 55:
yych = this._charAt(++cursor);
if (yych == 'e') { gotoCase = 100; continue; };
{ gotoCase = 49; continue; };
case 56:
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 63; continue; };
if (yych == 'x') { gotoCase = 63; continue; };
{ gotoCase = 49; continue; };
case 57:
yych = this._charAt(++cursor);
if (yych == 'r') { gotoCase = 98; continue; };
{ gotoCase = 49; continue; };
case 58:
yych = this._charAt(++cursor);
if (yych == 'n') { gotoCase = 63; continue; };
{ gotoCase = 49; continue; };
case 59:
yych = this._charAt(++cursor);
if (yych == 'H') { gotoCase = 97; continue; };
{ gotoCase = 49; continue; };
case 60:
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 63; continue; };
if (yych == 's') { gotoCase = 63; continue; };
{ gotoCase = 49; continue; };
case 61:
yych = this._charAt(++cursor);
if (yych <= 's') {
if (yych == 'c') { gotoCase = 63; continue; };
{ gotoCase = 49; continue; };
} else {
if (yych <= 't') { gotoCase = 63; continue; };
if (yych == 'x') { gotoCase = 63; continue; };
{ gotoCase = 49; continue; };
}
case 62:
yych = this._charAt(++cursor);
if (yych == 'a') { gotoCase = 95; continue; };
if (yych == 'e') { gotoCase = 96; continue; };
{ gotoCase = 49; continue; };
case 63:
yych = this._charAt(++cursor);
if (yych <= '9') {
if (yych <= '&') {
if (yych <= '"') {
if (yych <= ' ') { gotoCase = 39; continue; };
{ gotoCase = 48; continue; };
} else {
if (yych == '$') { gotoCase = 48; continue; };
{ gotoCase = 39; continue; };
}
} else {
if (yych <= ',') {
if (yych <= '\'') { gotoCase = 48; continue; };
{ gotoCase = 39; continue; };
} else {
if (yych == '.') { gotoCase = 39; continue; };
{ gotoCase = 48; continue; };
}
}
} else {
if (yych <= '\\') {
if (yych <= '=') {
if (yych <= '<') { gotoCase = 39; continue; };
{ gotoCase = 48; continue; };
} else {
if (yych <= '?') { gotoCase = 39; continue; };
if (yych <= '[') { gotoCase = 48; continue; };
{ gotoCase = 39; continue; };
}
} else {
if (yych <= '_') {
if (yych == '^') { gotoCase = 39; continue; };
{ gotoCase = 48; continue; };
} else {
if (yych <= '`') { gotoCase = 39; continue; };
if (yych <= 'z') { gotoCase = 48; continue; };
{ gotoCase = 39; continue; };
}
}
}
case 64:
yych = this._charAt(++cursor);
if (yych == 'u') { gotoCase = 93; continue; };
{ gotoCase = 49; continue; };
case 65:
yych = this._charAt(++cursor);
if (yych <= '/') { gotoCase = 66; continue; };
if (yych <= '9') { gotoCase = 68; continue; };
case 66:
cursor = YYMARKER;
if (yyaccept <= 0) {
{ gotoCase = 32; continue; };
} else {
{ gotoCase = 39; continue; };
}
case 67:
yych = this._charAt(++cursor);
{ gotoCase = 39; continue; };
case 68:
yyaccept = 1;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych <= 'f') {
if (yych <= 'H') {
if (yych <= '/') {
if (yych == '%') { gotoCase = 67; continue; };
{ gotoCase = 39; continue; };
} else {
if (yych <= '9') { gotoCase = 68; continue; };
if (yych <= 'G') { gotoCase = 39; continue; };
{ gotoCase = 80; continue; };
}
} else {
if (yych <= 'b') {
if (yych == '_') { gotoCase = 72; continue; };
{ gotoCase = 39; continue; };
} else {
if (yych <= 'c') { gotoCase = 74; continue; };
if (yych <= 'd') { gotoCase = 77; continue; };
if (yych >= 'f') { gotoCase = 39; continue; };
}
}
} else {
if (yych <= 'm') {
if (yych <= 'i') {
if (yych <= 'g') { gotoCase = 78; continue; };
if (yych <= 'h') { gotoCase = 39; continue; };
{ gotoCase = 76; continue; };
} else {
if (yych == 'k') { gotoCase = 81; continue; };
if (yych <= 'l') { gotoCase = 39; continue; };
{ gotoCase = 75; continue; };
}
} else {
if (yych <= 'q') {
if (yych == 'p') { gotoCase = 73; continue; };
{ gotoCase = 39; continue; };
} else {
if (yych <= 'r') { gotoCase = 71; continue; };
if (yych <= 's') { gotoCase = 67; continue; };
if (yych <= 't') { gotoCase = 79; continue; };
{ gotoCase = 39; continue; };
}
}
}
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 67; continue; };
if (yych == 'x') { gotoCase = 67; continue; };
{ gotoCase = 66; continue; };
case 71:
yych = this._charAt(++cursor);
if (yych == 'a') { gotoCase = 91; continue; };
if (yych == 'e') { gotoCase = 92; continue; };
{ gotoCase = 66; continue; };
case 72:
yych = this._charAt(++cursor);
if (yych == '_') { gotoCase = 88; continue; };
{ gotoCase = 66; continue; };
case 73:
yych = this._charAt(++cursor);
if (yych <= 's') {
if (yych == 'c') { gotoCase = 67; continue; };
{ gotoCase = 66; continue; };
} else {
if (yych <= 't') { gotoCase = 67; continue; };
if (yych == 'x') { gotoCase = 67; continue; };
{ gotoCase = 66; continue; };
}
case 74:
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 67; continue; };
{ gotoCase = 66; continue; };
case 75:
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 67; continue; };
if (yych == 's') { gotoCase = 67; continue; };
{ gotoCase = 66; continue; };
case 76:
yych = this._charAt(++cursor);
if (yych == 'n') { gotoCase = 67; continue; };
{ gotoCase = 66; continue; };
case 77:
yych = this._charAt(++cursor);
if (yych == 'e') { gotoCase = 87; continue; };
{ gotoCase = 66; continue; };
case 78:
yych = this._charAt(++cursor);
if (yych == 'r') { gotoCase = 85; continue; };
{ gotoCase = 66; continue; };
case 79:
yych = this._charAt(++cursor);
if (yych == 'u') { gotoCase = 83; continue; };
{ gotoCase = 66; continue; };
case 80:
yych = this._charAt(++cursor);
if (yych == 'z') { gotoCase = 67; continue; };
{ gotoCase = 66; continue; };
case 81:
yych = this._charAt(++cursor);
if (yych != 'H') { gotoCase = 66; continue; };
yych = this._charAt(++cursor);
if (yych == 'z') { gotoCase = 67; continue; };
{ gotoCase = 66; continue; };
case 83:
yych = this._charAt(++cursor);
if (yych != 'r') { gotoCase = 66; continue; };
yych = this._charAt(++cursor);
if (yych == 'n') { gotoCase = 67; continue; };
{ gotoCase = 66; continue; };
case 85:
yych = this._charAt(++cursor);
if (yych != 'a') { gotoCase = 66; continue; };
yych = this._charAt(++cursor);
if (yych == 'd') { gotoCase = 67; continue; };
{ gotoCase = 66; continue; };
case 87:
yych = this._charAt(++cursor);
if (yych == 'g') { gotoCase = 67; continue; };
{ gotoCase = 66; continue; };
case 88:
yych = this._charAt(++cursor);
if (yych != 'q') { gotoCase = 66; continue; };
yych = this._charAt(++cursor);
if (yych != 'e') { gotoCase = 66; continue; };
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 67; continue; };
{ gotoCase = 66; continue; };
case 91:
yych = this._charAt(++cursor);
if (yych == 'd') { gotoCase = 67; continue; };
{ gotoCase = 66; continue; };
case 92:
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 67; continue; };
{ gotoCase = 66; continue; };
case 93:
yych = this._charAt(++cursor);
if (yych != 'r') { gotoCase = 49; continue; };
yych = this._charAt(++cursor);
if (yych == 'n') { gotoCase = 63; continue; };
{ gotoCase = 49; continue; };
case 95:
yych = this._charAt(++cursor);
if (yych == 'd') { gotoCase = 63; continue; };
{ gotoCase = 49; continue; };
case 96:
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 63; continue; };
{ gotoCase = 49; continue; };
case 97:
yych = this._charAt(++cursor);
if (yych == 'z') { gotoCase = 63; continue; };
{ gotoCase = 49; continue; };
case 98:
yych = this._charAt(++cursor);
if (yych != 'a') { gotoCase = 49; continue; };
yych = this._charAt(++cursor);
if (yych == 'd') { gotoCase = 63; continue; };
{ gotoCase = 49; continue; };
case 100:
yych = this._charAt(++cursor);
if (yych == 'g') { gotoCase = 63; continue; };
{ gotoCase = 49; continue; };
case 101:
yych = this._charAt(++cursor);
if (yych != 'q') { gotoCase = 49; continue; };
yych = this._charAt(++cursor);
if (yych != 'e') { gotoCase = 49; continue; };
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 63; continue; };
{ gotoCase = 49; continue; };
case 104:
++cursor;
yych = this._charAt(cursor);
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 108; continue; };
{ gotoCase = 104; continue; };
} else {
if (yych <= '\r') { gotoCase = 108; continue; };
if (yych != '*') { gotoCase = 104; continue; };
}
case 106:
++cursor;
yych = this._charAt(cursor);
if (yych == '*') { gotoCase = 106; continue; };
if (yych == '/') { gotoCase = 110; continue; };
{ gotoCase = 104; continue; };
case 108:
++cursor;
this.setLexCondition(this._lexConditions.COMMENT);
{ this.tokenType = "css-comment"; return cursor; }
case 110:
++cursor;
{ this.tokenType = "css-comment"; return cursor; }
case 112:
yyaccept = 0;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych <= '-') {
if (yych <= '"') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 32; continue; };
{ gotoCase = 116; continue; };
} else {
if (yych <= '\r') { gotoCase = 32; continue; };
if (yych <= ' ') { gotoCase = 116; continue; };
{ gotoCase = 112; continue; };
}
} else {
if (yych <= '&') {
if (yych == '$') { gotoCase = 112; continue; };
{ gotoCase = 116; continue; };
} else {
if (yych <= '\'') { gotoCase = 114; continue; };
if (yych <= ',') { gotoCase = 116; continue; };
{ gotoCase = 112; continue; };
}
}
} else {
if (yych <= '[') {
if (yych <= '<') {
if (yych <= '.') { gotoCase = 116; continue; };
if (yych <= '9') { gotoCase = 112; continue; };
{ gotoCase = 116; continue; };
} else {
if (yych <= '=') { gotoCase = 112; continue; };
if (yych <= '?') { gotoCase = 116; continue; };
{ gotoCase = 112; continue; };
}
} else {
if (yych <= '^') {
if (yych <= '\\') { gotoCase = 118; continue; };
if (yych <= ']') { gotoCase = 112; continue; };
{ gotoCase = 116; continue; };
} else {
if (yych == '`') { gotoCase = 116; continue; };
if (yych <= 'z') { gotoCase = 112; continue; };
{ gotoCase = 116; continue; };
}
}
}
case 114:
++cursor;
if ((yych = this._charAt(cursor)) <= '9') {
if (yych <= '&') {
if (yych <= '"') {
if (yych >= '!') { gotoCase = 48; continue; };
} else {
if (yych == '$') { gotoCase = 48; continue; };
}
} else {
if (yych <= ',') {
if (yych <= '\'') { gotoCase = 48; continue; };
} else {
if (yych != '.') { gotoCase = 48; continue; };
}
}
} else {
if (yych <= '\\') {
if (yych <= '=') {
if (yych >= '=') { gotoCase = 48; continue; };
} else {
if (yych <= '?') { gotoCase = 115; continue; };
if (yych <= '[') { gotoCase = 48; continue; };
}
} else {
if (yych <= '_') {
if (yych != '^') { gotoCase = 48; continue; };
} else {
if (yych <= '`') { gotoCase = 115; continue; };
if (yych <= 'z') { gotoCase = 48; continue; };
}
}
}
case 115:
{ return this._stringToken(cursor, true); }
case 116:
++cursor;
yych = this._charAt(cursor);
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 66; continue; };
if (yych <= '\f') { gotoCase = 116; continue; };
{ gotoCase = 66; continue; };
} else {
if (yych <= '\'') {
if (yych <= '&') { gotoCase = 116; continue; };
{ gotoCase = 121; continue; };
} else {
if (yych != '\\') { gotoCase = 116; continue; };
}
}
case 118:
++cursor;
yych = this._charAt(cursor);
if (yych <= 'a') {
if (yych <= '!') {
if (yych <= '\n') {
if (yych <= '\t') { gotoCase = 66; continue; };
} else {
if (yych != '\r') { gotoCase = 66; continue; };
}
} else {
if (yych <= '\'') {
if (yych <= '"') { gotoCase = 116; continue; };
if (yych <= '&') { gotoCase = 66; continue; };
{ gotoCase = 116; continue; };
} else {
if (yych == '\\') { gotoCase = 116; continue; };
{ gotoCase = 66; continue; };
}
}
} else {
if (yych <= 'q') {
if (yych <= 'f') {
if (yych <= 'b') { gotoCase = 116; continue; };
if (yych <= 'e') { gotoCase = 66; continue; };
{ gotoCase = 116; continue; };
} else {
if (yych == 'n') { gotoCase = 116; continue; };
{ gotoCase = 66; continue; };
}
} else {
if (yych <= 't') {
if (yych == 's') { gotoCase = 66; continue; };
{ gotoCase = 116; continue; };
} else {
if (yych == 'v') { gotoCase = 116; continue; };
{ gotoCase = 66; continue; };
}
}
}
++cursor;
this.setLexCondition(this._lexConditions.SSTRING);
{ return this._stringToken(cursor); }
case 121:
yych = this._charAt(++cursor);
{ gotoCase = 115; continue; };
case 122:
yyaccept = 0;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych <= '-') {
if (yych <= '!') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 32; continue; };
} else {
if (yych <= '\r') { gotoCase = 32; continue; };
if (yych >= '!') { gotoCase = 122; continue; };
}
} else {
if (yych <= '$') {
if (yych <= '"') { gotoCase = 114; continue; };
if (yych >= '$') { gotoCase = 122; continue; };
} else {
if (yych == '\'') { gotoCase = 122; continue; };
if (yych >= '-') { gotoCase = 122; continue; };
}
}
} else {
if (yych <= '[') {
if (yych <= '<') {
if (yych <= '.') { gotoCase = 124; continue; };
if (yych <= '9') { gotoCase = 122; continue; };
} else {
if (yych <= '=') { gotoCase = 122; continue; };
if (yych >= '@') { gotoCase = 122; continue; };
}
} else {
if (yych <= '^') {
if (yych <= '\\') { gotoCase = 126; continue; };
if (yych <= ']') { gotoCase = 122; continue; };
} else {
if (yych == '`') { gotoCase = 124; continue; };
if (yych <= 'z') { gotoCase = 122; continue; };
}
}
}
case 124:
++cursor;
yych = this._charAt(cursor);
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 66; continue; };
if (yych <= '\f') { gotoCase = 124; continue; };
{ gotoCase = 66; continue; };
} else {
if (yych <= '"') {
if (yych <= '!') { gotoCase = 124; continue; };
{ gotoCase = 121; continue; };
} else {
if (yych != '\\') { gotoCase = 124; continue; };
}
}
case 126:
++cursor;
yych = this._charAt(cursor);
if (yych <= 'a') {
if (yych <= '!') {
if (yych <= '\n') {
if (yych <= '\t') { gotoCase = 66; continue; };
} else {
if (yych != '\r') { gotoCase = 66; continue; };
}
} else {
if (yych <= '\'') {
if (yych <= '"') { gotoCase = 124; continue; };
if (yych <= '&') { gotoCase = 66; continue; };
{ gotoCase = 124; continue; };
} else {
if (yych == '\\') { gotoCase = 124; continue; };
{ gotoCase = 66; continue; };
}
}
} else {
if (yych <= 'q') {
if (yych <= 'f') {
if (yych <= 'b') { gotoCase = 124; continue; };
if (yych <= 'e') { gotoCase = 66; continue; };
{ gotoCase = 124; continue; };
} else {
if (yych == 'n') { gotoCase = 124; continue; };
{ gotoCase = 66; continue; };
}
} else {
if (yych <= 't') {
if (yych == 's') { gotoCase = 66; continue; };
{ gotoCase = 124; continue; };
} else {
if (yych == 'v') { gotoCase = 124; continue; };
{ gotoCase = 66; continue; };
}
}
}
++cursor;
this.setLexCondition(this._lexConditions.DSTRING);
{ return this._stringToken(cursor); }

case this.case_SSTRING:
yych = this._charAt(cursor);
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 133; continue; };
if (yych <= '\f') { gotoCase = 132; continue; };
{ gotoCase = 133; continue; };
} else {
if (yych <= '\'') {
if (yych <= '&') { gotoCase = 132; continue; };
{ gotoCase = 135; continue; };
} else {
if (yych == '\\') { gotoCase = 137; continue; };
{ gotoCase = 132; continue; };
}
}
case 131:
{ return this._stringToken(cursor); }
case 132:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
{ gotoCase = 139; continue; };
case 133:
++cursor;
case 134:
{ this.tokenType = null; return cursor; }
case 135:
++cursor;
case 136:
this.setLexCondition(this._lexConditions.INITIAL);
{ return this._stringToken(cursor, true); }
case 137:
yych = this._charAt(++cursor);
if (yych <= 'e') {
if (yych <= '\'') {
if (yych == '"') { gotoCase = 138; continue; };
if (yych <= '&') { gotoCase = 134; continue; };
} else {
if (yych <= '\\') {
if (yych <= '[') { gotoCase = 134; continue; };
} else {
if (yych != 'b') { gotoCase = 134; continue; };
}
}
} else {
if (yych <= 'r') {
if (yych <= 'm') {
if (yych >= 'g') { gotoCase = 134; continue; };
} else {
if (yych <= 'n') { gotoCase = 138; continue; };
if (yych <= 'q') { gotoCase = 134; continue; };
}
} else {
if (yych <= 't') {
if (yych <= 's') { gotoCase = 134; continue; };
} else {
if (yych != 'v') { gotoCase = 134; continue; };
}
}
}
case 138:
yyaccept = 0;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
case 139:
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 131; continue; };
if (yych <= '\f') { gotoCase = 138; continue; };
{ gotoCase = 131; continue; };
} else {
if (yych <= '\'') {
if (yych <= '&') { gotoCase = 138; continue; };
{ gotoCase = 142; continue; };
} else {
if (yych != '\\') { gotoCase = 138; continue; };
}
}
++cursor;
yych = this._charAt(cursor);
if (yych <= 'e') {
if (yych <= '\'') {
if (yych == '"') { gotoCase = 138; continue; };
if (yych >= '\'') { gotoCase = 138; continue; };
} else {
if (yych <= '\\') {
if (yych >= '\\') { gotoCase = 138; continue; };
} else {
if (yych == 'b') { gotoCase = 138; continue; };
}
}
} else {
if (yych <= 'r') {
if (yych <= 'm') {
if (yych <= 'f') { gotoCase = 138; continue; };
} else {
if (yych <= 'n') { gotoCase = 138; continue; };
if (yych >= 'r') { gotoCase = 138; continue; };
}
} else {
if (yych <= 't') {
if (yych >= 't') { gotoCase = 138; continue; };
} else {
if (yych == 'v') { gotoCase = 138; continue; };
}
}
}
cursor = YYMARKER;
{ gotoCase = 131; continue; };
case 142:
++cursor;
yych = this._charAt(cursor);
{ gotoCase = 136; continue; };
}

}
}
}

WebInspector.SourceCSSTokenizer.prototype.__proto__ = WebInspector.SourceTokenizer.prototype;


















WebInspector.SourceHTMLTokenizer = function()
{
WebInspector.SourceTokenizer.call(this);


this._lexConditions = {
INITIAL: 0,
COMMENT: 1,
DOCTYPE: 2,
TAG: 3,
DSTRING: 4,
SSTRING: 5
};
this.case_INITIAL = 1000;
this.case_COMMENT = 1001;
this.case_DOCTYPE = 1002;
this.case_TAG = 1003;
this.case_DSTRING = 1004;
this.case_SSTRING = 1005;

this._parseConditions = {
INITIAL: 0,
ATTRIBUTE: 1,
ATTRIBUTE_VALUE: 2,
LINKIFY: 4,
A_NODE: 8,
SCRIPT: 16,
STYLE: 32
};

this.condition = this.createInitialCondition();
}

WebInspector.SourceHTMLTokenizer.prototype = {
createInitialCondition: function()
{
return { lexCondition: this._lexConditions.INITIAL, parseCondition: this._parseConditions.INITIAL };
},

set line(line) {
if (this._condition.internalJavaScriptTokenizerCondition) {
var match = /<\/script/i.exec(line);
if (match) {
this._internalJavaScriptTokenizer.line = line.substring(0, match.index);
} else
this._internalJavaScriptTokenizer.line = line;
} else if (this._condition.internalCSSTokenizerCondition) {
var match = /<\/style/i.exec(line);
if (match) {
this._internalCSSTokenizer.line = line.substring(0, match.index);
} else
this._internalCSSTokenizer.line = line;
}
this._line = line;
},

_isExpectingAttribute: function()
{
return this._condition.parseCondition & this._parseConditions.ATTRIBUTE;
},

_isExpectingAttributeValue: function()
{
return this._condition.parseCondition & this._parseConditions.ATTRIBUTE_VALUE;
},

_setExpectingAttribute: function()
{
if (this._isExpectingAttributeValue())
this._condition.parseCondition ^= this._parseConditions.ATTRIBUTE_VALUE;
this._condition.parseCondition |= this._parseConditions.ATTRIBUTE;
},

_setExpectingAttributeValue: function()
{
if (this._isExpectingAttribute())
this._condition.parseCondition ^= this._parseConditions.ATTRIBUTE;
this._condition.parseCondition |= this._parseConditions.ATTRIBUTE_VALUE;
},

_stringToken: function(cursor, stringEnds)
{
if (!this._isExpectingAttributeValue()) {
this.tokenType = null;
return cursor;
}
this.tokenType = this._attrValueTokenType();
if (stringEnds)
this._setExpectingAttribute();
return cursor;
},

_attrValueTokenType: function()
{
if (this._condition.parseCondition & this._parseConditions.LINKIFY) {
if (this._condition.parseCondition & this._parseConditions.A_NODE)
return "html-external-link";
return "html-resource-link";
}
return "html-attribute-value";
},

get _internalJavaScriptTokenizer()
{
return WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/javascript");
},

get _internalCSSTokenizer()
{
return WebInspector.SourceTokenizer.Registry.getInstance().getTokenizer("text/css");
},

scriptStarted: function(cursor)
{
this._condition.internalJavaScriptTokenizerCondition = this._internalJavaScriptTokenizer.createInitialCondition();
},

scriptEnded: function(cursor)
{
},

styleSheetStarted: function(cursor)
{
this._condition.internalCSSTokenizerCondition = this._internalCSSTokenizer.createInitialCondition();
},

styleSheetEnded: function(cursor)
{
},

nextToken: function(cursor)
{
if (this._condition.internalJavaScriptTokenizerCondition) {

this.line = this._line;
if (cursor !== this._internalJavaScriptTokenizer._line.length) {

this._internalJavaScriptTokenizer.condition = this._condition.internalJavaScriptTokenizerCondition;
var result = this._internalJavaScriptTokenizer.nextToken(cursor);
this.tokenType = this._internalJavaScriptTokenizer.tokenType;
this._condition.internalJavaScriptTokenizerCondition = this._internalJavaScriptTokenizer.condition;
return result;
} else if (cursor !== this._line.length)
delete this._condition.internalJavaScriptTokenizerCondition;
} else if (this._condition.internalCSSTokenizerCondition) {

this.line = this._line;
if (cursor !== this._internalCSSTokenizer._line.length) {

this._internalCSSTokenizer.condition = this._condition.internalCSSTokenizerCondition;
var result = this._internalCSSTokenizer.nextToken(cursor);
this.tokenType = this._internalCSSTokenizer.tokenType;
this._condition.internalCSSTokenizerCondition = this._internalCSSTokenizer.condition;
return result;
} else if (cursor !== this._line.length)
delete this._condition.internalCSSTokenizerCondition;
}

var cursorOnEnter = cursor;
var gotoCase = 1;
while (1) {
switch (gotoCase)


{
case 1: var yych;
var yyaccept = 0;
if (this.getLexCondition() < 3) {
if (this.getLexCondition() < 1) {
{ gotoCase = this.case_INITIAL; continue; };
} else {
if (this.getLexCondition() < 2) {
{ gotoCase = this.case_COMMENT; continue; };
} else {
{ gotoCase = this.case_DOCTYPE; continue; };
}
}
} else {
if (this.getLexCondition() < 4) {
{ gotoCase = this.case_TAG; continue; };
} else {
if (this.getLexCondition() < 5) {
{ gotoCase = this.case_DSTRING; continue; };
} else {
{ gotoCase = this.case_SSTRING; continue; };
}
}
}

case this.case_COMMENT:

yych = this._charAt(cursor);
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 4; continue; };
{ gotoCase = 3; continue; };
} else {
if (yych <= '\r') { gotoCase = 4; continue; };
if (yych == '-') { gotoCase = 6; continue; };
{ gotoCase = 3; continue; };
}
case 2:
{ this.tokenType = "html-comment"; return cursor; }
case 3:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
{ gotoCase = 9; continue; };
case 4:
++cursor;
case 5:
{ this.tokenType = null; return cursor; }
case 6:
yyaccept = 1;
yych = this._charAt(YYMARKER = ++cursor);
if (yych != '-') { gotoCase = 5; continue; };
case 7:
++cursor;
yych = this._charAt(cursor);
if (yych == '>') { gotoCase = 10; continue; };
case 8:
yyaccept = 0;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
case 9:
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 2; continue; };
{ gotoCase = 8; continue; };
} else {
if (yych <= '\r') { gotoCase = 2; continue; };
if (yych == '-') { gotoCase = 12; continue; };
{ gotoCase = 8; continue; };
}
case 10:
++cursor;
this.setLexCondition(this._lexConditions.INITIAL);
{ this.tokenType = "html-comment"; return cursor; }
case 12:
++cursor;
yych = this._charAt(cursor);
if (yych == '-') { gotoCase = 7; continue; };
cursor = YYMARKER;
if (yyaccept <= 0) {
{ gotoCase = 2; continue; };
} else {
{ gotoCase = 5; continue; };
}

case this.case_DOCTYPE:
yych = this._charAt(cursor);
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 18; continue; };
{ gotoCase = 17; continue; };
} else {
if (yych <= '\r') { gotoCase = 18; continue; };
if (yych == '>') { gotoCase = 20; continue; };
{ gotoCase = 17; continue; };
}
case 16:
{ this.tokenType = "html-doctype"; return cursor; }
case 17:
yych = this._charAt(++cursor);
{ gotoCase = 23; continue; };
case 18:
++cursor;
{ this.tokenType = null; return cursor; }
case 20:
++cursor;
this.setLexCondition(this._lexConditions.INITIAL);
{ this.tokenType = "html-doctype"; return cursor; }
case 22:
++cursor;
yych = this._charAt(cursor);
case 23:
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 16; continue; };
{ gotoCase = 22; continue; };
} else {
if (yych <= '\r') { gotoCase = 16; continue; };
if (yych == '>') { gotoCase = 16; continue; };
{ gotoCase = 22; continue; };
}

case this.case_DSTRING:
yych = this._charAt(cursor);
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 28; continue; };
{ gotoCase = 27; continue; };
} else {
if (yych <= '\r') { gotoCase = 28; continue; };
if (yych == '"') { gotoCase = 30; continue; };
{ gotoCase = 27; continue; };
}
case 26:
{ return this._stringToken(cursor); }
case 27:
yych = this._charAt(++cursor);
{ gotoCase = 34; continue; };
case 28:
++cursor;
{ this.tokenType = null; return cursor; }
case 30:
++cursor;
case 31:
this.setLexCondition(this._lexConditions.TAG);
{ return this._stringToken(cursor, true); }
case 32:
yych = this._charAt(++cursor);
{ gotoCase = 31; continue; };
case 33:
++cursor;
yych = this._charAt(cursor);
case 34:
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 26; continue; };
{ gotoCase = 33; continue; };
} else {
if (yych <= '\r') { gotoCase = 26; continue; };
if (yych == '"') { gotoCase = 32; continue; };
{ gotoCase = 33; continue; };
}

case this.case_INITIAL:
yych = this._charAt(cursor);
if (yych == '<') { gotoCase = 39; continue; };
++cursor;
{ this.tokenType = null; return cursor; }
case 39:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych <= '/') {
if (yych == '!') { gotoCase = 44; continue; };
if (yych >= '/') { gotoCase = 41; continue; };
} else {
if (yych <= 'S') {
if (yych >= 'S') { gotoCase = 42; continue; };
} else {
if (yych == 's') { gotoCase = 42; continue; };
}
}
case 40:
this.setLexCondition(this._lexConditions.TAG);
{
if (this._condition.parseCondition & (this._parseConditions.SCRIPT | this._parseConditions.STYLE)) {

this.setLexCondition(this._lexConditions.INITIAL);
this.tokenType = null;
return cursor;
}

this._condition.parseCondition = this._parseConditions.INITIAL;
this.tokenType = "html-tag";
return cursor;
}
case 41:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych == 'S') { gotoCase = 73; continue; };
if (yych == 's') { gotoCase = 73; continue; };
{ gotoCase = 40; continue; };
case 42:
yych = this._charAt(++cursor);
if (yych <= 'T') {
if (yych == 'C') { gotoCase = 62; continue; };
if (yych >= 'T') { gotoCase = 63; continue; };
} else {
if (yych <= 'c') {
if (yych >= 'c') { gotoCase = 62; continue; };
} else {
if (yych == 't') { gotoCase = 63; continue; };
}
}
case 43:
cursor = YYMARKER;
{ gotoCase = 40; continue; };
case 44:
yych = this._charAt(++cursor);
if (yych <= 'C') {
if (yych != '-') { gotoCase = 43; continue; };
} else {
if (yych <= 'D') { gotoCase = 46; continue; };
if (yych == 'd') { gotoCase = 46; continue; };
{ gotoCase = 43; continue; };
}
yych = this._charAt(++cursor);
if (yych == '-') { gotoCase = 54; continue; };
{ gotoCase = 43; continue; };
case 46:
yych = this._charAt(++cursor);
if (yych == 'O') { gotoCase = 47; continue; };
if (yych != 'o') { gotoCase = 43; continue; };
case 47:
yych = this._charAt(++cursor);
if (yych == 'C') { gotoCase = 48; continue; };
if (yych != 'c') { gotoCase = 43; continue; };
case 48:
yych = this._charAt(++cursor);
if (yych == 'T') { gotoCase = 49; continue; };
if (yych != 't') { gotoCase = 43; continue; };
case 49:
yych = this._charAt(++cursor);
if (yych == 'Y') { gotoCase = 50; continue; };
if (yych != 'y') { gotoCase = 43; continue; };
case 50:
yych = this._charAt(++cursor);
if (yych == 'P') { gotoCase = 51; continue; };
if (yych != 'p') { gotoCase = 43; continue; };
case 51:
yych = this._charAt(++cursor);
if (yych == 'E') { gotoCase = 52; continue; };
if (yych != 'e') { gotoCase = 43; continue; };
case 52:
++cursor;
this.setLexCondition(this._lexConditions.DOCTYPE);
{ this.tokenType = "html-doctype"; return cursor; }
case 54:
++cursor;
yych = this._charAt(cursor);
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 57; continue; };
{ gotoCase = 54; continue; };
} else {
if (yych <= '\r') { gotoCase = 57; continue; };
if (yych != '-') { gotoCase = 54; continue; };
}
++cursor;
yych = this._charAt(cursor);
if (yych == '-') { gotoCase = 59; continue; };
{ gotoCase = 43; continue; };
case 57:
++cursor;
this.setLexCondition(this._lexConditions.COMMENT);
{ this.tokenType = "html-comment"; return cursor; }
case 59:
++cursor;
yych = this._charAt(cursor);
if (yych != '>') { gotoCase = 54; continue; };
++cursor;
{ this.tokenType = "html-comment"; return cursor; }
case 62:
yych = this._charAt(++cursor);
if (yych == 'R') { gotoCase = 68; continue; };
if (yych == 'r') { gotoCase = 68; continue; };
{ gotoCase = 43; continue; };
case 63:
yych = this._charAt(++cursor);
if (yych == 'Y') { gotoCase = 64; continue; };
if (yych != 'y') { gotoCase = 43; continue; };
case 64:
yych = this._charAt(++cursor);
if (yych == 'L') { gotoCase = 65; continue; };
if (yych != 'l') { gotoCase = 43; continue; };
case 65:
yych = this._charAt(++cursor);
if (yych == 'E') { gotoCase = 66; continue; };
if (yych != 'e') { gotoCase = 43; continue; };
case 66:
++cursor;
this.setLexCondition(this._lexConditions.TAG);
{
if (this._condition.parseCondition & this._parseConditions.STYLE) {

this.setLexCondition(this._lexConditions.INITIAL);
this.tokenType = null;
return cursor;
}
this.tokenType = "html-tag";
this._condition.parseCondition = this._parseConditions.STYLE;
this._setExpectingAttribute();
return cursor;
}
case 68:
yych = this._charAt(++cursor);
if (yych == 'I') { gotoCase = 69; continue; };
if (yych != 'i') { gotoCase = 43; continue; };
case 69:
yych = this._charAt(++cursor);
if (yych == 'P') { gotoCase = 70; continue; };
if (yych != 'p') { gotoCase = 43; continue; };
case 70:
yych = this._charAt(++cursor);
if (yych == 'T') { gotoCase = 71; continue; };
if (yych != 't') { gotoCase = 43; continue; };
case 71:
++cursor;
this.setLexCondition(this._lexConditions.TAG);
{
if (this._condition.parseCondition & this._parseConditions.SCRIPT) {

this.setLexCondition(this._lexConditions.INITIAL);
this.tokenType = null;
return cursor;
}
this.tokenType = "html-tag";
this._condition.parseCondition = this._parseConditions.SCRIPT;
this._setExpectingAttribute();
return cursor;
}
case 73:
yych = this._charAt(++cursor);
if (yych <= 'T') {
if (yych == 'C') { gotoCase = 75; continue; };
if (yych <= 'S') { gotoCase = 43; continue; };
} else {
if (yych <= 'c') {
if (yych <= 'b') { gotoCase = 43; continue; };
{ gotoCase = 75; continue; };
} else {
if (yych != 't') { gotoCase = 43; continue; };
}
}
yych = this._charAt(++cursor);
if (yych == 'Y') { gotoCase = 81; continue; };
if (yych == 'y') { gotoCase = 81; continue; };
{ gotoCase = 43; continue; };
case 75:
yych = this._charAt(++cursor);
if (yych == 'R') { gotoCase = 76; continue; };
if (yych != 'r') { gotoCase = 43; continue; };
case 76:
yych = this._charAt(++cursor);
if (yych == 'I') { gotoCase = 77; continue; };
if (yych != 'i') { gotoCase = 43; continue; };
case 77:
yych = this._charAt(++cursor);
if (yych == 'P') { gotoCase = 78; continue; };
if (yych != 'p') { gotoCase = 43; continue; };
case 78:
yych = this._charAt(++cursor);
if (yych == 'T') { gotoCase = 79; continue; };
if (yych != 't') { gotoCase = 43; continue; };
case 79:
++cursor;
this.setLexCondition(this._lexConditions.TAG);
{
this.tokenType = "html-tag";
this._condition.parseCondition = this._parseConditions.INITIAL;
this.scriptEnded(cursor - 8);
return cursor;
}
case 81:
yych = this._charAt(++cursor);
if (yych == 'L') { gotoCase = 82; continue; };
if (yych != 'l') { gotoCase = 43; continue; };
case 82:
yych = this._charAt(++cursor);
if (yych == 'E') { gotoCase = 83; continue; };
if (yych != 'e') { gotoCase = 43; continue; };
case 83:
++cursor;
this.setLexCondition(this._lexConditions.TAG);
{
this.tokenType = "html-tag";
this._condition.parseCondition = this._parseConditions.INITIAL;
this.styleSheetEnded(cursor - 7);
return cursor;
}

case this.case_SSTRING:
yych = this._charAt(cursor);
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 89; continue; };
{ gotoCase = 88; continue; };
} else {
if (yych <= '\r') { gotoCase = 89; continue; };
if (yych == '\'') { gotoCase = 91; continue; };
{ gotoCase = 88; continue; };
}
case 87:
{ return this._stringToken(cursor); }
case 88:
yych = this._charAt(++cursor);
{ gotoCase = 95; continue; };
case 89:
++cursor;
{ this.tokenType = null; return cursor; }
case 91:
++cursor;
case 92:
this.setLexCondition(this._lexConditions.TAG);
{ return this._stringToken(cursor, true); }
case 93:
yych = this._charAt(++cursor);
{ gotoCase = 92; continue; };
case 94:
++cursor;
yych = this._charAt(cursor);
case 95:
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 87; continue; };
{ gotoCase = 94; continue; };
} else {
if (yych <= '\r') { gotoCase = 87; continue; };
if (yych == '\'') { gotoCase = 93; continue; };
{ gotoCase = 94; continue; };
}

case this.case_TAG:
yych = this._charAt(cursor);
if (yych <= '&') {
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 100; continue; };
if (yych >= '\r') { gotoCase = 100; continue; };
} else {
if (yych <= ' ') {
if (yych >= ' ') { gotoCase = 100; continue; };
} else {
if (yych == '"') { gotoCase = 102; continue; };
}
}
} else {
if (yych <= '>') {
if (yych <= ';') {
if (yych <= '\'') { gotoCase = 103; continue; };
} else {
if (yych <= '<') { gotoCase = 100; continue; };
if (yych <= '=') { gotoCase = 104; continue; };
{ gotoCase = 106; continue; };
}
} else {
if (yych <= '[') {
if (yych >= '[') { gotoCase = 100; continue; };
} else {
if (yych == ']') { gotoCase = 100; continue; };
}
}
}
++cursor;
yych = this._charAt(cursor);
{ gotoCase = 119; continue; };
case 99:
{
if (this._condition.parseCondition === this._parseConditions.SCRIPT || this._condition.parseCondition === this._parseConditions.STYLE) {

this.tokenType = null;
return cursor;
}

if (this._condition.parseCondition === this._parseConditions.INITIAL) {
this.tokenType = "html-tag";
this._setExpectingAttribute();
var token = this._line.substring(cursorOnEnter, cursor);
if (token === "a")
this._condition.parseCondition |= this._parseConditions.A_NODE;
else if (this._condition.parseCondition & this._parseConditions.A_NODE)
this._condition.parseCondition ^= this._parseConditions.A_NODE;
} else if (this._isExpectingAttribute()) {
var token = this._line.substring(cursorOnEnter, cursor);
if (token === "href" || token === "src")
this._condition.parseCondition |= this._parseConditions.LINKIFY;
else if (this._condition.parseCondition |= this._parseConditions.LINKIFY)
this._condition.parseCondition ^= this._parseConditions.LINKIFY;
this.tokenType = "html-attribute-name";
} else if (this._isExpectingAttributeValue())
this.tokenType = this._attrValueTokenType();
else
this.tokenType = null;
return cursor;
}
case 100:
++cursor;
{ this.tokenType = null; return cursor; }
case 102:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
{ gotoCase = 115; continue; };
case 103:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
{ gotoCase = 109; continue; };
case 104:
++cursor;
{
if (this._isExpectingAttribute())
this._setExpectingAttributeValue();
this.tokenType = null;
return cursor;
}
case 106:
++cursor;
this.setLexCondition(this._lexConditions.INITIAL);
{
this.tokenType = "html-tag";
if (this._condition.parseCondition & this._parseConditions.SCRIPT) {
this.scriptStarted(cursor);

return cursor;
}

if (this._condition.parseCondition & this._parseConditions.STYLE) {
this.styleSheetStarted(cursor);

return cursor;
}

this._condition.parseCondition = this._parseConditions.INITIAL;
return cursor;
}
case 108:
++cursor;
yych = this._charAt(cursor);
case 109:
if (yych <= '\f') {
if (yych != '\n') { gotoCase = 108; continue; };
} else {
if (yych <= '\r') { gotoCase = 110; continue; };
if (yych == '\'') { gotoCase = 112; continue; };
{ gotoCase = 108; continue; };
}
case 110:
++cursor;
this.setLexCondition(this._lexConditions.SSTRING);
{ return this._stringToken(cursor); }
case 112:
++cursor;
{ return this._stringToken(cursor, true); }
case 114:
++cursor;
yych = this._charAt(cursor);
case 115:
if (yych <= '\f') {
if (yych != '\n') { gotoCase = 114; continue; };
} else {
if (yych <= '\r') { gotoCase = 116; continue; };
if (yych == '"') { gotoCase = 112; continue; };
{ gotoCase = 114; continue; };
}
case 116:
++cursor;
this.setLexCondition(this._lexConditions.DSTRING);
{ return this._stringToken(cursor); }
case 118:
++cursor;
yych = this._charAt(cursor);
case 119:
if (yych <= '"') {
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 99; continue; };
if (yych <= '\f') { gotoCase = 118; continue; };
{ gotoCase = 99; continue; };
} else {
if (yych == ' ') { gotoCase = 99; continue; };
if (yych <= '!') { gotoCase = 118; continue; };
{ gotoCase = 99; continue; };
}
} else {
if (yych <= '>') {
if (yych == '\'') { gotoCase = 99; continue; };
if (yych <= ';') { gotoCase = 118; continue; };
{ gotoCase = 99; continue; };
} else {
if (yych <= '[') {
if (yych <= 'Z') { gotoCase = 118; continue; };
{ gotoCase = 99; continue; };
} else {
if (yych == ']') { gotoCase = 99; continue; };
{ gotoCase = 118; continue; };
}
}
}
}

}
}
}

WebInspector.SourceHTMLTokenizer.prototype.__proto__ = WebInspector.SourceTokenizer.prototype;



















WebInspector.SourceJavaScriptTokenizer = function()
{
WebInspector.SourceTokenizer.call(this);

this._keywords = [
"null", "true", "false", "break", "case", "catch", "const", "default", "finally", "for",
"instanceof", "new", "var", "continue", "function", "return", "void", "delete", "if",
"this", "do", "while", "else", "in", "switch", "throw", "try", "typeof", "debugger",
"class", "enum", "export", "extends", "import", "super", "get", "set", "with"
].keySet();

this._lexConditions = {
DIV: 0,
NODIV: 1,
COMMENT: 2,
DSTRING: 3,
SSTRING: 4,
REGEX: 5
};

this.case_DIV = 1000;
this.case_NODIV = 1001;
this.case_COMMENT = 1002;
this.case_DSTRING = 1003;
this.case_SSTRING = 1004;
this.case_REGEX = 1005;

this.condition = this.createInitialCondition();
}

WebInspector.SourceJavaScriptTokenizer.prototype = {
createInitialCondition: function()
{
return { lexCondition: this._lexConditions.NODIV };
},

nextToken: function(cursor)
{
var cursorOnEnter = cursor;
var gotoCase = 1;
while (1) {
switch (gotoCase)


{
case 1: var yych;
var yyaccept = 0;
if (this.getLexCondition() < 3) {
if (this.getLexCondition() < 1) {
{ gotoCase = this.case_DIV; continue; };
} else {
if (this.getLexCondition() < 2) {
{ gotoCase = this.case_NODIV; continue; };
} else {
{ gotoCase = this.case_COMMENT; continue; };
}
}
} else {
if (this.getLexCondition() < 4) {
{ gotoCase = this.case_DSTRING; continue; };
} else {
if (this.getLexCondition() < 5) {
{ gotoCase = this.case_SSTRING; continue; };
} else {
{ gotoCase = this.case_REGEX; continue; };
}
}
}

case this.case_COMMENT:

yych = this._charAt(cursor);
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 4; continue; };
{ gotoCase = 3; continue; };
} else {
if (yych <= '\r') { gotoCase = 4; continue; };
if (yych == '*') { gotoCase = 6; continue; };
{ gotoCase = 3; continue; };
}
case 2:
{ this.tokenType = "javascript-comment"; return cursor; }
case 3:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
{ gotoCase = 12; continue; };
case 4:
++cursor;
{ this.tokenType = null; return cursor; }
case 6:
yyaccept = 1;
yych = this._charAt(YYMARKER = ++cursor);
if (yych == '*') { gotoCase = 9; continue; };
if (yych != '/') { gotoCase = 11; continue; };
case 7:
++cursor;
this.setLexCondition(this._lexConditions.NODIV);
{ this.tokenType = "javascript-comment"; return cursor; }
case 9:
++cursor;
yych = this._charAt(cursor);
if (yych == '*') { gotoCase = 9; continue; };
if (yych == '/') { gotoCase = 7; continue; };
case 11:
yyaccept = 0;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
case 12:
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 2; continue; };
{ gotoCase = 11; continue; };
} else {
if (yych <= '\r') { gotoCase = 2; continue; };
if (yych == '*') { gotoCase = 9; continue; };
{ gotoCase = 11; continue; };
}

case this.case_DIV:
yych = this._charAt(cursor);
if (yych <= '9') {
if (yych <= '(') {
if (yych <= '#') {
if (yych <= ' ') { gotoCase = 15; continue; };
if (yych <= '!') { gotoCase = 17; continue; };
if (yych <= '"') { gotoCase = 19; continue; };
} else {
if (yych <= '%') {
if (yych <= '$') { gotoCase = 20; continue; };
{ gotoCase = 22; continue; };
} else {
if (yych <= '&') { gotoCase = 23; continue; };
if (yych <= '\'') { gotoCase = 24; continue; };
{ gotoCase = 25; continue; };
}
}
} else {
if (yych <= ',') {
if (yych <= ')') { gotoCase = 26; continue; };
if (yych <= '*') { gotoCase = 28; continue; };
if (yych <= '+') { gotoCase = 29; continue; };
{ gotoCase = 25; continue; };
} else {
if (yych <= '.') {
if (yych <= '-') { gotoCase = 30; continue; };
{ gotoCase = 31; continue; };
} else {
if (yych <= '/') { gotoCase = 32; continue; };
if (yych <= '0') { gotoCase = 34; continue; };
{ gotoCase = 36; continue; };
}
}
}
} else {
if (yych <= '\\') {
if (yych <= '>') {
if (yych <= ';') { gotoCase = 25; continue; };
if (yych <= '<') { gotoCase = 37; continue; };
if (yych <= '=') { gotoCase = 38; continue; };
{ gotoCase = 39; continue; };
} else {
if (yych <= '@') {
if (yych <= '?') { gotoCase = 25; continue; };
} else {
if (yych <= 'Z') { gotoCase = 20; continue; };
if (yych <= '[') { gotoCase = 25; continue; };
{ gotoCase = 40; continue; };
}
}
} else {
if (yych <= 'z') {
if (yych <= '^') {
if (yych <= ']') { gotoCase = 25; continue; };
{ gotoCase = 41; continue; };
} else {
if (yych != '`') { gotoCase = 20; continue; };
}
} else {
if (yych <= '|') {
if (yych <= '{') { gotoCase = 25; continue; };
{ gotoCase = 42; continue; };
} else {
if (yych <= '~') { gotoCase = 25; continue; };
if (yych >= 0x80) { gotoCase = 20; continue; };
}
}
}
}
case 15:
++cursor;
case 16:
{ this.tokenType = null; return cursor; }
case 17:
++cursor;
if ((yych = this._charAt(cursor)) == '=') { gotoCase = 115; continue; };
case 18:
this.setLexCondition(this._lexConditions.NODIV);
{ this.tokenType = null; return cursor; }
case 19:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych == '\n') { gotoCase = 16; continue; };
if (yych == '\r') { gotoCase = 16; continue; };
{ gotoCase = 107; continue; };
case 20:
yyaccept = 1;
yych = this._charAt(YYMARKER = ++cursor);
{ gotoCase = 50; continue; };
case 21:
{
var token = this._line.substring(cursorOnEnter, cursor);
if (this._keywords[token] === true && token !== "__proto__")
this.tokenType = "javascript-keyword";
else
this.tokenType = "javascript-ident";
return cursor;
}
case 22:
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 43; continue; };
{ gotoCase = 18; continue; };
case 23:
yych = this._charAt(++cursor);
if (yych == '&') { gotoCase = 43; continue; };
if (yych == '=') { gotoCase = 43; continue; };
{ gotoCase = 18; continue; };
case 24:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych == '\n') { gotoCase = 16; continue; };
if (yych == '\r') { gotoCase = 16; continue; };
{ gotoCase = 96; continue; };
case 25:
yych = this._charAt(++cursor);
{ gotoCase = 18; continue; };
case 26:
++cursor;
{ this.tokenType = null; return cursor; }
case 28:
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 43; continue; };
{ gotoCase = 18; continue; };
case 29:
yych = this._charAt(++cursor);
if (yych == '+') { gotoCase = 43; continue; };
if (yych == '=') { gotoCase = 43; continue; };
{ gotoCase = 18; continue; };
case 30:
yych = this._charAt(++cursor);
if (yych == '-') { gotoCase = 43; continue; };
if (yych == '=') { gotoCase = 43; continue; };
{ gotoCase = 18; continue; };
case 31:
yych = this._charAt(++cursor);
if (yych <= '/') { gotoCase = 18; continue; };
if (yych <= '9') { gotoCase = 89; continue; };
{ gotoCase = 18; continue; };
case 32:
yyaccept = 2;
yych = this._charAt(YYMARKER = ++cursor);
if (yych <= '.') {
if (yych == '*') { gotoCase = 78; continue; };
} else {
if (yych <= '/') { gotoCase = 80; continue; };
if (yych == '=') { gotoCase = 77; continue; };
}
case 33:
this.setLexCondition(this._lexConditions.NODIV);
{ this.tokenType = null; return cursor; }
case 34:
yyaccept = 3;
yych = this._charAt(YYMARKER = ++cursor);
if (yych <= 'E') {
if (yych <= '/') {
if (yych == '.') { gotoCase = 63; continue; };
} else {
if (yych <= '7') { gotoCase = 72; continue; };
if (yych >= 'E') { gotoCase = 62; continue; };
}
} else {
if (yych <= 'd') {
if (yych == 'X') { gotoCase = 74; continue; };
} else {
if (yych <= 'e') { gotoCase = 62; continue; };
if (yych == 'x') { gotoCase = 74; continue; };
}
}
case 35:
{ this.tokenType = "javascript-number"; return cursor; }
case 36:
yyaccept = 3;
yych = this._charAt(YYMARKER = ++cursor);
if (yych <= '9') {
if (yych == '.') { gotoCase = 63; continue; };
if (yych <= '/') { gotoCase = 35; continue; };
{ gotoCase = 60; continue; };
} else {
if (yych <= 'E') {
if (yych <= 'D') { gotoCase = 35; continue; };
{ gotoCase = 62; continue; };
} else {
if (yych == 'e') { gotoCase = 62; continue; };
{ gotoCase = 35; continue; };
}
}
case 37:
yych = this._charAt(++cursor);
if (yych <= ';') { gotoCase = 18; continue; };
if (yych <= '<') { gotoCase = 59; continue; };
if (yych <= '=') { gotoCase = 43; continue; };
{ gotoCase = 18; continue; };
case 38:
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 58; continue; };
{ gotoCase = 18; continue; };
case 39:
yych = this._charAt(++cursor);
if (yych <= '<') { gotoCase = 18; continue; };
if (yych <= '=') { gotoCase = 43; continue; };
if (yych <= '>') { gotoCase = 56; continue; };
{ gotoCase = 18; continue; };
case 40:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych == 'u') { gotoCase = 44; continue; };
{ gotoCase = 16; continue; };
case 41:
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 43; continue; };
{ gotoCase = 18; continue; };
case 42:
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 43; continue; };
if (yych != '|') { gotoCase = 18; continue; };
case 43:
yych = this._charAt(++cursor);
{ gotoCase = 18; continue; };
case 44:
yych = this._charAt(++cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych <= '9') { gotoCase = 46; continue; };
} else {
if (yych <= 'F') { gotoCase = 46; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych <= 'f') { gotoCase = 46; continue; };
}
case 45:
cursor = YYMARKER;
if (yyaccept <= 1) {
if (yyaccept <= 0) {
{ gotoCase = 16; continue; };
} else {
{ gotoCase = 21; continue; };
}
} else {
if (yyaccept <= 2) {
{ gotoCase = 33; continue; };
} else {
{ gotoCase = 35; continue; };
}
}
case 46:
yych = this._charAt(++cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych >= ':') { gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 47; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych >= 'g') { gotoCase = 45; continue; };
}
case 47:
yych = this._charAt(++cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych >= ':') { gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 48; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych >= 'g') { gotoCase = 45; continue; };
}
case 48:
yych = this._charAt(++cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych >= ':') { gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 49; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych >= 'g') { gotoCase = 45; continue; };
}
case 49:
yyaccept = 1;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
case 50:
if (yych <= '[') {
if (yych <= '/') {
if (yych == '$') { gotoCase = 49; continue; };
{ gotoCase = 21; continue; };
} else {
if (yych <= '9') { gotoCase = 49; continue; };
if (yych <= '@') { gotoCase = 21; continue; };
if (yych <= 'Z') { gotoCase = 49; continue; };
{ gotoCase = 21; continue; };
}
} else {
if (yych <= '_') {
if (yych <= '\\') { gotoCase = 51; continue; };
if (yych <= '^') { gotoCase = 21; continue; };
{ gotoCase = 49; continue; };
} else {
if (yych <= '`') { gotoCase = 21; continue; };
if (yych <= 'z') { gotoCase = 49; continue; };
if (yych <= String.fromCharCode(0x7F)) { gotoCase = 21; continue; };
{ gotoCase = 49; continue; };
}
}
case 51:
++cursor;
yych = this._charAt(cursor);
if (yych != 'u') { gotoCase = 45; continue; };
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych >= ':') { gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 53; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych >= 'g') { gotoCase = 45; continue; };
}
case 53:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych >= ':') { gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 54; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych >= 'g') { gotoCase = 45; continue; };
}
case 54:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych >= ':') { gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 55; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych >= 'g') { gotoCase = 45; continue; };
}
case 55:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych <= '9') { gotoCase = 49; continue; };
{ gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 49; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych <= 'f') { gotoCase = 49; continue; };
{ gotoCase = 45; continue; };
}
case 56:
yych = this._charAt(++cursor);
if (yych <= '<') { gotoCase = 18; continue; };
if (yych <= '=') { gotoCase = 43; continue; };
if (yych >= '?') { gotoCase = 18; continue; };
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 43; continue; };
{ gotoCase = 18; continue; };
case 58:
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 43; continue; };
{ gotoCase = 18; continue; };
case 59:
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 43; continue; };
{ gotoCase = 18; continue; };
case 60:
yyaccept = 3;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych <= '9') {
if (yych == '.') { gotoCase = 63; continue; };
if (yych <= '/') { gotoCase = 35; continue; };
{ gotoCase = 60; continue; };
} else {
if (yych <= 'E') {
if (yych <= 'D') { gotoCase = 35; continue; };
} else {
if (yych != 'e') { gotoCase = 35; continue; };
}
}
case 62:
yych = this._charAt(++cursor);
if (yych <= ',') {
if (yych == '+') { gotoCase = 69; continue; };
{ gotoCase = 45; continue; };
} else {
if (yych <= '-') { gotoCase = 69; continue; };
if (yych <= '/') { gotoCase = 45; continue; };
if (yych <= '9') { gotoCase = 70; continue; };
{ gotoCase = 45; continue; };
}
case 63:
yyaccept = 3;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych <= 'D') {
if (yych <= '/') { gotoCase = 35; continue; };
if (yych <= '9') { gotoCase = 63; continue; };
{ gotoCase = 35; continue; };
} else {
if (yych <= 'E') { gotoCase = 65; continue; };
if (yych != 'e') { gotoCase = 35; continue; };
}
case 65:
yych = this._charAt(++cursor);
if (yych <= ',') {
if (yych != '+') { gotoCase = 45; continue; };
} else {
if (yych <= '-') { gotoCase = 66; continue; };
if (yych <= '/') { gotoCase = 45; continue; };
if (yych <= '9') { gotoCase = 67; continue; };
{ gotoCase = 45; continue; };
}
case 66:
yych = this._charAt(++cursor);
if (yych <= '/') { gotoCase = 45; continue; };
if (yych >= ':') { gotoCase = 45; continue; };
case 67:
++cursor;
yych = this._charAt(cursor);
if (yych <= '/') { gotoCase = 35; continue; };
if (yych <= '9') { gotoCase = 67; continue; };
{ gotoCase = 35; continue; };
case 69:
yych = this._charAt(++cursor);
if (yych <= '/') { gotoCase = 45; continue; };
if (yych >= ':') { gotoCase = 45; continue; };
case 70:
++cursor;
yych = this._charAt(cursor);
if (yych <= '/') { gotoCase = 35; continue; };
if (yych <= '9') { gotoCase = 70; continue; };
{ gotoCase = 35; continue; };
case 72:
++cursor;
yych = this._charAt(cursor);
if (yych <= '/') { gotoCase = 35; continue; };
if (yych <= '7') { gotoCase = 72; continue; };
{ gotoCase = 35; continue; };
case 74:
yych = this._charAt(++cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych >= ':') { gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 75; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych >= 'g') { gotoCase = 45; continue; };
}
case 75:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 35; continue; };
if (yych <= '9') { gotoCase = 75; continue; };
{ gotoCase = 35; continue; };
} else {
if (yych <= 'F') { gotoCase = 75; continue; };
if (yych <= '`') { gotoCase = 35; continue; };
if (yych <= 'f') { gotoCase = 75; continue; };
{ gotoCase = 35; continue; };
}
case 77:
yych = this._charAt(++cursor);
{ gotoCase = 33; continue; };
case 78:
++cursor;
yych = this._charAt(cursor);
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 85; continue; };
{ gotoCase = 78; continue; };
} else {
if (yych <= '\r') { gotoCase = 85; continue; };
if (yych == '*') { gotoCase = 83; continue; };
{ gotoCase = 78; continue; };
}
case 80:
++cursor;
yych = this._charAt(cursor);
if (yych == '\n') { gotoCase = 82; continue; };
if (yych != '\r') { gotoCase = 80; continue; };
case 82:
{ this.tokenType = "javascript-comment"; return cursor; }
case 83:
++cursor;
yych = this._charAt(cursor);
if (yych == '*') { gotoCase = 83; continue; };
if (yych == '/') { gotoCase = 87; continue; };
{ gotoCase = 78; continue; };
case 85:
++cursor;
this.setLexCondition(this._lexConditions.COMMENT);
{ this.tokenType = "javascript-comment"; return cursor; }
case 87:
++cursor;
{ this.tokenType = "javascript-comment"; return cursor; }
case 89:
yyaccept = 3;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych <= 'D') {
if (yych <= '/') { gotoCase = 35; continue; };
if (yych <= '9') { gotoCase = 89; continue; };
{ gotoCase = 35; continue; };
} else {
if (yych <= 'E') { gotoCase = 91; continue; };
if (yych != 'e') { gotoCase = 35; continue; };
}
case 91:
yych = this._charAt(++cursor);
if (yych <= ',') {
if (yych != '+') { gotoCase = 45; continue; };
} else {
if (yych <= '-') { gotoCase = 92; continue; };
if (yych <= '/') { gotoCase = 45; continue; };
if (yych <= '9') { gotoCase = 93; continue; };
{ gotoCase = 45; continue; };
}
case 92:
yych = this._charAt(++cursor);
if (yych <= '/') { gotoCase = 45; continue; };
if (yych >= ':') { gotoCase = 45; continue; };
case 93:
++cursor;
yych = this._charAt(cursor);
if (yych <= '/') { gotoCase = 35; continue; };
if (yych <= '9') { gotoCase = 93; continue; };
{ gotoCase = 35; continue; };
case 95:
++cursor;
yych = this._charAt(cursor);
case 96:
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 45; continue; };
if (yych <= '\f') { gotoCase = 95; continue; };
{ gotoCase = 45; continue; };
} else {
if (yych <= '\'') {
if (yych <= '&') { gotoCase = 95; continue; };
{ gotoCase = 98; continue; };
} else {
if (yych != '\\') { gotoCase = 95; continue; };
}
}
++cursor;
yych = this._charAt(cursor);
if (yych <= 'a') {
if (yych <= '!') {
if (yych <= '\n') {
if (yych <= '\t') { gotoCase = 45; continue; };
{ gotoCase = 101; continue; };
} else {
if (yych == '\r') { gotoCase = 101; continue; };
{ gotoCase = 45; continue; };
}
} else {
if (yych <= '\'') {
if (yych <= '"') { gotoCase = 95; continue; };
if (yych <= '&') { gotoCase = 45; continue; };
{ gotoCase = 95; continue; };
} else {
if (yych == '\\') { gotoCase = 95; continue; };
{ gotoCase = 45; continue; };
}
}
} else {
if (yych <= 'q') {
if (yych <= 'f') {
if (yych <= 'b') { gotoCase = 95; continue; };
if (yych <= 'e') { gotoCase = 45; continue; };
{ gotoCase = 95; continue; };
} else {
if (yych == 'n') { gotoCase = 95; continue; };
{ gotoCase = 45; continue; };
}
} else {
if (yych <= 't') {
if (yych == 's') { gotoCase = 45; continue; };
{ gotoCase = 95; continue; };
} else {
if (yych <= 'u') { gotoCase = 100; continue; };
if (yych <= 'v') { gotoCase = 95; continue; };
{ gotoCase = 45; continue; };
}
}
}
case 98:
++cursor;
{ this.tokenType = "javascript-string"; return cursor; }
case 100:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych <= '9') { gotoCase = 103; continue; };
{ gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 103; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych <= 'f') { gotoCase = 103; continue; };
{ gotoCase = 45; continue; };
}
case 101:
++cursor;
this.setLexCondition(this._lexConditions.SSTRING);
{ this.tokenType = "javascript-string"; return cursor; }
case 103:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych >= ':') { gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 104; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych >= 'g') { gotoCase = 45; continue; };
}
case 104:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych >= ':') { gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 105; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych >= 'g') { gotoCase = 45; continue; };
}
case 105:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych <= '9') { gotoCase = 95; continue; };
{ gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 95; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych <= 'f') { gotoCase = 95; continue; };
{ gotoCase = 45; continue; };
}
case 106:
++cursor;
yych = this._charAt(cursor);
case 107:
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 45; continue; };
if (yych <= '\f') { gotoCase = 106; continue; };
{ gotoCase = 45; continue; };
} else {
if (yych <= '"') {
if (yych <= '!') { gotoCase = 106; continue; };
{ gotoCase = 98; continue; };
} else {
if (yych != '\\') { gotoCase = 106; continue; };
}
}
++cursor;
yych = this._charAt(cursor);
if (yych <= 'a') {
if (yych <= '!') {
if (yych <= '\n') {
if (yych <= '\t') { gotoCase = 45; continue; };
{ gotoCase = 110; continue; };
} else {
if (yych == '\r') { gotoCase = 110; continue; };
{ gotoCase = 45; continue; };
}
} else {
if (yych <= '\'') {
if (yych <= '"') { gotoCase = 106; continue; };
if (yych <= '&') { gotoCase = 45; continue; };
{ gotoCase = 106; continue; };
} else {
if (yych == '\\') { gotoCase = 106; continue; };
{ gotoCase = 45; continue; };
}
}
} else {
if (yych <= 'q') {
if (yych <= 'f') {
if (yych <= 'b') { gotoCase = 106; continue; };
if (yych <= 'e') { gotoCase = 45; continue; };
{ gotoCase = 106; continue; };
} else {
if (yych == 'n') { gotoCase = 106; continue; };
{ gotoCase = 45; continue; };
}
} else {
if (yych <= 't') {
if (yych == 's') { gotoCase = 45; continue; };
{ gotoCase = 106; continue; };
} else {
if (yych <= 'u') { gotoCase = 109; continue; };
if (yych <= 'v') { gotoCase = 106; continue; };
{ gotoCase = 45; continue; };
}
}
}
case 109:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych <= '9') { gotoCase = 112; continue; };
{ gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 112; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych <= 'f') { gotoCase = 112; continue; };
{ gotoCase = 45; continue; };
}
case 110:
++cursor;
this.setLexCondition(this._lexConditions.DSTRING);
{ this.tokenType = "javascript-string"; return cursor; }
case 112:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych >= ':') { gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 113; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych >= 'g') { gotoCase = 45; continue; };
}
case 113:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych >= ':') { gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 114; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych >= 'g') { gotoCase = 45; continue; };
}
case 114:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 45; continue; };
if (yych <= '9') { gotoCase = 106; continue; };
{ gotoCase = 45; continue; };
} else {
if (yych <= 'F') { gotoCase = 106; continue; };
if (yych <= '`') { gotoCase = 45; continue; };
if (yych <= 'f') { gotoCase = 106; continue; };
{ gotoCase = 45; continue; };
}
case 115:
++cursor;
if ((yych = this._charAt(cursor)) == '=') { gotoCase = 43; continue; };
{ gotoCase = 18; continue; };

case this.case_DSTRING:
yych = this._charAt(cursor);
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 120; continue; };
if (yych <= '\f') { gotoCase = 119; continue; };
{ gotoCase = 120; continue; };
} else {
if (yych <= '"') {
if (yych <= '!') { gotoCase = 119; continue; };
{ gotoCase = 122; continue; };
} else {
if (yych == '\\') { gotoCase = 124; continue; };
{ gotoCase = 119; continue; };
}
}
case 118:
{ this.tokenType = "javascript-string"; return cursor; }
case 119:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
{ gotoCase = 126; continue; };
case 120:
++cursor;
case 121:
{ this.tokenType = null; return cursor; }
case 122:
++cursor;
case 123:
this.setLexCondition(this._lexConditions.NODIV);
{ this.tokenType = "javascript-string"; return cursor; }
case 124:
yyaccept = 1;
yych = this._charAt(YYMARKER = ++cursor);
if (yych <= 'e') {
if (yych <= '\'') {
if (yych == '"') { gotoCase = 125; continue; };
if (yych <= '&') { gotoCase = 121; continue; };
} else {
if (yych <= '\\') {
if (yych <= '[') { gotoCase = 121; continue; };
} else {
if (yych != 'b') { gotoCase = 121; continue; };
}
}
} else {
if (yych <= 'r') {
if (yych <= 'm') {
if (yych >= 'g') { gotoCase = 121; continue; };
} else {
if (yych <= 'n') { gotoCase = 125; continue; };
if (yych <= 'q') { gotoCase = 121; continue; };
}
} else {
if (yych <= 't') {
if (yych <= 's') { gotoCase = 121; continue; };
} else {
if (yych <= 'u') { gotoCase = 127; continue; };
if (yych >= 'w') { gotoCase = 121; continue; };
}
}
}
case 125:
yyaccept = 0;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
case 126:
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 118; continue; };
if (yych <= '\f') { gotoCase = 125; continue; };
{ gotoCase = 118; continue; };
} else {
if (yych <= '"') {
if (yych <= '!') { gotoCase = 125; continue; };
{ gotoCase = 133; continue; };
} else {
if (yych == '\\') { gotoCase = 132; continue; };
{ gotoCase = 125; continue; };
}
}
case 127:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 128; continue; };
if (yych <= '9') { gotoCase = 129; continue; };
} else {
if (yych <= 'F') { gotoCase = 129; continue; };
if (yych <= '`') { gotoCase = 128; continue; };
if (yych <= 'f') { gotoCase = 129; continue; };
}
case 128:
cursor = YYMARKER;
if (yyaccept <= 0) {
{ gotoCase = 118; continue; };
} else {
{ gotoCase = 121; continue; };
}
case 129:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 128; continue; };
if (yych >= ':') { gotoCase = 128; continue; };
} else {
if (yych <= 'F') { gotoCase = 130; continue; };
if (yych <= '`') { gotoCase = 128; continue; };
if (yych >= 'g') { gotoCase = 128; continue; };
}
case 130:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 128; continue; };
if (yych >= ':') { gotoCase = 128; continue; };
} else {
if (yych <= 'F') { gotoCase = 131; continue; };
if (yych <= '`') { gotoCase = 128; continue; };
if (yych >= 'g') { gotoCase = 128; continue; };
}
case 131:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 128; continue; };
if (yych <= '9') { gotoCase = 125; continue; };
{ gotoCase = 128; continue; };
} else {
if (yych <= 'F') { gotoCase = 125; continue; };
if (yych <= '`') { gotoCase = 128; continue; };
if (yych <= 'f') { gotoCase = 125; continue; };
{ gotoCase = 128; continue; };
}
case 132:
++cursor;
yych = this._charAt(cursor);
if (yych <= 'e') {
if (yych <= '\'') {
if (yych == '"') { gotoCase = 125; continue; };
if (yych <= '&') { gotoCase = 128; continue; };
{ gotoCase = 125; continue; };
} else {
if (yych <= '\\') {
if (yych <= '[') { gotoCase = 128; continue; };
{ gotoCase = 125; continue; };
} else {
if (yych == 'b') { gotoCase = 125; continue; };
{ gotoCase = 128; continue; };
}
}
} else {
if (yych <= 'r') {
if (yych <= 'm') {
if (yych <= 'f') { gotoCase = 125; continue; };
{ gotoCase = 128; continue; };
} else {
if (yych <= 'n') { gotoCase = 125; continue; };
if (yych <= 'q') { gotoCase = 128; continue; };
{ gotoCase = 125; continue; };
}
} else {
if (yych <= 't') {
if (yych <= 's') { gotoCase = 128; continue; };
{ gotoCase = 125; continue; };
} else {
if (yych <= 'u') { gotoCase = 127; continue; };
if (yych <= 'v') { gotoCase = 125; continue; };
{ gotoCase = 128; continue; };
}
}
}
case 133:
++cursor;
yych = this._charAt(cursor);
{ gotoCase = 123; continue; };

case this.case_NODIV:
yych = this._charAt(cursor);
if (yych <= '9') {
if (yych <= '(') {
if (yych <= '#') {
if (yych <= ' ') { gotoCase = 136; continue; };
if (yych <= '!') { gotoCase = 138; continue; };
if (yych <= '"') { gotoCase = 140; continue; };
} else {
if (yych <= '%') {
if (yych <= '$') { gotoCase = 141; continue; };
{ gotoCase = 143; continue; };
} else {
if (yych <= '&') { gotoCase = 144; continue; };
if (yych <= '\'') { gotoCase = 145; continue; };
{ gotoCase = 146; continue; };
}
}
} else {
if (yych <= ',') {
if (yych <= ')') { gotoCase = 147; continue; };
if (yych <= '*') { gotoCase = 149; continue; };
if (yych <= '+') { gotoCase = 150; continue; };
{ gotoCase = 146; continue; };
} else {
if (yych <= '.') {
if (yych <= '-') { gotoCase = 151; continue; };
{ gotoCase = 152; continue; };
} else {
if (yych <= '/') { gotoCase = 153; continue; };
if (yych <= '0') { gotoCase = 154; continue; };
{ gotoCase = 156; continue; };
}
}
}
} else {
if (yych <= '\\') {
if (yych <= '>') {
if (yych <= ';') { gotoCase = 146; continue; };
if (yych <= '<') { gotoCase = 157; continue; };
if (yych <= '=') { gotoCase = 158; continue; };
{ gotoCase = 159; continue; };
} else {
if (yych <= '@') {
if (yych <= '?') { gotoCase = 146; continue; };
} else {
if (yych <= 'Z') { gotoCase = 141; continue; };
if (yych <= '[') { gotoCase = 146; continue; };
{ gotoCase = 160; continue; };
}
}
} else {
if (yych <= 'z') {
if (yych <= '^') {
if (yych <= ']') { gotoCase = 146; continue; };
{ gotoCase = 161; continue; };
} else {
if (yych != '`') { gotoCase = 141; continue; };
}
} else {
if (yych <= '|') {
if (yych <= '{') { gotoCase = 146; continue; };
{ gotoCase = 162; continue; };
} else {
if (yych <= '~') { gotoCase = 146; continue; };
if (yych >= 0x80) { gotoCase = 141; continue; };
}
}
}
}
case 136:
++cursor;
case 137:
{ this.tokenType = null; return cursor; }
case 138:
++cursor;
if ((yych = this._charAt(cursor)) == '=') { gotoCase = 260; continue; };
case 139:
{ this.tokenType = null; return cursor; }
case 140:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych == '\n') { gotoCase = 137; continue; };
if (yych == '\r') { gotoCase = 137; continue; };
{ gotoCase = 252; continue; };
case 141:
yyaccept = 1;
yych = this._charAt(YYMARKER = ++cursor);
{ gotoCase = 170; continue; };
case 142:
this.setLexCondition(this._lexConditions.DIV);
{
var token = this._line.substring(cursorOnEnter, cursor);
if (this._keywords[token] === true && token !== "__proto__")
this.tokenType = "javascript-keyword";
else
this.tokenType = "javascript-ident";
return cursor;
}
case 143:
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 163; continue; };
{ gotoCase = 139; continue; };
case 144:
yych = this._charAt(++cursor);
if (yych == '&') { gotoCase = 163; continue; };
if (yych == '=') { gotoCase = 163; continue; };
{ gotoCase = 139; continue; };
case 145:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych == '\n') { gotoCase = 137; continue; };
if (yych == '\r') { gotoCase = 137; continue; };
{ gotoCase = 241; continue; };
case 146:
yych = this._charAt(++cursor);
{ gotoCase = 139; continue; };
case 147:
++cursor;
this.setLexCondition(this._lexConditions.DIV);
{ this.tokenType = null; return cursor; }
case 149:
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 163; continue; };
{ gotoCase = 139; continue; };
case 150:
yych = this._charAt(++cursor);
if (yych == '+') { gotoCase = 163; continue; };
if (yych == '=') { gotoCase = 163; continue; };
{ gotoCase = 139; continue; };
case 151:
yych = this._charAt(++cursor);
if (yych == '-') { gotoCase = 163; continue; };
if (yych == '=') { gotoCase = 163; continue; };
{ gotoCase = 139; continue; };
case 152:
yych = this._charAt(++cursor);
if (yych <= '/') { gotoCase = 139; continue; };
if (yych <= '9') { gotoCase = 234; continue; };
{ gotoCase = 139; continue; };
case 153:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych <= '*') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 137; continue; };
{ gotoCase = 197; continue; };
} else {
if (yych <= '\r') { gotoCase = 137; continue; };
if (yych <= ')') { gotoCase = 197; continue; };
{ gotoCase = 202; continue; };
}
} else {
if (yych <= 'Z') {
if (yych == '/') { gotoCase = 204; continue; };
{ gotoCase = 197; continue; };
} else {
if (yych <= '[') { gotoCase = 200; continue; };
if (yych <= '\\') { gotoCase = 199; continue; };
if (yych <= ']') { gotoCase = 137; continue; };
{ gotoCase = 197; continue; };
}
}
case 154:
yyaccept = 2;
yych = this._charAt(YYMARKER = ++cursor);
if (yych <= 'E') {
if (yych <= '/') {
if (yych == '.') { gotoCase = 183; continue; };
} else {
if (yych <= '7') { gotoCase = 192; continue; };
if (yych >= 'E') { gotoCase = 182; continue; };
}
} else {
if (yych <= 'd') {
if (yych == 'X') { gotoCase = 194; continue; };
} else {
if (yych <= 'e') { gotoCase = 182; continue; };
if (yych == 'x') { gotoCase = 194; continue; };
}
}
case 155:
this.setLexCondition(this._lexConditions.DIV);
{ this.tokenType = "javascript-number"; return cursor; }
case 156:
yyaccept = 2;
yych = this._charAt(YYMARKER = ++cursor);
if (yych <= '9') {
if (yych == '.') { gotoCase = 183; continue; };
if (yych <= '/') { gotoCase = 155; continue; };
{ gotoCase = 180; continue; };
} else {
if (yych <= 'E') {
if (yych <= 'D') { gotoCase = 155; continue; };
{ gotoCase = 182; continue; };
} else {
if (yych == 'e') { gotoCase = 182; continue; };
{ gotoCase = 155; continue; };
}
}
case 157:
yych = this._charAt(++cursor);
if (yych <= ';') { gotoCase = 139; continue; };
if (yych <= '<') { gotoCase = 179; continue; };
if (yych <= '=') { gotoCase = 163; continue; };
{ gotoCase = 139; continue; };
case 158:
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 178; continue; };
{ gotoCase = 139; continue; };
case 159:
yych = this._charAt(++cursor);
if (yych <= '<') { gotoCase = 139; continue; };
if (yych <= '=') { gotoCase = 163; continue; };
if (yych <= '>') { gotoCase = 176; continue; };
{ gotoCase = 139; continue; };
case 160:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych == 'u') { gotoCase = 164; continue; };
{ gotoCase = 137; continue; };
case 161:
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 163; continue; };
{ gotoCase = 139; continue; };
case 162:
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 163; continue; };
if (yych != '|') { gotoCase = 139; continue; };
case 163:
yych = this._charAt(++cursor);
{ gotoCase = 139; continue; };
case 164:
yych = this._charAt(++cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych <= '9') { gotoCase = 166; continue; };
} else {
if (yych <= 'F') { gotoCase = 166; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych <= 'f') { gotoCase = 166; continue; };
}
case 165:
cursor = YYMARKER;
if (yyaccept <= 1) {
if (yyaccept <= 0) {
{ gotoCase = 137; continue; };
} else {
{ gotoCase = 142; continue; };
}
} else {
if (yyaccept <= 2) {
{ gotoCase = 155; continue; };
} else {
{ gotoCase = 217; continue; };
}
}
case 166:
yych = this._charAt(++cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych >= ':') { gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 167; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych >= 'g') { gotoCase = 165; continue; };
}
case 167:
yych = this._charAt(++cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych >= ':') { gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 168; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych >= 'g') { gotoCase = 165; continue; };
}
case 168:
yych = this._charAt(++cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych >= ':') { gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 169; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych >= 'g') { gotoCase = 165; continue; };
}
case 169:
yyaccept = 1;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
case 170:
if (yych <= '[') {
if (yych <= '/') {
if (yych == '$') { gotoCase = 169; continue; };
{ gotoCase = 142; continue; };
} else {
if (yych <= '9') { gotoCase = 169; continue; };
if (yych <= '@') { gotoCase = 142; continue; };
if (yych <= 'Z') { gotoCase = 169; continue; };
{ gotoCase = 142; continue; };
}
} else {
if (yych <= '_') {
if (yych <= '\\') { gotoCase = 171; continue; };
if (yych <= '^') { gotoCase = 142; continue; };
{ gotoCase = 169; continue; };
} else {
if (yych <= '`') { gotoCase = 142; continue; };
if (yych <= 'z') { gotoCase = 169; continue; };
if (yych <= String.fromCharCode(0x7F)) { gotoCase = 142; continue; };
{ gotoCase = 169; continue; };
}
}
case 171:
++cursor;
yych = this._charAt(cursor);
if (yych != 'u') { gotoCase = 165; continue; };
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych >= ':') { gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 173; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych >= 'g') { gotoCase = 165; continue; };
}
case 173:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych >= ':') { gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 174; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych >= 'g') { gotoCase = 165; continue; };
}
case 174:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych >= ':') { gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 175; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych >= 'g') { gotoCase = 165; continue; };
}
case 175:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych <= '9') { gotoCase = 169; continue; };
{ gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 169; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych <= 'f') { gotoCase = 169; continue; };
{ gotoCase = 165; continue; };
}
case 176:
yych = this._charAt(++cursor);
if (yych <= '<') { gotoCase = 139; continue; };
if (yych <= '=') { gotoCase = 163; continue; };
if (yych >= '?') { gotoCase = 139; continue; };
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 163; continue; };
{ gotoCase = 139; continue; };
case 178:
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 163; continue; };
{ gotoCase = 139; continue; };
case 179:
yych = this._charAt(++cursor);
if (yych == '=') { gotoCase = 163; continue; };
{ gotoCase = 139; continue; };
case 180:
yyaccept = 2;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych <= '9') {
if (yych == '.') { gotoCase = 183; continue; };
if (yych <= '/') { gotoCase = 155; continue; };
{ gotoCase = 180; continue; };
} else {
if (yych <= 'E') {
if (yych <= 'D') { gotoCase = 155; continue; };
} else {
if (yych != 'e') { gotoCase = 155; continue; };
}
}
case 182:
yych = this._charAt(++cursor);
if (yych <= ',') {
if (yych == '+') { gotoCase = 189; continue; };
{ gotoCase = 165; continue; };
} else {
if (yych <= '-') { gotoCase = 189; continue; };
if (yych <= '/') { gotoCase = 165; continue; };
if (yych <= '9') { gotoCase = 190; continue; };
{ gotoCase = 165; continue; };
}
case 183:
yyaccept = 2;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych <= 'D') {
if (yych <= '/') { gotoCase = 155; continue; };
if (yych <= '9') { gotoCase = 183; continue; };
{ gotoCase = 155; continue; };
} else {
if (yych <= 'E') { gotoCase = 185; continue; };
if (yych != 'e') { gotoCase = 155; continue; };
}
case 185:
yych = this._charAt(++cursor);
if (yych <= ',') {
if (yych != '+') { gotoCase = 165; continue; };
} else {
if (yych <= '-') { gotoCase = 186; continue; };
if (yych <= '/') { gotoCase = 165; continue; };
if (yych <= '9') { gotoCase = 187; continue; };
{ gotoCase = 165; continue; };
}
case 186:
yych = this._charAt(++cursor);
if (yych <= '/') { gotoCase = 165; continue; };
if (yych >= ':') { gotoCase = 165; continue; };
case 187:
++cursor;
yych = this._charAt(cursor);
if (yych <= '/') { gotoCase = 155; continue; };
if (yych <= '9') { gotoCase = 187; continue; };
{ gotoCase = 155; continue; };
case 189:
yych = this._charAt(++cursor);
if (yych <= '/') { gotoCase = 165; continue; };
if (yych >= ':') { gotoCase = 165; continue; };
case 190:
++cursor;
yych = this._charAt(cursor);
if (yych <= '/') { gotoCase = 155; continue; };
if (yych <= '9') { gotoCase = 190; continue; };
{ gotoCase = 155; continue; };
case 192:
++cursor;
yych = this._charAt(cursor);
if (yych <= '/') { gotoCase = 155; continue; };
if (yych <= '7') { gotoCase = 192; continue; };
{ gotoCase = 155; continue; };
case 194:
yych = this._charAt(++cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych >= ':') { gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 195; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych >= 'g') { gotoCase = 165; continue; };
}
case 195:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 155; continue; };
if (yych <= '9') { gotoCase = 195; continue; };
{ gotoCase = 155; continue; };
} else {
if (yych <= 'F') { gotoCase = 195; continue; };
if (yych <= '`') { gotoCase = 155; continue; };
if (yych <= 'f') { gotoCase = 195; continue; };
{ gotoCase = 155; continue; };
}
case 197:
++cursor;
yych = this._charAt(cursor);
if (yych <= '.') {
if (yych <= '\n') {
if (yych <= '\t') { gotoCase = 197; continue; };
{ gotoCase = 165; continue; };
} else {
if (yych == '\r') { gotoCase = 165; continue; };
{ gotoCase = 197; continue; };
}
} else {
if (yych <= '[') {
if (yych <= '/') { gotoCase = 220; continue; };
if (yych <= 'Z') { gotoCase = 197; continue; };
{ gotoCase = 228; continue; };
} else {
if (yych <= '\\') { gotoCase = 227; continue; };
if (yych <= ']') { gotoCase = 165; continue; };
{ gotoCase = 197; continue; };
}
}
case 199:
yych = this._charAt(++cursor);
if (yych == '\n') { gotoCase = 165; continue; };
if (yych == '\r') { gotoCase = 165; continue; };
{ gotoCase = 197; continue; };
case 200:
++cursor;
yych = this._charAt(cursor);
if (yych <= '*') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 165; continue; };
{ gotoCase = 200; continue; };
} else {
if (yych <= '\r') { gotoCase = 165; continue; };
if (yych <= ')') { gotoCase = 200; continue; };
{ gotoCase = 165; continue; };
}
} else {
if (yych <= '[') {
if (yych == '/') { gotoCase = 165; continue; };
{ gotoCase = 200; continue; };
} else {
if (yych <= '\\') { gotoCase = 215; continue; };
if (yych <= ']') { gotoCase = 213; continue; };
{ gotoCase = 200; continue; };
}
}
case 202:
++cursor;
yych = this._charAt(cursor);
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 209; continue; };
{ gotoCase = 202; continue; };
} else {
if (yych <= '\r') { gotoCase = 209; continue; };
if (yych == '*') { gotoCase = 207; continue; };
{ gotoCase = 202; continue; };
}
case 204:
++cursor;
yych = this._charAt(cursor);
if (yych == '\n') { gotoCase = 206; continue; };
if (yych != '\r') { gotoCase = 204; continue; };
case 206:
{ this.tokenType = "javascript-comment"; return cursor; }
case 207:
++cursor;
yych = this._charAt(cursor);
if (yych == '*') { gotoCase = 207; continue; };
if (yych == '/') { gotoCase = 211; continue; };
{ gotoCase = 202; continue; };
case 209:
++cursor;
this.setLexCondition(this._lexConditions.COMMENT);
{ this.tokenType = "javascript-comment"; return cursor; }
case 211:
++cursor;
{ this.tokenType = "javascript-comment"; return cursor; }
case 213:
++cursor;
yych = this._charAt(cursor);
if (yych <= '*') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 165; continue; };
{ gotoCase = 213; continue; };
} else {
if (yych <= '\r') { gotoCase = 165; continue; };
if (yych <= ')') { gotoCase = 213; continue; };
{ gotoCase = 197; continue; };
}
} else {
if (yych <= 'Z') {
if (yych == '/') { gotoCase = 220; continue; };
{ gotoCase = 213; continue; };
} else {
if (yych <= '[') { gotoCase = 218; continue; };
if (yych <= '\\') { gotoCase = 216; continue; };
{ gotoCase = 213; continue; };
}
}
case 215:
++cursor;
yych = this._charAt(cursor);
if (yych == '\n') { gotoCase = 165; continue; };
if (yych == '\r') { gotoCase = 165; continue; };
{ gotoCase = 200; continue; };
case 216:
yyaccept = 3;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych == '\n') { gotoCase = 217; continue; };
if (yych != '\r') { gotoCase = 213; continue; };
case 217:
this.setLexCondition(this._lexConditions.REGEX);
{ this.tokenType = "javascript-regexp"; return cursor; }
case 218:
++cursor;
yych = this._charAt(cursor);
if (yych <= '*') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 165; continue; };
{ gotoCase = 218; continue; };
} else {
if (yych <= '\r') { gotoCase = 165; continue; };
if (yych <= ')') { gotoCase = 218; continue; };
{ gotoCase = 165; continue; };
}
} else {
if (yych <= '[') {
if (yych == '/') { gotoCase = 165; continue; };
{ gotoCase = 218; continue; };
} else {
if (yych <= '\\') { gotoCase = 225; continue; };
if (yych <= ']') { gotoCase = 223; continue; };
{ gotoCase = 218; continue; };
}
}
case 220:
++cursor;
yych = this._charAt(cursor);
if (yych <= 'h') {
if (yych == 'g') { gotoCase = 220; continue; };
} else {
if (yych <= 'i') { gotoCase = 220; continue; };
if (yych == 'm') { gotoCase = 220; continue; };
}
{ this.tokenType = "javascript-regexp"; return cursor; }
case 223:
++cursor;
yych = this._charAt(cursor);
if (yych <= '*') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 165; continue; };
{ gotoCase = 223; continue; };
} else {
if (yych <= '\r') { gotoCase = 165; continue; };
if (yych <= ')') { gotoCase = 223; continue; };
{ gotoCase = 197; continue; };
}
} else {
if (yych <= 'Z') {
if (yych == '/') { gotoCase = 220; continue; };
{ gotoCase = 223; continue; };
} else {
if (yych <= '[') { gotoCase = 218; continue; };
if (yych <= '\\') { gotoCase = 226; continue; };
{ gotoCase = 223; continue; };
}
}
case 225:
++cursor;
yych = this._charAt(cursor);
if (yych == '\n') { gotoCase = 165; continue; };
if (yych == '\r') { gotoCase = 165; continue; };
{ gotoCase = 218; continue; };
case 226:
yyaccept = 3;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych == '\n') { gotoCase = 217; continue; };
if (yych == '\r') { gotoCase = 217; continue; };
{ gotoCase = 223; continue; };
case 227:
yyaccept = 3;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych == '\n') { gotoCase = 217; continue; };
if (yych == '\r') { gotoCase = 217; continue; };
{ gotoCase = 197; continue; };
case 228:
++cursor;
yych = this._charAt(cursor);
if (yych <= '*') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 165; continue; };
{ gotoCase = 228; continue; };
} else {
if (yych <= '\r') { gotoCase = 165; continue; };
if (yych <= ')') { gotoCase = 228; continue; };
{ gotoCase = 165; continue; };
}
} else {
if (yych <= '[') {
if (yych == '/') { gotoCase = 165; continue; };
{ gotoCase = 228; continue; };
} else {
if (yych <= '\\') { gotoCase = 232; continue; };
if (yych >= '^') { gotoCase = 228; continue; };
}
}
case 230:
++cursor;
yych = this._charAt(cursor);
if (yych <= '*') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 165; continue; };
{ gotoCase = 230; continue; };
} else {
if (yych <= '\r') { gotoCase = 165; continue; };
if (yych <= ')') { gotoCase = 230; continue; };
{ gotoCase = 197; continue; };
}
} else {
if (yych <= 'Z') {
if (yych == '/') { gotoCase = 220; continue; };
{ gotoCase = 230; continue; };
} else {
if (yych <= '[') { gotoCase = 228; continue; };
if (yych <= '\\') { gotoCase = 233; continue; };
{ gotoCase = 230; continue; };
}
}
case 232:
++cursor;
yych = this._charAt(cursor);
if (yych == '\n') { gotoCase = 165; continue; };
if (yych == '\r') { gotoCase = 165; continue; };
{ gotoCase = 228; continue; };
case 233:
yyaccept = 3;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych == '\n') { gotoCase = 217; continue; };
if (yych == '\r') { gotoCase = 217; continue; };
{ gotoCase = 230; continue; };
case 234:
yyaccept = 2;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych <= 'D') {
if (yych <= '/') { gotoCase = 155; continue; };
if (yych <= '9') { gotoCase = 234; continue; };
{ gotoCase = 155; continue; };
} else {
if (yych <= 'E') { gotoCase = 236; continue; };
if (yych != 'e') { gotoCase = 155; continue; };
}
case 236:
yych = this._charAt(++cursor);
if (yych <= ',') {
if (yych != '+') { gotoCase = 165; continue; };
} else {
if (yych <= '-') { gotoCase = 237; continue; };
if (yych <= '/') { gotoCase = 165; continue; };
if (yych <= '9') { gotoCase = 238; continue; };
{ gotoCase = 165; continue; };
}
case 237:
yych = this._charAt(++cursor);
if (yych <= '/') { gotoCase = 165; continue; };
if (yych >= ':') { gotoCase = 165; continue; };
case 238:
++cursor;
yych = this._charAt(cursor);
if (yych <= '/') { gotoCase = 155; continue; };
if (yych <= '9') { gotoCase = 238; continue; };
{ gotoCase = 155; continue; };
case 240:
++cursor;
yych = this._charAt(cursor);
case 241:
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 165; continue; };
if (yych <= '\f') { gotoCase = 240; continue; };
{ gotoCase = 165; continue; };
} else {
if (yych <= '\'') {
if (yych <= '&') { gotoCase = 240; continue; };
{ gotoCase = 243; continue; };
} else {
if (yych != '\\') { gotoCase = 240; continue; };
}
}
++cursor;
yych = this._charAt(cursor);
if (yych <= 'a') {
if (yych <= '!') {
if (yych <= '\n') {
if (yych <= '\t') { gotoCase = 165; continue; };
{ gotoCase = 246; continue; };
} else {
if (yych == '\r') { gotoCase = 246; continue; };
{ gotoCase = 165; continue; };
}
} else {
if (yych <= '\'') {
if (yych <= '"') { gotoCase = 240; continue; };
if (yych <= '&') { gotoCase = 165; continue; };
{ gotoCase = 240; continue; };
} else {
if (yych == '\\') { gotoCase = 240; continue; };
{ gotoCase = 165; continue; };
}
}
} else {
if (yych <= 'q') {
if (yych <= 'f') {
if (yych <= 'b') { gotoCase = 240; continue; };
if (yych <= 'e') { gotoCase = 165; continue; };
{ gotoCase = 240; continue; };
} else {
if (yych == 'n') { gotoCase = 240; continue; };
{ gotoCase = 165; continue; };
}
} else {
if (yych <= 't') {
if (yych == 's') { gotoCase = 165; continue; };
{ gotoCase = 240; continue; };
} else {
if (yych <= 'u') { gotoCase = 245; continue; };
if (yych <= 'v') { gotoCase = 240; continue; };
{ gotoCase = 165; continue; };
}
}
}
case 243:
++cursor;
{ this.tokenType = "javascript-string"; return cursor; }
case 245:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych <= '9') { gotoCase = 248; continue; };
{ gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 248; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych <= 'f') { gotoCase = 248; continue; };
{ gotoCase = 165; continue; };
}
case 246:
++cursor;
this.setLexCondition(this._lexConditions.SSTRING);
{ this.tokenType = "javascript-string"; return cursor; }
case 248:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych >= ':') { gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 249; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych >= 'g') { gotoCase = 165; continue; };
}
case 249:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych >= ':') { gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 250; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych >= 'g') { gotoCase = 165; continue; };
}
case 250:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych <= '9') { gotoCase = 240; continue; };
{ gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 240; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych <= 'f') { gotoCase = 240; continue; };
{ gotoCase = 165; continue; };
}
case 251:
++cursor;
yych = this._charAt(cursor);
case 252:
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 165; continue; };
if (yych <= '\f') { gotoCase = 251; continue; };
{ gotoCase = 165; continue; };
} else {
if (yych <= '"') {
if (yych <= '!') { gotoCase = 251; continue; };
{ gotoCase = 243; continue; };
} else {
if (yych != '\\') { gotoCase = 251; continue; };
}
}
++cursor;
yych = this._charAt(cursor);
if (yych <= 'a') {
if (yych <= '!') {
if (yych <= '\n') {
if (yych <= '\t') { gotoCase = 165; continue; };
{ gotoCase = 255; continue; };
} else {
if (yych == '\r') { gotoCase = 255; continue; };
{ gotoCase = 165; continue; };
}
} else {
if (yych <= '\'') {
if (yych <= '"') { gotoCase = 251; continue; };
if (yych <= '&') { gotoCase = 165; continue; };
{ gotoCase = 251; continue; };
} else {
if (yych == '\\') { gotoCase = 251; continue; };
{ gotoCase = 165; continue; };
}
}
} else {
if (yych <= 'q') {
if (yych <= 'f') {
if (yych <= 'b') { gotoCase = 251; continue; };
if (yych <= 'e') { gotoCase = 165; continue; };
{ gotoCase = 251; continue; };
} else {
if (yych == 'n') { gotoCase = 251; continue; };
{ gotoCase = 165; continue; };
}
} else {
if (yych <= 't') {
if (yych == 's') { gotoCase = 165; continue; };
{ gotoCase = 251; continue; };
} else {
if (yych <= 'u') { gotoCase = 254; continue; };
if (yych <= 'v') { gotoCase = 251; continue; };
{ gotoCase = 165; continue; };
}
}
}
case 254:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych <= '9') { gotoCase = 257; continue; };
{ gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 257; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych <= 'f') { gotoCase = 257; continue; };
{ gotoCase = 165; continue; };
}
case 255:
++cursor;
this.setLexCondition(this._lexConditions.DSTRING);
{ this.tokenType = "javascript-string"; return cursor; }
case 257:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych >= ':') { gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 258; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych >= 'g') { gotoCase = 165; continue; };
}
case 258:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych >= ':') { gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 259; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych >= 'g') { gotoCase = 165; continue; };
}
case 259:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 165; continue; };
if (yych <= '9') { gotoCase = 251; continue; };
{ gotoCase = 165; continue; };
} else {
if (yych <= 'F') { gotoCase = 251; continue; };
if (yych <= '`') { gotoCase = 165; continue; };
if (yych <= 'f') { gotoCase = 251; continue; };
{ gotoCase = 165; continue; };
}
case 260:
++cursor;
if ((yych = this._charAt(cursor)) == '=') { gotoCase = 163; continue; };
{ gotoCase = 139; continue; };

case this.case_REGEX:
yych = this._charAt(cursor);
if (yych <= '.') {
if (yych <= '\n') {
if (yych <= '\t') { gotoCase = 264; continue; };
{ gotoCase = 265; continue; };
} else {
if (yych == '\r') { gotoCase = 265; continue; };
{ gotoCase = 264; continue; };
}
} else {
if (yych <= '[') {
if (yych <= '/') { gotoCase = 267; continue; };
if (yych <= 'Z') { gotoCase = 264; continue; };
{ gotoCase = 269; continue; };
} else {
if (yych <= '\\') { gotoCase = 270; continue; };
if (yych <= ']') { gotoCase = 265; continue; };
{ gotoCase = 264; continue; };
}
}
case 263:
{ this.tokenType = "javascript-regexp"; return cursor; }
case 264:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
{ gotoCase = 272; continue; };
case 265:
++cursor;
case 266:
{ this.tokenType = null; return cursor; }
case 267:
++cursor;
yych = this._charAt(cursor);
{ gotoCase = 278; continue; };
case 268:
this.setLexCondition(this._lexConditions.NODIV);
{ this.tokenType = "javascript-regexp"; return cursor; }
case 269:
yyaccept = 1;
yych = this._charAt(YYMARKER = ++cursor);
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 266; continue; };
if (yych <= '\f') { gotoCase = 276; continue; };
{ gotoCase = 266; continue; };
} else {
if (yych <= '*') {
if (yych <= ')') { gotoCase = 276; continue; };
{ gotoCase = 266; continue; };
} else {
if (yych == '/') { gotoCase = 266; continue; };
{ gotoCase = 276; continue; };
}
}
case 270:
yych = this._charAt(++cursor);
if (yych == '\n') { gotoCase = 266; continue; };
if (yych == '\r') { gotoCase = 266; continue; };
case 271:
yyaccept = 0;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
case 272:
if (yych <= '.') {
if (yych <= '\n') {
if (yych <= '\t') { gotoCase = 271; continue; };
{ gotoCase = 263; continue; };
} else {
if (yych == '\r') { gotoCase = 263; continue; };
{ gotoCase = 271; continue; };
}
} else {
if (yych <= '[') {
if (yych <= '/') { gotoCase = 277; continue; };
if (yych <= 'Z') { gotoCase = 271; continue; };
{ gotoCase = 275; continue; };
} else {
if (yych <= '\\') { gotoCase = 273; continue; };
if (yych <= ']') { gotoCase = 263; continue; };
{ gotoCase = 271; continue; };
}
}
case 273:
++cursor;
yych = this._charAt(cursor);
if (yych == '\n') { gotoCase = 274; continue; };
if (yych != '\r') { gotoCase = 271; continue; };
case 274:
cursor = YYMARKER;
if (yyaccept <= 0) {
{ gotoCase = 263; continue; };
} else {
{ gotoCase = 266; continue; };
}
case 275:
++cursor;
yych = this._charAt(cursor);
case 276:
if (yych <= '*') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 274; continue; };
{ gotoCase = 275; continue; };
} else {
if (yych <= '\r') { gotoCase = 274; continue; };
if (yych <= ')') { gotoCase = 275; continue; };
{ gotoCase = 274; continue; };
}
} else {
if (yych <= '[') {
if (yych == '/') { gotoCase = 274; continue; };
{ gotoCase = 275; continue; };
} else {
if (yych <= '\\') { gotoCase = 281; continue; };
if (yych <= ']') { gotoCase = 279; continue; };
{ gotoCase = 275; continue; };
}
}
case 277:
++cursor;
yych = this._charAt(cursor);
case 278:
if (yych <= 'h') {
if (yych == 'g') { gotoCase = 277; continue; };
{ gotoCase = 268; continue; };
} else {
if (yych <= 'i') { gotoCase = 277; continue; };
if (yych == 'm') { gotoCase = 277; continue; };
{ gotoCase = 268; continue; };
}
case 279:
yyaccept = 0;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych <= '*') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 263; continue; };
{ gotoCase = 279; continue; };
} else {
if (yych <= '\r') { gotoCase = 263; continue; };
if (yych <= ')') { gotoCase = 279; continue; };
{ gotoCase = 271; continue; };
}
} else {
if (yych <= 'Z') {
if (yych == '/') { gotoCase = 277; continue; };
{ gotoCase = 279; continue; };
} else {
if (yych <= '[') { gotoCase = 275; continue; };
if (yych <= '\\') { gotoCase = 282; continue; };
{ gotoCase = 279; continue; };
}
}
case 281:
++cursor;
yych = this._charAt(cursor);
if (yych == '\n') { gotoCase = 274; continue; };
if (yych == '\r') { gotoCase = 274; continue; };
{ gotoCase = 275; continue; };
case 282:
++cursor;
yych = this._charAt(cursor);
if (yych == '\n') { gotoCase = 274; continue; };
if (yych == '\r') { gotoCase = 274; continue; };
{ gotoCase = 279; continue; };

case this.case_SSTRING:
yych = this._charAt(cursor);
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 287; continue; };
if (yych <= '\f') { gotoCase = 286; continue; };
{ gotoCase = 287; continue; };
} else {
if (yych <= '\'') {
if (yych <= '&') { gotoCase = 286; continue; };
{ gotoCase = 289; continue; };
} else {
if (yych == '\\') { gotoCase = 291; continue; };
{ gotoCase = 286; continue; };
}
}
case 285:
{ this.tokenType = "javascript-string"; return cursor; }
case 286:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
{ gotoCase = 293; continue; };
case 287:
++cursor;
case 288:
{ this.tokenType = null; return cursor; }
case 289:
++cursor;
case 290:
this.setLexCondition(this._lexConditions.NODIV);
{ this.tokenType = "javascript-string"; return cursor; }
case 291:
yyaccept = 1;
yych = this._charAt(YYMARKER = ++cursor);
if (yych <= 'e') {
if (yych <= '\'') {
if (yych == '"') { gotoCase = 292; continue; };
if (yych <= '&') { gotoCase = 288; continue; };
} else {
if (yych <= '\\') {
if (yych <= '[') { gotoCase = 288; continue; };
} else {
if (yych != 'b') { gotoCase = 288; continue; };
}
}
} else {
if (yych <= 'r') {
if (yych <= 'm') {
if (yych >= 'g') { gotoCase = 288; continue; };
} else {
if (yych <= 'n') { gotoCase = 292; continue; };
if (yych <= 'q') { gotoCase = 288; continue; };
}
} else {
if (yych <= 't') {
if (yych <= 's') { gotoCase = 288; continue; };
} else {
if (yych <= 'u') { gotoCase = 294; continue; };
if (yych >= 'w') { gotoCase = 288; continue; };
}
}
}
case 292:
yyaccept = 0;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
case 293:
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 285; continue; };
if (yych <= '\f') { gotoCase = 292; continue; };
{ gotoCase = 285; continue; };
} else {
if (yych <= '\'') {
if (yych <= '&') { gotoCase = 292; continue; };
{ gotoCase = 300; continue; };
} else {
if (yych == '\\') { gotoCase = 299; continue; };
{ gotoCase = 292; continue; };
}
}
case 294:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 295; continue; };
if (yych <= '9') { gotoCase = 296; continue; };
} else {
if (yych <= 'F') { gotoCase = 296; continue; };
if (yych <= '`') { gotoCase = 295; continue; };
if (yych <= 'f') { gotoCase = 296; continue; };
}
case 295:
cursor = YYMARKER;
if (yyaccept <= 0) {
{ gotoCase = 285; continue; };
} else {
{ gotoCase = 288; continue; };
}
case 296:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 295; continue; };
if (yych >= ':') { gotoCase = 295; continue; };
} else {
if (yych <= 'F') { gotoCase = 297; continue; };
if (yych <= '`') { gotoCase = 295; continue; };
if (yych >= 'g') { gotoCase = 295; continue; };
}
case 297:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 295; continue; };
if (yych >= ':') { gotoCase = 295; continue; };
} else {
if (yych <= 'F') { gotoCase = 298; continue; };
if (yych <= '`') { gotoCase = 295; continue; };
if (yych >= 'g') { gotoCase = 295; continue; };
}
case 298:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 295; continue; };
if (yych <= '9') { gotoCase = 292; continue; };
{ gotoCase = 295; continue; };
} else {
if (yych <= 'F') { gotoCase = 292; continue; };
if (yych <= '`') { gotoCase = 295; continue; };
if (yych <= 'f') { gotoCase = 292; continue; };
{ gotoCase = 295; continue; };
}
case 299:
++cursor;
yych = this._charAt(cursor);
if (yych <= 'e') {
if (yych <= '\'') {
if (yych == '"') { gotoCase = 292; continue; };
if (yych <= '&') { gotoCase = 295; continue; };
{ gotoCase = 292; continue; };
} else {
if (yych <= '\\') {
if (yych <= '[') { gotoCase = 295; continue; };
{ gotoCase = 292; continue; };
} else {
if (yych == 'b') { gotoCase = 292; continue; };
{ gotoCase = 295; continue; };
}
}
} else {
if (yych <= 'r') {
if (yych <= 'm') {
if (yych <= 'f') { gotoCase = 292; continue; };
{ gotoCase = 295; continue; };
} else {
if (yych <= 'n') { gotoCase = 292; continue; };
if (yych <= 'q') { gotoCase = 295; continue; };
{ gotoCase = 292; continue; };
}
} else {
if (yych <= 't') {
if (yych <= 's') { gotoCase = 295; continue; };
{ gotoCase = 292; continue; };
} else {
if (yych <= 'u') { gotoCase = 294; continue; };
if (yych <= 'v') { gotoCase = 292; continue; };
{ gotoCase = 295; continue; };
}
}
}
case 300:
++cursor;
yych = this._charAt(cursor);
{ gotoCase = 290; continue; };
}

}
}
}

WebInspector.SourceJavaScriptTokenizer.prototype.__proto__ = WebInspector.SourceTokenizer.prototype;





WebInspector.FontView = function(resource)
{
WebInspector.ResourceView.call(this, resource);

this.element.addStyleClass("font");
}

WebInspector.FontView._fontInnerHTML = "ABCDEFGHIJKLM<br>NOPQRSTUVWXYZ<br>abcdefghijklm<br>nopqrstuvwxyz<br>1234567890";

WebInspector.FontView._fontId = 0;

WebInspector.FontView._measureFontSize = 50;

WebInspector.FontView.prototype = {
hasContent: function()
{
return true;
},

_createContentIfNeeded: function()
{
if (this.fontPreviewElement)
return;

var uniqueFontName = "WebInspectorFontPreview" + (++WebInspector.FontView._fontId);

this.fontStyleElement = document.createElement("style");
this.fontStyleElement.textContent = "@font-face { font-family: \"" + uniqueFontName + "\"; src: url(" + this.resource.url + "); }";
document.head.appendChild(this.fontStyleElement);

this.fontPreviewElement = document.createElement("div");
this.fontPreviewElement.innerHTML = WebInspector.FontView._fontInnerHTML;
this.fontPreviewElement.style.setProperty("font-family", uniqueFontName, null);
this.fontPreviewElement.style.setProperty("visibility", "hidden", null);

this._dummyElement = document.createElement("div");
this._dummyElement.style.visibility = "hidden";
this._dummyElement.style.zIndex = "-1";
this._dummyElement.style.display = "inline";
this._dummyElement.style.position = "absolute";
this._dummyElement.style.setProperty("font-family", uniqueFontName, null);
this._dummyElement.style.setProperty("font-size", WebInspector.FontView._measureFontSize + "px", null);
this._dummyElement.innerHTML = WebInspector.FontView._fontInnerHTML;

this.element.appendChild(this.fontPreviewElement);
},

show: function(parentElement)
{
WebInspector.ResourceView.prototype.show.call(this, parentElement);
this._createContentIfNeeded();

this.updateFontPreviewSize();
},

resize: function()
{
if (this._inResize)
return;

this._inResize = true;
try {
this.updateFontPreviewSize();
} finally {
delete this._inResize;
}
},

_measureElement: function()
{
this.element.appendChild(this._dummyElement);
var result = { width: this._dummyElement.offsetWidth, height: this._dummyElement.offsetHeight };
this.element.removeChild(this._dummyElement);

return result;
},

updateFontPreviewSize: function()
{
if (!this.fontPreviewElement || !this.visible)
return;

this.fontPreviewElement.style.removeProperty("visibility");
var dimension = this._measureElement();

const height = dimension.height;
const width = dimension.width;


const containerWidth = this.element.offsetWidth - 50;
const containerHeight = this.element.offsetHeight - 30;

if (!height || !width || !containerWidth || !containerHeight) {
this.fontPreviewElement.style.removeProperty("font-size");
return;
}

var widthRatio = containerWidth / width;
var heightRatio = containerHeight / height;
var finalFontSize = Math.floor(WebInspector.FontView._measureFontSize * Math.min(widthRatio, heightRatio)) - 2;

this.fontPreviewElement.style.setProperty("font-size", finalFontSize + "px", null);
}
}

WebInspector.FontView.prototype.__proto__ = WebInspector.ResourceView.prototype;





WebInspector.ImageView = function(resource)
{
WebInspector.ResourceView.call(this, resource);

this.element.addStyleClass("image");
}

WebInspector.ImageView.prototype = {
hasContent: function()
{
return true;
},

show: function(parentElement)
{
WebInspector.ResourceView.prototype.show.call(this, parentElement);
this._createContentIfNeeded();
},

_createContentIfNeeded: function()
{
if (this._container)
return;

var imageContainer = document.createElement("div");
imageContainer.className = "image";
this.element.appendChild(imageContainer);

var imagePreviewElement = document.createElement("img");
imagePreviewElement.addStyleClass("resource-image-view");
imageContainer.appendChild(imagePreviewElement);

this._container = document.createElement("div");
this._container.className = "info";
this.element.appendChild(this._container);

var imageNameElement = document.createElement("h1");
imageNameElement.className = "title";
imageNameElement.textContent = this.resource.displayName;
this._container.appendChild(imageNameElement);

var infoListElement = document.createElement("dl");
infoListElement.className = "infoList";

this.resource.populateImageSource(imagePreviewElement);

function onImageLoad()
{
var content = this.resource.content;
if (content)
var resourceSize = this._base64ToSize(content);
else
var resourceSize = this.resource.resourceSize;

var imageProperties = [
{ name: WebInspector.UIString("Dimensions"), value: WebInspector.UIString("%d × %d", imagePreviewElement.naturalWidth, imagePreviewElement.naturalHeight) },
{ name: WebInspector.UIString("File size"), value: Number.bytesToString(resourceSize) },
{ name: WebInspector.UIString("MIME type"), value: this.resource.mimeType }
];

infoListElement.removeChildren();
for (var i = 0; i < imageProperties.length; ++i) {
var dt = document.createElement("dt");
dt.textContent = imageProperties[i].name;
infoListElement.appendChild(dt);
var dd = document.createElement("dd");
dd.textContent = imageProperties[i].value;
infoListElement.appendChild(dd);
}
var dt = document.createElement("dt");
dt.textContent = WebInspector.UIString("URL");
infoListElement.appendChild(dt);
var dd = document.createElement("dd");
var externalResource = true;
dd.appendChild(WebInspector.linkifyURLAsNode(this.resource.url, null, null, externalResource));
infoListElement.appendChild(dd);

this._container.appendChild(infoListElement);
}
imagePreviewElement.addEventListener("load", onImageLoad.bind(this), false);
},

_base64ToSize: function(content)
{
if (!content.length)
return 0;
var size = (content.length || 0) * 3 / 4;
if (content.length > 0 && content[content.length - 1] === "=")
size--;
if (content.length > 1 && content[content.length - 2] === "=")
size--;
return size;
}
}

WebInspector.ImageView.prototype.__proto__ = WebInspector.ResourceView.prototype;





WebInspector.DatabaseTableView = function(database, tableName)
{
WebInspector.View.call(this);

this.database = database;
this.tableName = tableName;

this.element.addStyleClass("storage-view");
this.element.addStyleClass("table");

this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
this.refreshButton.addEventListener("click", this._refreshButtonClicked.bind(this), false);
}

WebInspector.DatabaseTableView.prototype = {
show: function(parentElement)
{
WebInspector.View.prototype.show.call(this, parentElement);
this.update();
},

get statusBarItems()
{
return [this.refreshButton.element];
},

update: function()
{
this.database.executeSql("SELECT * FROM " + this.tableName, this._queryFinished.bind(this), this._queryError.bind(this));
},

_queryFinished: function(columnNames, values)
{
this.element.removeChildren();

var dataGrid = WebInspector.panels.resources.dataGridForResult(columnNames, values);
if (!dataGrid) {
var emptyMsgElement = document.createElement("div");
emptyMsgElement.className = "storage-empty-view";
emptyMsgElement.textContent = WebInspector.UIString("The “%s”\ntable is empty.", this.tableName);
this.element.appendChild(emptyMsgElement);
return;
}

this.element.appendChild(dataGrid.element);
dataGrid.autoSizeColumns(5);
},

_queryError: function(error)
{
this.element.removeChildren();

var errorMsgElement = document.createElement("div");
errorMsgElement.className = "storage-table-error";
errorMsgElement.textContent = WebInspector.UIString("An error occurred trying to\nread the “%s” table.", this.tableName);
this.element.appendChild(errorMsgElement);
},

_refreshButtonClicked: function(event)
{
this.update();
}
}

WebInspector.DatabaseTableView.prototype.__proto__ = WebInspector.View.prototype;





WebInspector.DatabaseQueryView = function(database)
{
WebInspector.View.call(this);

this.database = database;

this.element.addStyleClass("storage-view");
this.element.addStyleClass("query");
this.element.addStyleClass("monospace");
this.element.tabIndex = 0;

this.element.addEventListener("selectstart", this._selectStart.bind(this), false);

this.promptElement = document.createElement("div");
this.promptElement.className = "database-query-prompt";
this.promptElement.appendChild(document.createElement("br"));
this.promptElement.addEventListener("keydown", this._promptKeyDown.bind(this), true);
this.element.appendChild(this.promptElement);

this.prompt = new WebInspector.TextPrompt(this.promptElement, this.completions.bind(this), " ");
}

WebInspector.DatabaseQueryView.prototype = {
show: function(parentElement)
{
WebInspector.View.prototype.show.call(this, parentElement);

function moveBackIfOutside()
{
if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
this.prompt.moveCaretToEndOfPrompt();
}

setTimeout(moveBackIfOutside.bind(this), 0);
},

completions: function(wordRange, bestMatchOnly, completionsReadyCallback)
{
var prefix = wordRange.toString().toLowerCase();
if (!prefix.length)
return;

var results = [];

function accumulateMatches(textArray)
{
if (bestMatchOnly && results.length)
return;
for (var i = 0; i < textArray.length; ++i) {
var text = textArray[i].toLowerCase();
if (text.length < prefix.length)
continue;
if (text.indexOf(prefix) !== 0)
continue;
results.push(textArray[i]);
if (bestMatchOnly)
return;
}
}

function tableNamesCallback(tableNames)
{
accumulateMatches(tableNames.map(function(name) { return name + " " }));
accumulateMatches(["SELECT ", "FROM ", "WHERE ", "LIMIT ", "DELETE FROM ", "CREATE ", "DROP ", "TABLE ", "INDEX ", "UPDATE ", "INSERT INTO ", "VALUES ("]);

completionsReadyCallback(results);
}
this.database.getTableNames(tableNamesCallback);
},

_promptKeyDown: function(event)
{
if (isEnterKey(event)) {
this._enterKeyPressed(event);
return;
}
},

_selectStart: function(event)
{
if (this._selectionTimeout)
clearTimeout(this._selectionTimeout);

this.prompt.clearAutoComplete();

function moveBackIfOutside()
{
delete this._selectionTimeout;
if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
this.prompt.moveCaretToEndOfPrompt();
this.prompt.autoCompleteSoon();
}

this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
},

_enterKeyPressed: function(event)
{
event.preventDefault();
event.stopPropagation();

this.prompt.clearAutoComplete(true);

var query = this.prompt.text;
if (!query.length)
return;

this.prompt.history.push(query);
this.prompt.historyOffset = 0;
this.prompt.text = "";

this.database.executeSql(query, this._queryFinished.bind(this, query), this._queryError.bind(this, query));
},

_queryFinished: function(query, columnNames, values)
{
var dataGrid = WebInspector.panels.resources.dataGridForResult(columnNames, values);
var trimmedQuery = query.trim();

if (dataGrid) {
dataGrid.element.addStyleClass("inline");
this._appendQueryResult(trimmedQuery, dataGrid.element);
dataGrid.autoSizeColumns(5);            
}

if (trimmedQuery.match(/^create /i) || trimmedQuery.match(/^drop table /i))
WebInspector.panels.resources.updateDatabaseTables(this.database);
},

_queryError: function(query, error)
{
if (error.message)
var message = error.message;
else if (error.code == 2)
var message = WebInspector.UIString("Database no longer has expected version.");
else
var message = WebInspector.UIString("An unexpected error %s occurred.", error.code);

this._appendQueryResult(query, message, "error");
},

_appendQueryResult: function(query, result, resultClassName)
{
var element = document.createElement("div");
element.className = "database-user-query";

var commandTextElement = document.createElement("span");
commandTextElement.className = "database-query-text";
commandTextElement.textContent = query;
element.appendChild(commandTextElement);

var resultElement = document.createElement("div");
resultElement.className = "database-query-result";

if (resultClassName)
resultElement.addStyleClass(resultClassName);

if (typeof result === "string" || result instanceof String)
resultElement.textContent = result;
else if (result && result.nodeName)
resultElement.appendChild(result);

if (resultElement.childNodes.length)
element.appendChild(resultElement);

this.element.insertBefore(element, this.promptElement);
this.promptElement.scrollIntoView(false);
}
}

WebInspector.DatabaseQueryView.prototype.__proto__ = WebInspector.View.prototype;





WebInspector.ProfileDataGridNode = function(profileView, profileNode, owningTree, hasChildren)
{
this.profileView = profileView;
this.profileNode = profileNode;

WebInspector.DataGridNode.call(this, null, hasChildren);

this.addEventListener("populate", this._populate, this);

this.tree = owningTree;

this.childrenByCallUID = {};
this.lastComparator = null;

this.callUID = profileNode.callUID;
this.selfTime = profileNode.selfTime;
this.totalTime = profileNode.totalTime;
this.functionName = profileNode.functionName;
this.numberOfCalls = profileNode.numberOfCalls;
this.url = profileNode.url;
}

WebInspector.ProfileDataGridNode.prototype = {
get data()
{
function formatMilliseconds(time)
{
return Number.secondsToString(time / 1000, !Preferences.samplingCPUProfiler);
}

var data = {};

data["function"] = this.functionName;
data["calls"] = this.numberOfCalls;

if (this.profileView.showSelfTimeAsPercent)
data["self"] = WebInspector.UIString("%.2f%%", this.selfPercent);
else
data["self"] = formatMilliseconds(this.selfTime);

if (this.profileView.showTotalTimeAsPercent)
data["total"] = WebInspector.UIString("%.2f%%", this.totalPercent);
else
data["total"] = formatMilliseconds(this.totalTime);

if (this.profileView.showAverageTimeAsPercent)
data["average"] = WebInspector.UIString("%.2f%%", this.averagePercent);
else
data["average"] = formatMilliseconds(this.averageTime);

return data;
},

createCell: function(columnIdentifier)
{
var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);

if (columnIdentifier === "self" && this._searchMatchedSelfColumn)
cell.addStyleClass("highlight");
else if (columnIdentifier === "total" && this._searchMatchedTotalColumn)
cell.addStyleClass("highlight");
else if (columnIdentifier === "average" && this._searchMatchedAverageColumn)
cell.addStyleClass("highlight");
else if (columnIdentifier === "calls" && this._searchMatchedCallsColumn)
cell.addStyleClass("highlight");

if (columnIdentifier !== "function")
return cell;

if (this.profileNode._searchMatchedFunctionColumn)
cell.addStyleClass("highlight");

if (this.profileNode.url) {
var lineNumber;
if (this.profileNode.lineNumber > 0)
lineNumber = this.profileNode.lineNumber;
var urlElement = WebInspector.linkifyResourceAsNode(this.profileNode.url, "scripts", lineNumber, "profile-node-file");
cell.insertBefore(urlElement, cell.firstChild);
}

return cell;
},

select: function(supressSelectedEvent)
{
WebInspector.DataGridNode.prototype.select.call(this, supressSelectedEvent);
this.profileView._dataGridNodeSelected(this);
},

deselect: function(supressDeselectedEvent)
{
WebInspector.DataGridNode.prototype.deselect.call(this, supressDeselectedEvent);
this.profileView._dataGridNodeDeselected(this);
},

sort: function(  comparator,   force)
{
var gridNodeGroups = [[this]];

for (var gridNodeGroupIndex = 0; gridNodeGroupIndex < gridNodeGroups.length; ++gridNodeGroupIndex) {
var gridNodes = gridNodeGroups[gridNodeGroupIndex];
var count = gridNodes.length;

for (var index = 0; index < count; ++index) {
var gridNode = gridNodes[index];



if (!force && (!gridNode.expanded || gridNode.lastComparator === comparator)) {
if (gridNode.children.length)
gridNode.shouldRefreshChildren = true;
continue;
}

gridNode.lastComparator = comparator;

var children = gridNode.children;
var childCount = children.length;

if (childCount) {
children.sort(comparator);

for (var childIndex = 0; childIndex < childCount; ++childIndex)
children[childIndex]._recalculateSiblings(childIndex);

gridNodeGroups.push(children);
}
}
}
},

insertChild: function(  profileDataGridNode, index)
{
WebInspector.DataGridNode.prototype.insertChild.call(this, profileDataGridNode, index);

this.childrenByCallUID[profileDataGridNode.callUID] = profileDataGridNode;
},

removeChild: function(  profileDataGridNode)
{
WebInspector.DataGridNode.prototype.removeChild.call(this, profileDataGridNode);

delete this.childrenByCallUID[profileDataGridNode.callUID];
},

removeChildren: function(  profileDataGridNode)
{
WebInspector.DataGridNode.prototype.removeChildren.call(this);

this.childrenByCallUID = {};
},

findChild: function(  node)
{
if (!node)
return null;
return this.childrenByCallUID[node.callUID];
},

get averageTime()
{
return this.selfTime / Math.max(1, this.numberOfCalls);
},

get averagePercent()
{
return this.averageTime / this.tree.totalTime * 100.0;
},

get selfPercent()
{
return this.selfTime / this.tree.totalTime * 100.0;
},

get totalPercent()
{
return this.totalTime / this.tree.totalTime * 100.0;
},

get _parent()
{
return this.parent !== this.dataGrid ? this.parent : this.tree;
},

_populate: function(event)
{
this._sharedPopulate();

if (this._parent) {
var currentComparator = this._parent.lastComparator;

if (currentComparator)
this.sort(currentComparator, true);
}

if (this.removeEventListener)
this.removeEventListener("populate", this._populate, this);
},



_save: function()
{
if (this._savedChildren)
return;

this._savedSelfTime = this.selfTime;
this._savedTotalTime = this.totalTime;
this._savedNumberOfCalls = this.numberOfCalls;

this._savedChildren = this.children.slice();
},



_restore: function()
{
if (!this._savedChildren)
return;

this.selfTime = this._savedSelfTime;
this.totalTime = this._savedTotalTime;
this.numberOfCalls = this._savedNumberOfCalls;

this.removeChildren();

var children = this._savedChildren;
var count = children.length;

for (var index = 0; index < count; ++index) {
children[index]._restore();
this.appendChild(children[index]);
}
},

_merge: function(child, shouldAbsorb)
{
this.selfTime += child.selfTime;

if (!shouldAbsorb) {
this.totalTime += child.totalTime;
this.numberOfCalls += child.numberOfCalls;
}

var children = this.children.slice();

this.removeChildren();

var count = children.length;

for (var index = 0; index < count; ++index) {
if (!shouldAbsorb || children[index] !== child)
this.appendChild(children[index]);
}

children = child.children.slice();
count = children.length;

for (var index = 0; index < count; ++index) {
var orphanedChild = children[index],
existingChild = this.childrenByCallUID[orphanedChild.callUID];

if (existingChild)
existingChild._merge(orphanedChild, false);
else
this.appendChild(orphanedChild);
}
}
}

WebInspector.ProfileDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;

WebInspector.ProfileDataGridTree = function(profileView, profileNode)
{
this.tree = this;
this.children = [];

this.profileView = profileView;

this.totalTime = profileNode.totalTime;
this.lastComparator = null;

this.childrenByCallUID = {};
}

WebInspector.ProfileDataGridTree.prototype = {
get expanded()
{
return true;
},

appendChild: function(child)
{
this.insertChild(child, this.children.length);
},

insertChild: function(child, index)
{
this.children.splice(index, 0, child);
this.childrenByCallUID[child.callUID] = child;
},

removeChildren: function()
{
this.children = [];
this.childrenByCallUID = {};
},

findChild: WebInspector.ProfileDataGridNode.prototype.findChild,
sort: WebInspector.ProfileDataGridNode.prototype.sort,

_save: function()
{
if (this._savedChildren)
return;

this._savedTotalTime = this.totalTime;
this._savedChildren = this.children.slice();
},

restore: function()
{
if (!this._savedChildren)
return;

this.children = this._savedChildren;
this.totalTime = this._savedTotalTime;

var children = this.children;
var count = children.length;

for (var index = 0; index < count; ++index)
children[index]._restore();

this._savedChildren = null;
}
}

WebInspector.ProfileDataGridTree.propertyComparators = [{}, {}];

WebInspector.ProfileDataGridTree.propertyComparator = function(  property,   isAscending)
{
var comparator = this.propertyComparators[(isAscending ? 1 : 0)][property];

if (!comparator) {
if (isAscending) {
comparator = function(lhs, rhs)
{
if (lhs[property] < rhs[property])
return -1;

if (lhs[property] > rhs[property])
return 1;

return 0;
}
} else {
comparator = function(lhs, rhs)
{
if (lhs[property] > rhs[property])
return -1;

if (lhs[property] < rhs[property])
return 1;

return 0;
}
}

this.propertyComparators[(isAscending ? 1 : 0)][property] = comparator;
}

return comparator;
}











WebInspector.BottomUpProfileDataGridNode = function(  profileView,   profileNode,   owningTree)
{
WebInspector.ProfileDataGridNode.call(this, profileView, profileNode, owningTree, this._willHaveChildren(profileNode));

this._remainingNodeInfos = [];
}

WebInspector.BottomUpProfileDataGridNode.prototype = {
_takePropertiesFromProfileDataGridNode: function(  profileDataGridNode)
{
this._save();

this.selfTime = profileDataGridNode.selfTime;
this.totalTime = profileDataGridNode.totalTime;
this.numberOfCalls = profileDataGridNode.numberOfCalls;
},


_keepOnlyChild: function(  child)
{
this._save();

this.removeChildren();
this.appendChild(child);
},

_exclude: function(aCallUID)
{
if (this._remainingNodeInfos)
this._populate();

this._save();

var children = this.children;
var index = this.children.length;

while (index--)
children[index]._exclude(aCallUID);

var child = this.childrenByCallUID[aCallUID];

if (child)
this._merge(child, true);
},

_restore: function()
{
WebInspector.ProfileDataGridNode.prototype._restore();

if (!this.children.length)
this.hasChildren = this._willHaveChildren();
},

_merge: function(  child,   shouldAbsorb)
{
this.selfTime -= child.selfTime;

WebInspector.ProfileDataGridNode.prototype._merge.call(this, child, shouldAbsorb);
},

_sharedPopulate: function()
{
var remainingNodeInfos = this._remainingNodeInfos;
var count = remainingNodeInfos.length;

for (var index = 0; index < count; ++index) {
var nodeInfo = remainingNodeInfos[index];
var ancestor = nodeInfo.ancestor;
var focusNode = nodeInfo.focusNode;
var child = this.findChild(ancestor);


if (child) {
var totalTimeAccountedFor = nodeInfo.totalTimeAccountedFor;

child.selfTime += focusNode.selfTime;
child.numberOfCalls += focusNode.numberOfCalls;

if (!totalTimeAccountedFor)
child.totalTime += focusNode.totalTime;
} else {


var child = new WebInspector.BottomUpProfileDataGridNode(this.profileView, ancestor, this.tree);

if (ancestor !== focusNode) {

child.selfTime = focusNode.selfTime;
child.totalTime = focusNode.totalTime;
child.numberOfCalls = focusNode.numberOfCalls;
}

this.appendChild(child);
}

var parent = ancestor.parent;
if (parent && parent.parent) {
nodeInfo.ancestor = parent;
child._remainingNodeInfos.push(nodeInfo);
}
}

delete this._remainingNodeInfos;
},

_willHaveChildren: function(profileNode)
{
profileNode = profileNode || this.profileNode;


return !!(profileNode.parent && profileNode.parent.parent);
}
}

WebInspector.BottomUpProfileDataGridNode.prototype.__proto__ = WebInspector.ProfileDataGridNode.prototype;

WebInspector.BottomUpProfileDataGridTree = function(  aProfileView,   aProfileNode)
{
WebInspector.ProfileDataGridTree.call(this, aProfileView, aProfileNode);


var profileNodeUIDs = 0;
var profileNodeGroups = [[], [aProfileNode]];
var visitedProfileNodesForCallUID = {};

this._remainingNodeInfos = [];

for (var profileNodeGroupIndex = 0; profileNodeGroupIndex < profileNodeGroups.length; ++profileNodeGroupIndex) {
var parentProfileNodes = profileNodeGroups[profileNodeGroupIndex];
var profileNodes = profileNodeGroups[++profileNodeGroupIndex];
var count = profileNodes.length;

for (var index = 0; index < count; ++index) {
var profileNode = profileNodes[index];

if (!profileNode.UID)
profileNode.UID = ++profileNodeUIDs;

if (profileNode.head && profileNode !== profileNode.head) {

var visitedNodes = visitedProfileNodesForCallUID[profileNode.callUID];
var totalTimeAccountedFor = false;

if (!visitedNodes) {
visitedNodes = {}
visitedProfileNodesForCallUID[profileNode.callUID] = visitedNodes;
} else {


var parentCount = parentProfileNodes.length;
for (var parentIndex = 0; parentIndex < parentCount; ++parentIndex) {
if (visitedNodes[parentProfileNodes[parentIndex].UID]) {
totalTimeAccountedFor = true;
break;
}
}
}

visitedNodes[profileNode.UID] = true;

this._remainingNodeInfos.push({ ancestor:profileNode, focusNode:profileNode, totalTimeAccountedFor:totalTimeAccountedFor });
}

var children = profileNode.children;
if (children.length) {
profileNodeGroups.push(parentProfileNodes.concat([profileNode]))
profileNodeGroups.push(children);
}
}
}


WebInspector.BottomUpProfileDataGridNode.prototype._populate.call(this);

return this;
}

WebInspector.BottomUpProfileDataGridTree.prototype = {

focus: function(  profileDataGridNode)
{
if (!profileDataGridNode)
return;

this._save();

var currentNode = profileDataGridNode;
var focusNode = profileDataGridNode;

while (currentNode.parent && (currentNode instanceof WebInspector.ProfileDataGridNode)) {
currentNode._takePropertiesFromProfileDataGridNode(profileDataGridNode);

focusNode = currentNode;
currentNode = currentNode.parent;

if (currentNode instanceof WebInspector.ProfileDataGridNode)
currentNode._keepOnlyChild(focusNode);
}

this.children = [focusNode];
this.totalTime = profileDataGridNode.totalTime;
},

exclude: function(  profileDataGridNode)
{
if (!profileDataGridNode)
return;

this._save();

var excludedCallUID = profileDataGridNode.callUID;
var excludedTopLevelChild = this.childrenByCallUID[excludedCallUID];



if (excludedTopLevelChild)
this.children.remove(excludedTopLevelChild);

var children = this.children;
var count = children.length;

for (var index = 0; index < count; ++index)
children[index]._exclude(excludedCallUID);

if (this.lastComparator)
this.sort(this.lastComparator, true);
},

_sharedPopulate: WebInspector.BottomUpProfileDataGridNode.prototype._sharedPopulate
}

WebInspector.BottomUpProfileDataGridTree.prototype.__proto__ = WebInspector.ProfileDataGridTree.prototype;






WebInspector.TopDownProfileDataGridNode = function(  profileView,   profileNode,   owningTree)
{
var hasChildren = (profileNode.children && profileNode.children.length);

WebInspector.ProfileDataGridNode.call(this, profileView, profileNode, owningTree, hasChildren);

this._remainingChildren = profileNode.children;
}

WebInspector.TopDownProfileDataGridNode.prototype = {
_sharedPopulate: function()
{
var children = this._remainingChildren;
var childrenLength = children.length;

for (var i = 0; i < childrenLength; ++i)
this.appendChild(new WebInspector.TopDownProfileDataGridNode(this.profileView, children[i], this.tree));

this._remainingChildren = null;
},

_exclude: function(aCallUID)
{
if (this._remainingChildren)
this._populate();

this._save();

var children = this.children;
var index = this.children.length;

while (index--)
children[index]._exclude(aCallUID);

var child = this.childrenByCallUID[aCallUID];

if (child)
this._merge(child, true);
}
}

WebInspector.TopDownProfileDataGridNode.prototype.__proto__ = WebInspector.ProfileDataGridNode.prototype;

WebInspector.TopDownProfileDataGridTree = function(  profileView,   profileNode)
{
WebInspector.ProfileDataGridTree.call(this, profileView, profileNode);

this._remainingChildren = profileNode.children;

WebInspector.TopDownProfileDataGridNode.prototype._populate.call(this);
}

WebInspector.TopDownProfileDataGridTree.prototype = {
focus: function(  profileDataGrideNode)
{
if (!profileDataGrideNode)
return;

this._save();
profileDataGrideNode.savePosition();

this.children = [profileDataGrideNode];
this.totalTime = profileDataGrideNode.totalTime;
},

exclude: function(  profileDataGrideNode)
{
if (!profileDataGrideNode)
return;

this._save();

var excludedCallUID = profileDataGrideNode.callUID;

WebInspector.TopDownProfileDataGridNode.prototype._exclude.call(this, excludedCallUID);

if (this.lastComparator)
this.sort(this.lastComparator, true);
},

restore: function()
{
if (!this._savedChildren)
return;

this.children[0].restorePosition();

WebInspector.ProfileDataGridTree.prototype.restore.call(this);
},

_merge: WebInspector.TopDownProfileDataGridNode.prototype._merge,

_sharedPopulate: WebInspector.TopDownProfileDataGridNode.prototype._sharedPopulate
}

WebInspector.TopDownProfileDataGridTree.prototype.__proto__ = WebInspector.ProfileDataGridTree.prototype;







WebInspector.CPUProfileView = function(profile)
{
WebInspector.View.call(this);

this.element.addStyleClass("profile-view");

this.showSelfTimeAsPercent = true;
this.showTotalTimeAsPercent = true;
this.showAverageTimeAsPercent = true;

var columns = { "self": { title: WebInspector.UIString("Self"), width: "72px", sort: "descending", sortable: true },
"total": { title: WebInspector.UIString("Total"), width: "72px", sortable: true },
"average": { title: WebInspector.UIString("Average"), width: "72px", sortable: true },
"calls": { title: WebInspector.UIString("Calls"), width: "54px", sortable: true },
"function": { title: WebInspector.UIString("Function"), disclosure: true, sortable: true } };

if (Preferences.samplingCPUProfiler) {
delete columns.average;
delete columns.calls;
}

this.dataGrid = new WebInspector.DataGrid(columns);
this.dataGrid.addEventListener("sorting changed", this._sortData, this);
this.dataGrid.element.addEventListener("mousedown", this._mouseDownInDataGrid.bind(this), true);
this.element.appendChild(this.dataGrid.element);

this.viewSelectElement = document.createElement("select");
this.viewSelectElement.className = "status-bar-item";
this.viewSelectElement.addEventListener("change", this._changeView.bind(this), false);
this.view = "Heavy";

var heavyViewOption = document.createElement("option");
heavyViewOption.label = WebInspector.UIString("Heavy (Bottom Up)");
var treeViewOption = document.createElement("option");
treeViewOption.label = WebInspector.UIString("Tree (Top Down)");
this.viewSelectElement.appendChild(heavyViewOption);
this.viewSelectElement.appendChild(treeViewOption);

this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item");
this.percentButton.addEventListener("click", this._percentClicked.bind(this), false);

this.focusButton = new WebInspector.StatusBarButton(WebInspector.UIString("Focus selected function."), "focus-profile-node-status-bar-item");
this.focusButton.disabled = true;
this.focusButton.addEventListener("click", this._focusClicked.bind(this), false);

this.excludeButton = new WebInspector.StatusBarButton(WebInspector.UIString("Exclude selected function."), "exclude-profile-node-status-bar-item");
this.excludeButton.disabled = true;
this.excludeButton.addEventListener("click", this._excludeClicked.bind(this), false);

this.resetButton = new WebInspector.StatusBarButton(WebInspector.UIString("Restore all functions."), "reset-profile-status-bar-item");
this.resetButton.visible = false;
this.resetButton.addEventListener("click", this._resetClicked.bind(this), false);

this.profile = profile;

var self = this;
function profileCallback(error, profile)
{
if (error)
return;
self.profile.head = profile.head;
self._assignParentsInProfile();

self.profileDataGridTree = self.bottomUpProfileDataGridTree;
self.profileDataGridTree.sort(WebInspector.ProfileDataGridTree.propertyComparator("selfTime", false));

self.refresh();

self._updatePercentButton();
}

ProfilerAgent.getProfile(this.profile.typeId, this.profile.uid, profileCallback);
}

WebInspector.CPUProfileView.prototype = {
get statusBarItems()
{
return [this.viewSelectElement, this.percentButton.element, this.focusButton.element, this.excludeButton.element, this.resetButton.element];
},

get profile()
{
return this._profile;
},

set profile(profile)
{
this._profile = profile;
},

get bottomUpProfileDataGridTree()
{
if (!this._bottomUpProfileDataGridTree) {
if (this.profile.bottomUpHead)
this._bottomUpProfileDataGridTree = new WebInspector.TopDownProfileDataGridTree(this, this.profile.bottomUpHead);
else
this._bottomUpProfileDataGridTree = new WebInspector.BottomUpProfileDataGridTree(this, this.profile.head);
}
return this._bottomUpProfileDataGridTree;
},

get topDownProfileDataGridTree()
{
if (!this._topDownProfileDataGridTree)
this._topDownProfileDataGridTree = new WebInspector.TopDownProfileDataGridTree(this, this.profile.head);
return this._topDownProfileDataGridTree;
},

get currentTree()
{
return this._currentTree;
},

set currentTree(tree)
{
this._currentTree = tree;
this.refresh();
},

get topDownTree()
{
if (!this._topDownTree) {
this._topDownTree = WebInspector.TopDownTreeFactory.create(this.profile.head);
this._sortProfile(this._topDownTree);
}

return this._topDownTree;
},

get bottomUpTree()
{
if (!this._bottomUpTree) {
this._bottomUpTree = WebInspector.BottomUpTreeFactory.create(this.profile.head);
this._sortProfile(this._bottomUpTree);
}

return this._bottomUpTree;
},

show: function(parentElement)
{
WebInspector.View.prototype.show.call(this, parentElement);
this.dataGrid.updateWidths();
},

hide: function()
{
WebInspector.View.prototype.hide.call(this);
this._currentSearchResultIndex = -1;
},

resize: function()
{
if (this.dataGrid)
this.dataGrid.updateWidths();
},

refresh: function()
{
var selectedProfileNode = this.dataGrid.selectedNode ? this.dataGrid.selectedNode.profileNode : null;

this.dataGrid.removeChildren();

var children = this.profileDataGridTree.children;
var count = children.length;

for (var index = 0; index < count; ++index)
this.dataGrid.appendChild(children[index]);

if (selectedProfileNode)
selectedProfileNode.selected = true;
},

refreshVisibleData: function()
{
var child = this.dataGrid.children[0];
while (child) {
child.refresh();
child = child.traverseNextNode(false, null, true);
}
},

refreshShowAsPercents: function()
{
this._updatePercentButton();
this.refreshVisibleData();
},

searchCanceled: function()
{
if (this._searchResults) {
for (var i = 0; i < this._searchResults.length; ++i) {
var profileNode = this._searchResults[i].profileNode;

delete profileNode._searchMatchedSelfColumn;
delete profileNode._searchMatchedTotalColumn;
delete profileNode._searchMatchedCallsColumn;
delete profileNode._searchMatchedFunctionColumn;

profileNode.refresh();
}
}

delete this._searchFinishedCallback;
this._currentSearchResultIndex = -1;
this._searchResults = [];
},

performSearch: function(query, finishedCallback)
{

this.searchCanceled();

query = query.trim();

if (!query.length)
return;

this._searchFinishedCallback = finishedCallback;

var greaterThan = (query.indexOf(">") === 0);
var lessThan = (query.indexOf("<") === 0);
var equalTo = (query.indexOf("=") === 0 || ((greaterThan || lessThan) && query.indexOf("=") === 1));
var percentUnits = (query.lastIndexOf("%") === (query.length - 1));
var millisecondsUnits = (query.length > 2 && query.lastIndexOf("ms") === (query.length - 2));
var secondsUnits = (!millisecondsUnits && query.lastIndexOf("s") === (query.length - 1));

var queryNumber = parseFloat(query);
if (greaterThan || lessThan || equalTo) {
if (equalTo && (greaterThan || lessThan))
queryNumber = parseFloat(query.substring(2));
else
queryNumber = parseFloat(query.substring(1));
}

var queryNumberMilliseconds = (secondsUnits ? (queryNumber * 1000) : queryNumber);


if (!isNaN(queryNumber) && !(greaterThan || lessThan))
equalTo = true;

function matchesQuery(  profileDataGridNode)
{
delete profileDataGridNode._searchMatchedSelfColumn;
delete profileDataGridNode._searchMatchedTotalColumn;
delete profileDataGridNode._searchMatchedAverageColumn;
delete profileDataGridNode._searchMatchedCallsColumn;
delete profileDataGridNode._searchMatchedFunctionColumn;

if (percentUnits) {
if (lessThan) {
if (profileDataGridNode.selfPercent < queryNumber)
profileDataGridNode._searchMatchedSelfColumn = true;
if (profileDataGridNode.totalPercent < queryNumber)
profileDataGridNode._searchMatchedTotalColumn = true;
if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
profileDataGridNode._searchMatchedAverageColumn = true;
} else if (greaterThan) {
if (profileDataGridNode.selfPercent > queryNumber)
profileDataGridNode._searchMatchedSelfColumn = true;
if (profileDataGridNode.totalPercent > queryNumber)
profileDataGridNode._searchMatchedTotalColumn = true;
if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
profileDataGridNode._searchMatchedAverageColumn = true;
}

if (equalTo) {
if (profileDataGridNode.selfPercent == queryNumber)
profileDataGridNode._searchMatchedSelfColumn = true;
if (profileDataGridNode.totalPercent == queryNumber)
profileDataGridNode._searchMatchedTotalColumn = true;
if (profileDataGridNode.averagePercent < queryNumberMilliseconds)
profileDataGridNode._searchMatchedAverageColumn = true;
}
} else if (millisecondsUnits || secondsUnits) {
if (lessThan) {
if (profileDataGridNode.selfTime < queryNumberMilliseconds)
profileDataGridNode._searchMatchedSelfColumn = true;
if (profileDataGridNode.totalTime < queryNumberMilliseconds)
profileDataGridNode._searchMatchedTotalColumn = true;
if (profileDataGridNode.averageTime < queryNumberMilliseconds)
profileDataGridNode._searchMatchedAverageColumn = true;
} else if (greaterThan) {
if (profileDataGridNode.selfTime > queryNumberMilliseconds)
profileDataGridNode._searchMatchedSelfColumn = true;
if (profileDataGridNode.totalTime > queryNumberMilliseconds)
profileDataGridNode._searchMatchedTotalColumn = true;
if (profileDataGridNode.averageTime > queryNumberMilliseconds)
profileDataGridNode._searchMatchedAverageColumn = true;
}

if (equalTo) {
if (profileDataGridNode.selfTime == queryNumberMilliseconds)
profileDataGridNode._searchMatchedSelfColumn = true;
if (profileDataGridNode.totalTime == queryNumberMilliseconds)
profileDataGridNode._searchMatchedTotalColumn = true;
if (profileDataGridNode.averageTime == queryNumberMilliseconds)
profileDataGridNode._searchMatchedAverageColumn = true;
}
} else {
if (equalTo && profileDataGridNode.numberOfCalls == queryNumber)
profileDataGridNode._searchMatchedCallsColumn = true;
if (greaterThan && profileDataGridNode.numberOfCalls > queryNumber)
profileDataGridNode._searchMatchedCallsColumn = true;
if (lessThan && profileDataGridNode.numberOfCalls < queryNumber)
profileDataGridNode._searchMatchedCallsColumn = true;
}

if (profileDataGridNode.functionName.hasSubstring(query, true) || profileDataGridNode.url.hasSubstring(query, true))
profileDataGridNode._searchMatchedFunctionColumn = true;

if (profileDataGridNode._searchMatchedSelfColumn ||
profileDataGridNode._searchMatchedTotalColumn ||
profileDataGridNode._searchMatchedAverageColumn ||
profileDataGridNode._searchMatchedCallsColumn ||
profileDataGridNode._searchMatchedFunctionColumn)
{
profileDataGridNode.refresh();
return true;
}

return false;
}

var current = this.profileDataGridTree.children[0];

while (current) {
if (matchesQuery(current)) {
this._searchResults.push({ profileNode: current });
}

current = current.traverseNextNode(false, null, false);
}

finishedCallback(this, this._searchResults.length);
},

jumpToFirstSearchResult: function()
{
if (!this._searchResults || !this._searchResults.length)
return;
this._currentSearchResultIndex = 0;
this._jumpToSearchResult(this._currentSearchResultIndex);
},

jumpToLastSearchResult: function()
{
if (!this._searchResults || !this._searchResults.length)
return;
this._currentSearchResultIndex = (this._searchResults.length - 1);
this._jumpToSearchResult(this._currentSearchResultIndex);
},

jumpToNextSearchResult: function()
{
if (!this._searchResults || !this._searchResults.length)
return;
if (++this._currentSearchResultIndex >= this._searchResults.length)
this._currentSearchResultIndex = 0;
this._jumpToSearchResult(this._currentSearchResultIndex);
},

jumpToPreviousSearchResult: function()
{
if (!this._searchResults || !this._searchResults.length)
return;
if (--this._currentSearchResultIndex < 0)
this._currentSearchResultIndex = (this._searchResults.length - 1);
this._jumpToSearchResult(this._currentSearchResultIndex);
},

showingFirstSearchResult: function()
{
return (this._currentSearchResultIndex === 0);
},

showingLastSearchResult: function()
{
return (this._searchResults && this._currentSearchResultIndex === (this._searchResults.length - 1));
},

_jumpToSearchResult: function(index)
{
var searchResult = this._searchResults[index];
if (!searchResult)
return;

var profileNode = searchResult.profileNode;
profileNode.reveal();
profileNode.select();
},

_changeView: function(event)
{
if (!event || !this.profile)
return;

if (event.target.selectedIndex == 1 && this.view == "Heavy") {
this.profileDataGridTree = this.topDownProfileDataGridTree;
this._sortProfile();
this.view = "Tree";
} else if (event.target.selectedIndex == 0 && this.view == "Tree") {
this.profileDataGridTree = this.bottomUpProfileDataGridTree;
this._sortProfile();
this.view = "Heavy";
}

if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults)
return;




this._searchFinishedCallback(this, -this._searchResults.length);
this.performSearch(this.currentQuery, this._searchFinishedCallback);
},

_percentClicked: function(event)
{
var currentState = this.showSelfTimeAsPercent && this.showTotalTimeAsPercent && this.showAverageTimeAsPercent;
this.showSelfTimeAsPercent = !currentState;
this.showTotalTimeAsPercent = !currentState;
this.showAverageTimeAsPercent = !currentState;
this.refreshShowAsPercents();
},

_updatePercentButton: function()
{
if (this.showSelfTimeAsPercent && this.showTotalTimeAsPercent && this.showAverageTimeAsPercent) {
this.percentButton.title = WebInspector.UIString("Show absolute total and self times.");
this.percentButton.toggled = true;
} else {
this.percentButton.title = WebInspector.UIString("Show total and self times as percentages.");
this.percentButton.toggled = false;
}
},

_focusClicked: function(event)
{
if (!this.dataGrid.selectedNode)
return;

this.resetButton.visible = true;
this.profileDataGridTree.focus(this.dataGrid.selectedNode);
this.refresh();
this.refreshVisibleData();
},

_excludeClicked: function(event)
{
var selectedNode = this.dataGrid.selectedNode

if (!selectedNode)
return;

selectedNode.deselect();

this.resetButton.visible = true;
this.profileDataGridTree.exclude(selectedNode);
this.refresh();
this.refreshVisibleData();
},

_resetClicked: function(event)
{
this.resetButton.visible = false;
this.profileDataGridTree.restore();
this.refresh();
this.refreshVisibleData();
},

_dataGridNodeSelected: function(node)
{
this.focusButton.disabled = false;
this.excludeButton.disabled = false;
},

_dataGridNodeDeselected: function(node)
{
this.focusButton.disabled = true;
this.excludeButton.disabled = true;
},

_sortData: function(event)
{
this._sortProfile(this.profile);
},

_sortProfile: function()
{
var sortAscending = this.dataGrid.sortOrder === "ascending";
var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
var sortProperty = {
"average": "averageTime",
"self": "selfTime",
"total": "totalTime",
"calls": "numberOfCalls",
"function": "functionName"
}[sortColumnIdentifier];

this.profileDataGridTree.sort(WebInspector.ProfileDataGridTree.propertyComparator(sortProperty, sortAscending));

this.refresh();
},

_mouseDownInDataGrid: function(event)
{
if (event.detail < 2)
return;

var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
if (!cell || (!cell.hasStyleClass("total-column") && !cell.hasStyleClass("self-column") && !cell.hasStyleClass("average-column")))
return;

if (cell.hasStyleClass("total-column"))
this.showTotalTimeAsPercent = !this.showTotalTimeAsPercent;
else if (cell.hasStyleClass("self-column"))
this.showSelfTimeAsPercent = !this.showSelfTimeAsPercent;
else if (cell.hasStyleClass("average-column"))
this.showAverageTimeAsPercent = !this.showAverageTimeAsPercent;

this.refreshShowAsPercents();

event.preventDefault();
event.stopPropagation();
},

_assignParentsInProfile: function()
{
var head = this.profile.head;
head.parent = null;
head.head = null;
var nodesToTraverse = [ { parent: head, children: head.children } ];
while (nodesToTraverse.length > 0) {
var pair = nodesToTraverse.shift();
var parent = pair.parent;
var children = pair.children;
var length = children.length;
for (var i = 0; i < length; ++i) {
children[i].head = head;
children[i].parent = parent;
if (children[i].children.length > 0)
nodesToTraverse.push({ parent: children[i], children: children[i].children });
}
}
}
}

WebInspector.CPUProfileView.prototype.__proto__ = WebInspector.View.prototype;

WebInspector.CPUProfileType = function()
{
WebInspector.ProfileType.call(this, WebInspector.CPUProfileType.TypeId, WebInspector.UIString("CPU PROFILES"));
this._recording = false;
}

WebInspector.CPUProfileType.TypeId = "CPU";

WebInspector.CPUProfileType.prototype = {
get buttonTooltip()
{
return this._recording ? WebInspector.UIString("Stop profiling.") : WebInspector.UIString("Start profiling.");
},

get buttonStyle()
{
return this._recording ? "record-profile-status-bar-item status-bar-item toggled-on" : "record-profile-status-bar-item status-bar-item";
},

buttonClicked: function()
{
this._recording = !this._recording;

if (this._recording)
ProfilerAgent.start();
else
ProfilerAgent.stop();
},

get welcomeMessage()
{
return WebInspector.UIString("Control CPU profiling by pressing the %s button on the status bar.");
},

setRecordingProfile: function(isProfiling)
{
this._recording = isProfiling;
},

createSidebarTreeElementForProfile: function(profile)
{
return new WebInspector.ProfileSidebarTreeElement(profile, WebInspector.UIString("Profile %d"), "profile-sidebar-tree-item");
},

createView: function(profile)
{
return new WebInspector.CPUProfileView(profile);
}
}

WebInspector.CPUProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype;





WebInspector.HeapSnapshotLoader = function()
{
this._json = "";
this._state = "find-snapshot-info";
this._snapshot = {};
}

WebInspector.HeapSnapshotLoader.prototype = {
_findBalancedCurlyBrackets: function()
{
var counter = 0;
var openingBracket = "{".charCodeAt(0), closingBracket = "}".charCodeAt(0);
for (var i = 0, l = this._json.length; i < l; ++i) {
var character = this._json.charCodeAt(i);
if (character === openingBracket)
++counter;
else if (character === closingBracket) {
if (--counter === 0)
return i + 1;
}
}
return -1;
},

finishLoading: function()
{
if (!this._json)
return null;
this._parseStringsArray();
this._json = "";
var result = new WebInspector.HeapSnapshot(this._snapshot);
this._json = "";
this._snapshot = {};
return result;
},

_parseNodes: function()
{
var index = 0;
var char0 = "0".charCodeAt(0), char9 = "9".charCodeAt(0), closingBracket = "]".charCodeAt(0);
var length = this._json.length;
while (true) {
while (index < length) {
var code = this._json.charCodeAt(index);
if (char0 <= code && code <= char9)
break;
else if (code === closingBracket) {
this._json = this._json.slice(index + 1);

this._snapshot.nodes = this._snapshot.nodes.slice(0);
return false;
}
++index;
}
if (index === length) {
this._json = "";
return true;
}
var startIndex = index;
while (index < length) {
var code = this._json.charCodeAt(index);
if (char0 > code || code > char9)
break;
++index;
}
if (index === length) {
this._json = this._json.slice(startIndex);
return true;
}
this._snapshot.nodes.push(parseInt(this._json.slice(startIndex, index)));
}
},

_parseStringsArray: function()
{
var closingBracketIndex = this._json.lastIndexOf("]");
if (closingBracketIndex === -1)
throw new Error("Incomplete JSON");
this._json = this._json.slice(0, closingBracketIndex + 1);
this._snapshot.strings = JSON.parse(this._json);
},

pushJSONChunk: function(chunk)
{
this._json += chunk;
switch (this._state) {
case "find-snapshot-info": {
var snapshotToken = "\"snapshot\"";
var snapshotTokenIndex = this._json.indexOf(snapshotToken);
if (snapshotTokenIndex === -1)
throw new Error("Snapshot token not found");
this._json = this._json.slice(snapshotTokenIndex + snapshotToken.length + 1);
this._state = "parse-snapshot-info";
this.pushJSONChunk("");
break;
}
case "parse-snapshot-info": {
var closingBracketIndex = this._findBalancedCurlyBrackets();
if (closingBracketIndex === -1)
return;
this._snapshot.snapshot = JSON.parse(this._json.slice(0, closingBracketIndex));
this._json = this._json.slice(closingBracketIndex);
this._state = "find-nodes";
this.pushJSONChunk("");
break;
}
case "find-nodes": {
var nodesToken = "\"nodes\"";
var nodesTokenIndex = this._json.indexOf(nodesToken);
if (nodesTokenIndex === -1)
return;
var bracketIndex = this._json.indexOf("[", nodesTokenIndex);
if (bracketIndex === -1)
return;
this._json = this._json.slice(bracketIndex + 1);
this._state = "parse-nodes-meta-info";
this.pushJSONChunk("");
break;
}
case "parse-nodes-meta-info": {
var closingBracketIndex = this._findBalancedCurlyBrackets();
if (closingBracketIndex === -1)
return;
this._snapshot.nodes = [JSON.parse(this._json.slice(0, closingBracketIndex))];
this._json = this._json.slice(closingBracketIndex);
this._state = "parse-nodes";
this.pushJSONChunk("");
break;          
}
case "parse-nodes": {
if (this._parseNodes())
return;
this._state = "find-strings";
this.pushJSONChunk("");
break;
}
case "find-strings": {
var stringsToken = "\"strings\"";
var stringsTokenIndex = this._json.indexOf(stringsToken);
if (stringsTokenIndex === -1)
return;
var bracketIndex = this._json.indexOf("[", stringsTokenIndex);
if (bracketIndex === -1)
return;
this._json = this._json.slice(bracketIndex);
this._state = "accumulate-strings";
break;
}
case "accumulate-strings":
break;
}
}
};

WebInspector.HeapSnapshotArraySlice = function(snapshot, arrayName, start, end)
{


this._snapshot = snapshot;
this._arrayName = arrayName;
this._start = start;
this.length = end - start;
}

WebInspector.HeapSnapshotArraySlice.prototype = {
item: function(index)
{
return this._snapshot[this._arrayName][this._start + index];
}
}

WebInspector.HeapSnapshotEdge = function(snapshot, edges, edgeIndex)
{
this._snapshot = snapshot;
this._edges = edges;
this.edgeIndex = edgeIndex || 0;
}

WebInspector.HeapSnapshotEdge.prototype = {
clone: function()
{
return new WebInspector.HeapSnapshotEdge(this._snapshot, this._edges, this.edgeIndex);
},

get hasStringName()
{
if (!this.isShortcut)
return this._hasStringName;
return isNaN(parseInt(this._name, 10));
},

get isElement()
{
return this._type() === this._snapshot._edgeElementType;
},

get isHidden()
{
return this._type() === this._snapshot._edgeHiddenType;
},

get isInternal()
{
return this._type() === this._snapshot._edgeInternalType;
},

get isInvisible()
{
return this._type() === this._snapshot._edgeInvisibleType;
},

get isShortcut()
{
return this._type() === this._snapshot._edgeShortcutType;
},

get name()
{
if (!this.isShortcut)
return this._name;
var numName = parseInt(this._name, 10);
return isNaN(numName) ? this._name : numName;
},

get node()
{
return new WebInspector.HeapSnapshotNode(this._snapshot, this.nodeIndex);
},

get nodeIndex()
{
return this._edges.item(this.edgeIndex + this._snapshot._edgeToNodeOffset);
},

get rawEdges()
{
return this._edges;
},

toString: function()
{
switch (this.type) {
case "context": return "->" + this.name;
case "element": return "[" + this.name + "]";
case "property":
return this.name.indexOf(" ") === -1 ? "." + this.name : "[\"" + this.name + "\"]";
case "shortcut":
var name = this.name;
if (typeof name === "string")
return this.name.indexOf(" ") === -1 ? "." + this.name : "[\"" + this.name + "\"]";
else
return "[" + this.name + "]";
case "internal":
case "hidden":
case "invisible":
return "{" + this.name + "}";
};
return "?" + this.name + "?";
},

get type()
{
return this._snapshot._edgeTypes[this._type()];
},

get _hasStringName()
{
return !this.isElement && !this.isHidden;
},

get _name()
{
return this._hasStringName ? this._snapshot._strings[this._nameOrIndex] : this._nameOrIndex;
},

get _nameOrIndex()
{
return this._edges.item(this.edgeIndex + this._snapshot._edgeNameOffset);
},

_type: function()
{
return this._edges.item(this.edgeIndex + this._snapshot._edgeTypeOffset);
}
};

WebInspector.HeapSnapshotEdgeIterator = function(edge)
{
this.edge = edge;
}

WebInspector.HeapSnapshotEdgeIterator.prototype = {
first: function()
{
this.edge.edgeIndex = 0;
},

hasNext: function()
{
return this.edge.edgeIndex < this.edge._edges.length;
},

get index()
{
return this.edge.edgeIndex;
},

set index(newIndex)
{
this.edge.edgeIndex = newIndex;
},

get item()
{
return this.edge;
},

next: function()
{
this.edge.edgeIndex += this.edge._snapshot._edgeFieldsCount;
}
};

WebInspector.HeapSnapshotRetainerEdge = function(snapshot, retainers, retainerIndex)
{
this._snapshot = snapshot;
this._retainers = retainers;
this.retainerIndex = retainerIndex || 0;
}

WebInspector.HeapSnapshotRetainerEdge.prototype = {
clone: function()
{
return new WebInspector.HeapSnapshotRetainerEdge(this._snapshot, this._retainers, this.retainerIndex);
},

get hasStringName()
{
return this._edge.hasStringName;
},

get isElement()
{
return this._edge.isElement;
},

get isHidden()
{
return this._edge.isHidden;
},

get isInternal()
{
return this._edge.isInternal;
},

get isInvisible()
{
return this._edge.isInvisible;
},

get isShortcut()
{
return this._edge.isShortcut;
},

get name()
{
return this._edge.name;
},

get node()
{
return this._node;
},

get nodeIndex()
{
return this._nodeIndex;
},

get retainerIndex()
{
return this._retainerIndex;
},

set retainerIndex(newIndex)
{
if (newIndex !== this._retainerIndex) {
this._retainerIndex = newIndex;
this._setupEdge();
}
},

_setupEdge: function()
{
var globalEdgeIndex = this._retainers.item(this._retainerIndex);
this._nodeIndex = this._snapshot._findNearestNodeIndex(globalEdgeIndex);
this._node = new WebInspector.HeapSnapshotNode(this._snapshot, this._nodeIndex);
var edgeIndex = globalEdgeIndex - this._nodeIndex - this._snapshot._firstEdgeOffset;
this._edge = new WebInspector.HeapSnapshotEdge(this._snapshot, this._node.rawEdges, edgeIndex);
},

toString: function()
{
return this._edge.toString();
},

get type()
{
return this._edge.type;
}
}

WebInspector.HeapSnapshotRetainerEdgeIterator = function(retainer)
{
this.retainer = retainer;
}

WebInspector.HeapSnapshotRetainerEdgeIterator.prototype = {
first: function()
{
this.retainer.retainerIndex = 0;
},

hasNext: function()
{
return this.retainer.retainerIndex < this.retainer._retainers.length;
},

get index()
{
return this.retainer.retainerIndex;
},

set index(newIndex)
{
this.retainer.retainerIndex = newIndex;
},

get item()
{
return this.retainer;
},

next: function()
{
++this.retainer.retainerIndex;
}
};

WebInspector.HeapSnapshotNode = function(snapshot, nodeIndex)
{
this._snapshot = snapshot;
this._firstNodeIndex = nodeIndex;
this.nodeIndex = nodeIndex;
}

WebInspector.HeapSnapshotNode.prototype = {
get className()
{
switch (this.type) {
case "hidden":
return WebInspector.UIString("(system)");
case "object": {
var commentPos = this.name.indexOf("/");
return commentPos !== -1 ? this.name.substring(0, commentPos).trimRight() : this.name;
}
case "native": {
var entitiesCountPos = this.name.indexOf("/");
return entitiesCountPos !== -1 ? this.name.substring(0, entitiesCountPos).trimRight() : this.name;
}
case "code":
return WebInspector.UIString("(compiled code)");
default:
return "(" + this.type + ")";
}
},

get dominatorIndex()
{
return this._nodes[this.nodeIndex + this._snapshot._dominatorOffset];
},

get edges()
{
return new WebInspector.HeapSnapshotEdgeIterator(new WebInspector.HeapSnapshotEdge(this._snapshot, this.rawEdges));
},

get edgesCount()
{
return this._nodes[this.nodeIndex + this._snapshot._edgesCountOffset];
},

get id()
{
return this._nodes[this.nodeIndex + this._snapshot._nodeIdOffset];
},

get instancesCount()
{
return this._nodes[this.nodeIndex + this._snapshot._nodeInstancesCountOffset];
},

get isHidden()
{
return this._type() === this._snapshot._nodeHiddenType;
},

get isRoot()
{
return this.nodeIndex === this._snapshot._rootNodeIndex;
},

get name()
{
return this._snapshot._strings[this._name()];
},

get rawEdges()
{
var firstEdgeIndex = this._firstEdgeIndex();
return new WebInspector.HeapSnapshotArraySlice(this._snapshot, "_nodes", firstEdgeIndex, firstEdgeIndex + this.edgesCount * this._snapshot._edgeFieldsCount);
},

get retainedSize()
{
return this._nodes[this.nodeIndex + this._snapshot._nodeRetainedSizeOffset];
},

get retainers()
{
return new WebInspector.HeapSnapshotRetainerEdgeIterator(new WebInspector.HeapSnapshotRetainerEdge(this._snapshot, this._snapshot._retainersForNode(this)));
},

get selfSize()
{
return this._nodes[this.nodeIndex + this._snapshot._nodeSelfSizeOffset];
},

get type()
{
return this._snapshot._nodeTypes[this._type()];
},

_name: function()
{
return this._nodes[this.nodeIndex + this._snapshot._nodeNameOffset];
},

get _nodes()
{
return this._snapshot._nodes;
},

_firstEdgeIndex: function()
{
return this.nodeIndex + this._snapshot._firstEdgeOffset;
},

get _nextNodeIndex()
{
return this._firstEdgeIndex() + this.edgesCount * this._snapshot._edgeFieldsCount;
},

_type: function()
{
return this._nodes[this.nodeIndex + this._snapshot._nodeTypeOffset];
}
};

WebInspector.HeapSnapshotNodeIterator = function(node)
{
this.node = node;
}

WebInspector.HeapSnapshotNodeIterator.prototype = {
first: function()
{
this.node.nodeIndex = this.node._firstNodeIndex;
},

hasNext: function()
{
return this.node.nodeIndex < this.node._nodes.length;
},

get index()
{
return this.node.nodeIndex;
},

set index(newIndex)
{
this.node.nodeIndex = newIndex;
},

get item()
{
return this.node;
},

next: function()
{
this.node.nodeIndex = this.node._nextNodeIndex;
}
}

WebInspector.HeapSnapshot = function(profile)
{
this.uid = profile.snapshot.uid;
this._nodes = profile.nodes;
this._strings = profile.strings;

this._init();
}

WebInspector.HeapSnapshot.prototype = {
_init: function()
{
this._metaNodeIndex = 0;
this._rootNodeIndex = 1;
var meta = this._nodes[this._metaNodeIndex];
this._nodeTypeOffset = meta.fields.indexOf("type");
this._nodeNameOffset = meta.fields.indexOf("name");
this._nodeIdOffset = meta.fields.indexOf("id");
this._nodeInstancesCountOffset = this._nodeIdOffset;
this._nodeSelfSizeOffset = meta.fields.indexOf("self_size");
this._nodeRetainedSizeOffset = meta.fields.indexOf("retained_size");
this._dominatorOffset = meta.fields.indexOf("dominator");
this._edgesCountOffset = meta.fields.indexOf("children_count");
this._firstEdgeOffset = meta.fields.indexOf("children");
this._nodeTypes = meta.types[this._nodeTypeOffset];
this._nodeHiddenType = this._nodeTypes.indexOf("hidden");
var edgesMeta = meta.types[this._firstEdgeOffset];
this._edgeFieldsCount = edgesMeta.fields.length;
this._edgeTypeOffset = edgesMeta.fields.indexOf("type");
this._edgeNameOffset = edgesMeta.fields.indexOf("name_or_index");
this._edgeToNodeOffset = edgesMeta.fields.indexOf("to_node");
this._edgeTypes = edgesMeta.types[this._edgeTypeOffset];
this._edgeElementType = this._edgeTypes.indexOf("element");
this._edgeHiddenType = this._edgeTypes.indexOf("hidden");
this._edgeInternalType = this._edgeTypes.indexOf("internal");
this._edgeShortcutType = this._edgeTypes.indexOf("shortcut");
this._edgeInvisibleType = this._edgeTypes.length;
this._edgeTypes.push("invisible");

this._markInvisibleEdges();
},

dispose: function()
{
delete this._nodes;
delete this._strings;
delete this._retainers;
delete this._retainerIndex;
delete this._nodeIndex;
if (this._aggregates) {
delete this._aggregates;
this._aggregatesIndexesSorted = false;
}
delete this._baseNodeIds;
},

get _allNodes()
{
return new WebInspector.HeapSnapshotNodeIterator(this.rootNode);
},

get nodeCount()
{
if (this._nodeCount)
return this._nodeCount;

this._nodeCount = 0;
for (var iter = this._allNodes; iter.hasNext(); iter.next())
++this._nodeCount;
return this._nodeCount;
},

nodeFieldValuesByIndex: function(fieldName, indexes)
{
var node = new WebInspector.HeapSnapshotNode(this);
var result = new Array(indexes.length);
for (var i = 0, l = indexes.length; i < l; ++i) {
node.nodeIndex = indexes[i];
result[i] = node[fieldName];
}
return result;
},

get rootNode()
{
return new WebInspector.HeapSnapshotNode(this, this._rootNodeIndex);
},

get rootNodeIndex()
{
return this._rootNodeIndex;
},

get totalSize()
{
return this.rootNode.retainedSize;
},

_retainersForNode: function(node)
{
if (!this._retainers)
this._buildRetainers();

var retIndexFrom = this._getRetainerIndex(node.nodeIndex);
var retIndexTo = this._getRetainerIndex(node._nextNodeIndex);
return new WebInspector.HeapSnapshotArraySlice(this, "_retainers", retIndexFrom, retIndexTo);
},

aggregates: function(sortedIndexes)
{
if (!this._aggregates)
this._buildAggregates();
if (sortedIndexes && !this._aggregatesIndexesSorted)
this._sortAggregateIndexes();
return this._aggregates;
},

_buildRetainers: function()
{
if (!this._nodeIndex)
this._buildNodeIndex();

this._retainerIndex = new Array(this._nodeIndex.length);
for (var i = 0, l = this._retainerIndex.length; i < l; ++i)
this._retainerIndex[i] = 0;
for (var nodesIter = this._allNodes; nodesIter.hasNext(); nodesIter.next()) {
var node = nodesIter.node;
for (var edgesIter = node.edges; edgesIter.hasNext(); edgesIter.next()) {
var edge = edgesIter.edge;
var nodeIndex = edge.nodeIndex;
var position = this._findNodePositionInIndex(nodeIndex);
++this._retainerIndex[position];
}
}
var retainerCount = 0;
for (i = 0, l = this._retainerIndex.length; i < l; ++i)
retainerCount += this._retainerIndex[i];
this._retainers = new Array(retainerCount + 1);
var retainerPosition = 0;
for (i = 0, l = this._retainerIndex.length; i < l; ++i) {
retainerCount = this._retainers[retainerPosition] = this._retainerIndex[i];
this._retainerIndex[i] = retainerPosition;
retainerPosition += retainerCount;
}
for (nodesIter = this._allNodes; nodesIter.hasNext(); nodesIter.next()) {
var node = nodesIter.node;
for (var edgesIter = node.edges; edgesIter.hasNext(); edgesIter.next()) {
var edge = edgesIter.edge;
var nodeIndex = edge.nodeIndex;
var retIndex = this._getRetainerIndex(nodeIndex);
var idx = retIndex + (--this._retainers[retIndex]);
this._retainers[idx] = node.nodeIndex + this._firstEdgeOffset + edge.edgeIndex;
}
}
},

_buildAggregates: function()
{
this._aggregates = {};
for (var iter = this._allNodes; iter.hasNext(); iter.next()) {
var node = iter.node;
var className = node.className;
var nameMatters = node.type === "object" || node.type === "native";
if (node.type !== "native" && node.selfSize === 0)
continue;
if (!(className in this._aggregates))
this._aggregates[className] = { count: 0, self: 0, maxRet: 0, type: node.type, name: nameMatters ? node.name : null, idxs: [] };
var clss = this._aggregates[className];
++clss.count;
clss.self += node.selfSize;
if (node.retainedSize > clss.maxRet)
clss.maxRet = node.retainedSize;
clss.idxs.push(node.nodeIndex);
}

for (var className in this._aggregates)
this._aggregates[className].idxs = this._aggregates[className].idxs.slice(0);
},

_sortAggregateIndexes: function()
{
var nodeA = new WebInspector.HeapSnapshotNode(this);
var nodeB = new WebInspector.HeapSnapshotNode(this);
for (var clss in this._aggregates)
this._aggregates[clss].idxs.sort(
function(idxA, idxB) {
nodeA.nodeIndex = idxA;
nodeB.nodeIndex = idxB;
return nodeA.id < nodeB.id ? -1 : 1;
});

this._aggregatesIndexesSorted = true;
},

_buildNodeIndex: function()
{
var count = 0;
for (var nodesIter = this._allNodes; nodesIter.hasNext(); nodesIter.next(), ++count);
this._nodeIndex = new Array(count + 1);
count = 0;
for (nodesIter = this._allNodes; nodesIter.hasNext(); nodesIter.next(), ++count)
this._nodeIndex[count] = nodesIter.index;
this._nodeIndex[count] = this._nodes.length;
},

_findNodePositionInIndex: function(index)
{
return binarySearch(index, this._nodeIndex, this._numbersComparator);
},

_findNearestNodeIndex: function(index)
{
var result = this._findNodePositionInIndex(index);
if (result < 0) {
result = -result - 1;
nodeIndex = this._nodeIndex[result];

if (nodeIndex > index)
nodeIndex = this._nodeIndex[result - 1];
} else
var nodeIndex = this._nodeIndex[result];
return nodeIndex;
},

_getRetainerIndex: function(nodeIndex)
{
var nodePosition = this._findNodePositionInIndex(nodeIndex);
return this._retainerIndex[nodePosition];
},

_markInvisibleEdges: function()
{



for (var iter = this.rootNode.edges; iter.hasNext(); iter.next()) {
var edge = iter.edge;
if (!edge.isShortcut)
continue;
var node = edge.node;
var propNames = {};
for (var innerIter = node.edges; innerIter.hasNext(); innerIter.next()) {
var globalObjEdge = innerIter.edge;
if (globalObjEdge.isShortcut)
propNames[globalObjEdge._nameOrIndex] = true;
}
for (innerIter.first(); innerIter.hasNext(); innerIter.next()) {
var globalObjEdge = innerIter.edge;
if (!globalObjEdge.isShortcut
&& globalObjEdge.node.isHidden
&& globalObjEdge._hasStringName
&& (globalObjEdge._nameOrIndex in propNames))
this._nodes[globalObjEdge._edges._start + globalObjEdge.edgeIndex + this._edgeTypeOffset] = this._edgeInvisibleType;
}
}
},

_numbersComparator: function(a, b)
{
return a < b ? -1 : (a > b ? 1 : 0);
},

baseSnapshotHasNode: function(baseSnapshotId, className, nodeId)
{
return this._baseNodeIds[baseSnapshotId][className].binaryIndexOf(nodeId, this._numbersComparator) !== -1;
},

pushBaseIds: function(baseSnapshotId, className, nodeIds)
{
if (!this._baseNodeIds)
this._baseNodeIds = [];
if (!this._baseNodeIds[baseSnapshotId])
this._baseNodeIds[baseSnapshotId] = {};
this._baseNodeIds[baseSnapshotId][className] = nodeIds;
},

createDiff: function(className)
{
return new WebInspector.HeapSnapshotsDiff(this, className);
},

_parseFilter: function(filter)
{
if (!filter)
return null;
var parsedFilter = eval("(function(){return " + filter + "})()");
return parsedFilter.bind(this);
},

createEdgesProvider: function(nodeIndex, filter)
{
return new WebInspector.HeapSnapshotEdgesProvider(this, nodeIndex, this._parseFilter(filter));
},

createNodesProvider: function(filter)
{
return new WebInspector.HeapSnapshotNodesProvider(this, this._parseFilter(filter));
},

createNodesProviderForClass: function(className)
{
return new WebInspector.HeapSnapshotNodesProvider(this, null, className);
},

createPathFinder: function(targetNodeIndex, skipHidden)
{
return new WebInspector.HeapSnapshotPathFinder(this, targetNodeIndex, skipHidden);
},

updateStaticData: function()
{
return {nodeCount: this.nodeCount, rootNodeIndex: this._rootNodeIndex, totalSize: this.totalSize, uid: this.uid};
}
};

WebInspector.HeapSnapshotFilteredOrderedIterator = function(iterator, filter, iterationOrder)
{
this._filter = filter;
this._iterator = iterator;
this._iterationOrder = iterationOrder ? iterationOrder.slice(0) : null;
this._position = 0;
this._lastComparator = null;
}

WebInspector.HeapSnapshotFilteredOrderedIterator.prototype = {
_createIterationOrder: function()
{
this._iterationOrder = [];
var iterator = this._iterator;
if (!this._filter) {
for (iterator.first(); iterator.hasNext(); iterator.next())
this._iterationOrder.push(iterator.index);
} else {
for (iterator.first(); iterator.hasNext(); iterator.next()) {
if (this._filter(iterator.item))
this._iterationOrder.push(iterator.index);
}
}
},

first: function()
{
this._position = 0;
},

hasNext: function()
{
return this._position < this._iterationOrder.length;
},

get isEmpty()
{
if (this._iterationOrder)
return !this._iterationOrder.length;
if (this._unfilteredIterationOrder && !this._filter)
return !this._unfilteredIterationOrder.length;
var iterator = this._iterator;
if (!this._unfilteredIterationOrder && !this._filter) {
iterator.first();
return !iterator.hasNext();
} else if (!this._unfilteredIterationOrder) {
for (iterator.first(); iterator.hasNext(); iterator.next())
if (this._filter(iterator.item))
return false;
} else {
var order = this._unfilteredIterationOrder.constructor === Array ?
this._unfilteredIterationOrder : this._unfilteredIterationOrder.slice(0);
for (var i = 0, l = order.length; i < l; ++i) {
iterator.index = order[i];
if (this._filter(iterator.item))
return false;
}
}
return true;
},

get item()
{
this._iterator.index = this._iterationOrder[this._position];
return this._iterator.item;
},

get length()
{
if (!this._iterationOrder)
this._createIterationOrder();
return this._iterationOrder.length;
},

next: function()
{
++this._position;
},

serializeNextItems: function(count)
{
var result = new Array(count);
for (var i = 0 ; i < count && this.hasNext(); ++i, this.next())
result[i] = this._serialize(this.item);
result.length = i;
result.hasNext = this.hasNext();
result.totalLength = this.length;
return result;
},

sortAndRewind: function(comparator)
{
var result = this.sort(comparator);
if (result)
this.first();
return result;
}
}

WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator = function(fieldNames)
{
return {fieldName1:fieldNames[0], ascending1:fieldNames[1], fieldName2:fieldNames[2], ascending2:fieldNames[3]};
}

WebInspector.HeapSnapshotEdgesProvider = function(snapshot, nodeIndex, filter)
{
this.snapshot = snapshot;
var node = new WebInspector.HeapSnapshotNode(snapshot, nodeIndex);
WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, new WebInspector.HeapSnapshotEdgeIterator(new WebInspector.HeapSnapshotEdge(snapshot, node.rawEdges)), filter);
}

WebInspector.HeapSnapshotEdgesProvider.prototype = {
_serialize: function(edge)
{
return {name: edge.name, node: WebInspector.HeapSnapshotNodesProvider.prototype._serialize(edge.node), nodeIndex: edge.nodeIndex, type: edge.type};
},

sort: function(comparator)
{
if (this._lastComparator === comparator)
return false;
this._lastComparator = comparator;
var fieldName1 = comparator.fieldName1;
var fieldName2 = comparator.fieldName2;
var ascending1 = comparator.ascending1;
var ascending2 = comparator.ascending2;

var edgeA = this._iterator.item.clone();
var edgeB = edgeA.clone();
var nodeA = new WebInspector.HeapSnapshotNode(this.snapshot);
var nodeB = new WebInspector.HeapSnapshotNode(this.snapshot);

function sortByEdgeFieldName(ascending, indexA, indexB)
{
edgeA.edgeIndex = indexA;
edgeB.edgeIndex = indexB;
if (edgeB.name === "__proto__") return -1;
if (edgeA.name === "__proto__") return 1;
var result =
edgeA.hasStringName === edgeB.hasStringName ?
(edgeA.name < edgeB.name ? -1 : (edgeA.name > edgeB.name ? 1 : 0)) :
(edgeA.hasStringName ? -1 : 1);
return ascending ? result : -result;
}

function sortByNodeField(fieldName, ascending, indexA, indexB)
{
edgeA.edgeIndex = indexA;
edgeB.edgeIndex = indexB;
nodeA.nodeIndex = edgeA.nodeIndex;
nodeB.nodeIndex = edgeB.nodeIndex;
var valueA = nodeA[fieldName];
var valueB = nodeB[fieldName];
var result = valueA < valueB ? -1 : (valueA > valueB ? 1 : 0);
return ascending ? result : -result;
}

if (!this._iterationOrder)
this._createIterationOrder();

function sortByEdgeAndNode(indexA, indexB) {
var result = sortByEdgeFieldName(ascending1, indexA, indexB);
if (result === 0)
result = sortByNodeField(fieldName2, ascending2, indexA, indexB);
return result;
}

function sortByNodeAndEdge(indexA, indexB) {
var result = sortByNodeField(fieldName1, ascending1, indexA, indexB);
if (result === 0)
result = sortByEdgeFieldName(ascending2, indexA, indexB);
return result;
}

function sortByNodeAndNode(indexA, indexB) {
var result = sortByNodeField(fieldName1, ascending1, indexA, indexB);
if (result === 0)
result = sortByNodeField(fieldName2, ascending2, indexA, indexB);
return result;
}

if (fieldName1 === "!edgeName")
this._iterationOrder.sort(sortByEdgeAndNode);
else if (fieldName2 === "!edgeName")
this._iterationOrder.sort(sortByNodeAndEdge);
else
this._iterationOrder.sort(sortByNodeAndNode);
return true;
}
};

WebInspector.HeapSnapshotEdgesProvider.prototype.__proto__ = WebInspector.HeapSnapshotFilteredOrderedIterator.prototype;

WebInspector.HeapSnapshotNodesProvider = function(snapshot, filter, className)
{
this.snapshot = snapshot;
if (!className)
WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, snapshot._allNodes, filter);
else
WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, snapshot._allNodes, null, snapshot.aggregates(false)[className].idxs);
}

WebInspector.HeapSnapshotNodesProvider.prototype = {
_serialize: function(node)
{
return {id: node.id, name: node.name, nodeIndex: node.nodeIndex, retainedSize: node.retainedSize, selfSize: node.selfSize, type: node.type};
},

sort: function(comparator)
{
if (this._lastComparator === comparator)
return false;
this._lastComparator = comparator;
var fieldName1 = comparator.fieldName1;
var fieldName2 = comparator.fieldName2;
var ascending1 = comparator.ascending1;
var ascending2 = comparator.ascending2;

var nodeA = new WebInspector.HeapSnapshotNode(this.snapshot);
var nodeB = new WebInspector.HeapSnapshotNode(this.snapshot);

function sortByNodeField(fieldName, ascending, indexA, indexB)
{
nodeA.nodeIndex = indexA;
nodeB.nodeIndex = indexB;
var valueA = nodeA[fieldName];
var valueB = nodeB[fieldName];
var result = valueA < valueB ? -1 : (valueA > valueB ? 1 : 0);
return ascending ? result : -result;
}

if (!this._iterationOrder)
this._createIterationOrder();

function sortByComparator(indexA, indexB) {
var result = sortByNodeField(fieldName1, ascending1, indexA, indexB);
if (result === 0)
result = sortByNodeField(fieldName2, ascending2, indexA, indexB);
return result;
}

this._iterationOrder.sort(sortByComparator);
return true;
}
};

WebInspector.HeapSnapshotNodesProvider.prototype.__proto__ = WebInspector.HeapSnapshotFilteredOrderedIterator.prototype;

WebInspector.HeapSnapshotPathFinder = function(snapshot, targetNodeIndex, skipHidden)
{
this._snapshot = snapshot;
this._maxLength = 1;
this._lengthLimit = 15;
this._targetNodeIndex = targetNodeIndex;
this._currentPath = null;
this._skipHidden = skipHidden;
this._rootChildren = this._fillRootChildren();
}

WebInspector.HeapSnapshotPathFinder.prototype = {
findNext: function()
{
for (var i = 0; i < 100000; ++i) {
if (!this._buildNextPath()) {
if (++this._maxLength >= this._lengthLimit)
return null;
this._currentPath = null;
if (!this._buildNextPath())
return null;
}
if (this._isPathFound())
return {path:this._pathToString(this._currentPath), route:this._pathToRoute(this._currentPath), len:this._currentPath.length};
}

return false;
},

updateRoots: function(filter)
{
if (filter)
filter = eval("(function(){return " + filter + "})()");
this._rootChildren = this._fillRootChildren(filter);  
this._reset();
},

_reset: function()
{
this._maxLength = 1;
this._currentPath = null;
},

_fillRootChildren: function(filter)
{
var result = [];
for (var iter = this._snapshot.rootNode.edges; iter.hasNext(); iter.next()) {
if (!filter || filter(iter.edge.node))
result[iter.edge.nodeIndex] = true;
}
return result;
},

_appendToCurrentPath: function(iter)
{
this._currentPath._cache[this._lastEdge.nodeIndex] = true;
this._currentPath.push(iter);
},

_removeLastFromCurrentPath: function()
{
this._currentPath.pop();
delete this._currentPath._cache[this._lastEdge.nodeIndex];
},

_hasInPath: function(nodeIndex)
{
return this._targetNodeIndex === nodeIndex
|| !!this._currentPath._cache[nodeIndex];
},

_isPathFound: function()
{
return this._currentPath.length === this._maxLength
&& this._lastEdge.nodeIndex in this._rootChildren;
},

get _lastEdgeIter()
{
return this._currentPath[this._currentPath.length - 1];
},

get _lastEdge()
{
return this._lastEdgeIter.item;
},

_skipEdge: function(edge)
{
return edge.isInvisible
|| (this._skipHidden && (edge.isHidden || edge.node.isHidden))
|| this._hasInPath(edge.nodeIndex);
},

_nextEdgeIter: function()
{
var iter = this._lastEdgeIter;
while (iter.hasNext() && this._skipEdge(iter.item))
iter.next();
return iter;
},

_buildNextPath: function()
{
if (this._currentPath !== null) {
var iter = this._lastEdgeIter;
while (true) {
iter.next();
iter = this._nextEdgeIter();
if (iter.hasNext())
return true;
while (true) {
if (this._currentPath.length > 1) {
this._removeLastFromCurrentPath();
iter = this._lastEdgeIter;
iter.next();
iter = this._nextEdgeIter();
if (iter.hasNext()) {
while (this._currentPath.length < this._maxLength) {
iter = this._nextEdgeIter();
if (iter.hasNext())
this._appendToCurrentPath(iter.item.node.retainers);
else
return true;
}
return true;
}
} else
return false;
}
}
} else {
var node = new WebInspector.HeapSnapshotNode(this._snapshot, this._targetNodeIndex);
this._currentPath = [node.retainers];
this._currentPath._cache = {};
while (this._currentPath.length < this._maxLength) {
var iter = this._nextEdgeIter();
if (iter.hasNext())
this._appendToCurrentPath(iter.item.node.retainers);
else
break;
}
return true;
}
},

_nodeToString: function(node)
{
if (node.id === 1)
return node.name;
else
return node.name + "@" + node.id;
},

_pathToString: function(path)
{
if (!path)
return "";
var sPath = [];
for (var j = 0; j < path.length; ++j)
sPath.push(path[j].item.toString());
sPath.push(this._nodeToString(path[path.length - 1].item.node));
sPath.reverse();
return sPath.join("");
},

_pathToRoute: function(path)
{
if (!path)
return [];
var route = [];
route.push(this._targetNodeIndex);
for (var i = 0; i < path.length; ++i)
route.push(path[i].item.nodeIndex);
route.reverse();
return route;
}
};

WebInspector.HeapSnapshotsDiff = function(snapshot, className)
{
this._snapshot = snapshot;
this._className = className;
};

WebInspector.HeapSnapshotsDiff.prototype = {
calculate: function()
{
var aggregates = this._snapshot.aggregates(true)[this._className];
var indexes = aggregates ? aggregates.idxs : [];
var i = 0, l = this._baseIds.length;
var j = 0, m = indexes.length;
var diff = { addedCount: 0, removedCount: 0, addedSize: 0, removedSize: 0 };

var nodeB = new WebInspector.HeapSnapshotNode(this._snapshot, indexes[j]);
while (i < l && j < m) {
var nodeAId = this._baseIds[i];
if (nodeAId < nodeB.id) {
diff.removedCount++;
diff.removedSize += this._baseSelfSizes[i];
++i;
} else if (nodeAId > nodeB.id) {
diff.addedCount++;
diff.addedSize += nodeB.selfSize;
nodeB.nodeIndex = indexes[++j];                
} else {
++i;
nodeB.nodeIndex = indexes[++j];                
}
}
while (i < l) {
diff.removedCount++;
diff.removedSize += this._baseSelfSizes[i];
++i;
}
while (j < m) {
diff.addedCount++;
diff.addedSize += nodeB.selfSize;
nodeB.nodeIndex = indexes[++j];
}
diff.countDelta = diff.addedCount - diff.removedCount;
diff.sizeDelta = diff.addedSize - diff.removedSize;
return diff;
},

pushBaseIds: function(baseIds)
{
this._baseIds = baseIds;
},

pushBaseSelfSizes: function(baseSelfSizes)
{
this._baseSelfSizes = baseSelfSizes;
}
};





WebInspector.HeapSnapshotRealWorker = function()
{
this._worker = new Worker("HeapSnapshotWorker.js");
this._worker.addEventListener("message", this._messageReceived.bind(this), false);
}

WebInspector.HeapSnapshotRealWorker.prototype = {
_messageReceived: function(event)
{
this.dispatchEventToListeners("message", event.data);
},

postMessage: function(message)
{
this._worker.postMessage(message);
},

terminate: function()
{
this._worker.terminate();
}
};

WebInspector.HeapSnapshotRealWorker.prototype.__proto__ = WebInspector.Object.prototype;

WebInspector.HeapSnapshotFakeWorker = function()
{
this._dispatcher = new WebInspector.HeapSnapshotWorkerDispatcher(window, this._postMessageFromWorker.bind(this));
}

WebInspector.HeapSnapshotFakeWorker.prototype = {
postMessage: function(message)
{
function dispatch()
{
if (this._dispatcher)
this._dispatcher.dispatchMessage({data: message});
}
setTimeout(dispatch.bind(this), 0);
},

terminate: function()
{
this._dispatcher = null;
},

_postMessageFromWorker: function(message)
{
function send()
{
this.dispatchEventToListeners("message", message);
}
setTimeout(send.bind(this), 0);
}
};

WebInspector.HeapSnapshotFakeWorker.prototype.__proto__ = WebInspector.Object.prototype;

WebInspector.HeapSnapshotWorker = function()
{
this._nextObjectId = 1;
this._nextCallId = 1;
this._callbacks = [];

this._worker = typeof InspectorTest === "undefined" ? new WebInspector.HeapSnapshotRealWorker() : new WebInspector.HeapSnapshotFakeWorker();
this._worker.addEventListener("message", this._messageReceived.bind(this), false);
}

WebInspector.HeapSnapshotWorker.prototype = {
createObject: function(constructorName)
{
var proxyConstructorFunction = this._findFunction(constructorName + "Proxy");
var objectId = this._nextObjectId++;
var proxy = new proxyConstructorFunction(this, objectId);
this._postMessage({callId: this._nextCallId++, disposition: "create", objectId: objectId, methodName: constructorName});
return proxy;
},

dispose: function()
{
this._worker.terminate();
},

disposeObject: function(objectId)
{
this._postMessage({callId: this._nextCallId++, disposition: "dispose", objectId: objectId});
},

callGetter: function(callback, objectId, getterName)
{
var callId = this._nextCallId++;
this._callbacks[callId] = callback;
this._postMessage({callId: callId, disposition: "getter", objectId: objectId, methodName: getterName});
},

callFactoryMethod: function(callback, objectId, methodName, proxyConstructorName)
{
var callId = this._nextCallId++;
var methodArguments = Array.prototype.slice.call(arguments, 4);
var newObjectId = this._nextObjectId++;
var proxyConstructorFunction = this._findFunction(proxyConstructorName);
if (callback) {
function wrapCallback(remoteResult)
{
callback(remoteResult ? new proxyConstructorFunction(this, newObjectId) : null);
}
this._callbacks[callId] = wrapCallback.bind(this);
this._postMessage({callId: callId, disposition: "factory", objectId: objectId, methodName: methodName, methodArguments: methodArguments, newObjectId: newObjectId});
return null;
} else {
this._postMessage({callId: callId, disposition: "factory", objectId: objectId, methodName: methodName, methodArguments: methodArguments, newObjectId: newObjectId});
return new proxyConstructorFunction(this, newObjectId);
}
},

callMethod: function(callback, objectId, methodName)
{
var callId = this._nextCallId++;
var methodArguments = Array.prototype.slice.call(arguments, 3);
if (callback)
this._callbacks[callId] = callback;
this._postMessage({callId: callId, disposition: "method", objectId: objectId, methodName: methodName, methodArguments: methodArguments});
},

_findFunction: function(name)
{
var path = name.split(".");
var result = window;
for (var i = 0; i < path.length; ++i)
result = result[path[i]];
return result;
},

_messageReceived: function(event)
{
var data = event.data;
if (!this._callbacks[data.callId])
return;
var callback = this._callbacks[data.callId];
delete this._callbacks[data.callId];
callback(data.result);
},

_postMessage: function(message)
{
this._worker.postMessage(message);      
}
};

WebInspector.HeapSnapshotProxyObject = function(worker, objectId)
{
this._worker = worker;
this._objectId = objectId;
}

WebInspector.HeapSnapshotProxyObject.prototype = {
_callWorker: function(workerMethodName, args)
{
args.splice(1, 0, this._objectId);
return this._worker[workerMethodName].apply(this._worker, args);
},

dispose: function()
{
this._worker.disposeObject(this._objectId);
},

disposeWorker: function()
{
this._worker.dispose();
},

callFactoryMethod: function(callback, methodName, proxyConstructorName)
{
return this._callWorker("callFactoryMethod", Array.prototype.slice.call(arguments, 0));
},

callGetter: function(callback, getterName)
{
return this._callWorker("callGetter", Array.prototype.slice.call(arguments, 0));
},

callMethod: function(callback, methodName)
{
return this._callWorker("callMethod", Array.prototype.slice.call(arguments, 0));
}
};

WebInspector.HeapSnapshotLoaderProxy = function(worker, objectId)
{
WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId);
this._loading = false;
this._loaded = false;
}

WebInspector.HeapSnapshotLoaderProxy.prototype = {
finishLoading: function(callback)
{
if (!this._loading)
return false;
var loadCallbacks = this._onLoadCallbacks;
loadCallbacks.splice(0, 0, callback);
delete this._onLoadCallbacks;
this._loading = false;
this._loaded = true;
function callLoadCallbacks(snapshotProxy)
{
for (var i = 0; i < loadCallbacks.length; ++i)
loadCallbacks[i](snapshotProxy);
}
function updateStaticData(snapshotProxy)
{
this.dispose();
snapshotProxy.updateStaticData(callLoadCallbacks);
}
this.callFactoryMethod(updateStaticData.bind(this), "finishLoading", "WebInspector.HeapSnapshotProxy");
return true;
},

get loaded()
{
return this._loaded;
},

startLoading: function(callback)
{
if (!this._loading) {
this._onLoadCallbacks = [callback];
this._loading = true;
return true;
} else {
this._onLoadCallbacks.push(callback);
return false;
}
},

pushJSONChunk: function(chunk)
{
if (!this._loading)
return;
this.callMethod(null, "pushJSONChunk", chunk);
}
};

WebInspector.HeapSnapshotLoaderProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype;

WebInspector.HeapSnapshotProxy = function(worker, objectId)
{
WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId);
}

WebInspector.HeapSnapshotProxy.prototype = {
aggregates: function(sortedIndexes, callback)
{
this.callMethod(callback, "aggregates", sortedIndexes);
},

createDiff: function(className)
{
return this.callFactoryMethod(null, "createDiff",  "WebInspector.HeapSnapshotsDiffProxy", className);
},

createEdgesProvider: function(nodeIndex, filter)
{
return this.callFactoryMethod(null, "createEdgesProvider", "WebInspector.HeapSnapshotProviderProxy", nodeIndex, filter);
},

createNodesProvider: function(filter)
{
return this.callFactoryMethod(null, "createNodesProvider", "WebInspector.HeapSnapshotProviderProxy", filter);
},

createNodesProviderForClass: function(className)
{
return this.callFactoryMethod(null, "createNodesProviderForClass", "WebInspector.HeapSnapshotProviderProxy", className);
},

createPathFinder: function(targetNodeIndex)
{
return this.callFactoryMethod(null, "createPathFinder", "WebInspector.HeapSnapshotPathFinderProxy", targetNodeIndex);
},

dispose: function()
{
this.disposeWorker();
},

finishLoading: function()
{
return false;
},

get loaded()
{
return !!this._objectId;
},

get nodeCount()
{
return this._staticData.nodeCount;
},

nodeFieldValuesByIndex: function(fieldName, indexes, callback)
{
this.callMethod(callback, "nodeFieldValuesByIndex", fieldName, indexes);
},

pushBaseIds: function(snapshotId, className, nodeIds)
{
this.callMethod(null, "pushBaseIds", snapshotId, className, nodeIds);
},

get rootNodeIndex()
{
return this._staticData.rootNodeIndex;
},

updateStaticData: function(callback)
{
function dataReceived(staticData)
{
this._staticData = staticData;
callback(this);
}
this.callMethod(dataReceived.bind(this), "updateStaticData");
},

startLoading: function(callback)
{
setTimeout(callback, 0);
return false;
},

get totalSize()
{
return this._staticData.totalSize;
},

get uid()
{
return this._staticData.uid;
}
};

WebInspector.HeapSnapshotProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype;

WebInspector.HeapSnapshotProviderProxy = function(worker, objectId)
{
WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId);
}

WebInspector.HeapSnapshotProviderProxy.prototype = {
isEmpty: function(callback)
{
this.callGetter(callback, "isEmpty");
},

serializeNextItems: function(count, callback)
{
this.callMethod(callback, "serializeNextItems", count);
},

sortAndRewind: function(comparator, callback)
{
this.callMethod(callback, "sortAndRewind", comparator);
}
};

WebInspector.HeapSnapshotProviderProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype;

WebInspector.HeapSnapshotPathFinderProxy = function(worker, objectId)
{
WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId);
}

WebInspector.HeapSnapshotPathFinderProxy.prototype = {
findNext: function(callback)
{
this.callMethod(callback, "findNext");
},

updateRoots: function(filter)
{
this.callMethod(null, "updateRoots", filter);
}
};

WebInspector.HeapSnapshotPathFinderProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype;

WebInspector.HeapSnapshotsDiffProxy = function(worker, objectId)
{
WebInspector.HeapSnapshotProxyObject.call(this, worker, objectId);
}

WebInspector.HeapSnapshotsDiffProxy.prototype = {
calculate: function(callback)
{
this.callMethod(callback, "calculate");
},

pushBaseIds: function(baseIds)
{
this.callMethod(null, "pushBaseIds", baseIds);
},

pushBaseSelfSizes: function(baseSelfSizes)
{
this.callMethod(null, "pushBaseSelfSizes", baseSelfSizes);
}
};

WebInspector.HeapSnapshotsDiffProxy.prototype.__proto__ = WebInspector.HeapSnapshotProxyObject.prototype;





WebInspector.HeapSnapshotView = function(parent, profile)
{
WebInspector.View.call(this);

this.element.addStyleClass("heap-snapshot-view");

this.parent = parent;
this.parent.addEventListener("profile added", this._updateBaseOptions, this);

this.showCountAsPercent = false;
this.showSizeAsPercent = false;
this.showCountDeltaAsPercent = false;
this.showSizeDeltaAsPercent = false;

this.categories = {
code: new WebInspector.ResourceCategory("code", WebInspector.UIString("Code"), "rgb(255,121,0)"),
data: new WebInspector.ResourceCategory("data", WebInspector.UIString("Objects"), "rgb(47,102,236)")
};

var summaryContainer = document.createElement("div");
summaryContainer.id = "heap-snapshot-summary-container";

this.countsSummaryBar = new WebInspector.SummaryBar(this.categories);
this.countsSummaryBar.element.className = "heap-snapshot-summary";
this.countsSummaryBar.calculator = new WebInspector.HeapSummaryCountCalculator();
var countsLabel = document.createElement("div");
countsLabel.className = "heap-snapshot-summary-label";
countsLabel.textContent = WebInspector.UIString("Count");
this.countsSummaryBar.element.appendChild(countsLabel);
summaryContainer.appendChild(this.countsSummaryBar.element);

this.sizesSummaryBar = new WebInspector.SummaryBar(this.categories);
this.sizesSummaryBar.element.className = "heap-snapshot-summary";
this.sizesSummaryBar.calculator = new WebInspector.HeapSummarySizeCalculator();
var sizesLabel = document.createElement("label");
sizesLabel.className = "heap-snapshot-summary-label";
sizesLabel.textContent = WebInspector.UIString("Size");
this.sizesSummaryBar.element.appendChild(sizesLabel);
summaryContainer.appendChild(this.sizesSummaryBar.element);

this.element.appendChild(summaryContainer);

var columns = {
cons: { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true },
count: { title: WebInspector.UIString("Count"), width: "54px", sortable: true },
size: { title: WebInspector.UIString("Size"), width: "72px", sort: "descending", sortable: true },

countDelta: { title: WebInspector.UIString("\xb1 Count"), width: "72px", sortable: true },
sizeDelta: { title: WebInspector.UIString("\xb1 Size"), width: "72px", sortable: true }
};

this.dataGrid = new WebInspector.DataGrid(columns);
this.dataGrid.addEventListener("sorting changed", this._sortData, this);
this.dataGrid.element.addEventListener("mousedown", this._mouseDownInDataGrid.bind(this), true);
this.element.appendChild(this.dataGrid.element);

this.profile = profile;

this.baseSelectElement = document.createElement("select");
this.baseSelectElement.className = "status-bar-item";
this.baseSelectElement.addEventListener("change", this._changeBase.bind(this), false);
this._updateBaseOptions();

this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item status-bar-item");
this.percentButton.addEventListener("click", this._percentClicked.bind(this), false);

this._loadProfile(this.profile, profileCallback.bind(this));

function profileCallback(profile)
{
var list = this._profiles();
var profileIndex;
for (var i = 0; i < list.length; ++i)
if (list[i].uid === profile.uid) {
profileIndex = i;
break;
}
if (profileIndex > 0)
this.baseSelectElement.selectedIndex = profileIndex - 1;
else
this.baseSelectElement.selectedIndex = profileIndex;
this._resetDataGridList(resetCompleted.bind(this));
}

function resetCompleted()
{
this.refresh();
this._updatePercentButton();
}
}

WebInspector.HeapSnapshotView.prototype = {
get statusBarItems()
{
return [this.baseSelectElement, this.percentButton.element];
},

get profile()
{
return this._profile;
},

set profile(profile)
{
this._profile = profile;
},

show: function(parentElement)
{
WebInspector.View.prototype.show.call(this, parentElement);
this.dataGrid.updateWidths();
},

hide: function()
{
WebInspector.View.prototype.hide.call(this);
this._currentSearchResultIndex = -1;
},

resize: function()
{
if (this.dataGrid)
this.dataGrid.updateWidths();
},

refresh: function()
{
this.dataGrid.removeChildren();

var children = this.snapshotDataGridList.children;
var count = children.length;
for (var index = 0; index < count; ++index)
this.dataGrid.appendChild(children[index]);

this._updateSummaryGraph();
},

refreshShowAsPercents: function()
{
this._updatePercentButton();
this.refreshVisibleData();
},

_deleteSearchMatchedFlags: function(node)
{
delete node._searchMatchedConsColumn;
delete node._searchMatchedCountColumn;
delete node._searchMatchedSizeColumn;
delete node._searchMatchedCountDeltaColumn;
delete node._searchMatchedSizeDeltaColumn;
},

searchCanceled: function()
{
if (this._searchResults) {
for (var i = 0; i < this._searchResults.length; ++i) {
var profileNode = this._searchResults[i].profileNode;
this._deleteSearchMatchedFlags(profileNode);
profileNode.refresh();
}
}

delete this._searchFinishedCallback;
this._currentSearchResultIndex = -1;
this._searchResults = [];
},

performSearch: function(query, finishedCallback)
{

this.searchCanceled();

query = query.trim();

if (!query.length)
return;

this._searchFinishedCallback = finishedCallback;

var helper = WebInspector.HeapSnapshotView.SearchHelper;

var operationAndNumber = helper.parseOperationAndNumber(query);
var operation = operationAndNumber[0];
var queryNumber = operationAndNumber[1];

var percentUnits = helper.percents.test(query);
var megaBytesUnits = helper.megaBytes.test(query);
var kiloBytesUnits = helper.kiloBytes.test(query);
var bytesUnits = helper.bytes.test(query);

var queryNumberBytes = (megaBytesUnits ? (queryNumber * 1024 * 1024) : (kiloBytesUnits ? (queryNumber * 1024) : queryNumber));

function matchesQuery(heapSnapshotDataGridNode)
{
WebInspector.HeapSnapshotView.prototype._deleteSearchMatchedFlags(heapSnapshotDataGridNode);

if (percentUnits) {
heapSnapshotDataGridNode._searchMatchedCountColumn = operation(heapSnapshotDataGridNode.countPercent, queryNumber);
heapSnapshotDataGridNode._searchMatchedSizeColumn = operation(heapSnapshotDataGridNode.sizePercent, queryNumber);
heapSnapshotDataGridNode._searchMatchedCountDeltaColumn = operation(heapSnapshotDataGridNode.countDeltaPercent, queryNumber);
heapSnapshotDataGridNode._searchMatchedSizeDeltaColumn = operation(heapSnapshotDataGridNode.sizeDeltaPercent, queryNumber);
} else if (megaBytesUnits || kiloBytesUnits || bytesUnits) {
heapSnapshotDataGridNode._searchMatchedSizeColumn = operation(heapSnapshotDataGridNode.size, queryNumberBytes);
heapSnapshotDataGridNode._searchMatchedSizeDeltaColumn = operation(heapSnapshotDataGridNode.sizeDelta, queryNumberBytes);
} else {
heapSnapshotDataGridNode._searchMatchedCountColumn = operation(heapSnapshotDataGridNode.count, queryNumber);
heapSnapshotDataGridNode._searchMatchedCountDeltaColumn = operation(heapSnapshotDataGridNode.countDelta, queryNumber);
}

if (heapSnapshotDataGridNode.constructorName.hasSubstring(query, true))
heapSnapshotDataGridNode._searchMatchedConsColumn = true;

if (heapSnapshotDataGridNode._searchMatchedConsColumn ||
heapSnapshotDataGridNode._searchMatchedCountColumn ||
heapSnapshotDataGridNode._searchMatchedSizeColumn ||
heapSnapshotDataGridNode._searchMatchedCountDeltaColumn ||
heapSnapshotDataGridNode._searchMatchedSizeDeltaColumn) {
heapSnapshotDataGridNode.refresh();
return true;
}

return false;
}

var current = this.snapshotDataGridList.children[0];
var depth = 0;
var info = {};




const maxDepth = 2;

while (current) {
if (matchesQuery(current))
this._searchResults.push({ profileNode: current });
current = current.traverseNextNode(false, null, (depth >= maxDepth), info);
depth += info.depthChange;
}

finishedCallback(this, this._searchResults.length);
},


jumpToFirstSearchResult: WebInspector.CPUProfileView.prototype.jumpToFirstSearchResult,
jumpToLastSearchResult: WebInspector.CPUProfileView.prototype.jumpToLastSearchResult,
jumpToNextSearchResult: WebInspector.CPUProfileView.prototype.jumpToNextSearchResult,
jumpToPreviousSearchResult: WebInspector.CPUProfileView.prototype.jumpToPreviousSearchResult,
showingFirstSearchResult: WebInspector.CPUProfileView.prototype.showingFirstSearchResult,
showingLastSearchResult: WebInspector.CPUProfileView.prototype.showingLastSearchResult,
_jumpToSearchResult: WebInspector.CPUProfileView.prototype._jumpToSearchResult,

refreshVisibleData: function()
{
var child = this.dataGrid.children[0];
while (child) {
child.refresh();
child = child.traverseNextNode(false, null, true);
}
this._updateSummaryGraph();
},

_changeBase: function()
{
if (this.baseSnapshot.uid === this._profiles()[this.baseSelectElement.selectedIndex].uid)
return;

this._resetDataGridList(resetCompleted.bind(this));

function resetCompleted() {
this.refresh();

if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults)
return;




this._searchFinishedCallback(this, -this._searchResults.length);
this.performSearch(this.currentQuery, this._searchFinishedCallback);
}
},

_createSnapshotDataGridList: function()
{
if (this._snapshotDataGridList)
delete this._snapshotDataGridList;

this._snapshotDataGridList = new WebInspector.HeapSnapshotDataGridList(this, this.baseSnapshot.entries, this.profile.entries);
return this._snapshotDataGridList;
},

_profiles: function()
{
return WebInspector.panels.profiles.getProfiles(WebInspector.HeapSnapshotProfileType.TypeId);
},

_loadProfile: function(profile, callback)
{
WebInspector.panels.profiles.loadHeapSnapshot(profile.uid, callback);
},

processLoadedSnapshot: function(profile, loadedSnapshot)
{
var snapshot = WebInspector.HeapSnapshotView.prototype._convertSnapshot(loadedSnapshot);
profile.children = snapshot.children;
profile.entries = snapshot.entries;
profile.lowlevels = snapshot.lowlevels;
WebInspector.HeapSnapshotView.prototype._prepareProfile(profile);
},

_mouseDownInDataGrid: function(event)
{
if (event.detail < 2)
return;

var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
if (!cell || (!cell.hasStyleClass("count-column") && !cell.hasStyleClass("size-column") && !cell.hasStyleClass("countDelta-column") && !cell.hasStyleClass("sizeDelta-column")))
return;

if (cell.hasStyleClass("count-column"))
this.showCountAsPercent = !this.showCountAsPercent;
else if (cell.hasStyleClass("size-column"))
this.showSizeAsPercent = !this.showSizeAsPercent;
else if (cell.hasStyleClass("countDelta-column"))
this.showCountDeltaAsPercent = !this.showCountDeltaAsPercent;
else if (cell.hasStyleClass("sizeDelta-column"))
this.showSizeDeltaAsPercent = !this.showSizeDeltaAsPercent;

this.refreshShowAsPercents();

event.preventDefault();
event.stopPropagation();
},

get _isShowingAsPercent()
{
return this.showCountAsPercent && this.showSizeAsPercent && this.showCountDeltaAsPercent && this.showSizeDeltaAsPercent;
},

_percentClicked: function(event)
{
var currentState = this._isShowingAsPercent;
this.showCountAsPercent = !currentState;
this.showSizeAsPercent = !currentState;
this.showCountDeltaAsPercent = !currentState;
this.showSizeDeltaAsPercent = !currentState;
this.refreshShowAsPercents();
},

_convertSnapshot: function(loadedSnapshot)
{
var snapshot = new WebInspector.HeapSnapshot(loadedSnapshot);
var result = {lowlevels: {}, entries: {}, children: {}};
var rootEdgesIter = snapshot.rootNode.edges;
for (var iter = rootEdgesIter; iter.hasNext(); iter.next()) {
var node = iter.edge.node;
if (node.isHidden)
result.lowlevels[node.name] = {count: node.instancesCount, size: node.selfSize, type: node.name};
else if (node.instancesCount)
result.entries[node.name] = {constructorName: node.name, count: node.instancesCount, size: node.selfSize};
else {
var entry = {constructorName: node.name};
for (var innerIter = node.edges; innerIter.hasNext(); innerIter.next()) {
var edge = innerIter.edge;
entry[edge.nodeIndex] = {constructorName: edge.node.name, count: edge.name};
}
result.children[rootEdgesIter.edge.nodeIndex] = entry;
}
}
return result;
},

_prepareProfile: function(profile)
{
for (var profileEntry in profile.entries)
profile.entries[profileEntry].retainers = {};
profile.clusters = {};

for (var addr in profile.children) {
var retainer = profile.children[addr];
var retainerId = retainer.constructorName + ":" + addr;
for (var childAddr in retainer) {
if (childAddr === "constructorName") continue;
var item = retainer[childAddr];
var itemId = item.constructorName + ":" + childAddr;
if ((item.constructorName === "Object" || item.constructorName === "Array")) {
if (!(itemId in profile.clusters))
profile.clusters[itemId] = { constructorName: itemId, retainers: {} };
mergeRetainers(profile.clusters[itemId], item);
}
mergeRetainers(profile.entries[item.constructorName], item);
}
}

function mergeRetainers(entry, item)
{
if (!(retainer.constructorName in entry.retainers))
entry.retainers[retainer.constructorName] = { constructorName: retainer.constructorName, count: 0, clusters: {} };
var retainerEntry = entry.retainers[retainer.constructorName];
retainerEntry.count += item.count;
if (retainer.constructorName === "Object" || retainer.constructorName === "Array")
retainerEntry.clusters[retainerId] = true;
}
},

_resetDataGridList: function(callback)
{
this._loadProfile(this._profiles()[this.baseSelectElement.selectedIndex], profileLoaded.bind(this));

function profileLoaded(profile)
{
this.baseSnapshot = profile;
var lastComparator = WebInspector.HeapSnapshotDataGridList.propertyComparator("size", false);
if (this.snapshotDataGridList)
lastComparator = this.snapshotDataGridList.lastComparator;
this.snapshotDataGridList = this._createSnapshotDataGridList();
this.snapshotDataGridList.sort(lastComparator, true);
callback();
}
},

_sortData: function()
{
var sortAscending = this.dataGrid.sortOrder === "ascending";
var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
var sortProperty = {
cons: ["constructorName", null],
count: ["count", "constructorName"],
size: ["size", "constructorName"],
countDelta: [this.showCountDeltaAsPercent ? "countDeltaPercent" : "countDelta", "constructorName"],
sizeDelta: [this.showSizeDeltaAsPercent ? "sizeDeltaPercent" : "sizeDelta", "constructorName"]
}[sortColumnIdentifier];

this.snapshotDataGridList.sort(WebInspector.HeapSnapshotDataGridList.propertyComparator(sortProperty[0], sortProperty[1], sortAscending));

this.refresh();
},

_updateBaseOptions: function()
{
var list = this._profiles();

if (this.baseSelectElement.length === list.length)
return;

for (var i = this.baseSelectElement.length, n = list.length; i < n; ++i) {
var baseOption = document.createElement("option");
var title = list[i].title;
if (!title.indexOf(UserInitiatedProfileName))
title = WebInspector.UIString("Snapshot %d", title.substring(UserInitiatedProfileName.length + 1));
baseOption.label = WebInspector.UIString("Compared to %s", title);
this.baseSelectElement.appendChild(baseOption);
}
},

_updatePercentButton: function()
{
if (this._isShowingAsPercent) {
this.percentButton.title = WebInspector.UIString("Show absolute counts and sizes.");
this.percentButton.toggled = true;
} else {
this.percentButton.title = WebInspector.UIString("Show counts and sizes as percentages.");
this.percentButton.toggled = false;
}
},

_updateSummaryGraph: function()
{
this.countsSummaryBar.calculator.showAsPercent = this._isShowingAsPercent;
this.countsSummaryBar.update(this.profile.lowlevels);

this.sizesSummaryBar.calculator.showAsPercent = this._isShowingAsPercent;
this.sizesSummaryBar.update(this.profile.lowlevels);
}
};

WebInspector.HeapSnapshotView.prototype.__proto__ = WebInspector.View.prototype;

WebInspector.HeapSnapshotView.SearchHelper = {

operations: {
LESS: function (a, b) { return a !== null && a < b; },
LESS_OR_EQUAL: function (a, b) { return a !== null && a <= b; },
EQUAL: function (a, b) { return a !== null && a === b; },
GREATER_OR_EQUAL: function (a, b) { return a !== null && a >= b; },
GREATER: function (a, b) { return a !== null && a > b; }
},

operationParsers: {
LESS: /^<(\d+)/,
LESS_OR_EQUAL: /^<=(\d+)/,
GREATER_OR_EQUAL: /^>=(\d+)/,
GREATER: /^>(\d+)/
},

parseOperationAndNumber: function(query)
{
var operations = WebInspector.HeapSnapshotView.SearchHelper.operations;
var parsers = WebInspector.HeapSnapshotView.SearchHelper.operationParsers;
for (var operation in parsers) {
var match = query.match(parsers[operation]);
if (match !== null)
return [operations[operation], parseFloat(match[1])];
}
return [operations.EQUAL, parseFloat(query)];
},

percents: /%$/,

megaBytes: /MB$/i,

kiloBytes: /KB$/i,

bytes: /B$/i
}

WebInspector.HeapSummaryCalculator = function(lowLevelField)
{
this.total = 1;
this.lowLevelField = lowLevelField;
}

WebInspector.HeapSummaryCalculator.prototype = {
computeSummaryValues: function(lowLevels)
{
var highLevels = { data: 0, code: 0 };
this.total = 0;
for (var item in lowLevels) {
var highItem = this._highFromLow(item);
if (highItem) {
var value = lowLevels[item][this.lowLevelField];
highLevels[highItem] += value;
this.total += value;
}
}
var result = { categoryValues: highLevels };
if (!this.showAsPercent)
result.total = this.total;
return result;
},

formatValue: function(value)
{
if (this.showAsPercent)
return WebInspector.UIString("%.2f%%", value / this.total * 100.0);
else
return this._valueToString(value);
},

get showAsPercent()
{
return this._showAsPercent;
},

set showAsPercent(x)
{
this._showAsPercent = x;
}
}

WebInspector.HeapSummaryCountCalculator = function()
{
WebInspector.HeapSummaryCalculator.call(this, "count");
}

WebInspector.HeapSummaryCountCalculator.prototype = {
_highFromLow: function(type)
{
if (type === "CODE_TYPE" || type === "SHARED_FUNCTION_INFO_TYPE" || type === "SCRIPT_TYPE") return "code";
if (type === "STRING_TYPE" || type === "HEAP_NUMBER_TYPE" || type.match(/^JS_/)) return "data";
return null;
},

_valueToString: function(value)
{
return value.toString();
}
}

WebInspector.HeapSummaryCountCalculator.prototype.__proto__ = WebInspector.HeapSummaryCalculator.prototype;

WebInspector.HeapSummarySizeCalculator = function()
{
WebInspector.HeapSummaryCalculator.call(this, "size");
}

WebInspector.HeapSummarySizeCalculator.prototype = {
_highFromLow: function(type)
{
if (type === "CODE_TYPE" || type === "SHARED_FUNCTION_INFO_TYPE" || type === "SCRIPT_TYPE")
return "code";
if (type === "STRING_TYPE" || type === "HEAP_NUMBER_TYPE" || type.match(/^JS_/) || type.match(/_ARRAY_TYPE$/))
return "data";
return null;
},

_valueToString: Number.bytesToString
}

WebInspector.HeapSummarySizeCalculator.prototype.__proto__ = WebInspector.HeapSummaryCalculator.prototype;

WebInspector.HeapSnapshotDataGridNodeWithRetainers = function(owningTree)
{
this.tree = owningTree;

WebInspector.DataGridNode.call(this, null, this._hasRetainers);

this.addEventListener("populate", this._populate, this);
};

WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype = {
isEmptySet: function(set)
{
for (var x in set)
return false;
return true;
},

get _hasRetainers()
{
return !this.isEmptySet(this.retainers);
},

get _parent()
{

return this.parent !== this.dataGrid ? this.parent : this.tree;
},

_populate: function(event)
{
function appendDiffEntry(baseItem, snapshotItem)
{
this.appendChild(new WebInspector.HeapSnapshotDataGridRetainerNode(this.snapshotView, baseItem, snapshotItem, this.tree));
}

this.produceDiff(this.baseRetainers, this.retainers, appendDiffEntry.bind(this));

if (this._parent) {
var currentComparator = this._parent.lastComparator;
if (currentComparator)
this.sort(currentComparator, true);
}

this.removeEventListener("populate", this._populate, this);
},

produceDiff: function(baseEntries, currentEntries, callback)
{
for (var item in currentEntries)
callback(baseEntries[item], currentEntries[item]);

for (item in baseEntries) {
if (!(item in currentEntries))
callback(baseEntries[item], null);
}
},

sort: function(comparator, force) {
if (!force && this.lastComparator === comparator)
return;

this.children.sort(comparator);
var childCount = this.children.length;
for (var childIndex = 0; childIndex < childCount; ++childIndex)
this.children[childIndex]._recalculateSiblings(childIndex);
for (var i = 0; i < this.children.length; ++i) {
var child = this.children[i];
if (!force && (!child.expanded || child.lastComparator === comparator))
continue;
child.sort(comparator, force);
}
this.lastComparator = comparator;
},

signForDelta: function(delta) {
if (delta === 0)
return "";
if (delta > 0)
return "+";
else
return "\u2212";  
},

showDeltaAsPercent: function(value)
{
if (value === Number.POSITIVE_INFINITY)
return WebInspector.UIString("new");
else if (value === Number.NEGATIVE_INFINITY)
return WebInspector.UIString("deleted");
if (value > 1000.0)
return WebInspector.UIString("%s >1000%%", this.signForDelta(value));
return WebInspector.UIString("%s%.2f%%", this.signForDelta(value), Math.abs(value));
},

getTotalCount: function()
{
if (!this._count) {
this._count = 0;
for (var i = 0, n = this.children.length; i < n; ++i)
this._count += this.children[i].count;
}
return this._count;
},

getTotalSize: function()
{
if (!this._size) {
this._size = 0;
for (var i = 0, n = this.children.length; i < n; ++i)
this._size += this.children[i].size;
}
return this._size;
},

get countPercent()
{
return this.count / this._parent.getTotalCount() * 100.0;
},

get sizePercent()
{
return this.size / this._parent.getTotalSize() * 100.0;
},

get countDeltaPercent()
{
if (this.baseCount > 0) {
if (this.count > 0)
return this.countDelta / this.baseCount * 100.0;
else
return Number.NEGATIVE_INFINITY;
} else
return Number.POSITIVE_INFINITY;
},

get sizeDeltaPercent()
{
if (this.baseSize > 0) {
if (this.size > 0)
return this.sizeDelta / this.baseSize * 100.0;
else
return Number.NEGATIVE_INFINITY;
} else
return Number.POSITIVE_INFINITY;
},

get data()
{
var data = {};

data["cons"] = this.constructorName;

if (this.snapshotView.showCountAsPercent)
data["count"] = WebInspector.UIString("%.2f%%", this.countPercent);
else
data["count"] = this.count;

if (this.size !== null) {
if (this.snapshotView.showSizeAsPercent)
data["size"] = WebInspector.UIString("%.2f%%", this.sizePercent);
else
data["size"] = Number.bytesToString(this.size);
} else
data["size"] = "";

if (this.snapshotView.showCountDeltaAsPercent)
data["countDelta"] = this.showDeltaAsPercent(this.countDeltaPercent);
else
data["countDelta"] = WebInspector.UIString("%s%d", this.signForDelta(this.countDelta), Math.abs(this.countDelta));

if (this.sizeDelta !== null) {
if (this.snapshotView.showSizeDeltaAsPercent)
data["sizeDelta"] = this.showDeltaAsPercent(this.sizeDeltaPercent);
else
data["sizeDelta"] = WebInspector.UIString("%s%s", this.signForDelta(this.sizeDelta), Number.bytesToString(Math.abs(this.sizeDelta)));
} else
data["sizeDelta"] = "";

return data;
},

createCell: function(columnIdentifier)
{
var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);

if ((columnIdentifier === "cons" && this._searchMatchedConsColumn) ||
(columnIdentifier === "count" && this._searchMatchedCountColumn) ||
(columnIdentifier === "size" && this._searchMatchedSizeColumn) ||
(columnIdentifier === "countDelta" && this._searchMatchedCountDeltaColumn) ||
(columnIdentifier === "sizeDelta" && this._searchMatchedSizeDeltaColumn))
cell.addStyleClass("highlight");

return cell;
}
};

WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.__proto__ = WebInspector.DataGridNode.prototype;

WebInspector.HeapSnapshotDataGridNode = function(snapshotView, baseEntry, snapshotEntry, owningTree)
{
this.snapshotView = snapshotView;

if (!snapshotEntry)
snapshotEntry = { constructorName: baseEntry.constructorName, count: 0, size: 0, retainers: {} };
this.constructorName = snapshotEntry.constructorName;
this.count = snapshotEntry.count;
this.size = snapshotEntry.size;
this.retainers = snapshotEntry.retainers;

if (!baseEntry)
baseEntry = { count: 0, size: 0, retainers: {} };
this.baseCount = baseEntry.count;
this.countDelta = this.count - this.baseCount;
this.baseSize = baseEntry.size;
this.sizeDelta = this.size - this.baseSize;
this.baseRetainers = baseEntry.retainers;

WebInspector.HeapSnapshotDataGridNodeWithRetainers.call(this, owningTree);
};

WebInspector.HeapSnapshotDataGridNode.prototype.__proto__ = WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype;

WebInspector.HeapSnapshotDataGridList = function(snapshotView, baseEntries, snapshotEntries)
{
this.tree = this;
this.snapshotView = snapshotView;
this.children = [];
this.lastComparator = null;
this.populateChildren(baseEntries, snapshotEntries);
};

WebInspector.HeapSnapshotDataGridList.prototype = {
appendChild: function(child)
{
this.insertChild(child, this.children.length);
},

insertChild: function(child, index)
{
this.children.splice(index, 0, child);
},

removeChildren: function()
{
this.children = [];
},

populateChildren: function(baseEntries, snapshotEntries)
{
function appendListEntry(baseItem, snapshotItem)
{
this.appendChild(new WebInspector.HeapSnapshotDataGridNode(this.snapshotView, baseItem, snapshotItem, this));
}
this.produceDiff(baseEntries, snapshotEntries, appendListEntry.bind(this));
},

produceDiff: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.produceDiff,
sort: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.sort,
getTotalCount: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.getTotalCount,
getTotalSize: WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype.getTotalSize
};

WebInspector.HeapSnapshotDataGridList.propertyComparators = [{}, {}];

WebInspector.HeapSnapshotDataGridList.propertyComparator = function(property, property2, isAscending)
{
var propertyHash = property + "#" + property2;
var comparator = this.propertyComparators[(isAscending ? 1 : 0)][propertyHash];
if (!comparator) {
comparator = function(lhs, rhs) {
var l = lhs[property], r = rhs[property];
var result = 0;
if (l !== null && r !== null) {
result = l < r ? -1 : (l > r ? 1 : 0);
}
if (result !== 0 || property2 === null) {
return isAscending ? result : -result;
} else {
l = lhs[property2];
r = rhs[property2];
return l < r ? -1 : (l > r ? 1 : 0);
}
};
this.propertyComparators[(isAscending ? 1 : 0)][propertyHash] = comparator;
}
return comparator;
};

WebInspector.HeapSnapshotDataGridRetainerNode = function(snapshotView, baseEntry, snapshotEntry, owningTree)
{
this.snapshotView = snapshotView;

if (!snapshotEntry)
snapshotEntry = { constructorName: baseEntry.constructorName, count: 0, clusters: {} };
this.constructorName = snapshotEntry.constructorName;
this.count = snapshotEntry.count;
this.retainers = this._calculateRetainers(this.snapshotView.profile, snapshotEntry.clusters);

if (!baseEntry)
baseEntry = { count: 0, clusters: {} };
this.baseCount = baseEntry.count;
this.countDelta = this.count - this.baseCount;
this.baseRetainers = this._calculateRetainers(this.snapshotView.baseSnapshot, baseEntry.clusters);

this.size = null;
this.sizeDelta = null;

WebInspector.HeapSnapshotDataGridNodeWithRetainers.call(this, owningTree);
}

WebInspector.HeapSnapshotDataGridRetainerNode.prototype = {
get sizePercent()
{
return null;
},

get sizeDeltaPercent()
{
return null;
},

_calculateRetainers: function(snapshot, clusters)
{
var retainers = {};
if (this.isEmptySet(clusters)) {
if (this.constructorName in snapshot.entries)
return snapshot.entries[this.constructorName].retainers;
} else {











for (var clusterName in clusters) {
if (clusterName in snapshot.clusters) {
var clusterRetainers = snapshot.clusters[clusterName].retainers;
for (var clusterRetainer in clusterRetainers) {
var clusterRetainerEntry = clusterRetainers[clusterRetainer];
if (!(clusterRetainer in retainers))
retainers[clusterRetainer] = { constructorName: clusterRetainerEntry.constructorName, count: 0, clusters: {} };
retainers[clusterRetainer].count += clusterRetainerEntry.count;
for (var clusterRetainerCluster in clusterRetainerEntry.clusters)
retainers[clusterRetainer].clusters[clusterRetainerCluster] = true;
}
}
}
}
return retainers;
}
};

WebInspector.HeapSnapshotDataGridRetainerNode.prototype.__proto__ = WebInspector.HeapSnapshotDataGridNodeWithRetainers.prototype;


WebInspector.HeapSnapshotProfileType = function()
{
WebInspector.ProfileType.call(this, WebInspector.HeapSnapshotProfileType.TypeId, WebInspector.UIString("HEAP SNAPSHOTS"));
}

WebInspector.HeapSnapshotProfileType.TypeId = "HEAP";

WebInspector.HeapSnapshotProfileType.prototype = {
get buttonTooltip()
{
return WebInspector.UIString("Take heap snapshot.");
},

get buttonStyle()
{
return "heap-snapshot-status-bar-item status-bar-item";
},

buttonClicked: function()
{
ProfilerAgent.takeHeapSnapshot(false);
},

get welcomeMessage()
{
return WebInspector.UIString("Get a heap snapshot by pressing the %s button on the status bar.");
},

createSidebarTreeElementForProfile: function(profile)
{
return new WebInspector.ProfileSidebarTreeElement(profile, WebInspector.UIString("Snapshot %d"), "heap-snapshot-sidebar-tree-item");
},

createView: function(profile)
{
return new WebInspector.HeapSnapshotView(WebInspector.panels.profiles, profile);
}
}

WebInspector.HeapSnapshotProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype;





WebInspector.HeapSnapshotWorkerDispatcher = function(globalObject, postMessage)
{
this._objects = [];
this._global = globalObject;
this._postMessage = postMessage;
}

WebInspector.HeapSnapshotWorkerDispatcher.prototype = {
_findFunction: function(name)
{
var path = name.split(".");
var result = this._global;
for (var i = 0; i < path.length; ++i)
result = result[path[i]];
return result;
},

dispatchMessage: function(event)
{
var data = event.data;
switch (data.disposition) {
case "create": {
var constructorFunction = this._findFunction(data.methodName);
this._objects[data.objectId] = new constructorFunction();
this._postMessage({callId: data.callId});
break;
}
case "dispose": {
delete this._objects[data.objectId];
this._postMessage({callId: data.callId});
break;
}
case "getter": {
var object = this._objects[data.objectId];
var result = object[data.methodName];
this._postMessage({callId: data.callId, result: result});
break;
}
case "factory": {
var object = this._objects[data.objectId];
var result = object[data.methodName].apply(object, data.methodArguments);
if (result)
this._objects[data.newObjectId] = result;            
this._postMessage({callId: data.callId, result: !!result});
break;
}
case "method": {
var object = this._objects[data.objectId];
var result = object[data.methodName].apply(object, data.methodArguments);
this._postMessage({callId: data.callId, result: result});
break;
}
}
}
};





WebInspector.HeapSnapshotGridNode = function(tree, hasChildren)
{
WebInspector.DataGridNode.call(this, null, hasChildren);
this._defaultPopulateCount = tree._defaultPopulateCount;
this._provider = null;
this.addEventListener("populate", this._populate, this);
}

WebInspector.HeapSnapshotGridNode.prototype = {
createCell: function(columnIdentifier)
{
var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);
if (this._searchMatched)
cell.addStyleClass("highlight");
return cell;
},

dispose: function()
{
if (this._provider)
this._provider.dispose();
for (var node = this.children[0]; node; node = node.traverseNextNode(true, this, true))
if (node.dispose)
node.dispose();
},

hasHoverMessage: false,

hoverMessage: function(callback)
{
callback("");
},

_populate: function(event)
{
this.removeEventListener("populate", this._populate, this);
function sorted(ignored)
{
this.populateChildren();
}
WebInspector.PleaseWaitMessage.prototype.show(this.dataGrid.element);
this._provider.sortAndRewind(this.comparator(), sorted.bind(this));
},

populateChildren: function(provider, howMany, atIndex, afterPopulate, suppressNotifyAboutCompletion)
{
WebInspector.PleaseWaitMessage.prototype.show(this.dataGrid.element);
if (!howMany && provider) {
howMany = provider.instanceCount;
provider.instanceCount = 0;
}
provider = provider || this._provider;
if (!("instanceCount" in provider))
provider.instanceCount = 0;
howMany = howMany || this._defaultPopulateCount;
atIndex = atIndex || this.children.length;
var haveSavedChildren = !!this._savedChildren;
if (haveSavedChildren) {
haveSavedChildren = false;
for (var c in this._savedChildren) {
haveSavedChildren = true;
break;
}
}

function childrenRetrieved(items)
{
var hasNext = items.hasNext;
var length = items.totalLength;
for (var i = 0, l = items.length; i < l; ++i) {
var item = items[i];
if (haveSavedChildren) {
var hash = this._childHashForEntity(item);
if (hash in this._savedChildren) {
this.insertChild(this._savedChildren[hash], atIndex++);
continue;
}
}
this.insertChild(this._createChildNode(item, provider), atIndex++);
}
provider.instanceCount += items.length;

if (hasNext)
this.insertChild(new WebInspector.ShowMoreDataGridNode(this.populateChildren.bind(this, provider), this._defaultPopulateCount, length), atIndex++);
if (afterPopulate)
afterPopulate();
if (!suppressNotifyAboutCompletion) {
function notify()
{
this.dispatchEventToListeners("populate complete");
}
setTimeout(notify.bind(this), 0);
}
WebInspector.PleaseWaitMessage.prototype.hide();
}
function callSerialize()
{
provider.serializeNextItems(howMany, childrenRetrieved.bind(this));
}
setTimeout(callSerialize.bind(this), 0);
},

_saveChildren: function()
{
this._savedChildren = {};
for (var i = 0, childrenCount = this.children.length; i < childrenCount; ++i) {
var child = this.children[i];
if (child.expanded)
this._savedChildren[this._childHashForNode(child)] = child;
}
},

sort: function()
{
WebInspector.PleaseWaitMessage.prototype.showAndWaitFor(this.dataGrid.element, this.dataGrid, "sorting complete");
this.dataGrid.recursiveSortingEnter();
function afterSort(sorted)
{
if (!sorted) {
this.dataGrid.recursiveSortingLeave();
return;
}
this._saveChildren();
this.removeChildren();

function afterPopulate()
{
for (var i = 0, l = this.children.length; i < l; ++i) {
var child = this.children[i];
if (child.expanded)
child.sort();
}
this.dataGrid.recursiveSortingLeave();
}
this.populateChildren(this._provider, null, null, afterPopulate.bind(this));
}
this._provider.sortAndRewind(this.comparator(), afterSort.bind(this));
}
};

WebInspector.HeapSnapshotGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;

WebInspector.HeapSnapshotGenericObjectNode = function(tree, node)
{
WebInspector.HeapSnapshotGridNode.call(this, tree, false);
this._name = node.name;
this._type = node.type;
this._shallowSize = node.selfSize;
this._retainedSize = node.retainedSize;
this.snapshotNodeId = node.id;
this.snapshotNodeIndex = node.nodeIndex;
if (this._type === "string")
this.hasHoverMessage = true;
else if (this._type === "object" && this.isDOMWindow(this._name)) {
var url = [];
this._name = this.shortenWindowURL(this._name, false, url);
this._url = url[0];
this.hasHoverMessage = true;
}
};

WebInspector.HeapSnapshotGenericObjectNode.prototype = {
createCell: function(columnIdentifier)
{
var cell = columnIdentifier !== "object" ? WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier) : this._createObjectCell();
if (this._searchMatched)
cell.addStyleClass("highlight");
return cell;
},

_createObjectCell: function()
{
var cell = document.createElement("td");
cell.className = "object-column";
var div = document.createElement("div");
div.className = "source-code event-properties";
div.style.overflow = "hidden";
var data = this.data["object"];
if (this._prefixObjectCell)
this._prefixObjectCell(div, data);
var valueSpan = document.createElement("span");
valueSpan.className = "value console-formatted-" + data.valueStyle;
valueSpan.textContent = data.value;
div.appendChild(valueSpan);
cell.appendChild(div);
cell.addStyleClass("disclosure");
if (this.depth)
cell.style.setProperty("padding-left", (this.depth * this.dataGrid.indentWidth) + "px");
return cell;
},

get _countPercent()
{
return this._count / this.dataGrid.snapshot.nodeCount * 100.0;
},

get data()
{
var data = this._emptyData();

var value = this._name;
var valueStyle = "object";
switch (this._type) {
case "string":
value = "\"" + value + "\"";
valueStyle = "string";
break;
case "regexp":
value = "/" + value + "/";
valueStyle = "string";
break;
case "closure":
value = "function " + value + "()";
valueStyle = "function";
break;
case "number":
valueStyle = "number";
break;
case "hidden":
valueStyle = "null";
break;
case "array":
value += "[]";
break;
};
data["object"] = { valueStyle: valueStyle, value: value + " @" + this.snapshotNodeId };

var view = this.dataGrid.snapshotView;
data["shallowSize"] = view.showShallowSizeAsPercent ? WebInspector.UIString("%.2f%%", this._shallowSizePercent) : Number.bytesToString(this._shallowSize);
data["retainedSize"] = view.showRetainedSizeAsPercent ? WebInspector.UIString("%.2f%%", this._retainedSizePercent) : Number.bytesToString(this._retainedSize);

return this._enhanceData ? this._enhanceData(data) : data;
},

hoverMessage: function(callback)
{
if (this._type === "string")
callback("\"" + this._name + "\"", "console-formatted-string");
else if (this._url)
callback(this._url, "console-formatted-object");
},

get _retainedSizePercent()
{
return this._retainedSize / this.dataGrid.snapshot.totalSize * 100.0;
},

get _shallowSizePercent()
{
return this._shallowSize / this.dataGrid.snapshot.totalSize * 100.0;
},

_updateHasChildren: function()
{
function isEmptyCallback(isEmpty)
{
this.hasChildren = !isEmpty;
}
this._provider.isEmpty(isEmptyCallback.bind(this));
},

isDOMWindow: function(fullName)
{
return fullName.substr(0, 9) === "DOMWindow";
},

shortenWindowURL: function(fullName, hasObjectId, fullURLPtr)
{
var startPos = fullName.indexOf("/");
var endPos = hasObjectId ? fullName.indexOf("@") : fullName.length;
if (startPos !== -1 && endPos !== -1) {
var fullURL = fullName.substring(startPos + 1, endPos).trimLeft();
if (fullURLPtr)
fullURLPtr[0] = fullURL;
var url = fullURL.trimURL();
if (url.length > 40)
url = url.trimMiddle(40);
return fullName.substr(0, startPos + 2) + url + fullName.substr(endPos);
} else
return fullName;
}
}

WebInspector.HeapSnapshotGenericObjectNode.prototype.__proto__ = WebInspector.HeapSnapshotGridNode.prototype;

WebInspector.HeapSnapshotObjectNode = function(tree, isFromBaseSnapshot, edge)
{
WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, edge.node);
this._referenceName = edge.name;
this._referenceType = edge.type;
this._isFromBaseSnapshot = isFromBaseSnapshot;
this._provider = this._createProvider(!isFromBaseSnapshot ? tree.snapshot : tree.baseSnapshot, edge.nodeIndex);
this._updateHasChildren();
}

WebInspector.HeapSnapshotObjectNode.prototype = {
_createChildNode: function(item)
{
return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, this._isFromBaseSnapshot, item);
},

_createProvider: function(snapshot, nodeIndex)
{
var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData;
return snapshot.createEdgesProvider(
nodeIndex,
"function(edge) {" +
"    return !edge.isInvisible" +
"        && (" + showHiddenData + " || (!edge.isHidden && !edge.node.isHidden));" +
"}");
},

_childHashForEntity: function(edge)
{
return edge.type + "#" + edge.name;
},

_childHashForNode: function(childNode)
{
return childNode._referenceType + "#" + childNode._referenceName;
},

comparator: function()
{
var sortAscending = this.dataGrid.sortOrder === "ascending";
var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
var sortFields = {
object: ["!edgeName", sortAscending, "retainedSize", false],
count: ["!edgeName", true, "retainedSize", false],
shallowSize: ["selfSize", sortAscending, "!edgeName", true],
retainedSize: ["retainedSize", sortAscending, "!edgeName", true]
}[sortColumnIdentifier] || ["!edgeName", true, "retainedSize", false];
return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
},

_emptyData: function()
{
return {count:"", addedCount: "", removedCount: "", countDelta:"", addedSize: "", removedSize: "", sizeDelta: ""};
},

_enhanceData: function(data)
{
var name = this._referenceName;
if (name === "") name = "(empty)";
var nameClass = "name";
switch (this._referenceType) {
case "context":
nameClass = "console-formatted-number";
break;
case "internal":
case "hidden":
nameClass = "console-formatted-null";
break;
}
data["object"].nameClass = nameClass;
data["object"].name = name;
return data;
},

_prefixObjectCell: function(div, data)
{
var nameSpan = document.createElement("span");
nameSpan.className = data.nameClass;
nameSpan.textContent = data.name;
var separatorSpan = document.createElement("span");
separatorSpan.className = "separator";
separatorSpan.textContent = ": ";
div.appendChild(nameSpan);
div.appendChild(separatorSpan);
}
}

WebInspector.HeapSnapshotObjectNode.prototype.__proto__ = WebInspector.HeapSnapshotGenericObjectNode.prototype;

WebInspector.HeapSnapshotInstanceNode = function(tree, baseSnapshot, snapshot, node)
{
WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node);
this._isDeletedNode = !!baseSnapshot;
this._provider = this._createProvider(baseSnapshot || snapshot, node.nodeIndex);
this._updateHasChildren();
};

WebInspector.HeapSnapshotInstanceNode.prototype = {
_createChildNode: function(item)
{
return new WebInspector.HeapSnapshotObjectNode(this.dataGrid, this._isDeletedNode, item);
},

_createProvider: function(snapshot, nodeIndex)
{
var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData;
return snapshot.createEdgesProvider(
nodeIndex,
"function(edge) {" +
"    return !edge.isInvisible" +
"        && (" + showHiddenData + " || (!edge.isHidden && !edge.node.isHidden));" +
"}");
},

_childHashForEntity: function(edge)
{
return edge.type + "#" + edge.name;
},

_childHashForNode: function(childNode)
{
return childNode._referenceType + "#" + childNode._referenceName;
},

comparator: function()
{
var sortAscending = this.dataGrid.sortOrder === "ascending";
var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
var sortFields = {
object: ["!edgeName", sortAscending, "retainedSize", false],
count: ["!edgeName", true, "retainedSize", false],
addedSize: ["selfSize", sortAscending, "!edgeName", true],
removedSize: ["selfSize", sortAscending, "!edgeName", true],
shallowSize: ["selfSize", sortAscending, "!edgeName", true],
retainedSize: ["retainedSize", sortAscending, "!edgeName", true]
}[sortColumnIdentifier] || ["!edgeName", true, "retainedSize", false];
return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
},

_emptyData: function()
{
return {count:"", countDelta:"", sizeDelta: ""};
},

_enhanceData: function(data)
{
if (this._isDeletedNode) {
data["addedCount"] = "";
data["addedSize"] = "";
data["removedCount"] = "\u2022";
data["removedSize"] = Number.bytesToString(this._shallowSize);
} else {
data["addedCount"] = "\u2022";
data["addedSize"] = Number.bytesToString(this._shallowSize);
data["removedCount"] = "";
data["removedSize"] = "";
}
return data;
},

get isDeletedNode()
{
return this._isDeletedNode;
}
}

WebInspector.HeapSnapshotInstanceNode.prototype.__proto__ = WebInspector.HeapSnapshotGenericObjectNode.prototype;

WebInspector.HeapSnapshotConstructorNode = function(tree, className, aggregate)
{
WebInspector.HeapSnapshotGridNode.call(this, tree, aggregate.count > 0);
this._name = className;
this._count = aggregate.count;
this._shallowSize = aggregate.self;
this._retainedSize = aggregate.maxRet;
this._provider = this._createNodesProvider(tree.snapshot, className);
}

WebInspector.HeapSnapshotConstructorNode.prototype = {
_createChildNode: function(item)
{
return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, this.dataGrid.snapshot, item);
},

_createNodesProvider: function(snapshot, className)
{
return snapshot.createNodesProviderForClass(className);
},

comparator: function()
{
var sortAscending = this.dataGrid.sortOrder === "ascending";
var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
var sortFields = {
object: ["id", sortAscending, "retainedSize", false],
count: ["id", true, "retainedSize", false],
shallowSize: ["selfSize", sortAscending, "id", true],
retainedSize: ["retainedSize", sortAscending, "id", true]
}[sortColumnIdentifier];
return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
},

_childHashForEntity: function(node)
{
return node.id;
},

_childHashForNode: function(childNode)
{
return childNode.snapshotNodeId;
},

get data()
{
var data = {object: this._name, count: this._count};
var view = this.dataGrid.snapshotView;
data["count"] = view.showCountAsPercent ? WebInspector.UIString("%.2f%%", this._countPercent) : this._count;
data["shallowSize"] = view.showShallowSizeAsPercent ? WebInspector.UIString("%.2f%%", this._shallowSizePercent) : Number.bytesToString(this._shallowSize);
data["retainedSize"] = "> " + (view.showRetainedSizeAsPercent ? WebInspector.UIString("%.2f%%", this._retainedSizePercent) : Number.bytesToString(this._retainedSize));
return data;
},

get _countPercent()
{
return this._count / this.dataGrid.snapshot.nodeCount * 100.0;
},

get _retainedSizePercent()
{
return this._retainedSize / this.dataGrid.snapshot.totalSize * 100.0;
},

get _shallowSizePercent()
{
return this._shallowSize / this.dataGrid.snapshot.totalSize * 100.0;
}
};

WebInspector.HeapSnapshotConstructorNode.prototype.__proto__ = WebInspector.HeapSnapshotGridNode.prototype;

WebInspector.HeapSnapshotIteratorsTuple = function(it1, it2)
{
this._it1 = it1;
this._it2 = it2;
}

WebInspector.HeapSnapshotIteratorsTuple.prototype = {
dispose: function()
{
this._it1.dispose();
this._it2.dispose();
},

sortAndRewind: function(comparator, callback)
{
function afterSort(ignored)
{
this._it2.sortAndRewind(comparator, callback);
}
this._it1.sortAndRewind(comparator, afterSort.bind(this));
}
};

WebInspector.HeapSnapshotDiffNode = function(tree, className, baseAggregate, aggregate)
{
WebInspector.HeapSnapshotGridNode.call(this, tree, true);
this._name = className;
this._baseIndexes = baseAggregate ? baseAggregate.idxs : [];
this._indexes = aggregate ? aggregate.idxs : [];
this._provider = this._createNodesProvider(tree.baseSnapshot, tree.snapshot, aggregate ? aggregate.type : baseAggregate.type, className);
}

WebInspector.HeapSnapshotDiffNode.prototype = {
calculateDiff: function(dataGrid, callback)
{
var diff = dataGrid.snapshot.createDiff(this._name);

function diffCalculated(diffResult)
{
diff.dispose();
this._addedCount = diffResult.addedCount;
this._removedCount = diffResult.removedCount;
this._countDelta = diffResult.countDelta;
this._addedSize = diffResult.addedSize;
this._removedSize = diffResult.removedSize;
this._sizeDelta = diffResult.sizeDelta;
this._baseIndexes = null;
this._indexes = null;
callback(this._addedSize === 0 && this._removedSize === 0);
}
function baseSelfSizesReceived(baseSelfSizes)
{
diff.pushBaseSelfSizes(baseSelfSizes);
diff.calculate(diffCalculated.bind(this));
}
function baseIdsReceived(baseIds)
{
diff.pushBaseIds(baseIds);
dataGrid.snapshot.pushBaseIds(dataGrid.baseSnapshot.uid, this._name, baseIds);
dataGrid.baseSnapshot.nodeFieldValuesByIndex("selfSize", this._baseIndexes, baseSelfSizesReceived.bind(this));
}
function idsReceived(ids)
{
dataGrid.baseSnapshot.pushBaseIds(dataGrid.snapshot.uid, this._name, ids);
}
dataGrid.baseSnapshot.nodeFieldValuesByIndex("id", this._baseIndexes, baseIdsReceived.bind(this));
dataGrid.snapshot.nodeFieldValuesByIndex("id", this._indexes, idsReceived.bind(this));
},

_createChildNode: function(item, provider)
{
if (provider === this._provider._it1)
return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, provider.snapshot, item);
else
return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, provider.snapshot, null, item);
},

_createNodesProvider: function(baseSnapshot, snapshot, nodeType, nodeClassName)
{
var className = this._name;
return new WebInspector.HeapSnapshotIteratorsTuple(
createProvider(snapshot, baseSnapshot), createProvider(baseSnapshot, snapshot));

function createProvider(snapshot, otherSnapshot)
{
var otherSnapshotId = otherSnapshot.uid;
var provider = snapshot.createNodesProvider(
"function (node) {" +
"     return node.type === \"" + nodeType + "\" " +
(nodeClassName !== null ? "&& node.className === \"" + nodeClassName + "\"" : "") +
"         && !this.baseSnapshotHasNode(" + otherSnapshotId + ", \"" + className + "\", node.id);" +
"}");
provider.snapshot = snapshot;
return provider;
}
},

_childHashForEntity: function(node)
{
return node.id;
},

_childHashForNode: function(childNode)
{
return childNode.snapshotNodeId;
},

comparator: function()
{
var sortAscending = this.dataGrid.sortOrder === "ascending";
var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
var sortFields = {
object: ["id", sortAscending, "selfSize", false],
addedCount: ["selfSize", sortAscending, "id", true],
removedCount: ["selfSize", sortAscending, "id", true],
countDelta: ["selfSize", sortAscending, "id", true],
addedSize: ["selfSize", sortAscending, "id", true],
removedSize: ["selfSize", sortAscending, "id", true],
sizeDelta: ["selfSize", sortAscending, "id", true]
}[sortColumnIdentifier];
return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
},

populateChildren: function(provider, howMany, atIndex, afterPopulate)
{
if (!provider && !howMany) {
var firstProviderPopulated = function()
{
WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2, this._defaultPopulateCount, atIndex, afterPopulate);
};
WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1, this._defaultPopulateCount, atIndex, firstProviderPopulated.bind(this), true);
} else if (!howMany) {
var firstProviderPopulated = function()
{
WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it2, null, atIndex, afterPopulate);
};
WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, this._provider._it1, null, atIndex, firstProviderPopulated.bind(this), true);
} else
WebInspector.HeapSnapshotGridNode.prototype.populateChildren.call(this, provider, howMany, atIndex, afterPopulate);
},

_signForDelta: function(delta)
{
if (delta === 0)
return "";
if (delta > 0)
return "+";
else
return "\u2212";  
},

get data()
{
var data = {object: this._name};

data["addedCount"] = this._addedCount;
data["removedCount"] = this._removedCount;
data["countDelta"] = WebInspector.UIString("%s%d", this._signForDelta(this._countDelta), Math.abs(this._countDelta));
data["addedSize"] = Number.bytesToString(this._addedSize);
data["removedSize"] = Number.bytesToString(this._removedSize);
data["sizeDelta"] = WebInspector.UIString("%s%s", this._signForDelta(this._sizeDelta), Number.bytesToString(Math.abs(this._sizeDelta)));

return data;
}
};

WebInspector.HeapSnapshotDiffNode.prototype.__proto__ = WebInspector.HeapSnapshotGridNode.prototype;

WebInspector.HeapSnapshotDominatorObjectNode = function(tree, node)
{
WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node);
this._provider = this._createProvider(tree.snapshot, node.nodeIndex);
this._updateHasChildren();
};

WebInspector.HeapSnapshotDominatorObjectNode.prototype = {
_createChildNode: function(item)
{
return new WebInspector.HeapSnapshotDominatorObjectNode(this.dataGrid, item);
},

_createProvider: function(snapshot, nodeIndex)
{
var showHiddenData = WebInspector.DetailedHeapshotView.prototype.showHiddenData;
return snapshot.createNodesProvider(
"function (node) {" +
"     var dominatorIndex = node.dominatorIndex;" +
"     return dominatorIndex === " + nodeIndex + 
"         && dominatorIndex !== node.nodeIndex" +
"         && (" + showHiddenData + " || !node.isHidden);" +
"}");
},

_childHashForEntity: function(node)
{
return node.id;
},

_childHashForNode: function(childNode)
{
return childNode.snapshotNodeId;
},

comparator: function()
{
var sortAscending = this.dataGrid.sortOrder === "ascending";
var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;
var sortFields = {
object: ["id", sortAscending, "retainedSize", false],
shallowSize: ["selfSize", sortAscending, "id", true],
retainedSize: ["retainedSize", sortAscending, "id", true]
}[sortColumnIdentifier];
return WebInspector.HeapSnapshotFilteredOrderedIterator.prototype.createComparator(sortFields);
},

_emptyData: function()
{
return {};
}
};

WebInspector.HeapSnapshotDominatorObjectNode.prototype.__proto__ = WebInspector.HeapSnapshotGenericObjectNode.prototype;

function MixInSnapshotNodeFunctions(sourcePrototype, targetPrototype)
{
targetPrototype._childHashForEntity = sourcePrototype._childHashForEntity;
targetPrototype._childHashForNode = sourcePrototype._childHashForNode;
targetPrototype.comparator = sourcePrototype.comparator;
targetPrototype._createChildNode = sourcePrototype._createChildNode;
targetPrototype._createProvider = sourcePrototype._createProvider;
targetPrototype.dispose = sourcePrototype.dispose;
targetPrototype.populateChildren = sourcePrototype.populateChildren;
targetPrototype._saveChildren = sourcePrototype._saveChildren;
targetPrototype.sort = sourcePrototype.sort;
}





WebInspector.HeapSnapshotSortableDataGrid = function(columns)
{
WebInspector.DataGrid.call(this, columns);
this.addEventListener("sorting changed", this.sortingChanged, this);
}

WebInspector.HeapSnapshotSortableDataGrid.prototype = {
dispose: function()
{
for (var i = 0, l = this.children.length; i < l; ++i)
this.children[i].dispose();
},

resetSortingCache: function()
{
delete this._lastSortColumnIdentifier;
delete this._lastSortAscending;
},

sortingChanged: function()
{
var sortAscending = this.sortOrder === "ascending";
var sortColumnIdentifier = this.sortColumnIdentifier;
if (this._lastSortColumnIdentifier === sortColumnIdentifier && this._lastSortAscending === sortAscending)
return;
this._lastSortColumnIdentifier = sortColumnIdentifier;
this._lastSortAscending = sortAscending;
var sortFields = this._sortFields(sortColumnIdentifier, sortAscending);

function SortByTwoFields(nodeA, nodeB)
{
var field1 = nodeA[sortFields[0]];
var field2 = nodeB[sortFields[0]];
var result = field1 < field2 ? -1 : (field1 > field2 ? 1 : 0);
if (!sortFields[1])
result = -result;
if (result !== 0)
return result;
field1 = nodeA[sortFields[2]];
field2 = nodeB[sortFields[2]];
result = field1 < field2 ? -1 : (field1 > field2 ? 1 : 0);
if (!sortFields[3])
result = -result;
return result;
}

WebInspector.PleaseWaitMessage.prototype.showAndWaitFor(this.element, this, "sorting complete", sort.bind(this));
function sort()
{
this._performSorting(SortByTwoFields);
}
},

_performSorting: function(sortFunction)
{
this.recursiveSortingEnter();
var children = this.children;
this.removeChildren();
children.sort(sortFunction);
for (var i = 0, l = children.length; i < l; ++i) {
var child = children[i];
this.appendChild(child);
if (child.expanded)
child.sort();
}
this.recursiveSortingLeave();
},

recursiveSortingEnter: function()
{
if (!("_recursiveSortingDepth" in this))
this._recursiveSortingDepth = 1;
else
++this._recursiveSortingDepth;
},

recursiveSortingLeave: function()
{
if (!("_recursiveSortingDepth" in this))
return;
if (!--this._recursiveSortingDepth) {
delete this._recursiveSortingDepth;
this.dispatchEventToListeners("sorting complete");
}
}
};

WebInspector.HeapSnapshotSortableDataGrid.prototype.__proto__ = WebInspector.DataGrid.prototype;

WebInspector.HeapSnapshotContainmentDataGrid = function()
{
var columns = {
object: { title: WebInspector.UIString("Object"), disclosure: true, sortable: true, sort: "ascending" },
shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "90px", sortable: true },
retainedSize: { title: WebInspector.UIString("Retained Size"), width: "90px", sortable: true }
};
WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
}

WebInspector.HeapSnapshotContainmentDataGrid.prototype = {
_defaultPopulateCount: 100,

expandRoute: function(route)
{
function nextStep(parent, hopIndex)
{
if (hopIndex >= route.length) {
parent.element.scrollIntoViewIfNeeded(true);
parent.select();
return;
}
var nodeIndex = route[hopIndex];
for (var i = 0, l = parent.children.length; i < l; ++i) {
var child = parent.children[i];
if (child.snapshotNodeIndex === nodeIndex) {
if (child.expanded)
nextStep(child, hopIndex + 1);
else {
function afterExpand()
{
child.removeEventListener("populate complete", afterExpand, null);
var lastChild = child.children[child.children.length - 1];
if (!lastChild.showAll)
nextStep(child, hopIndex + 1);
else {
child.addEventListener("populate complete", afterExpand, null);
lastChild.showAll.click();
}
}
child.addEventListener("populate complete", afterExpand, null);
child.expand();
}
break;
}
}
}
nextStep(this, 0);
},

setDataSource: function(snapshotView, snapshot)
{
this.snapshotView = snapshotView;
this.snapshot = snapshot;
this.snapshotNodeIndex = this.snapshot.rootNodeIndex;
this._provider = this._createProvider(snapshot, this.snapshotNodeIndex);
this.sort();
},

sortingChanged: function()
{
this.sort();
}
};

MixInSnapshotNodeFunctions(WebInspector.HeapSnapshotObjectNode.prototype, WebInspector.HeapSnapshotContainmentDataGrid.prototype);
WebInspector.HeapSnapshotContainmentDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype;

WebInspector.HeapSnapshotConstructorsDataGrid = function()
{
var columns = {
object: { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true },
count: { title: WebInspector.UIString("#"), width: "45px", sortable: true },
shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "90px", sortable: true },
retainedSize: { title: WebInspector.UIString("Retained Size"), width: "90px", sort: "descending", sortable: true }
};
WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
}

WebInspector.HeapSnapshotConstructorsDataGrid.prototype = {
_defaultPopulateCount: 100,

_sortFields: function(sortColumn, sortAscending)
{
return {
object: ["_name", sortAscending, "_count", false],
count: ["_count", sortAscending, "_name", true],
shallowSize: ["_shallowSize", sortAscending, "_name", true],
retainedSize: ["_retainedSize", sortAscending, "_name", true]
}[sortColumn];
},

setDataSource: function(snapshotView, snapshot)
{
this.snapshotView = snapshotView;
this.snapshot = snapshot;
this.populateChildren();
},

populateChildren: function()
{
function aggregatesReceived(aggregates)
{
for (var constructor in aggregates)
this.appendChild(new WebInspector.HeapSnapshotConstructorNode(this, constructor, aggregates[constructor]));
this.sortingChanged();
}
this.snapshot.aggregates(false, aggregatesReceived.bind(this));
}
};

WebInspector.HeapSnapshotConstructorsDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype;

WebInspector.HeapSnapshotDiffDataGrid = function()
{
var columns = {
object: { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true },
addedCount: { title: WebInspector.UIString("# New"), width: "72px", sortable: true, sort: "descending" },
removedCount: { title: WebInspector.UIString("# Deleted"), width: "72px", sortable: true },

countDelta: { title: "\u0394", width: "40px", sortable: true },
addedSize: { title: WebInspector.UIString("Alloc. Size"), width: "72px", sortable: true },
removedSize: { title: WebInspector.UIString("Freed Size"), width: "72px", sortable: true },
sizeDelta: { title: "\u0394", width: "72px", sortable: true }
};
WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
}

WebInspector.HeapSnapshotDiffDataGrid.prototype = {
_defaultPopulateCount: 50,

_sortFields: function(sortColumn, sortAscending)
{
return {
object: ["_name", sortAscending, "_count", false],
addedCount: ["_addedCount", sortAscending, "_name", true],
removedCount: ["_removedCount", sortAscending, "_name", true],
countDelta: ["_countDelta", sortAscending, "_name", true],
addedSize: ["_addedSize", sortAscending, "_name", true],
removedSize: ["_removedSize", sortAscending, "_name", true],
sizeDelta: ["_sizeDelta", sortAscending, "_name", true]
}[sortColumn];
},

setDataSource: function(snapshotView, snapshot)
{
this.snapshotView = snapshotView;
this.snapshot = snapshot;
},

setBaseDataSource: function(baseSnapshot)
{
this.baseSnapshot = baseSnapshot;
this.dispose();
this.removeChildren();
this.resetSortingCache();
if (this.baseSnapshot === this.snapshot) {
this.dispatchEventToListeners("sorting complete");
return;
}
this.populateChildren();        
},

populateChildren: function()
{
function baseAggregatesReceived(baseClasses)
{
function aggregatesReceived(classes)
{
var nodeCount = 0;
var nodes = [];
for (var clss in baseClasses)
nodes.push(new WebInspector.HeapSnapshotDiffNode(this, clss, baseClasses[clss], classes[clss]));
for (clss in classes) {
if (!(clss in baseClasses))
nodes.push(new WebInspector.HeapSnapshotDiffNode(this, clss, null, classes[clss]));
}
nodeCount = nodes.length;
function addNodeIfNonZeroDiff(boundNode, zeroDiff)
{
if (!zeroDiff)
this.appendChild(boundNode);
if (!--nodeCount)
this.sortingChanged();
}
for (var i = 0, l = nodes.length; i < l; ++i) {
var node = nodes[i];
node.calculateDiff(this, addNodeIfNonZeroDiff.bind(this, node));
}
}
this.snapshot.aggregates(true, aggregatesReceived.bind(this));
}
this.baseSnapshot.aggregates(true, baseAggregatesReceived.bind(this));
}
};

WebInspector.HeapSnapshotDiffDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype;

WebInspector.HeapSnapshotDominatorsDataGrid = function()
{
var columns = {
object: { title: WebInspector.UIString("Object"), disclosure: true, sortable: true },
shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "90px", sortable: true },
retainedSize: { title: WebInspector.UIString("Retained Size"), width: "90px", sort: "descending", sortable: true }
};
WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
}

WebInspector.HeapSnapshotDominatorsDataGrid.prototype = {
_defaultPopulateCount: 25,

setDataSource: function(snapshotView, snapshot)
{
this.snapshotView = snapshotView;
this.snapshot = snapshot;
this.snapshotNodeIndex = this.snapshot.rootNodeIndex;
this._provider = this._createProvider(snapshot, this.snapshotNodeIndex);
this.sort();
},

sortingChanged: function()
{
this.sort();
}
};

MixInSnapshotNodeFunctions(WebInspector.HeapSnapshotDominatorObjectNode.prototype, WebInspector.HeapSnapshotDominatorsDataGrid.prototype);
WebInspector.HeapSnapshotDominatorsDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype;

WebInspector.HeapSnapshotRetainingPathsList = function()
{
var columns = {
path: { title: WebInspector.UIString("Retaining path"), sortable: true },
len: { title: WebInspector.UIString("Length"), width: "90px", sortable: true, sort: "ascending" }
};
WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
this._defaultPopulateCount = 100;
}

WebInspector.HeapSnapshotRetainingPathsList.prototype = {
dispose: function()
{
if (this.pathFinder)
this.pathFinder.dispose();
}, 

_sortFields: function(sortColumn, sortAscending)
{
return {
path: ["path", sortAscending, "len", true],
len: ["len", sortAscending, "path", true]
}[sortColumn];
},

_resetPaths: function()
{
this._setRootChildrenForFinder();
this.removeChildren();
this.resetSortingCache();
this._counter = 0;
this.showNext(this._defaultPopulateCount);
},

setDataSource: function(snapshotView, snapshot, nodeIndex, prefix)
{
this.snapshotView = snapshotView;
this._prefix = prefix;

if (this.pathFinder) {
this.searchCancelled();
this.pathFinder.dispose();
}
this.pathFinder = snapshot.createPathFinder(nodeIndex, !WebInspector.DetailedHeapshotView.prototype.showHiddenData);
this._resetPaths();
},

refresh: function()
{
delete this._cancel;
this._resetPaths();
},

reset: function()
{
delete this._cancel;
this.removeChildren();
this.resetSortingCache();
this._counter = 0;
this.appendChild(new WebInspector.DataGridNode({path:WebInspector.UIString("Click on an object to show retaining paths"), len:""}, false));
},

showNext: function(pathsCount)
{
WebInspector.PleaseWaitMessage.prototype.show(this.element, this.searchCancelled.bind(this, pathsCount));

function pathFound(result)
{
if (result === null) {
WebInspector.PleaseWaitMessage.prototype.hide();
if (!this.children.length)
this.appendChild(new WebInspector.DataGridNode({path:WebInspector.UIString("Can't find any paths."), len:""}, false));
return;
} else if (result !== false) {
if (WebInspector.HeapSnapshotGenericObjectNode.prototype.isDOMWindow(result.path))
result.path = WebInspector.HeapSnapshotGenericObjectNode.prototype.shortenWindowURL(result.path, true);
if (this._prefix)
result.path = this._prefix + result.path;
var node = new WebInspector.DataGridNode(result, false);
node.route = result.route;
this.appendChild(node);
++this._counter;
}
setTimeout(startSearching.bind(this), 0);
}

function startSearching()
{
if (this._cancel === this.pathFinder)
return;
delete this._cancel;
if (this._counter < pathsCount)
this.pathFinder.findNext(pathFound.bind(this));
else {
this.searchCancelled.call(this, pathsCount);
delete this._cancel;
}
}
startSearching.call(this);
},

searchCancelled: function(pathsCount)
{
WebInspector.PleaseWaitMessage.prototype.hide();
this._counter = 0;
this._cancel = this.pathFinder;
if (pathsCount) {
this.appendChild(new WebInspector.ShowMoreDataGridNode(this.showNext.bind(this), pathsCount));
this.resetSortingCache();
this.sortingChanged();
}
},

_setRootChildrenForFinder: function()
{
if (this.snapshotView.isTracingToWindowObjects)
this.pathFinder.updateRoots(
"function (node) { return node.name.substr(0, 9) === \"DOMWindow\"; }");
else
this.pathFinder.updateRoots();
},

_performSorting: function(sortFunction)
{
function DataExtractorWrapper(nodeA, nodeB)
{
return sortFunction(nodeA.data, nodeB.data);
}
this.recursiveSortingEnter();
this.sortNodes(DataExtractorWrapper);
this.recursiveSortingLeave();
}
};

WebInspector.HeapSnapshotRetainingPathsList.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype;

WebInspector.DetailedHeapshotView = function(parent, profile)
{
WebInspector.View.call(this);

this.element.addStyleClass("detailed-heapshot-view");

this.parent = parent;
this.parent.addEventListener("profile added", this._updateBaseOptions, this);

this.showCountAsPercent = false;
this.showShallowSizeAsPercent = false;
this.showRetainedSizeAsPercent = false;

this.viewsContainer = document.createElement("div");
this.viewsContainer.addStyleClass("views-container");
this.element.appendChild(this.viewsContainer);

this.containmentView = new WebInspector.View();
this.containmentView.element.addStyleClass("view");
this.containmentDataGrid = new WebInspector.HeapSnapshotContainmentDataGrid();
this.containmentDataGrid.element.addEventListener("click", this._mouseClickInContainmentGrid.bind(this), true);
this.containmentView.element.appendChild(this.containmentDataGrid.element);
this.viewsContainer.appendChild(this.containmentView.element);

this.constructorsView = new WebInspector.View();
this.constructorsView.element.addStyleClass("view");
this.constructorsDataGrid = new WebInspector.HeapSnapshotConstructorsDataGrid();
this.constructorsDataGrid.element.addEventListener("click", this._mouseClickInContainmentGrid.bind(this), true);
this.constructorsView.element.appendChild(this.constructorsDataGrid.element);
this.viewsContainer.appendChild(this.constructorsView.element);

this.diffView = new WebInspector.View();
this.diffView.element.addStyleClass("view");
this.diffDataGrid = new WebInspector.HeapSnapshotDiffDataGrid();
this.diffDataGrid.element.addEventListener("click", this._mouseClickInContainmentGrid.bind(this), true);
this.diffView.element.appendChild(this.diffDataGrid.element);
this.viewsContainer.appendChild(this.diffView.element);

this.dominatorView = new WebInspector.View();
this.dominatorView.element.addStyleClass("view");
this.dominatorDataGrid = new WebInspector.HeapSnapshotDominatorsDataGrid();
this.dominatorDataGrid.element.addEventListener("click", this._mouseClickInContainmentGrid.bind(this), true);
this.dominatorView.element.appendChild(this.dominatorDataGrid.element);
this.viewsContainer.appendChild(this.dominatorView.element);

this.retainmentViewHeader = document.createElement("div");
this.retainmentViewHeader.addStyleClass("retainers-view-header");
this.retainmentViewHeader.addEventListener("mousedown", this._startRetainersHeaderDragging.bind(this), true);
var retainingPathsTitleDiv = document.createElement("div");
retainingPathsTitleDiv.className = "title";
var retainingPathsTitle = document.createElement("span");
retainingPathsTitle.textContent = WebInspector.UIString("Paths from the selected object");
this.retainingPathsRoot = document.createElement("select");
this.retainingPathsRoot.className = "status-bar-item";
this.retainingPathsRoot.addEventListener("change", this._changeRetainingPathsRoot.bind(this), false);
var toGCRootsTraceOption = document.createElement("option");
toGCRootsTraceOption.label = WebInspector.UIString("to GC roots");
var toWindowObjectsTraceOption = document.createElement("option");
toWindowObjectsTraceOption.label = WebInspector.UIString("to window objects");
this.retainingPathsRoot.appendChild(toGCRootsTraceOption);
this.retainingPathsRoot.appendChild(toWindowObjectsTraceOption);
retainingPathsTitleDiv.appendChild(retainingPathsTitle);
retainingPathsTitleDiv.appendChild(this.retainingPathsRoot);
this.retainmentViewHeader.appendChild(retainingPathsTitleDiv);
this.element.appendChild(this.retainmentViewHeader);

this.retainmentView = new WebInspector.View();
this.retainmentView.element.addStyleClass("view");
this.retainmentView.element.addStyleClass("retaining-paths-view");
this.retainmentDataGrid = new WebInspector.HeapSnapshotRetainingPathsList();
this.retainmentDataGrid.element.addEventListener("click", this._mouseClickInRetainmentGrid.bind(this), true);
this.retainmentView.element.appendChild(this.retainmentDataGrid.element);
this.retainmentView.visible = true;
this.element.appendChild(this.retainmentView.element);
this.retainmentDataGrid.reset();

this.dataGrid = this.constructorsDataGrid;
this.currentView = this.constructorsView;

this.viewSelectElement = document.createElement("select");
this.viewSelectElement.className = "status-bar-item";
this.viewSelectElement.addEventListener("change", this._changeView.bind(this), false);

this.views = [{title: "Summary", view: this.constructorsView, grid: this.constructorsDataGrid},
{title: "Comparison", view: this.diffView, grid: this.diffDataGrid},
{title: "Containment", view: this.containmentView, grid: this.containmentDataGrid},
{title: "Dominators", view: this.dominatorView, grid: this.dominatorDataGrid}];
this.views.current = 0;
for (var i = 0; i < this.views.length; ++i) {
var view = this.views[i];
var option = document.createElement("option");
option.label = WebInspector.UIString(view.title);
this.viewSelectElement.appendChild(option);
}

this._profileUid = profile.uid;

this.baseSelectElement = document.createElement("select");
this.baseSelectElement.className = "status-bar-item hidden";
this.baseSelectElement.addEventListener("change", this._changeBase.bind(this), false);
this._updateBaseOptions();

this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item status-bar-item");
this.percentButton.addEventListener("click", this._percentClicked.bind(this), false);
this.helpButton = new WebInspector.StatusBarButton("", "heapshot-help-status-bar-item status-bar-item");
this.helpButton.addEventListener("click", this._helpClicked.bind(this), false);

var popoverHelper = new WebInspector.PopoverHelper(this.element, this._getHoverAnchor.bind(this), this._showStringContentPopup.bind(this));

this._loadProfile(this._profileUid, profileCallback.bind(this));

function profileCallback()
{
var list = this._profiles();
var profileIndex;
for (var i = 0; i < list.length; ++i)
if (list[i].uid === this._profileUid) {
profileIndex = i;
break;
}
if (profileIndex > 0)
this.baseSelectElement.selectedIndex = profileIndex - 1;
else
this.baseSelectElement.selectedIndex = profileIndex;
WebInspector.PleaseWaitMessage.prototype.showAndWaitFor(this.currentView.element, this.dataGrid, "sorting complete", setDataSource.bind(this));
}

function setDataSource()
{
this.dataGrid.setDataSource(this, this.profileWrapper); 
this._updatePercentButton();
}
}

WebInspector.DetailedHeapshotView.prototype = {
dispose: function()
{
this.profileWrapper.dispose();
if (this.baseProfile)
this.baseProfileWrapper.dispose();
this.containmentDataGrid.dispose();
this.constructorsDataGrid.dispose();
this.diffDataGrid.dispose();
this.dominatorDataGrid.dispose();
this.retainmentDataGrid.dispose();
},

get statusBarItems()
{
return [this.viewSelectElement, this.baseSelectElement, this.percentButton.element, this.helpButton.element];
},

get profile()
{
return this.parent.getProfile(WebInspector.HeapSnapshotProfileType.TypeId, this._profileUid);
},

get profileWrapper()
{
return this.profile.proxy;
},

get baseProfile()
{
return this.parent.getProfile(WebInspector.HeapSnapshotProfileType.TypeId, this._baseProfileUid);
},

get baseProfileWrapper()
{
return this.baseProfile.proxy;
},

show: function(parentElement)
{
WebInspector.View.prototype.show.call(this, parentElement);
if (!this.profileWrapper.loaded)
this._loadProfile(this._profileUid, profileCallback1.bind(this));
else
profileCallback1.call(this);

function profileCallback1() {
if (this.baseProfile && !this.baseProfileWrapper.loaded)
this._loadProfile(this._baseProfileUid, profileCallback2.bind(this));
else
profileCallback2.call(this);
}

function profileCallback2() {
this.currentView.show();
this.dataGrid.updateWidths();
}
},

hide: function()
{
WebInspector.View.prototype.hide.call(this);
this._currentSearchResultIndex = -1;
},

resize: function()
{
if (this.dataGrid)
this.dataGrid.updateWidths();

var height = this.retainmentView.element.clientHeight;
this._updateRetainmentViewHeight(height);
},

refreshShowAsPercents: function()
{
this._updatePercentButton();
this.refreshVisibleData();
},

searchCanceled: function()
{
if (this._searchResults) {
for (var i = 0; i < this._searchResults.length; ++i) {
var node = this._searchResults[i].node;
delete node._searchMatched;
node.refresh();
}
}

delete this._searchFinishedCallback;
this._currentSearchResultIndex = -1;
this._searchResults = [];
},

performSearch: function(query, finishedCallback)
{

this.searchCanceled();

query = query.trim();

if (!query.length)
return;
if (this.currentView !== this.constructorsView && this.currentView !== this.diffView)
return;

this._searchFinishedCallback = finishedCallback;

function matchesByName(gridNode) {
return ("name" in gridNode) && gridNode.name.hasSubstring(query, true);
}

function matchesById(gridNode) {
return ("snapshotNodeId" in gridNode) && gridNode.snapshotNodeId === query;
}

var matchPredicate;
if (query.charAt(0) !== "@")
matchPredicate = matchesByName;
else {
query = parseInt(query.substring(1), 10);
matchPredicate = matchesById;
}

function matchesQuery(gridNode)
{
delete gridNode._searchMatched;
if (matchPredicate(gridNode)) {
gridNode._searchMatched = true;
gridNode.refresh();
return true;
}
return false;
}

var current = this.dataGrid.children[0];
var depth = 0;
var info = {};


const maxDepth = 1;

while (current) {
if (matchesQuery(current))
this._searchResults.push({ node: current });
current = current.traverseNextNode(false, null, (depth >= maxDepth), info);
depth += info.depthChange;
}

finishedCallback(this, this._searchResults.length);
},

jumpToFirstSearchResult: function()
{
if (!this._searchResults || !this._searchResults.length)
return;
this._currentSearchResultIndex = 0;
this._jumpToSearchResult(this._currentSearchResultIndex);
},

jumpToLastSearchResult: function()
{
if (!this._searchResults || !this._searchResults.length)
return;
this._currentSearchResultIndex = (this._searchResults.length - 1);
this._jumpToSearchResult(this._currentSearchResultIndex);
},

jumpToNextSearchResult: function()
{
if (!this._searchResults || !this._searchResults.length)
return;
if (++this._currentSearchResultIndex >= this._searchResults.length)
this._currentSearchResultIndex = 0;
this._jumpToSearchResult(this._currentSearchResultIndex);
},

jumpToPreviousSearchResult: function()
{
if (!this._searchResults || !this._searchResults.length)
return;
if (--this._currentSearchResultIndex < 0)
this._currentSearchResultIndex = (this._searchResults.length - 1);
this._jumpToSearchResult(this._currentSearchResultIndex);
},

showingFirstSearchResult: function()
{
return (this._currentSearchResultIndex === 0);
},

showingLastSearchResult: function()
{
return (this._searchResults && this._currentSearchResultIndex === (this._searchResults.length - 1));
},

_jumpToSearchResult: function(index)
{
var searchResult = this._searchResults[index];
if (!searchResult)
return;

var node = searchResult.node;
node.reveal();
node.select();
},

refreshVisibleData: function()
{
var child = this.dataGrid.children[0];
while (child) {
child.refresh();
child = child.traverseNextNode(false, null, true);
}
},

_changeBase: function()
{
if (this._baseProfileUid === this._profiles()[this.baseSelectElement.selectedIndex].uid)
return;

this._baseProfileUid = this._profiles()[this.baseSelectElement.selectedIndex].uid;
this._loadProfile(this._baseProfileUid, baseProfileLoaded.bind(this));

function baseProfileLoaded()
{
delete this._baseProfileWrapper;
this.baseProfile._lastShown = Date.now();
WebInspector.PleaseWaitMessage.prototype.showAndWaitFor(this.currentView.element, this.diffDataGrid, "sorting complete", setDataSource.bind(this));
}

function setDataSource()
{
this.diffDataGrid.setBaseDataSource(this.baseProfileWrapper);
}

if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults)
return;




this._searchFinishedCallback(this, -this._searchResults.length);
this.performSearch(this.currentQuery, this._searchFinishedCallback);
},

_profiles: function()
{
return WebInspector.panels.profiles.getProfiles(WebInspector.HeapSnapshotProfileType.TypeId);
},

_loadProfile: function(profileUid, callback)
{
WebInspector.panels.profiles.loadHeapSnapshot(profileUid, callback);
},

isDetailedSnapshot: function(snapshot)
{
var s = new WebInspector.HeapSnapshot(snapshot);
for (var iter = s.rootNode.edges; iter.hasNext(); iter.next())
if (iter.edge.node.name === "(GC roots)")
return true;
return false;
},

processLoadedSnapshot: function(profile, snapshot)
{
profile.nodes = snapshot.nodes;
profile.strings = snapshot.strings;
var s = new WebInspector.HeapSnapshot(profile);
profile.sideBarElement.subtitle = Number.bytesToString(s.totalSize);
},

_mouseClickInContainmentGrid: function(event)
{
var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
if (!cell || (!cell.hasStyleClass("object-column") && !cell.hasStyleClass("shallowSize-column") && !cell.hasStyleClass("retainedSize-column")))
return;
var row = event.target.enclosingNodeOrSelfWithNodeName("tr");
if (!row)
return;
var nodeItem = row._dataGridNode;
if (!nodeItem || nodeItem.isEventWithinDisclosureTriangle(event))
return;
if (nodeItem.snapshotNodeIndex)
this.retainmentDataGrid.setDataSource(this, nodeItem.isDeletedNode ? nodeItem.dataGrid.baseSnapshot : nodeItem.dataGrid.snapshot, nodeItem.snapshotNodeIndex, nodeItem.isDeletedNode ? this.baseSelectElement.childNodes[this.baseSelectElement.selectedIndex].label + " | " : "");
else
this.retainmentDataGrid.reset();
},

_mouseClickInRetainmentGrid: function(event)
{
var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
if (!cell || (!cell.hasStyleClass("path-column")))
return;
var row = event.target.enclosingNodeOrSelfWithNodeName("tr");
var nodeItem = row._dataGridNode;
if (!nodeItem || !nodeItem.route)
return;
function expandRoute()
{
this.dataGrid.expandRoute(nodeItem.route);
}
this.changeView("Containment", expandRoute.bind(this));
},

changeView: function(viewTitle, callback)
{
var viewIndex = null;
for (var i = 0; i < this.views.length; ++i)
if (this.views[i].title === viewTitle) {
viewIndex = i;
break;
}
if (this.views.current === viewIndex) {
setTimeout(callback, 0);
return;
}
var grid = this.views[viewIndex].grid;
function sortingComplete()
{
grid.removeEventListener("sorting complete", sortingComplete, this);
setTimeout(callback, 0);
}
this.views[viewIndex].grid.addEventListener("sorting complete", sortingComplete, this);
this.viewSelectElement.selectedIndex = viewIndex;
this._changeView({target: {selectedIndex: viewIndex}});      
},

_changeView: function(event)
{
if (!event || !this._profileUid)
return;
if (event.target.selectedIndex === this.views.current)
return;

this.views.current = event.target.selectedIndex;
this.currentView.hide();
var view = this.views[this.views.current];
this.currentView = view.view;
this.dataGrid = view.grid;
this.currentView.show();
this.refreshVisibleData();
this.dataGrid.updateWidths();
if (this.currentView === this.diffView) {
this.baseSelectElement.removeStyleClass("hidden");
if (!this.dataGrid.snapshotView) {
this.dataGrid.setDataSource(this, this.profileWrapper);
this._changeBase();
}
} else {
this.baseSelectElement.addStyleClass("hidden");
if (!this.dataGrid.snapshotView)
WebInspector.PleaseWaitMessage.prototype.showAndWaitFor(this.currentView.element, this.dataGrid, "sorting complete", setDataSource.bind(this));
}

function setDataSource()
{
this.dataGrid.setDataSource(this, this.profileWrapper);
}


if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults)
return;




this._searchFinishedCallback(this, -this._searchResults.length);
this.performSearch(this.currentQuery, this._searchFinishedCallback);
},

_changeRetainingPathsRoot: function(event)
{
if (!event)
return;
this.retainmentDataGrid.refresh();
},

_getHoverAnchor: function(target)
{
var span = target.enclosingNodeOrSelfWithNodeName("span");
if (!span)
return;
var row = target.enclosingNodeOrSelfWithNodeName("tr");
if (!row)
return;
var gridNode = row._dataGridNode;
if (!gridNode.hasHoverMessage)
return;
span.node = gridNode;
return span;
},

get isTracingToWindowObjects()
{
return this.retainingPathsRoot.selectedIndex === 1;
},

get _isShowingAsPercent()
{
return this.showCountAsPercent && this.showShallowSizeAsPercent && this.showRetainedSizeAsPercent;
},

_percentClicked: function(event)
{
var currentState = this._isShowingAsPercent;
this.showCountAsPercent = !currentState;
this.showShallowSizeAsPercent = !currentState;
this.showRetainedSizeAsPercent = !currentState;
this.refreshShowAsPercents();
},

_showStringContentPopup: function(span)
{
var stringContentElement = document.createElement("span");
stringContentElement.className = "monospace";
stringContentElement.style.whiteSpace = "pre";

var popover = new WebInspector.Popover(stringContentElement);
function displayString(name, className)
{
stringContentElement.textContent = name;
stringContentElement.className += " " + className;
popover.show(span);
}
span.node.hoverMessage(displayString);
return popover;
},

_helpClicked: function(event)
{
if (!this.helpPopover) {
var refTypes = ["a:", "console-formatted-name", WebInspector.UIString("property"),
"0:", "console-formatted-name", WebInspector.UIString("element"),
"a:", "console-formatted-number", WebInspector.UIString("context var"),
"a:", "console-formatted-null", WebInspector.UIString("system prop")];
var objTypes = [" a ", "console-formatted-object", "Object",
"\"a\"", "console-formatted-string", "String",
"/a/", "console-formatted-string", "RegExp",
"a()", "console-formatted-function", "Function",
"a[]", "console-formatted-object", "Array",
"num", "console-formatted-number", "Number",
" a ", "console-formatted-null", "System"];

var contentElement = document.createElement("table");
contentElement.className = "heapshot-help";
var headerRow = document.createElement("tr");
var propsHeader = document.createElement("th");
propsHeader.textContent = WebInspector.UIString("Property types:");
headerRow.appendChild(propsHeader);
var objsHeader = document.createElement("th");
objsHeader.textContent = WebInspector.UIString("Object types:");
headerRow.appendChild(objsHeader);
contentElement.appendChild(headerRow);
var len = Math.max(refTypes.length, objTypes.length);
for (var i = 0; i < len; i += 3) {
var row = document.createElement("tr");
var refCell = document.createElement("td");
if (refTypes[i])
appendHelp(refTypes, i, refCell);
row.appendChild(refCell);
var objCell = document.createElement("td");
if (objTypes[i])
appendHelp(objTypes, i, objCell);
row.appendChild(objCell);
contentElement.appendChild(row);
}
this.helpPopover = new WebInspector.Popover(contentElement);

function appendHelp(help, index, cell)
{
var div = document.createElement("div");
div.className = "source-code event-properties";
var name = document.createElement("span");
name.textContent = help[index];
name.className = help[index + 1];
div.appendChild(name);
var desc = document.createElement("span");
desc.textContent = " " + help[index + 2];
div.appendChild(desc);
cell.appendChild(div);
}
}
if (this.helpPopover.visible)
this.helpPopover.hide();
else
this.helpPopover.show(this.helpButton.element);
},

_startRetainersHeaderDragging: function(event)
{
if (!this.visible || event.target === this.retainingPathsRoot)
return;

WebInspector.elementDragStart(this.retainmentViewHeader, this._retainersHeaderDragging.bind(this), this._endRetainersHeaderDragging.bind(this), event, "row-resize");
this._previousDragPosition = event.pageY;
event.stopPropagation();
},

_retainersHeaderDragging: function(event)
{
var height = this.retainmentView.element.clientHeight;
height += this._previousDragPosition - event.pageY;
this._previousDragPosition = event.pageY;
this._updateRetainmentViewHeight(height);
event.preventDefault();
event.stopPropagation();
},

_endRetainersHeaderDragging: function(event)
{
WebInspector.elementDragEnd(event);
delete this._previousDragPosition;
event.stopPropagation();
},

_updateRetainmentViewHeight: function(height)
{
height = Number.constrain(height, Preferences.minConsoleHeight, this.element.clientHeight - Preferences.minConsoleHeight);
this.viewsContainer.style.bottom = (height + this.retainmentViewHeader.clientHeight) + "px";
this.retainmentView.element.style.height = height + "px";
this.retainmentViewHeader.style.bottom = height + "px";        
},

_updateBaseOptions: function()
{
var list = this._profiles();

if (this.baseSelectElement.length === list.length)
return;

for (var i = this.baseSelectElement.length, n = list.length; i < n; ++i) {
var baseOption = document.createElement("option");
var title = list[i].title;
if (!title.indexOf(UserInitiatedProfileName))
title = WebInspector.UIString("Snapshot %d", title.substring(UserInitiatedProfileName.length + 1));
baseOption.label = title;
this.baseSelectElement.appendChild(baseOption);
}
},

_updatePercentButton: function()
{
if (this._isShowingAsPercent) {
this.percentButton.title = WebInspector.UIString("Show absolute counts and sizes.");
this.percentButton.toggled = true;
} else {
this.percentButton.title = WebInspector.UIString("Show counts and sizes as percentages.");
this.percentButton.toggled = false;
}
}
};

WebInspector.DetailedHeapshotView.prototype.__proto__ = WebInspector.View.prototype;

WebInspector.DetailedHeapshotView.prototype.showHiddenData = true;

WebInspector.DetailedHeapshotProfileType = function()
{
WebInspector.ProfileType.call(this, WebInspector.HeapSnapshotProfileType.TypeId, WebInspector.UIString("HEAP SNAPSHOTS"));
}

WebInspector.DetailedHeapshotProfileType.prototype = {
get buttonTooltip()
{
return WebInspector.UIString("Take heap snapshot.");
},

get buttonStyle()
{
return "heap-snapshot-status-bar-item status-bar-item";
},

buttonClicked: function()
{
WebInspector.panels.profiles.takeHeapSnapshot(true);
},

get welcomeMessage()
{
return WebInspector.UIString("Get a heap snapshot by pressing the %s button on the status bar.");
},

createSidebarTreeElementForProfile: function(profile)
{
return new WebInspector.ProfileSidebarTreeElement(profile, WebInspector.UIString("Snapshot %d"), "heap-snapshot-sidebar-tree-item");
},

createView: function(profile)
{
return new WebInspector.DetailedHeapshotView(WebInspector.panels.profiles, profile);
}
}

WebInspector.DetailedHeapshotProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype;





WebInspector.DebuggerModel = function()
{
this._debuggerPausedDetails = {};
this._scripts = {};

InspectorBackend.registerDomainDispatcher("Debugger", new WebInspector.DebuggerDispatcher(this));
}

WebInspector.DebuggerModel.Events = {
DebuggerWasEnabled: "debugger-was-enabled",
DebuggerWasDisabled: "debugger-was-disabled",
DebuggerPaused: "debugger-paused",
DebuggerResumed: "debugger-resumed",
ParsedScriptSource: "parsed-script-source",
FailedToParseScriptSource: "failed-to-parse-script-source",
BreakpointResolved: "breakpoint-resolved",
Reset: "reset"
}

WebInspector.DebuggerModel.prototype = {
enableDebugger: function()
{
DebuggerAgent.enable();
},

disableDebugger: function()
{
DebuggerAgent.disable();
},

_debuggerWasEnabled: function()
{
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerWasEnabled);
},

_debuggerWasDisabled: function()
{
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerWasDisabled);
},

continueToLocation: function(location)
{
DebuggerAgent.continueToLocation(location);
},

setBreakpoint: function(url, lineNumber, columnNumber, condition, callback)
{

var minColumnNumber = 0;
for (var id in this._scripts) {
var script = this._scripts[id];
if (url === script.sourceURL && lineNumber === script.lineOffset)
minColumnNumber = minColumnNumber ? Math.min(minColumnNumber, script.columnOffset) : script.columnOffset;
}
columnNumber = Math.max(columnNumber, minColumnNumber);

function didSetBreakpoint(error, breakpointId, locations)
{
if (callback)
callback(error ? null : breakpointId, locations);
}
DebuggerAgent.setBreakpointByUrl(url, lineNumber, columnNumber, condition, didSetBreakpoint.bind(this));
},

setBreakpointBySourceId: function(location, condition, callback)
{
function didSetBreakpoint(error, breakpointId, actualLocation)
{
if (callback)
callback(error ? null : breakpointId, [actualLocation]);
}
DebuggerAgent.setBreakpoint(location, condition, didSetBreakpoint.bind(this));
},

removeBreakpoint: function(breakpointId, callback)
{
DebuggerAgent.removeBreakpoint(breakpointId, callback);
},

_breakpointResolved: function(breakpointId, location)
{
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointResolved, {breakpointId: breakpointId, location: location});
},

reset: function()
{
this._debuggerPausedDetails = {};
this._scripts = {};
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.Reset);
},

get scripts()
{
return this._scripts;
},

scriptForSourceID: function(sourceId)
{
return this._scripts[sourceId];
},

scriptsForURL: function(url)
{
return this.queryScripts(function(s) { return s.sourceURL === url; });
},

queryScripts: function(filter)
{
var scripts = [];
for (var sourceId in this._scripts) {
var script = this._scripts[sourceId];
if (filter(script))
scripts.push(script);
}
return scripts;
},

editScriptSource: function(sourceId, newSource, callback)
{
this._scripts[sourceId].editSource(newSource, this._didEditScriptSource.bind(this, sourceId, newSource, callback));
},

_didEditScriptSource: function(sourceId, newSource, callback, error, callFrames)
{
if (!error && callFrames && callFrames.length)
this._debuggerPausedDetails.callFrames = callFrames;
callback(error);
},

get callFrames()
{
return this._debuggerPausedDetails.callFrames;
},

get debuggerPausedDetails()
{
return this._debuggerPausedDetails;
},

_pausedScript: function(details)
{
this._debuggerPausedDetails = details;
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerPaused, details);
},

_resumedScript: function()
{
this._debuggerPausedDetails = {};
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerResumed);
},

_parsedScriptSource: function(sourceId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript)
{
var script = new WebInspector.Script(sourceId, sourceURL, startLine, startColumn, endLine, endColumn, undefined, undefined, isContentScript);
this._scripts[sourceId] = script;
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.ParsedScriptSource, script);
},

_failedToParseScriptSource: function(sourceURL, source, startingLine, errorLine, errorMessage)
{
var script = new WebInspector.Script(null, sourceURL, startingLine, 0, 0, 0, errorLine, errorMessage, undefined);
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, script);
}
}

WebInspector.DebuggerModel.prototype.__proto__ = WebInspector.Object.prototype;

WebInspector.DebuggerEventTypes = {
JavaScriptPause: 0,
JavaScriptBreakpoint: 1,
NativeBreakpoint: 2
};

WebInspector.DebuggerDispatcher = function(debuggerModel)
{
this._debuggerModel = debuggerModel;
}

WebInspector.DebuggerDispatcher.prototype = {
paused: function(details)
{
this._debuggerModel._pausedScript(details);
},

resumed: function()
{
this._debuggerModel._resumedScript();
},

debuggerWasEnabled: function()
{
this._debuggerModel._debuggerWasEnabled();
},

debuggerWasDisabled: function()
{
this._debuggerModel._debuggerWasDisabled();
},

scriptParsed: function(sourceId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript)
{
this._debuggerModel._parsedScriptSource(sourceId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript);
},

scriptFailedToParse: function(sourceURL, source, startingLine, errorLine, errorMessage)
{
this._debuggerModel._failedToParseScriptSource(sourceURL, source, startingLine, errorLine, errorMessage);
},

breakpointResolved: function(breakpointId, sourceId, lineNumber, columnNumber)
{
this._debuggerModel._breakpointResolved(breakpointId, sourceId, lineNumber, columnNumber);
}
}





WebInspector.DebuggerPresentationModel = function()
{
this._sourceFiles = {};
this._messages = [];
this._breakpointsByDebuggerId = {};
this._breakpointsWithoutSourceFile = {};

this._presentationCallFrames = [];
this._selectedCallFrameIndex = 0;

WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasEnabled, this._debuggerWasEnabled, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, this._failedToParseScriptSource, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPaused, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.Reset, this._debuggerReset, this);

WebInspector.console.addEventListener(WebInspector.ConsoleView.Events.MessageAdded, this._consoleMessageAdded, this);
WebInspector.console.addEventListener(WebInspector.ConsoleView.Events.ConsoleCleared, this._consoleCleared, this);

new WebInspector.DebuggerPresentationModelResourceBinding(this);
}

WebInspector.DebuggerPresentationModel.Events = {
SourceFileAdded: "source-file-added",
SourceFileChanged: "source-file-changed",
ConsoleMessageAdded: "console-message-added",
ConsoleMessagesCleared: "console-messages-cleared",
BreakpointAdded: "breakpoint-added",
BreakpointRemoved: "breakpoint-removed",
DebuggerPaused: "debugger-paused",
DebuggerResumed: "debugger-resumed",
CallFrameSelected: "call-frame-selected"
}

WebInspector.DebuggerPresentationModel.prototype = {
_debuggerWasEnabled: function()
{
if (this._breakpointsRestored)
return;
this._restoreBreakpointsFromSettings();
this._breakpointsRestored = true;
},

sourceFile: function(sourceFileId)
{
return this._sourceFiles[sourceFileId];
},

sourceFileForScriptURL: function(scriptURL)
{
return this._sourceFiles[scriptURL];
},

requestSourceFileContent: function(sourceFileId, callback)
{
this._sourceFiles[sourceFileId].requestContent(callback);
},

_parsedScriptSource: function(event)
{
this._addScript(event.data);
},

_failedToParseScriptSource: function(event)
{
this._addScript(event.data);
},

_addScript: function(script)
{
var sourceFileId = this._createSourceFileId(script.sourceURL, script.sourceId);
var sourceFile = this._sourceFiles[sourceFileId];
if (sourceFile) {
sourceFile.addScript(script);
return;
}

function contentChanged(sourceFile)
{
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.SourceFileChanged, this._sourceFiles[sourceFileId]);
}
if (!this._formatSourceFiles)
sourceFile = new WebInspector.SourceFile(sourceFileId, script, contentChanged.bind(this));
else
sourceFile = new WebInspector.FormattedSourceFile(sourceFileId, script, contentChanged.bind(this), this._formatter());
this._sourceFiles[sourceFileId] = sourceFile;

this._restoreBreakpoints(sourceFile);

this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.SourceFileAdded, sourceFile);
},

_restoreBreakpoints: function(sourceFile)
{
var pendingBreakpoints = this._breakpointsWithoutSourceFile[sourceFile.id];
for (var i = 0; pendingBreakpoints && i < pendingBreakpoints.length; ++i) {
var breakpointData = pendingBreakpoints[i];
if ("debuggerId" in breakpointData) {
var breakpoint = new WebInspector.PresentationBreakpoint(sourceFile, breakpointData.lineNumber, breakpointData.condition, breakpointData.enabled);
this._bindDebuggerId(breakpoint, breakpointData.debuggerId);
this._breakpointAdded(breakpoint);
} else
this.setBreakpoint(sourceFile.id, breakpointData.lineNumber, breakpointData.condition, breakpointData.enabled, true);
}
delete this._breakpointsWithoutSourceFile[sourceFile.id];
},

canEditScriptSource: function(sourceFileId)
{
if (!Preferences.canEditScriptSource || this._formatSourceFiles)
return false;
var script = this._scriptForSourceFileId(sourceFileId);
return !script.lineOffset && !script.columnOffset;
},

editScriptSource: function(sourceFileId, newSource, callback)
{
var script = this._scriptForSourceFileId(sourceFileId);
var sourceFile = this._sourceFiles[sourceFileId];

function didEditScriptSource(oldSource, error)
{
if (!error) {
sourceFile.content = newSource;

var resource = WebInspector.resourceForURL(sourceFile.url);
if (resource)
resource.addRevision(newSource);
}

callback(error);

if (!error && WebInspector.debuggerModel.callFrames)
this._debuggerPaused();
}

var oldSource = sourceFile.requestContent(didReceiveSource.bind(this));
function didReceiveSource(oldSource)
{
WebInspector.debuggerModel.editScriptSource(script.sourceId, newSource, didEditScriptSource.bind(this, oldSource));
}
},

_updateBreakpointsAfterLiveEdit: function(sourceFileId, oldSource, newSource)
{
var sourceFile = this._sourceFiles[sourceFileId];


var diff = Array.diff(oldSource.split("\n"), newSource.split("\n"));
for (var lineNumber in sourceFile.breakpoints) {
var breakpoint = sourceFile.breakpoints[lineNumber];

var lineNumber = breakpoint.lineNumber;
this.removeBreakpoint(sourceFileId, lineNumber);

var newLineNumber = diff.left[lineNumber].row;
if (newLineNumber === undefined) {
for (var i = lineNumber - 1; i >= 0; --i) {
if (diff.left[i].row === undefined)
continue;
var shiftedLineNumber = diff.left[i].row + lineNumber - i;
if (shiftedLineNumber < diff.right.length) {
var originalLineNumber = diff.right[shiftedLineNumber].row;
if (originalLineNumber === lineNumber || originalLineNumber === undefined)
newLineNumber = shiftedLineNumber;
}
break;
}
}
if (newLineNumber !== undefined)
this.setBreakpoint(sourceFileId, newLineNumber, breakpoint.condition, breakpoint.enabled);
}
},

setFormatSourceFiles: function(formatSourceFiles)
{
if (this._formatSourceFiles === formatSourceFiles)
return;

this._formatSourceFiles = formatSourceFiles;

for (var id in this._sourceFiles) {
var sourceFile = this._sourceFiles[id];
for (var line in sourceFile.breakpoints)
this._removeBreakpointFromDebugger(sourceFile.breakpoints[line]);
}

for (var id in this._breakpointsWithoutSourceFile) {
var breakpoints = this._breakpointsWithoutSourceFile[id];
for (var i = 0; i < breakpoints.length; ++i)
this._removeBreakpointFromDebugger(breakpoints[i]);
}

var messages = this._messages;
this._reset();

var scripts = WebInspector.debuggerModel.scripts;
for (var id in scripts)
this._addScript(scripts[id]);

for (var i = 0; i < messages.length; ++i)
this._addConsoleMessage(messages[i]);

if (WebInspector.debuggerModel.callFrames)
this._debuggerPaused();
},

_formatter: function()
{
if (!this._scriptFormatter)
this._scriptFormatter = new WebInspector.ScriptFormatter();
return this._scriptFormatter;
},

_consoleMessageAdded: function(event)
{
var message = event.data;
if (message.isErrorOrWarning() && message.message)
this._addConsoleMessage(message);
},

_addConsoleMessage: function(message)
{
this._messages.push(message);

var sourceFile = this._sourceFileForScript(message.url);
if (!sourceFile)
return;

function didRequestSourceMapping(mapping)
{
var presentationMessage = {};
presentationMessage.sourceFileId = sourceFile.id;
presentationMessage.lineNumber = mapping.scriptLocationToSourceLine({lineNumber:message.line - 1, columnNumber:0});
presentationMessage.originalMessage = message;
sourceFile.messages.push(presentationMessage);
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.ConsoleMessageAdded, presentationMessage);
}
sourceFile.requestSourceMapping(didRequestSourceMapping.bind(this));
},

_consoleCleared: function()
{
this._messages = [];
for (var id in this._sourceFiles)
this._sourceFiles[id].messages = [];
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.ConsoleMessagesCleared);
},

continueToLine: function(sourceFileId, lineNumber)
{
function didRequestSourceMapping(mapping)
{
var location = mapping.sourceLineToScriptLocation(lineNumber);
WebInspector.debuggerModel.continueToLocation(location);
}
this._sourceFiles[sourceFileId].requestSourceMapping(didRequestSourceMapping.bind(this));
},

breakpointsForSourceFileId: function(sourceFileId)
{
var sourceFile = this.sourceFile(sourceFileId);
if (!sourceFile)
return [];
var breakpoints = [];
for (var lineNumber in sourceFile.breakpoints)
breakpoints.push(sourceFile.breakpoints[lineNumber]);
return breakpoints;
},

setBreakpoint: function(sourceFileId, lineNumber, condition, enabled, dontSaveBreakpoints)
{
var sourceFile = this._sourceFiles[sourceFileId];
if (!sourceFile)
return;

var breakpoint = new WebInspector.PresentationBreakpoint(sourceFile, lineNumber, condition, enabled);
if (!enabled) {
this._breakpointAdded(breakpoint);
if (!dontSaveBreakpoints)
this._saveBreakpoints();
return;
}

function callback()
{
this._breakpointAdded(breakpoint);
if (!dontSaveBreakpoints)
this._saveBreakpoints();
}
this._setBreakpointInDebugger(breakpoint, callback.bind(this));
},

_setBreakpointInDebugger: function(breakpoint, callback)
{
function didSetBreakpoint(breakpointId, locations)
{
if (!breakpointId)
return;

this._bindDebuggerId(breakpoint, breakpointId);
breakpoint.location = locations[0];
callback();
}

function didRequestSourceMapping(mapping)
{
var location = mapping.sourceLineToScriptLocation(breakpoint.lineNumber);
var script = WebInspector.debuggerModel.scriptForSourceID(location.sourceId);
if (script.sourceURL)
WebInspector.debuggerModel.setBreakpoint(script.sourceURL, location.lineNumber, location.columnNumber, breakpoint.condition, didSetBreakpoint.bind(this));
else {
location.sourceId = script.sourceId;
WebInspector.debuggerModel.setBreakpointBySourceId(location, breakpoint.condition, didSetBreakpoint.bind(this));
}
}
breakpoint.sourceFile.requestSourceMapping(didRequestSourceMapping.bind(this));
},

_removeBreakpointFromDebugger: function(breakpoint, callback)
{
if ("debuggerId" in breakpoint) {
WebInspector.debuggerModel.removeBreakpoint(breakpoint.debuggerId);
this._unbindDebuggerId(breakpoint);
}

if (callback)
callback();
},

_bindDebuggerId: function(breakpoint, debuggerId)
{
breakpoint.debuggerId = debuggerId;
this._breakpointsByDebuggerId[debuggerId] = breakpoint;
},

_unbindDebuggerId: function(breakpoint)
{
delete this._breakpointsByDebuggerId[breakpoint.debuggerId];
delete breakpoint.debuggerId;
},

setBreakpointEnabled: function(sourceFileId, lineNumber, enabled)
{
var breakpoint = this.findBreakpoint(sourceFileId, lineNumber);
if (!breakpoint)
return;

this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointRemoved, breakpoint);

breakpoint.enabled = enabled;

function afterUpdate()
{
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointAdded, breakpoint);
this._saveBreakpoints();
}

if (!enabled)
this._removeBreakpointFromDebugger(breakpoint, afterUpdate.call(this));
else
this._setBreakpointInDebugger(breakpoint, afterUpdate.bind(this));
},

updateBreakpoint: function(sourceFileId, lineNumber, condition, enabled)
{
this.removeBreakpoint(sourceFileId, lineNumber);
this.setBreakpoint(sourceFileId, lineNumber, condition, enabled);
},

removeBreakpoint: function(sourceFileId, lineNumber)
{
var breakpoint = this.findBreakpoint(sourceFileId, lineNumber);
if (!breakpoint)
return;

function callback()
{
this._breakpointRemoved(breakpoint);
this._saveBreakpoints();
}
this._removeBreakpointFromDebugger(breakpoint, callback.bind(this));
},

findBreakpoint: function(sourceFileId, lineNumber)
{
var sourceFile = this.sourceFile(sourceFileId);
if (sourceFile)
return sourceFile.breakpoints[lineNumber];
},

_breakpointAdded: function(breakpoint)
{
var sourceFile = breakpoint.sourceFile;
if (!sourceFile)
return;

function didRequestSourceMapping(mapping)
{

if (breakpoint.location)
breakpoint.lineNumber = mapping.scriptLocationToSourceLine(breakpoint.location);

var existingBreakpoint = this.findBreakpoint(sourceFile.id, breakpoint.lineNumber);
if (existingBreakpoint) {

this._removeBreakpointFromDebugger(breakpoint);
return;
}
sourceFile.breakpoints[breakpoint.lineNumber] = breakpoint;
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointAdded, breakpoint);
}
sourceFile.requestSourceMapping(didRequestSourceMapping.bind(this));
},

_breakpointRemoved: function(breakpoint)
{
var sourceFile = breakpoint.sourceFile;
if (sourceFile.breakpoints[breakpoint.lineNumber] === breakpoint) {

delete sourceFile.breakpoints[breakpoint.lineNumber];
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointRemoved, breakpoint);
}
},

_breakpointResolved: function(event)
{
var debuggerId = event.data.breakpointId;
if (!(debuggerId in this._breakpointsByDebuggerId))
return;
var breakpoint = this._breakpointsByDebuggerId[debuggerId];

this._breakpointRemoved(breakpoint);
breakpoint.location = event.data.location;
this._breakpointAdded(breakpoint);
},

_restoreBreakpointsFromSettings: function()
{
var breakpoints = WebInspector.settings.breakpoints;
for (var i = 0; i < breakpoints.length; ++i) {
var breakpointData = breakpoints[i];
var sourceFileId = breakpointData.sourceFileId;
if (!sourceFileId)
continue;
var sourceFile = this._sourceFiles[sourceFileId];
if (sourceFile) {
this.setBreakpoint(sourceFileId, breakpointData.lineNumber, breakpointData.condition, breakpointData.enabled);
continue;
}


var pendingBreakpoints = this._breakpointsWithoutSourceFile[sourceFileId];
if (!pendingBreakpoints) {
pendingBreakpoints = [];
this._breakpointsWithoutSourceFile[sourceFileId] = pendingBreakpoints;
}
pendingBreakpoints.push(breakpointData);
}
},

_saveBreakpoints: function()
{
var serializedBreakpoints = [];


for (var sourceFileId in this._sourceFiles) {
var sourceFile = this._sourceFiles[sourceFileId];
if (!sourceFile.url)
continue;

for (var lineNumber in sourceFile.breakpoints)
serializedBreakpoints.push(sourceFile.breakpoints[lineNumber].serialize());
}


for (var sourceFileId in this._breakpointsWithoutSourceFile)
serializedBreakpoints = serializedBreakpoints.concat(this._breakpointsWithoutSourceFile[sourceFileId]);


for (var i = 0; i < serializedBreakpoints.length; ++i) {
var breakpoint = serializedBreakpoints[i];
var breakpointCopy = {};
for (var property in breakpoint) {
if (property !== "debuggerId")
breakpointCopy[property] = breakpoint[property];
}
serializedBreakpoints[i] = breakpointCopy;
}

WebInspector.settings.breakpoints = serializedBreakpoints;
},

_debuggerPaused: function()
{
var callFrames = WebInspector.debuggerModel.callFrames;
this._presentationCallFrames = [];
for (var i = 0; i < callFrames.length; ++i) {
var callFrame = callFrames[i];
var sourceFile;
var script = WebInspector.debuggerModel.scriptForSourceID(callFrame.location.sourceId);
if (script)
sourceFile = this._sourceFileForScript(script.sourceURL, script.sourceId);
this._presentationCallFrames.push(new WebInspector.PresenationCallFrame(callFrame, i, sourceFile));
}
var details = WebInspector.debuggerModel.debuggerPausedDetails;
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.DebuggerPaused, { callFrames: this._presentationCallFrames, details: details });

this.selectedCallFrame = this._presentationCallFrames[this._selectedCallFrameIndex];
},

_debuggerResumed: function()
{
this._presentationCallFrames = [];
this._selectedCallFrameIndex = 0;
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.DebuggerResumed);
},

set selectedCallFrame(callFrame)
{
this._selectedCallFrameIndex = callFrame.index;
callFrame.select();
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.CallFrameSelected, callFrame);
},

get selectedCallFrame()
{
return this._presentationCallFrames[this._selectedCallFrameIndex];
},

_sourceFileForScript: function(sourceURL, sourceId)
{
return this._sourceFiles[this._createSourceFileId(sourceURL, sourceId)];
},

_scriptForSourceFileId: function(sourceFileId)
{
function filter(script)
{
return this._createSourceFileId(script.sourceURL, script.sourceId) === sourceFileId;
}
return WebInspector.debuggerModel.queryScripts(filter.bind(this))[0];
},

_createSourceFileId: function(sourceURL, sourceId)
{
var prefix = this._formatSourceFiles ? "deobfuscated:" : "";
return prefix + (sourceURL || sourceId);
},

_reset: function()
{
for (var id in this._sourceFiles) {
var sourceFile = this._sourceFiles[id];
for (var line in sourceFile.breakpoints) {
var breakpoints = this._breakpointsWithoutSourceFile[sourceFile.id];
if (!breakpoints) {
breakpoints = [];
this._breakpointsWithoutSourceFile[sourceFile.id] = breakpoints;
}
breakpoints.push(sourceFile.breakpoints[line].serialize());
}
}

this._sourceFiles = {};
this._messages = [];
this._breakpointsByDebuggerId = {};
},

_debuggerReset: function()
{
this._reset();
this._presentationCallFrames = [];
this._selectedCallFrameIndex = 0;
}
}

WebInspector.DebuggerPresentationModel.prototype.__proto__ = WebInspector.Object.prototype;

WebInspector.PresentationBreakpoint = function(sourceFile, lineNumber, condition, enabled)
{
this.sourceFile = sourceFile;
this.sourceFileId = sourceFile.id;
this.lineNumber = lineNumber;
this.condition = condition;
this.enabled = enabled;
}

WebInspector.PresentationBreakpoint.prototype = {
get url()
{
return this.sourceFile.url;
},

get resolved()
{
return !!this.location;
},

loadSnippet: function(callback)
{
function didRequestContent(mimeType, content)
{
var lineEndings = content.lineEndings();
var snippet = "";
if (this.lineNumber < lineEndings.length)
snippet = content.substring(lineEndings[this.lineNumber - 1], lineEndings[this.lineNumber]);
callback(snippet);
}
if (!this.sourceFile) {
callback(WebInspector.UIString("N/A"));
return;
}
this.sourceFile.requestContent(didRequestContent.bind(this));
},

serialize: function()
{
var serializedBreakpoint = {};
serializedBreakpoint.sourceFileId = this.sourceFile.id;
serializedBreakpoint.lineNumber = this.lineNumber;
serializedBreakpoint.condition = this.condition;
serializedBreakpoint.enabled = this.enabled;
if ("debuggerId" in this)
serializedBreakpoint.debuggerId = this.debuggerId;
return serializedBreakpoint;
}
}

WebInspector.PresenationCallFrame = function(callFrame, index, sourceFile)
{
this._callFrame = callFrame;
this._index = index;
this._sourceFile = sourceFile;
this._script = WebInspector.debuggerModel.scriptForSourceID(callFrame.location.sourceId);
}

WebInspector.PresenationCallFrame.prototype = {
get functionName()
{
return this._callFrame.functionName;
},

get type()
{
return this._callFrame.type;
},

get isInternalScript()
{
return !this._script;
},

get url()
{
if (this._sourceFile)
return this._sourceFile.url;
},

get scopeChain()
{
return this._callFrame.scopeChain;
},

get this()
{
return this._callFrame.this;
},

get index()
{
return this._index;
},

select: function()
{
if (this._sourceFile)
this._sourceFile.forceLoadContent(this._script);
},

evaluate: function(code, objectGroup, includeCommandLineAPI, callback)
{
function didEvaluateOnCallFrame(error, result, wasThrown)
{
callback(WebInspector.RemoteObject.fromPayload(result), wasThrown);
}
DebuggerAgent.evaluateOnCallFrame(this._callFrame.id, code, objectGroup, includeCommandLineAPI, didEvaluateOnCallFrame.bind(this));
},

sourceLine: function(callback)
{
if (!this._sourceFile) {
callback(undefined, this._callFrame.location.lineNumber);
return;
}

function didRequestSourceMapping(mapping)
{
callback(this._sourceFile.id, mapping.scriptLocationToSourceLine(this._callFrame.location));
}
this._sourceFile.requestSourceMapping(didRequestSourceMapping.bind(this));
}
}

WebInspector.DebuggerPresentationModelResourceBinding = function(model)
{
this._presentationModel = model;
WebInspector.Resource.registerDomainModelBinding(WebInspector.Resource.Type.Script, this);
}

WebInspector.DebuggerPresentationModelResourceBinding.prototype = {
canSetContent: function(resource)
{
var sourceFile = this._presentationModel._sourceFileForScript(resource.url)
if (!sourceFile)
return false;
return this._presentationModel.canEditScriptSource(sourceFile.id);
},

setContent: function(resource, content, majorChange, userCallback)
{
if (!majorChange)
return;

var sourceFile = this._presentationModel._sourceFileForScript(resource.url);
if (!sourceFile) {
userCallback("Resource is not editable");
return;
}

resource.requestContent(this._setContentWithInitialContent.bind(this, sourceFile, content, userCallback));
},

_setContentWithInitialContent: function(sourceFile, content, userCallback, oldContent)
{
function callback(error)
{
if (userCallback)
userCallback(error);
if (!error) {
this._presentationModel._updateBreakpointsAfterLiveEdit(sourceFile.id, oldContent, content);
sourceFile.reload();
}
}
this._presentationModel.editScriptSource(sourceFile.id, content, callback.bind(this));
}
}

WebInspector.DebuggerPresentationModelResourceBinding.prototype.__proto__ = WebInspector.ResourceDomainModelBinding.prototype;





WebInspector.SourceFile = function(id, script, contentChangedDelegate)
{
this._scripts = [script];
this._contentChangedDelegate = contentChangedDelegate;
if (script.sourceURL)
this._resource = WebInspector.networkManager.inflightResourceForURL(script.sourceURL) || WebInspector.resourceForURL(script.sourceURL);
this._requestContentCallbacks = [];

this.id = id;
this.url = script.sourceURL;
this.isContentScript = script.isContentScript;
this.messages = [];
this.breakpoints = {};

if (this._hasPendingResource())
this._resource.addEventListener("finished", this.reload.bind(this));
}

WebInspector.SourceFile.prototype = {
addScript: function(script)
{
this._scripts.push(script);
},

requestContent: function(callback)
{
if (this._contentLoaded) {
callback(this._mimeType, this._content);
return;
}

this._requestContentCallbacks.push(callback);
this._requestContent();
},

get displayName()
{
return this.url ? WebInspector.displayNameForURL(this.url) : WebInspector.UIString("(program)");
},

get content()
{
return this._content;
},

set content(content)
{

this._content = content;
},

requestSourceMapping: function(callback)
{
if (!this._mapping)
this._mapping = new WebInspector.SourceMapping(this._scripts);
callback(this._mapping);
},

forceLoadContent: function(script)
{
if (!this._hasPendingResource())
return;

if (!this._concatenatedScripts)
this._concatenatedScripts = {};
if (this._concatenatedScripts[script.sourceId])
return;
for (var i = 0; i < this._scripts.length; ++i)
this._concatenatedScripts[this._scripts[i].sourceId] = true;

this.reload();

if (!this._contentRequested) {
this._contentRequested = true;
this._loadAndConcatenateScriptsContent();
}
},

reload: function()
{
if (this._contentLoaded) {
this._contentLoaded = false;
this._contentChangedDelegate();
} else if (this._contentRequested)
this._reloadContent = true;
else if (this._requestContentCallbacks.length)
this._requestContent();
},

_requestContent: function()
{
if (this._contentRequested)
return;

this._contentRequested = true;
if (this._resource && this._resource.finished)
this._loadResourceContent(this._resource);
else if (!this._resource)
this._loadScriptContent();
else if (this._concatenatedScripts)
this._loadAndConcatenateScriptsContent();
else
this._contentRequested = false;
},

_loadResourceContent: function(resource)
{
function didRequestContent(text)
{
if (!text) {
this._loadAndConcatenateScriptsContent();
return;
}

var mimeType = resource.type === WebInspector.Resource.Type.Script ? "text/javascript" : "text/html";
this._didRequestContent(mimeType, text);
}
resource.requestContent(didRequestContent.bind(this));
},

_loadScriptContent: function()
{
this._scripts[0].requestSource(this._didRequestContent.bind(this, "text/javascript"));
},

_loadAndConcatenateScriptsContent: function()
{
var scripts = this._scripts.slice();
scripts.sort(function(x, y) { return x.lineOffset - y.lineOffset || x.columnOffset - y.columnOffset; });
var sources = [];
function didRequestSource(source)
{
sources.push(source);
if (sources.length < scripts.length)
return;
if (scripts.length === 1 && !scripts[0].lineOffset && !scripts[0].columnOffset)
this._didRequestContent("text/javascript", source);
else
this._concatenateScriptsContent(scripts, sources);
}
for (var i = 0; i < scripts.length; ++i)
scripts[i].requestSource(didRequestSource.bind(this));
},

_concatenateScriptsContent: function(scripts, sources)
{
var content = "";
var lineNumber = 0;
var columnNumber = 0;
var scriptRanges = [];
function appendChunk(chunk, script)
{
var start = { lineNumber: lineNumber, columnNumber: columnNumber };
content += chunk;
var lineEndings = chunk.lineEndings();
var lineCount = lineEndings.length;
if (lineCount === 1)
columnNumber += chunk.length;
else {
lineNumber += lineCount - 1;
columnNumber = lineEndings[lineCount - 1] - lineEndings[lineCount - 2] - 1;
}
var end = { lineNumber: lineNumber, columnNumber: columnNumber };
if (script)
scriptRanges.push({ start: start, end: end, sourceId: script.sourceId });
}

var scriptOpenTag = "<script>";
var scriptCloseTag = "</script>";
for (var i = 0; i < scripts.length; ++i) {

while (lineNumber < scripts[i].lineOffset)
appendChunk("\n");
while (columnNumber < scripts[i].columnOffset - scriptOpenTag.length)
appendChunk(" ");


appendChunk(scriptOpenTag);
appendChunk(sources[i], scripts[i]);
appendChunk(scriptCloseTag);
}

this._didRequestContent("text/html", content);
},

_didRequestContent: function(mimeType, content)
{
this._contentLoaded = true;
this._contentRequested = false;
this._mimeType = mimeType;
this._content = content;

for (var i = 0; i < this._requestContentCallbacks.length; ++i)
this._requestContentCallbacks[i](mimeType, content);
this._requestContentCallbacks = [];

if (this._reloadContent)
this.reload();
},

_hasPendingResource: function()
{
return this._resource && !this._resource.finished;
}
}

WebInspector.FormattedSourceFile = function(sourceFileId, script, contentChangedDelegate, formatter)
{
WebInspector.SourceFile.call(this, sourceFileId, script, contentChangedDelegate);
this._formatter = formatter;
}

WebInspector.FormattedSourceFile.prototype = {
requestSourceMapping: function(callback)
{
function didRequestContent()
{
callback(this._mapping);
}
this.requestContent(didRequestContent.bind(this));
},

_didRequestContent: function(mimeType, text)
{
function didFormatContent(formattedText, mapping)
{
this._mapping = new WebInspector.SourceMappingForFormattedSourceFile(this._scripts, mapping);
WebInspector.SourceFile.prototype._didRequestContent.call(this, mimeType, formattedText);
}
this._formatter.formatContent(mimeType, text, didFormatContent.bind(this));
}
}

WebInspector.FormattedSourceFile.prototype.__proto__ = WebInspector.SourceFile.prototype;

WebInspector.SourceMapping = function(scripts)
{
this._sortedScripts = scripts.slice();
this._sortedScripts.sort(function(x, y) { return x.lineOffset - y.lineOffset || x.columnOffset - y.columnOffset; });
}

WebInspector.SourceMapping.prototype = {
scriptLocationToSourceLine: function(location)
{
return location.lineNumber;
},

sourceLineToScriptLocation: function(lineNumber)
{
return this._sourceLocationToScriptLocation(lineNumber, 0);
},

_sourceLocationToScriptLocation: function(lineNumber, columnNumber)
{
var closestScript = this._sortedScripts[0];
for (var i = 1; i < this._sortedScripts.length; ++i) {
script = this._sortedScripts[i];
if (script.lineOffset > lineNumber || (script.lineOffset === lineNumber && script.columnOffset > columnNumber))
break;
closestScript = script;
}
return { sourceId: closestScript.sourceId, lineNumber: lineNumber, columnNumber: columnNumber };
}
}

WebInspector.SourceMappingForFormattedSourceFile = function(scripts, mapping)
{
WebInspector.SourceMapping.call(this, scripts);
this._mapping = mapping;
}

WebInspector.SourceMappingForFormattedSourceFile.prototype = {
scriptLocationToSourceLine: function(location)
{
return this._mapping.originalToFormatted(location).lineNumber;
},

sourceLineToScriptLocation: function(lineNumber)
{
var originalLocation = this._mapping.formattedToOriginal({ lineNumber: lineNumber, columnNumber: 0 });
return WebInspector.SourceMapping.prototype._sourceLocationToScriptLocation.call(this, originalLocation.lineNumber, originalLocation.columnNumber);
}
}

WebInspector.SourceMappingForFormattedSourceFile.prototype.__proto__ = WebInspector.SourceMapping.prototype;





WebInspector.DOMNode = function(doc, payload) {
this.ownerDocument = doc;

this.id = payload.id;
this._nodeType = payload.nodeType;
this._nodeName = payload.nodeName;
this._localName = payload.localName;
this._nodeValue = payload.nodeValue;

this._attributes = [];
this._attributesMap = {};
if (payload.attributes)
this._setAttributesPayload(payload.attributes);

this._childNodeCount = payload.childNodeCount;
this.children = null;

this.nextSibling = null;
this.prevSibling = null;
this.firstChild = null;
this.lastChild = null;
this.parentNode = null;

if (payload.children)
this._setChildrenPayload(payload.children);

this._computedStyle = null;
this.style = null;
this._matchedCSSRules = [];

if (this._nodeType === Node.ELEMENT_NODE) {

if (!this.ownerDocument.documentElement && this._nodeName === "HTML")
this.ownerDocument.documentElement = this;
if (!this.ownerDocument.body && this._nodeName === "BODY")
this.ownerDocument.body = this;
if (payload.documentURL)
this.documentURL = payload.documentURL;
} else if (this._nodeType === Node.DOCUMENT_TYPE_NODE) {
this.publicId = payload.publicId;
this.systemId = payload.systemId;
this.internalSubset = payload.internalSubset;
} else if (this._nodeType === Node.DOCUMENT_NODE) {
this.documentURL = payload.documentURL;
this.xmlVersion = payload.xmlVersion;
} else if (this._nodeType === Node.ATTRIBUTE_NODE) {
this.name = payload.name;
this.value = payload.value;
}
}

WebInspector.DOMNode.prototype = {
hasAttributes: function()
{
return this._attributes.length > 0;
},

hasChildNodes: function()
{
return this._childNodeCount > 0;
},

nodeType: function()
{
return this._nodeType;
},

nodeName: function()
{
return this._nodeName;
},

setNodeName: function(name, callback)
{
DOMAgent.setNodeName(this.id, name, callback);
},

localName: function()
{
return this._localName;
},

nodeValue: function()
{
return this._nodeValue;
},

setNodeValue: function(value, callback)
{
DOMAgent.setNodeValue(this.id, value, callback);
},

getAttribute: function(name)
{
var attr = this._attributesMap[name];
return attr ? attr.value : undefined;
},

setAttribute: function(name, value, callback)
{
DOMAgent.setAttribute(this.id, name, value, callback);
},

attributes: function()
{
return this._attributes;
},

removeAttribute: function(name, callback)
{
function mycallback(error, success)
{
if (!error) {
delete this._attributesMap[name];
for (var i = 0;  i < this._attributes.length; ++i) {
if (this._attributes[i].name === name) {
this._attributes.splice(i, 1);
break;
}
}
}

if (callback)
callback();
}
DOMAgent.removeAttribute(this.id, name, mycallback.bind(this));
},

getChildNodes: function(callback)
{
if (this.children) {
if (callback)
callback(this.children);
return;
}

function mycallback(error) {
if (!error && callback)
callback(this.children);
}
DOMAgent.getChildNodes(this.id, mycallback.bind(this));
},

getOuterHTML: function(callback)
{
DOMAgent.getOuterHTML(this.id, callback);
},

setOuterHTML: function(html, callback)
{
DOMAgent.setOuterHTML(this.id, html, callback);
},

removeNode: function(callback)
{
DOMAgent.removeNode(this.id, callback);
},

copyNode: function(callback)
{
DOMAgent.copyNode(this.id, callback);
},

eventListeners: function(callback)
{
DOMAgent.getEventListenersForNode(this.id, callback);
},

path: function()
{
var path = [];
var node = this;
while (node && "index" in node && node._nodeName.length) {
path.push([node.index, node._nodeName]);
node = node.parentNode;
}
path.reverse();
return path.join(",");
},

appropriateSelectorFor: function(justSelector)
{
var lowerCaseName = this.localName() || node.nodeName().toLowerCase();

var id = this.getAttribute("id");
if (id) {
var selector = "#" + id;
return (justSelector ? selector : lowerCaseName + selector);
}

var className = this.getAttribute("class");
if (className) {
var selector = "." + className.replace(/\s+/, ".");
return (justSelector ? selector : lowerCaseName + selector);
}

if (lowerCaseName === "input" && this.getAttribute("type"))
return lowerCaseName + "[type=\"" + this.getAttribute("type") + "\"]";

return lowerCaseName;
},

_setAttributesPayload: function(attrs)
{
this._attributes = [];
this._attributesMap = {};
for (var i = 0; i < attrs.length; i += 2)
this._addAttribute(attrs[i], attrs[i + 1]);
},

_insertChild: function(prev, payload)
{
var node = new WebInspector.DOMNode(this.ownerDocument, payload);
if (!prev) {
if (!this.children) {

this.children = [ node ];
} else
this.children.unshift(node);
} else
this.children.splice(this.children.indexOf(prev) + 1, 0, node);
this._renumber();
return node;
},

removeChild_: function(node)
{
this.children.splice(this.children.indexOf(node), 1);
node.parentNode = null;
this._renumber();
},

_setChildrenPayload: function(payloads)
{
this.children = [];
for (var i = 0; i < payloads.length; ++i) {
var payload = payloads[i];
var node = new WebInspector.DOMNode(this.ownerDocument, payload);
this.children.push(node);
}
this._renumber();
},

_renumber: function()
{
this._childNodeCount = this.children.length;
if (this._childNodeCount == 0) {
this.firstChild = null;
this.lastChild = null;
return;
}
this.firstChild = this.children[0];
this.lastChild = this.children[this._childNodeCount - 1];
for (var i = 0; i < this._childNodeCount; ++i) {
var child = this.children[i];
child.index = i;
child.nextSibling = i + 1 < this._childNodeCount ? this.children[i + 1] : null;
child.prevSibling = i - 1 >= 0 ? this.children[i - 1] : null;
child.parentNode = this;
}
},

_addAttribute: function(name, value)
{
var attr = {
"name": name,
"value": value,
"_node": this
};
this._attributesMap[name] = attr;
this._attributes.push(attr);
},

ownerDocumentElement: function()
{


var node = this;
while (node.parentNode && !node.parentNode.documentURL)
node = node.parentNode;
return node;
}
}

WebInspector.DOMDocument = function(domAgent, payload)
{
WebInspector.DOMNode.call(this, this, payload);
this._listeners = {};
this._domAgent = domAgent;
}

WebInspector.DOMDocument.prototype.__proto__ = WebInspector.DOMNode.prototype;

WebInspector.DOMAgent = function() {
this._idToDOMNode = null;
this._document = null;
InspectorBackend.registerDomainDispatcher("DOM", new WebInspector.DOMDispatcher(this));
}

WebInspector.DOMAgent.Events = {
AttrModified: "AttrModified",
CharacterDataModified: "CharacterDataModified",
NodeInserted: "NodeInserted",
NodeRemoved: "NodeRemoved",
DocumentUpdated: "DocumentUpdated",
ChildNodeCountUpdated: "ChildNodeCountUpdated"
}

WebInspector.DOMAgent.prototype = {
requestDocument: function(callback)
{
if (this._document) {
if (callback)
callback(this._document);
return;
}

if (this._pendingDocumentRequestCallbacks) {
this._pendingDocumentRequestCallbacks.push(callback);
return;
}

this._pendingDocumentRequestCallbacks = [callback];

function onDocumentAvailable(error, root)
{
if (!error)
this._setDocument(root);

for (var i = 0; i < this._pendingDocumentRequestCallbacks.length; ++i) {
var callback = this._pendingDocumentRequestCallbacks[i];
if (callback)
callback(this._document);
}
delete this._pendingDocumentRequestCallbacks;
}

DOMAgent.getDocument(onDocumentAvailable.bind(this));
},

pushNodeToFrontend: function(objectId, callback)
{
this._dispatchWhenDocumentAvailable(DOMAgent.pushNodeToFrontend.bind(DOMAgent), objectId, callback);
},

pushNodeByPathToFrontend: function(path, callback)
{
this._dispatchWhenDocumentAvailable(DOMAgent.pushNodeByPathToFrontend.bind(DOMAgent), path, callback);
},

_wrapClientCallback: function(callback)
{
if (!callback)
return;
return function(error, result)
{
if (error)
console.error("Error during DOMAgent operation: " + error);
callback(error ? null : result);
}
},

_dispatchWhenDocumentAvailable: function(action)
{
var requestArguments = Array.prototype.slice.call(arguments, 1);
var callbackWrapper;

if (typeof requestArguments[requestArguments.length - 1] === "function") {
var callback = requestArguments.pop();
callbackWrapper = this._wrapClientCallback(callback);
requestArguments.push(callbackWrapper);
}
function onDocumentAvailable()
{
if (this._document)
action.apply(null, requestArguments);
else {
if (callbackWrapper)
callbackWrapper("No document");
}
}
this.requestDocument(onDocumentAvailable.bind(this));
},

_attributesUpdated: function(nodeId, attrsArray)
{
var node = this._idToDOMNode[nodeId];
node._setAttributesPayload(attrsArray);
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.AttrModified, node);
},

_characterDataModified: function(nodeId, newValue)
{
var node = this._idToDOMNode[nodeId];
node._nodeValue = newValue;
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.CharacterDataModified, node);
},

nodeForId: function(nodeId)
{
return this._idToDOMNode[nodeId];
},

_documentUpdated: function()
{
this._setDocument(null);
this.requestDocument();
},

_setDocument: function(payload)
{
this._idToDOMNode = {};
if (payload && "id" in payload) {
this._document = new WebInspector.DOMDocument(this, payload);
this._idToDOMNode[payload.id] = this._document;
if (this._document.children)
this._bindNodes(this._document.children);
} else
this._document = null;
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.DocumentUpdated, this._document);
},

_setDetachedRoot: function(payload)
{
var root = new WebInspector.DOMNode(this._document, payload);
this._idToDOMNode[payload.id] = root;
},

_setChildNodes: function(parentId, payloads)
{
if (!parentId && payloads.length) {
this._setDetachedRoot(payloads[0]);
return;
}

var parent = this._idToDOMNode[parentId];
parent._setChildrenPayload(payloads);
this._bindNodes(parent.children);
},

_bindNodes: function(children)
{
for (var i = 0; i < children.length; ++i) {
var child = children[i];
this._idToDOMNode[child.id] = child;
if (child.children)
this._bindNodes(child.children);
}
},

_childNodeCountUpdated: function(nodeId, newValue)
{
var node = this._idToDOMNode[nodeId];
node._childNodeCount = newValue;
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.ChildNodeCountUpdated, node);
},

_childNodeInserted: function(parentId, prevId, payload)
{
var parent = this._idToDOMNode[parentId];
var prev = this._idToDOMNode[prevId];
var node = parent._insertChild(prev, payload);
this._idToDOMNode[node.id] = node;
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.NodeInserted, node);
},

_childNodeRemoved: function(parentId, nodeId)
{
var parent = this._idToDOMNode[parentId];
var node = this._idToDOMNode[nodeId];
parent.removeChild_(node);
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.NodeRemoved, {node:node, parent:parent});
delete this._idToDOMNode[nodeId];
if (Preferences.nativeInstrumentationEnabled)
WebInspector.panels.elements.sidebarPanes.domBreakpoints.nodeRemoved(node);
},

performSearch: function(query, searchResultCollector, searchSynchronously)
{
this._searchResultCollector = searchResultCollector;
DOMAgent.performSearch(query, !!searchSynchronously);
},

cancelSearch: function()
{
delete this._searchResultCollector;
DOMAgent.cancelSearch();
},

querySelector: function(nodeId, selectors, callback)
{
DOMAgent.querySelector(nodeId, selectors, this._wrapClientCallback(callback));
},

querySelectorAll: function(nodeId, selectors, callback)
{
DOMAgent.querySelectorAll(nodeId, selectors, this._wrapClientCallback(callback));
}
}

WebInspector.DOMAgent.prototype.__proto__ = WebInspector.Object.prototype;

WebInspector.DOMDispatcher = function(domAgent)
{
this._domAgent = domAgent;
}

WebInspector.DOMDispatcher.prototype = {
documentUpdated: function()
{
this._domAgent._documentUpdated();
},

attributesUpdated: function(nodeId, attrsArray)
{
this._domAgent._attributesUpdated(nodeId, attrsArray);
},

characterDataModified: function(nodeId, newValue)
{
this._domAgent._characterDataModified(nodeId, newValue);
},

setChildNodes: function(parentId, payloads)
{
this._domAgent._setChildNodes(parentId, payloads);
},

childNodeCountUpdated: function(nodeId, newValue)
{
this._domAgent._childNodeCountUpdated(nodeId, newValue);
},

childNodeInserted: function(parentId, prevId, payload)
{
this._domAgent._childNodeInserted(parentId, prevId, payload);
},

childNodeRemoved: function(parentId, nodeId)
{
this._domAgent._childNodeRemoved(parentId, nodeId);
},

inspectElementRequested: function(nodeId)
{
WebInspector.updateFocusedNode(nodeId);
},

searchResults: function(nodeIds)
{
if (this._domAgent._searchResultCollector)
this._domAgent._searchResultCollector(nodeIds);
}
}





WebInspector.TimelineAgent = function() {

}


WebInspector.TimelineAgent.RecordType = {
EventDispatch: "EventDispatch",
Layout: "Layout",
RecalculateStyles: "RecalculateStyles",
Paint: "Paint",
ParseHTML: "ParseHTML",

TimerInstall: "TimerInstall",
TimerRemove: "TimerRemove",
TimerFire: "TimerFire",

XHRReadyStateChange: "XHRReadyStateChange",
XHRLoad: "XHRLoad",
EvaluateScript: "EvaluateScript",

MarkTimeline: "MarkTimeline",
MarkLoad: "MarkLoad",
MarkDOMContent: "MarkDOMContent",

ScheduleResourceRequest: "ScheduleResourceRequest",
ResourceSendRequest: "ResourceSendRequest",
ResourceReceiveResponse: "ResourceReceiveResponse",
ResourceReceivedData: "ResourceReceivedData",
ResourceFinish: "ResourceFinish",

FunctionCall: "FunctionCall",
GCEvent: "GCEvent"
};





WebInspector.TimelinePanel = function()
{
WebInspector.Panel.call(this, "timeline");

this.element.appendChild(this._createTopPane());
this.element.tabIndex = 0;

this._sidebarBackgroundElement = document.createElement("div");
this._sidebarBackgroundElement.className = "sidebar timeline-sidebar-background";
this.element.appendChild(this._sidebarBackgroundElement);

this._containerElement = document.createElement("div");
this._containerElement.id = "timeline-container";
this._containerElement.addEventListener("scroll", this._onScroll.bind(this), false);
this.element.appendChild(this._containerElement);

this.createSidebar(this._containerElement, this._containerElement);
var itemsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("RECORDS"), {}, true);
itemsTreeElement.expanded = true;
this.sidebarTree.appendChild(itemsTreeElement);

this._sidebarListElement = document.createElement("div");
this.sidebarElement.appendChild(this._sidebarListElement);

this._containerContentElement = document.createElement("div");
this._containerContentElement.id = "resources-container-content";
this._containerElement.appendChild(this._containerContentElement);

this._timelineGrid = new WebInspector.TimelineGrid();
this._itemsGraphsElement = this._timelineGrid.itemsGraphsElement;
this._itemsGraphsElement.id = "timeline-graphs";
this._containerContentElement.appendChild(this._timelineGrid.element);

this._topGapElement = document.createElement("div");
this._topGapElement.className = "timeline-gap";
this._itemsGraphsElement.appendChild(this._topGapElement);

this._graphRowsElement = document.createElement("div");
this._itemsGraphsElement.appendChild(this._graphRowsElement);

this._bottomGapElement = document.createElement("div");
this._bottomGapElement.className = "timeline-gap";
this._itemsGraphsElement.appendChild(this._bottomGapElement);

this._expandElements = document.createElement("div");
this._expandElements.id = "orphan-expand-elements";
this._itemsGraphsElement.appendChild(this._expandElements);

this._rootRecord = this._createRootRecord();
this._sendRequestRecords = {};
this._scheduledResourceRequests = {};
this._timerRecords = {};

this._calculator = new WebInspector.TimelineCalculator();
this._calculator._showShortEvents = false;
var shortRecordThresholdTitle = Number.secondsToString(WebInspector.TimelinePanel.shortRecordThreshold);
this._showShortRecordsTitleText = WebInspector.UIString("Show the records that are shorter than %s", shortRecordThresholdTitle);
this._hideShortRecordsTitleText = WebInspector.UIString("Hide the records that are shorter than %s", shortRecordThresholdTitle);
this._createStatusbarButtons();

this._boundariesAreValid = true;
this._scrollTop = 0;

this._popoverHelper = new WebInspector.PopoverHelper(this._containerElement, this._getPopoverAnchor.bind(this), this._showPopover.bind(this), true);


this.toggleFilterButton.toggled = true;
this._calculator._showShortEvents = this.toggleFilterButton.toggled;
this._markTimelineRecords = [];
this._expandOffset = 15;

WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded, this._onTimelineEventRecorded, this);
}


WebInspector.TimelinePanel.rowHeight = 18;
WebInspector.TimelinePanel.shortRecordThreshold = 0.015;

WebInspector.TimelinePanel.prototype = {
_createTopPane: function() {
var topPaneElement = document.createElement("div");
topPaneElement.id = "timeline-overview-panel";

this._topPaneSidebarElement = document.createElement("div");
this._topPaneSidebarElement.id = "timeline-overview-sidebar";

var overviewTreeElement = document.createElement("ol");
overviewTreeElement.className = "sidebar-tree";
this._topPaneSidebarElement.appendChild(overviewTreeElement);
topPaneElement.appendChild(this._topPaneSidebarElement);

var topPaneSidebarTree = new TreeOutline(overviewTreeElement);
var timelinesOverviewItem = new WebInspector.SidebarTreeElement("resources-time-graph-sidebar-item", WebInspector.UIString("Timelines"));
topPaneSidebarTree.appendChild(timelinesOverviewItem);
timelinesOverviewItem.onselect = this._timelinesOverviewItemSelected.bind(this);
timelinesOverviewItem.select(true);

var memoryOverviewItem = new WebInspector.SidebarTreeElement("resources-size-graph-sidebar-item", WebInspector.UIString("Memory"));
topPaneSidebarTree.appendChild(memoryOverviewItem);
memoryOverviewItem.onselect = this._memoryOverviewItemSelected.bind(this);

this._overviewPane = new WebInspector.TimelineOverviewPane(this.categories);
this._overviewPane.addEventListener("window changed", this._windowChanged, this);
this._overviewPane.addEventListener("filter changed", this._refresh, this);
topPaneElement.appendChild(this._overviewPane.element);

var separatorElement = document.createElement("div");
separatorElement.id = "timeline-overview-separator";
topPaneElement.appendChild(separatorElement);
return topPaneElement;
},

get toolbarItemLabel()
{
return WebInspector.UIString("Timeline");
},

get statusBarItems()
{
return [this.toggleFilterButton.element, this.toggleTimelineButton.element, this.garbageCollectButton.element, this.clearButton.element, this._overviewPane.statusBarFilters];
},

get categories()
{
if (!this._categories) {
this._categories = {
loading: new WebInspector.TimelineCategory("loading", WebInspector.UIString("Loading"), "rgb(47,102,236)"),
scripting: new WebInspector.TimelineCategory("scripting", WebInspector.UIString("Scripting"), "rgb(157,231,119)"),
rendering: new WebInspector.TimelineCategory("rendering", WebInspector.UIString("Rendering"), "rgb(164,60,255)")
};
}
return this._categories;
},

get defaultFocusedElement()
{
return this.element;
},

get _recordStyles()
{
if (!this._recordStylesArray) {
var recordTypes = WebInspector.TimelineAgent.RecordType;
var recordStyles = {};
recordStyles[recordTypes.EventDispatch] = { title: WebInspector.UIString("Event"), category: this.categories.scripting };
recordStyles[recordTypes.Layout] = { title: WebInspector.UIString("Layout"), category: this.categories.rendering };
recordStyles[recordTypes.RecalculateStyles] = { title: WebInspector.UIString("Recalculate Style"), category: this.categories.rendering };
recordStyles[recordTypes.Paint] = { title: WebInspector.UIString("Paint"), category: this.categories.rendering };
recordStyles[recordTypes.ParseHTML] = { title: WebInspector.UIString("Parse"), category: this.categories.loading };
recordStyles[recordTypes.TimerInstall] = { title: WebInspector.UIString("Install Timer"), category: this.categories.scripting };
recordStyles[recordTypes.TimerRemove] = { title: WebInspector.UIString("Remove Timer"), category: this.categories.scripting };
recordStyles[recordTypes.TimerFire] = { title: WebInspector.UIString("Timer Fired"), category: this.categories.scripting };
recordStyles[recordTypes.XHRReadyStateChange] = { title: WebInspector.UIString("XHR Ready State Change"), category: this.categories.scripting };
recordStyles[recordTypes.XHRLoad] = { title: WebInspector.UIString("XHR Load"), category: this.categories.scripting };
recordStyles[recordTypes.EvaluateScript] = { title: WebInspector.UIString("Evaluate Script"), category: this.categories.scripting };
recordStyles[recordTypes.MarkTimeline] = { title: WebInspector.UIString("Mark"), category: this.categories.scripting };
recordStyles[recordTypes.ResourceSendRequest] = { title: WebInspector.UIString("Send Request"), category: this.categories.loading };
recordStyles[recordTypes.ResourceReceiveResponse] = { title: WebInspector.UIString("Receive Response"), category: this.categories.loading };
recordStyles[recordTypes.ResourceFinish] = { title: WebInspector.UIString("Finish Loading"), category: this.categories.loading };
recordStyles[recordTypes.FunctionCall] = { title: WebInspector.UIString("Function Call"), category: this.categories.scripting };
recordStyles[recordTypes.ResourceReceivedData] = { title: WebInspector.UIString("Receive Data"), category: this.categories.loading };
recordStyles[recordTypes.GCEvent] = { title: WebInspector.UIString("GC Event"), category: this.categories.scripting };
recordStyles[recordTypes.MarkDOMContent] = { title: WebInspector.UIString("DOMContent event"), category: this.categories.scripting };
recordStyles[recordTypes.MarkLoad] = { title: WebInspector.UIString("Load event"), category: this.categories.scripting };
recordStyles[recordTypes.ScheduleResourceRequest] = { title: WebInspector.UIString("Schedule Request"), category: this.categories.loading };
this._recordStylesArray = recordStyles;
}
return this._recordStylesArray;
},

_createStatusbarButtons: function()
{
this.toggleTimelineButton = new WebInspector.StatusBarButton(WebInspector.UIString("Record"), "record-profile-status-bar-item");
this.toggleTimelineButton.addEventListener("click", this._toggleTimelineButtonClicked.bind(this), false);

this.clearButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear"), "clear-status-bar-item");
this.clearButton.addEventListener("click", this._clearPanel.bind(this), false);

this.toggleFilterButton = new WebInspector.StatusBarButton(this._hideShortRecordsTitleText, "timeline-filter-status-bar-item");
this.toggleFilterButton.addEventListener("click", this._toggleFilterButtonClicked.bind(this), false);

this.garbageCollectButton = new WebInspector.StatusBarButton(WebInspector.UIString("Collect Garbage"), "garbage-collect-status-bar-item");
this.garbageCollectButton.addEventListener("click", this._garbageCollectButtonClicked.bind(this), false);

this.recordsCounter = document.createElement("span");
this.recordsCounter.className = "timeline-records-counter";
},

_updateRecordsCounter: function()
{
this.recordsCounter.textContent = WebInspector.UIString("%d of %d captured records are visible", this._rootRecord._visibleRecordsCount, this._rootRecord._allRecordsCount);
},

_updateEventDividers: function()
{
this._timelineGrid.removeEventDividers();
var clientWidth = this._graphRowsElement.offsetWidth - this._expandOffset;
var dividers = [];
for (var i = 0; i < this._markTimelineRecords.length; ++i) {
var record = this._markTimelineRecords[i];
var positions = this._calculator.computeBarGraphWindowPosition(record, clientWidth);
var dividerPosition = Math.round(positions.left);
if (dividerPosition < 0 || dividerPosition >= clientWidth || dividers[dividerPosition])
continue;
var divider = this._createEventDivider(record);
divider.style.left = (dividerPosition + this._expandOffset) + "px";
dividers[dividerPosition] = divider;
}
this._timelineGrid.addEventDividers(dividers);
this._overviewPane.updateEventDividers(this._markTimelineRecords, this._createEventDivider.bind(this));
},

_createEventDivider: function(record)
{
var eventDivider = document.createElement("div");
eventDivider.className = "resources-event-divider";
var recordTypes = WebInspector.TimelineAgent.RecordType;

var eventDividerPadding = document.createElement("div");
eventDividerPadding.className = "resources-event-divider-padding";
eventDividerPadding.title = record.title;

if (record.type === recordTypes.MarkDOMContent)
eventDivider.className += " resources-blue-divider";
else if (record.type === recordTypes.MarkLoad)
eventDivider.className += " resources-red-divider";
else if (record.type === recordTypes.MarkTimeline) {
eventDivider.className += " resources-orange-divider";
eventDividerPadding.title = record.data.message;
}
eventDividerPadding.appendChild(eventDivider);
return eventDividerPadding;
},

_timelinesOverviewItemSelected: function(event) {
this._overviewPane.showTimelines();
},

_memoryOverviewItemSelected: function(event) {
this._overviewPane.showMemoryGraph(this._rootRecord.children);
},

_toggleTimelineButtonClicked: function()
{
if (this.toggleTimelineButton.toggled)
WebInspector.timelineManager.stop();
else {
this._clearPanel();
WebInspector.timelineManager.start();
}
this.toggleTimelineButton.toggled = !this.toggleTimelineButton.toggled;
},

_toggleFilterButtonClicked: function()
{
this.toggleFilterButton.toggled = !this.toggleFilterButton.toggled;
this._calculator._showShortEvents = this.toggleFilterButton.toggled;
this.toggleFilterButton.element.title = this._calculator._showShortEvents ? this._hideShortRecordsTitleText : this._showShortRecordsTitleText;
this._scheduleRefresh(true);
},

_garbageCollectButtonClicked: function()
{
ProfilerAgent.collectGarbage();
},

_onTimelineEventRecorded: function(event)
{
if (this.toggleTimelineButton.toggled)
this._addRecordToTimeline(event.data);
},

_addRecordToTimeline: function(record)
{
if (record.type === WebInspector.TimelineAgent.RecordType.ResourceSendRequest) {
var isMainResource = (record.data.identifier === WebInspector.mainResource.identifier);
if (isMainResource && this._mainResourceIdentifier !== record.data.identifier) {



this._mainResourceIdentifier = record.data.identifier;
this._clearPanel();
}
}
this._innerAddRecordToTimeline(record, this._rootRecord);
this._scheduleRefresh();
},

_findParentRecord: function(record)
{
var recordTypes = WebInspector.TimelineAgent.RecordType;
var parentRecord;
if (record.type === recordTypes.ResourceReceiveResponse ||
record.type === recordTypes.ResourceFinish ||
record.type === recordTypes.ResourceReceivedData)
parentRecord = this._sendRequestRecords[record.data.identifier];
else if (record.type === recordTypes.TimerFire)
parentRecord = this._timerRecords[record.data.timerId];
else if (record.type === recordTypes.ResourceSendRequest)
parentRecord = this._scheduledResourceRequests[record.data.url];
return parentRecord;
},

_innerAddRecordToTimeline: function(record, parentRecord)
{
var connectedToOldRecord = false;
var recordTypes = WebInspector.TimelineAgent.RecordType;
if (record.type === recordTypes.MarkDOMContent || record.type === recordTypes.MarkLoad)
parentRecord = null; 
else if (parentRecord === this._rootRecord) {
var newParentRecord = this._findParentRecord(record);
if (newParentRecord) {
parentRecord = newParentRecord;
connectedToOldRecord = true;
}
}

var children = record.children;
var scriptDetails;
if (record.data && record.data.scriptName) {
scriptDetails = {
scriptName: record.data.scriptName,
scriptLine: record.data.scriptLine
}
};
if (record.type === recordTypes.TimerFire && children && children.length) {
var childRecord = children[0];
if (childRecord.type === recordTypes.FunctionCall) {
scriptDetails = {
scriptName: childRecord.data.scriptName,
scriptLine: childRecord.data.scriptLine
};
children = childRecord.children.concat(children.slice(1));
}
}

var formattedRecord = new WebInspector.TimelinePanel.FormattedRecord(record, parentRecord, this, scriptDetails);

if (record.type === recordTypes.MarkDOMContent || record.type === recordTypes.MarkLoad) {
this._markTimelineRecords.push(formattedRecord);
return;
}

++this._rootRecord._allRecordsCount;
formattedRecord.collapsed = (parentRecord === this._rootRecord);

var childrenCount = children ? children.length : 0;
for (var i = 0; i < childrenCount; ++i)
this._innerAddRecordToTimeline(children[i], formattedRecord);

formattedRecord._calculateAggregatedStats(this.categories);

if (connectedToOldRecord) {
var record = formattedRecord;
do {
var parent = record.parent;
parent._cpuTime += formattedRecord._cpuTime;
if (parent._lastChildEndTime < record._lastChildEndTime)
parent._lastChildEndTime = record._lastChildEndTime;
for (var category in formattedRecord._aggregatedStats)
parent._aggregatedStats[category] += formattedRecord._aggregatedStats[category];
record = parent;
} while (record.parent);
} else
if (parentRecord !== this._rootRecord)
parentRecord._selfTime -= formattedRecord.endTime - formattedRecord.startTime;


if (record.type === recordTypes.MarkTimeline)
this._markTimelineRecords.push(formattedRecord);
},

setSidebarWidth: function(width)
{
WebInspector.Panel.prototype.setSidebarWidth.call(this, width);
this._sidebarBackgroundElement.style.width = width + "px";
this._topPaneSidebarElement.style.width = width + "px";
},

updateMainViewWidth: function(width)
{
this._containerContentElement.style.left = width + "px";
this._scheduleRefresh();
this._overviewPane.updateMainViewWidth(width);
},

resize: function()
{
this._closeRecordDetails();
this._scheduleRefresh();
},

_createRootRecord: function()
{
var rootRecord = {};
rootRecord.children = [];
rootRecord._visibleRecordsCount = 0;
rootRecord._allRecordsCount = 0;
rootRecord._aggregatedStats = {};
return rootRecord;
},

_clearPanel: function()
{
this._markTimelineRecords = [];
this._sendRequestRecords = {};
this._scheduledResourceRequests = {};
this._timerRecords = {};
this._rootRecord = this._createRootRecord();
this._boundariesAreValid = false;
this._overviewPane.reset();
this._adjustScrollPosition(0);
this._refresh();
this._closeRecordDetails();
},

show: function()
{
WebInspector.Panel.prototype.show.call(this);
if (typeof this._scrollTop === "number")
this._containerElement.scrollTop = this._scrollTop;
this._refresh();
WebInspector.drawer.currentPanelCounters = this.recordsCounter;
},

hide: function()
{
WebInspector.Panel.prototype.hide.call(this);
this._closeRecordDetails();
WebInspector.drawer.currentPanelCounters = null;
},

_onScroll: function(event)
{
this._closeRecordDetails();
var scrollTop = this._containerElement.scrollTop;
var dividersTop = Math.max(0, scrollTop);
this._timelineGrid.setScrollAndDividerTop(scrollTop, dividersTop);
this._scheduleRefresh(true);
},

_windowChanged: function()
{
this._closeRecordDetails();
this._scheduleRefresh();
},

_scheduleRefresh: function(preserveBoundaries)
{
this._closeRecordDetails();
this._boundariesAreValid &= preserveBoundaries;

if (!this.visible)
return;

if (preserveBoundaries)
this._refresh();
else
if (!this._refreshTimeout)
this._refreshTimeout = setTimeout(this._refresh.bind(this), 100);
},

_refresh: function()
{
if (this._refreshTimeout) {
clearTimeout(this._refreshTimeout);
delete this._refreshTimeout;
}

this._overviewPane.update(this._rootRecord.children, this._calculator._showShortEvents);
this._refreshRecords(!this._boundariesAreValid);
this._updateRecordsCounter();
if(!this._boundariesAreValid)
this._updateEventDividers();
this._boundariesAreValid = true;
},

_updateBoundaries: function()
{
this._calculator.reset();
this._calculator.windowLeft = this._overviewPane.windowLeft;
this._calculator.windowRight = this._overviewPane.windowRight;

for (var i = 0; i < this._rootRecord.children.length; ++i)
this._calculator.updateBoundaries(this._rootRecord.children[i]);

this._calculator.calculateWindow();
},

_addToRecordsWindow: function(record, recordsWindow, parentIsCollapsed)
{
if (!this._calculator._showShortEvents && !record.isLong())
return;
var percentages = this._calculator.computeBarGraphPercentages(record);
if (percentages.start < 100 && percentages.endWithChildren >= 0 && !record.category.hidden) {
++this._rootRecord._visibleRecordsCount;
++record.parent._invisibleChildrenCount;
if (!parentIsCollapsed)
recordsWindow.push(record);
}

var index = recordsWindow.length;
record._invisibleChildrenCount = 0;
for (var i = 0; i < record.children.length; ++i)
this._addToRecordsWindow(record.children[i], recordsWindow, parentIsCollapsed || record.collapsed);
record._visibleChildrenCount = recordsWindow.length - index;
},

_filterRecords: function()
{
var recordsInWindow = [];
this._rootRecord._visibleRecordsCount = 0;
for (var i = 0; i < this._rootRecord.children.length; ++i)
this._addToRecordsWindow(this._rootRecord.children[i], recordsInWindow);
return recordsInWindow;
},

_refreshRecords: function(updateBoundaries)
{
if (updateBoundaries)
this._updateBoundaries();

var recordsInWindow = this._filterRecords();


this._scrollTop = this._containerElement.scrollTop;
var visibleTop = this._scrollTop;
var visibleBottom = visibleTop + this._containerElement.clientHeight;

const rowHeight = WebInspector.TimelinePanel.rowHeight;


var startIndex = Math.max(0, Math.min(Math.floor(visibleTop / rowHeight) - 1, recordsInWindow.length - 1));
var endIndex = Math.min(recordsInWindow.length, Math.ceil(visibleBottom / rowHeight));


const top = (startIndex * rowHeight) + "px";
this._topGapElement.style.height = top;
this.sidebarElement.style.top = top;
this.sidebarResizeElement.style.top = top;
this._bottomGapElement.style.height = (recordsInWindow.length - endIndex) * rowHeight + "px";


var listRowElement = this._sidebarListElement.firstChild;
var width = this._graphRowsElement.offsetWidth;
this._itemsGraphsElement.removeChild(this._graphRowsElement);
var graphRowElement = this._graphRowsElement.firstChild;
var scheduleRefreshCallback = this._scheduleRefresh.bind(this, true);
this._itemsGraphsElement.removeChild(this._expandElements);
this._expandElements.removeChildren();

for (var i = 0; i < endIndex; ++i) {
var record = recordsInWindow[i];
var isEven = !(i % 2);

if (i < startIndex) {
var lastChildIndex = i + record._visibleChildrenCount;
if (lastChildIndex >= startIndex && lastChildIndex < endIndex) {
var expandElement = new WebInspector.TimelineExpandableElement(this._expandElements);
expandElement._update(record, i, this._calculator.computeBarGraphWindowPosition(record, width - this._expandOffset));
}
} else {
if (!listRowElement) {
listRowElement = new WebInspector.TimelineRecordListRow().element;
this._sidebarListElement.appendChild(listRowElement);
}
if (!graphRowElement) {
graphRowElement = new WebInspector.TimelineRecordGraphRow(this._itemsGraphsElement, scheduleRefreshCallback, rowHeight).element;
this._graphRowsElement.appendChild(graphRowElement);
}

listRowElement.row.update(record, isEven, this._calculator, visibleTop);
graphRowElement.row.update(record, isEven, this._calculator, width, this._expandOffset, i);

listRowElement = listRowElement.nextSibling;
graphRowElement = graphRowElement.nextSibling;
}
}


while (listRowElement) {
var nextElement = listRowElement.nextSibling;
listRowElement.row.dispose();
listRowElement = nextElement;
}
while (graphRowElement) {
var nextElement = graphRowElement.nextSibling;
graphRowElement.row.dispose();
graphRowElement = nextElement;
}

this._itemsGraphsElement.insertBefore(this._graphRowsElement, this._bottomGapElement);
this._itemsGraphsElement.appendChild(this._expandElements);
this.sidebarResizeElement.style.height = this.sidebarElement.clientHeight + "px";

var timelinePaddingLeft = this._calculator.windowLeft === 0 ? this._expandOffset : 0;
if (updateBoundaries)
this._timelineGrid.updateDividers(true, this._calculator, timelinePaddingLeft);
this._adjustScrollPosition((recordsInWindow.length + 1) * rowHeight);
},

_adjustScrollPosition: function(totalHeight)
{

if ((this._containerElement.scrollTop + this._containerElement.offsetHeight) > totalHeight + 1)
this._containerElement.scrollTop = (totalHeight - this._containerElement.offsetHeight);
},

_getPopoverAnchor: function(element)
{
return element.enclosingNodeOrSelfWithClass("timeline-graph-bar") || element.enclosingNodeOrSelfWithClass("timeline-tree-item");
},

_showPopover: function(anchor)
{
var record = anchor.row._record;
var popover = new WebInspector.Popover(record._generatePopupContent(this._calculator, this.categories));
popover.show(anchor);
return popover;
},

_closeRecordDetails: function()
{
this._popoverHelper.hidePopup();
}
}

WebInspector.TimelinePanel.prototype.__proto__ = WebInspector.Panel.prototype;

WebInspector.TimelineCategory = function(name, title, color)
{
this.name = name;
this.title = title;
this.color = color;
}

WebInspector.TimelineCalculator = function()
{
this.reset();
this.windowLeft = 0.0;
this.windowRight = 1.0;
}

WebInspector.TimelineCalculator.prototype = {
computeBarGraphPercentages: function(record)
{
var start = (record.startTime - this.minimumBoundary) / this.boundarySpan * 100;
var end = (record.startTime + record._selfTime - this.minimumBoundary) / this.boundarySpan * 100;
var endWithChildren = (record._lastChildEndTime - this.minimumBoundary) / this.boundarySpan * 100;
var cpuWidth = record._cpuTime / this.boundarySpan * 100;
return {start: start, end: end, endWithChildren: endWithChildren, cpuWidth: cpuWidth};
},

computeBarGraphWindowPosition: function(record, clientWidth)
{
const minWidth = 5;
const borderWidth = 4;
var workingArea = clientWidth - minWidth - borderWidth;
var percentages = this.computeBarGraphPercentages(record);
var left = percentages.start / 100 * workingArea;
var width = (percentages.end - percentages.start) / 100 * workingArea + minWidth;
var widthWithChildren =  (percentages.endWithChildren - percentages.start) / 100 * workingArea;
var cpuWidth = percentages.cpuWidth / 100 * workingArea + minWidth;
if (percentages.endWithChildren > percentages.end)
widthWithChildren += borderWidth + minWidth;
return {left: left, width: width, widthWithChildren: widthWithChildren, cpuWidth: cpuWidth};
},

calculateWindow: function()
{
this.minimumBoundary = this._absoluteMinimumBoundary + this.windowLeft * (this._absoluteMaximumBoundary - this._absoluteMinimumBoundary);
this.maximumBoundary = this._absoluteMinimumBoundary + this.windowRight * (this._absoluteMaximumBoundary - this._absoluteMinimumBoundary);
this.boundarySpan = this.maximumBoundary - this.minimumBoundary;
},

reset: function()
{
this._absoluteMinimumBoundary = -1;
this._absoluteMaximumBoundary = -1;
},

updateBoundaries: function(record)
{
var lowerBound = record.startTime;
if (this._absoluteMinimumBoundary === -1 || lowerBound < this._absoluteMinimumBoundary)
this._absoluteMinimumBoundary = lowerBound;

const minimumTimeFrame = 0.1;
const minimumDeltaForZeroSizeEvents = 0.01;
var upperBound = Math.max(record._lastChildEndTime + minimumDeltaForZeroSizeEvents, lowerBound + minimumTimeFrame);
if (this._absoluteMaximumBoundary === -1 || upperBound > this._absoluteMaximumBoundary)
this._absoluteMaximumBoundary = upperBound;
},

formatValue: function(value)
{
return Number.secondsToString(value + this.minimumBoundary - this._absoluteMinimumBoundary);
}
}


WebInspector.TimelineRecordListRow = function()
{
this.element = document.createElement("div");
this.element.row = this;
this.element.style.cursor = "pointer";
var iconElement = document.createElement("span");
iconElement.className = "timeline-tree-icon";
this.element.appendChild(iconElement);

this._typeElement = document.createElement("span");
this._typeElement.className = "type";
this.element.appendChild(this._typeElement);

var separatorElement = document.createElement("span");
separatorElement.className = "separator";
separatorElement.textContent = " ";

this._dataElement = document.createElement("span");
this._dataElement.className = "data dimmed";

this.element.appendChild(separatorElement);
this.element.appendChild(this._dataElement);
}

WebInspector.TimelineRecordListRow.prototype = {
update: function(record, isEven, calculator, offset)
{
this._record = record;
this._calculator = calculator;
this._offset = offset;

this.element.className = "timeline-tree-item timeline-category-" + record.category.name + (isEven ? " even" : "");
this._typeElement.textContent = record.title;

if (this._dataElement.firstChild)
this._dataElement.removeChildren();
if (record.details) {
var detailsContainer = document.createElement("span");
if (typeof record.details === "object") {
detailsContainer.appendChild(document.createTextNode("("));
detailsContainer.appendChild(record.details);
detailsContainer.appendChild(document.createTextNode(")"));
} else
detailsContainer.textContent = "(" + record.details + ")";
this._dataElement.appendChild(detailsContainer);
}
},

dispose: function()
{
this.element.parentElement.removeChild(this.element);
}
}

WebInspector.TimelineRecordGraphRow = function(graphContainer, scheduleRefresh)
{
this.element = document.createElement("div");
this.element.row = this;

this._barAreaElement = document.createElement("div");
this._barAreaElement.className = "timeline-graph-bar-area";
this.element.appendChild(this._barAreaElement);

this._barWithChildrenElement = document.createElement("div");
this._barWithChildrenElement.className = "timeline-graph-bar with-children";
this._barWithChildrenElement.row = this;
this._barAreaElement.appendChild(this._barWithChildrenElement);

this._barCpuElement = document.createElement("div");
this._barCpuElement.className = "timeline-graph-bar cpu"
this._barCpuElement.row = this;
this._barAreaElement.appendChild(this._barCpuElement);

this._barElement = document.createElement("div");
this._barElement.className = "timeline-graph-bar";
this._barElement.row = this;
this._barAreaElement.appendChild(this._barElement);

this._expandElement = new WebInspector.TimelineExpandableElement(graphContainer);
this._expandElement._element.addEventListener("click", this._onClick.bind(this));

this._scheduleRefresh = scheduleRefresh;
}

WebInspector.TimelineRecordGraphRow.prototype = {
update: function(record, isEven, calculator, clientWidth, expandOffset, index)
{
this._record = record;
this.element.className = "timeline-graph-side timeline-category-" + record.category.name + (isEven ? " even" : "");
var barPosition = calculator.computeBarGraphWindowPosition(record, clientWidth - expandOffset);
this._barWithChildrenElement.style.left = barPosition.left + expandOffset + "px";
this._barWithChildrenElement.style.width = barPosition.widthWithChildren + "px";
this._barElement.style.left = barPosition.left + expandOffset + "px";
this._barElement.style.width =  barPosition.width + "px";
this._barCpuElement.style.left = barPosition.left + expandOffset + "px";
this._barCpuElement.style.width = barPosition.cpuWidth + "px";
this._expandElement._update(record, index, barPosition);
},

_onClick: function(event)
{
this._record.collapsed = !this._record.collapsed;
this._scheduleRefresh();
},

dispose: function()
{
this.element.parentElement.removeChild(this.element);
this._expandElement._dispose();
}
}

WebInspector.TimelinePanel.FormattedRecord = function(record, parentRecord, panel, scriptDetails)
{
var recordTypes = WebInspector.TimelineAgent.RecordType;
var style = panel._recordStyles[record.type];
this.parent = parentRecord;
if (parentRecord)
parentRecord.children.push(this);
this.category = style.category;
this.title = style.title;
this.startTime = record.startTime / 1000;
this.data = record.data;
this.type = record.type;
this.endTime = (typeof record.endTime !== "undefined") ? record.endTime / 1000 : this.startTime;
this._selfTime = this.endTime - this.startTime;
this._lastChildEndTime = this.endTime;
if (record.stackTrace && record.stackTrace.length)
this.stackTrace = record.stackTrace;
this.totalHeapSize = record.totalHeapSize;
this.usedHeapSize = record.usedHeapSize;
if (record.data && record.data.url)
this.url = record.data.url;
if (scriptDetails) {
this.scriptName = scriptDetails.scriptName;
this.scriptLine = scriptDetails.scriptLine;
}

if (record.type === recordTypes.ResourceSendRequest) {
panel._sendRequestRecords[record.data.identifier] = this;
} else if (record.type === recordTypes.ScheduleResourceRequest) {
panel._scheduledResourceRequests[record.data.url] = this;
} else if (record.type === recordTypes.ResourceReceiveResponse) {
var sendRequestRecord = panel._sendRequestRecords[record.data.identifier];
if (sendRequestRecord) { 
this.url = sendRequestRecord.url;

sendRequestRecord._refreshDetails();
if (sendRequestRecord.parent !== panel._rootRecord && sendRequestRecord.parent.type === recordTypes.ScheduleResourceRequest)
sendRequestRecord.parent._refreshDetails();
}
} else if (record.type === recordTypes.ResourceReceivedData || record.type === recordTypes.ResourceFinish) {
var sendRequestRecord = panel._sendRequestRecords[record.data.identifier];
if (sendRequestRecord) 
this.url = sendRequestRecord.url;
} else if (record.type === recordTypes.TimerInstall) {
this.timeout = record.data.timeout;
this.singleShot = record.data.singleShot;
panel._timerRecords[record.data.timerId] = this;
} else if (record.type === recordTypes.TimerFire) {
var timerInstalledRecord = panel._timerRecords[record.data.timerId];
if (timerInstalledRecord) {
this.callSiteStackTrace = timerInstalledRecord.stackTrace;
this.timeout = timerInstalledRecord.timeout;
this.singleShot = timerInstalledRecord.singleShot;
}
}
this._refreshDetails();
}

WebInspector.TimelinePanel.FormattedRecord.prototype = {
isLong: function()
{
return (this._lastChildEndTime - this.startTime) > WebInspector.TimelinePanel.shortRecordThreshold;
},

get children()
{
if (!this._children)
this._children = [];
return this._children;
},

_generateAggregatedInfo: function()
{
var cell = document.createElement("span");
cell.className = "timeline-aggregated-info";
for (var index in this._aggregatedStats) {
var label = document.createElement("div");
label.className = "timeline-aggregated-category timeline-" + index;
cell.appendChild(label);
var text = document.createElement("span");
text.textContent = Number.secondsToString(this._aggregatedStats[index] + 0.0001);
cell.appendChild(text);
}
return cell;
},

_generatePopupContent: function(calculator, categories)
{
var contentHelper = new WebInspector.TimelinePanel.PopupContentHelper(this.title);

if (this._children && this._children.length) {
contentHelper._appendTextRow(WebInspector.UIString("Self Time"), Number.secondsToString(this._selfTime + 0.0001));
contentHelper._appendElementRow(WebInspector.UIString("Aggregated Time"), this._generateAggregatedInfo());
}
var text = WebInspector.UIString("%s (at %s)", Number.secondsToString(this._lastChildEndTime - this.startTime),
calculator.formatValue(this.startTime - calculator.minimumBoundary));
contentHelper._appendTextRow(WebInspector.UIString("Duration"), text);

const recordTypes = WebInspector.TimelineAgent.RecordType;

switch (this.type) {
case recordTypes.GCEvent:
contentHelper._appendTextRow(WebInspector.UIString("Collected"), Number.bytesToString(this.data.usedHeapSizeDelta));
break;
case recordTypes.TimerInstall:
case recordTypes.TimerFire:
case recordTypes.TimerRemove:
contentHelper._appendTextRow(WebInspector.UIString("Timer ID"), this.data.timerId);
if (typeof this.timeout === "number") {
contentHelper._appendTextRow(WebInspector.UIString("Timeout"), Number.secondsToString(this.timeout / 1000));
contentHelper._appendTextRow(WebInspector.UIString("Repeats"), !this.singleShot);
}
break;
case recordTypes.FunctionCall:
contentHelper._appendLinkRow(WebInspector.UIString("Location"), this.scriptName, this.scriptLine);
break;
case recordTypes.ScheduleResourceRequest:
case recordTypes.ResourceSendRequest:
case recordTypes.ResourceReceiveResponse:
case recordTypes.ResourceReceivedData:
case recordTypes.ResourceFinish:
contentHelper._appendLinkRow(WebInspector.UIString("Resource"), this.url);
if (this.data.requestMethod)
contentHelper._appendTextRow(WebInspector.UIString("Request Method"), this.data.requestMethod);
if (typeof this.data.statusCode === "number")
contentHelper._appendTextRow(WebInspector.UIString("Status Code"), this.data.statusCode);
if (this.data.mimeType)
contentHelper._appendTextRow(WebInspector.UIString("MIME Type"), this.data.mimeType);
break;
case recordTypes.EvaluateScript:
if (this.data && this.url)
contentHelper._appendLinkRow(WebInspector.UIString("Script"), this.url, this.data.lineNumber);
break;
case recordTypes.Paint:
contentHelper._appendTextRow(WebInspector.UIString("Location"), WebInspector.UIString("(%d, %d)", this.data.x, this.data.y));
contentHelper._appendTextRow(WebInspector.UIString("Dimensions"), WebInspector.UIString("%d × %d", this.data.width, this.data.height));
case recordTypes.RecalculateStyles: 
break;
default:
if (this.details)
contentHelper._appendTextRow(WebInspector.UIString("Details"), this.details);
break;
}

if (this.scriptName && this.type !== recordTypes.FunctionCall)
contentHelper._appendLinkRow(WebInspector.UIString("Function Call"), this.scriptName, this.scriptLine);

if (this.usedHeapSize)
contentHelper._appendTextRow(WebInspector.UIString("Used Heap Size"), WebInspector.UIString("%s of %s", Number.bytesToString(this.usedHeapSize), Number.bytesToString(this.totalHeapSize)));

if (this.callSiteStackTrace && this.callSiteStackTrace.length)
contentHelper._appendStackTrace(WebInspector.UIString("Call Site stack"), this.callSiteStackTrace);

if (this.stackTrace)
contentHelper._appendStackTrace(WebInspector.UIString("Call Stack"), this.stackTrace);

return contentHelper._contentTable;
},

_refreshDetails: function()
{
this.details = this._getRecordDetails();
},

_getRecordDetails: function()
{
switch (this.type) {
case WebInspector.TimelineAgent.RecordType.GCEvent:
return WebInspector.UIString("%s collected", Number.bytesToString(this.data.usedHeapSizeDelta));
case WebInspector.TimelineAgent.RecordType.TimerFire:
return this.scriptName ? WebInspector.linkifyResourceAsNode(this.scriptName, "scripts", this.scriptLine, "", "") : this.data.timerId;
case WebInspector.TimelineAgent.RecordType.FunctionCall:
return this.scriptName ? WebInspector.linkifyResourceAsNode(this.scriptName, "scripts", this.scriptLine, "", "") : null;
case WebInspector.TimelineAgent.RecordType.EventDispatch:
return this.data ? this.data.type : null;
case WebInspector.TimelineAgent.RecordType.Paint:
return this.data.width + "\u2009\u00d7\u2009" + this.data.height;
case WebInspector.TimelineAgent.RecordType.TimerInstall:
case WebInspector.TimelineAgent.RecordType.TimerRemove:
return this.stackTrace ? WebInspector.linkifyResourceAsNode(this.stackTrace[0].url, "scripts", this.stackTrace[0].lineNumber, "", "") : this.data.timerId;
case WebInspector.TimelineAgent.RecordType.ParseHTML:
case WebInspector.TimelineAgent.RecordType.RecalculateStyles:
return this.stackTrace ? WebInspector.linkifyResourceAsNode(this.stackTrace[0].url, "scripts", this.stackTrace[0].lineNumber, "", "") : null;
case WebInspector.TimelineAgent.RecordType.EvaluateScript:
return this.url ? WebInspector.linkifyResourceAsNode(this.url, "scripts", this.data.lineNumber, "", "") : null;
case WebInspector.TimelineAgent.RecordType.XHRReadyStateChange:
case WebInspector.TimelineAgent.RecordType.XHRLoad:
case WebInspector.TimelineAgent.RecordType.ScheduleResourceRequest:
case WebInspector.TimelineAgent.RecordType.ResourceSendRequest:
case WebInspector.TimelineAgent.RecordType.ResourceReceivedData:
case WebInspector.TimelineAgent.RecordType.ResourceReceiveResponse:
case WebInspector.TimelineAgent.RecordType.ResourceFinish:
return WebInspector.displayNameForURL(this.url);
case WebInspector.TimelineAgent.RecordType.MarkTimeline:
return this.data.message;
default:
return null;
}
},

_calculateAggregatedStats: function(categories)
{
this._aggregatedStats = {};
for (var category in categories)
this._aggregatedStats[category] = 0;
this._cpuTime = this._selfTime;

if (this._children) {
for (var index = this._children.length; index; --index) {
var child = this._children[index - 1];
this._aggregatedStats[child.category.name] += child._selfTime;
for (var category in categories)
this._aggregatedStats[category] += child._aggregatedStats[category];
}
for (var category in this._aggregatedStats)
this._cpuTime += this._aggregatedStats[category];
}
}
}

WebInspector.TimelinePanel.PopupContentHelper = function(title)
{
this._contentTable = document.createElement("table");;
var titleCell = this._createCell(WebInspector.UIString("%s - Details", title), "timeline-details-title");
titleCell.colSpan = 2;
var titleRow = document.createElement("tr");
titleRow.appendChild(titleCell);
this._contentTable.appendChild(titleRow);
}

WebInspector.TimelinePanel.PopupContentHelper.prototype = {
_createCell: function(content, styleName)
{
var text = document.createElement("label");
text.appendChild(document.createTextNode(content));
var cell = document.createElement("td");
cell.className = "timeline-details";
if (styleName)
cell.className += " " + styleName;
cell.textContent = content;
return cell;
},

_appendTextRow: function(title, content)
{
var row = document.createElement("tr");
row.appendChild(this._createCell(title, "timeline-details-row-title"));
row.appendChild(this._createCell(content, "timeline-details-row-data"));
this._contentTable.appendChild(row);
},

_appendElementRow: function(title, content, titleStyle)
{
var row = document.createElement("tr");
var titleCell = this._createCell(title, "timeline-details-row-title");
if (titleStyle)
titleCell.addStyleClass(titleStyle);
row.appendChild(titleCell);
var cell = document.createElement("td");
cell.className = "timeline-details";
cell.appendChild(content);
row.appendChild(cell);
this._contentTable.appendChild(row);
},

_appendLinkRow: function(title, scriptName, scriptLine)
{
var link = WebInspector.linkifyResourceAsNode(scriptName, "scripts", scriptLine, "timeline-details");
this._appendElementRow(title, link);
},

_appendStackTrace: function(title, stackTrace)
{
this._appendTextRow("", "");
var framesTable = document.createElement("table");
for (var i = 0; i < stackTrace.length; ++i) {
var stackFrame = stackTrace[i];
var row = document.createElement("tr");
row.className = "timeline-details";
row.appendChild(this._createCell(stackFrame.functionName ? stackFrame.functionName : WebInspector.UIString("(anonymous function)"), "timeline-function-name"));
row.appendChild(this._createCell(" @ "));
var linkCell = document.createElement("td");
linkCell.appendChild(WebInspector.linkifyResourceAsNode(stackFrame.url, "scripts", stackFrame.lineNumber, "timeline-details"));
row.appendChild(linkCell);
framesTable.appendChild(row);
}
this._appendElementRow(title, framesTable, "timeline-stacktrace-title");
}
}

WebInspector.TimelineExpandableElement = function(container)
{
this._element = document.createElement("div");
this._element.className = "timeline-expandable";

var leftBorder = document.createElement("div");
leftBorder.className = "timeline-expandable-left";
this._element.appendChild(leftBorder);

container.appendChild(this._element);
}

WebInspector.TimelineExpandableElement.prototype = {
_update: function(record, index, barPosition)
{
const rowHeight = WebInspector.TimelinePanel.rowHeight;
if (record._visibleChildrenCount || record._invisibleChildrenCount) {
this._element.style.top = index * rowHeight + "px";
this._element.style.left = barPosition.left + "px";
this._element.style.width = Math.max(12, barPosition.width + 25) + "px";
if (!record.collapsed) {
this._element.style.height = (record._visibleChildrenCount + 1) * rowHeight + "px";
this._element.addStyleClass("timeline-expandable-expanded");
this._element.removeStyleClass("timeline-expandable-collapsed");
} else {
this._element.style.height = rowHeight + "px";
this._element.addStyleClass("timeline-expandable-collapsed");
this._element.removeStyleClass("timeline-expandable-expanded");
}
this._element.removeStyleClass("hidden");
} else
this._element.addStyleClass("hidden");
},

_dispose: function()
{
this._element.parentElement.removeChild(this._element);
}
}





WebInspector.TimelineOverviewPane = function(categories)
{
this._categories = categories;

this.statusBarFilters = document.createElement("div");
this.statusBarFilters.className = "status-bar-items";
for (var categoryName in this._categories) {
var category = this._categories[categoryName];
this.statusBarFilters.appendChild(this._createTimelineCategoryStatusBarCheckbox(category, this._onCheckboxClicked.bind(this, category)));
}

this._overviewGrid = new WebInspector.TimelineGrid();
this._overviewGrid.element.id = "timeline-overview-grid";
this._overviewGrid.itemsGraphsElement.id = "timeline-overview-timelines";
this._overviewGrid.element.addEventListener("mousedown", this._dragWindow.bind(this), true);

this._heapGraph = new WebInspector.HeapGraph();
this._heapGraph.element.id = "timeline-overview-memory";
this._overviewGrid.element.insertBefore(this._heapGraph.element, this._overviewGrid.itemsGraphsElement);

this.element = this._overviewGrid.element;

this._categoryGraphs = {};
var i = 0;
for (var category in this._categories) {
var categoryGraph = new WebInspector.TimelineCategoryGraph(this._categories[category], i++ % 2);
this._categoryGraphs[category] = categoryGraph;
this._overviewGrid.itemsGraphsElement.appendChild(categoryGraph.graphElement);
}
this._overviewGrid.setScrollAndDividerTop(0, 0);

this._overviewWindowElement = document.createElement("div");
this._overviewWindowElement.id = "timeline-overview-window";
this._overviewGrid.element.appendChild(this._overviewWindowElement);

this._overviewWindowBordersElement = document.createElement("div");
this._overviewWindowBordersElement.className = "timeline-overview-window-rulers";
this._overviewGrid.element.appendChild(this._overviewWindowBordersElement);

var overviewDividersBackground = document.createElement("div");
overviewDividersBackground.className = "timeline-overview-dividers-background";
this._overviewGrid.element.appendChild(overviewDividersBackground);

this._leftResizeElement = document.createElement("div");
this._leftResizeElement.className = "timeline-window-resizer";
this._leftResizeElement.style.left = 0;
this._overviewGrid.element.appendChild(this._leftResizeElement);

this._rightResizeElement = document.createElement("div");
this._rightResizeElement.className = "timeline-window-resizer timeline-window-resizer-right";
this._rightResizeElement.style.right = 0;
this._overviewGrid.element.appendChild(this._rightResizeElement);

this._overviewCalculator = new WebInspector.TimelineOverviewCalculator();

this.windowLeft = 0.0;
this.windowRight = 1.0;
}

WebInspector.TimelineOverviewPane.minSelectableSize = 12;

WebInspector.TimelineOverviewPane.prototype = {
showTimelines: function(event) {
this._heapGraph.hide();
this._overviewGrid.itemsGraphsElement.removeStyleClass("hidden");
},

showMemoryGraph: function(records) {
this._heapGraph.show();
this._heapGraph.update(records);
this._overviewGrid.itemsGraphsElement.addStyleClass("hidden");
},

_onCheckboxClicked: function (category, event) {
if (event.target.checked)
category.hidden = false;
else
category.hidden = true;
this._categoryGraphs[category.name].dimmed = !event.target.checked;
this.dispatchEventToListeners("filter changed");
},

_forAllRecords: function(recordsArray, callback)
{
if (!recordsArray)
return;
for (var i = 0; i < recordsArray.length; ++i) {
callback(recordsArray[i]);
this._forAllRecords(recordsArray[i].children, callback);
}
},

update: function(records, showShortEvents)
{
this._showShortEvents = showShortEvents;

var timelines = {};
for (var category in this._categories) {
timelines[category] = [];
this._categoryGraphs[category].clearChunks();
}


this._overviewCalculator.reset();
this._forAllRecords(records, this._overviewCalculator.updateBoundaries.bind(this._overviewCalculator));

function markTimeline(record)
{
if (!(this._showShortEvents || record.isLong()))
return;
var percentages = this._overviewCalculator.computeBarGraphPercentages(record);

var end = Math.round(percentages.end);
var categoryName = record.category.name;
for (var j = Math.round(percentages.start); j <= end; ++j)
timelines[categoryName][j] = true;
}
this._forAllRecords(records, markTimeline.bind(this));


for (var category in this._categories) {
var timeline = timelines[category];
window.timelineSaved = timeline;
var chunkStart = -1;
for (var j = 0; j < 101; ++j) {
if (timeline[j]) {
if (chunkStart === -1)
chunkStart = j;
} else {
if (chunkStart !== -1) {
this._categoryGraphs[category].addChunk(chunkStart, j);
chunkStart = -1;
}
}
}
if (chunkStart !== -1) {
this._categoryGraphs[category].addChunk(chunkStart, 100);
chunkStart = -1;
}
}

this._heapGraph.setSize(this._overviewGrid.element.offsetWidth, 60);
if (this._heapGraph.visible)
this._heapGraph.update(records);

this._overviewGrid.updateDividers(true, this._overviewCalculator);
},

updateEventDividers: function(records, dividerConstructor)
{
this._overviewGrid.removeEventDividers();
var dividers = [];
for (var i = 0; i < records.length; ++i) {
var record = records[i];
var positions = this._overviewCalculator.computeBarGraphPercentages(record);
var dividerPosition = Math.round(positions.start * 10);
if (dividers[dividerPosition])
continue;
var divider = dividerConstructor(record);
divider.style.left = positions.start + "%";
dividers[dividerPosition] = divider;
}
this._overviewGrid.addEventDividers(dividers);
},

updateMainViewWidth: function(width, records)
{
this._overviewGrid.element.style.left = width + "px";
this.statusBarFilters.style.left = Math.max(155, width) + "px";
},

reset: function()
{
this.windowLeft = 0.0;
this.windowRight = 1.0;
this._overviewWindowElement.style.left = "0%";
this._overviewWindowElement.style.width = "100%";
this._overviewWindowBordersElement.style.left = "0%";
this._overviewWindowBordersElement.style.right = "0%";
this._leftResizeElement.style.left = "0%";
this._rightResizeElement.style.left = "100%";
this._overviewCalculator.reset();
this._overviewGrid.updateDividers(true, this._overviewCalculator);
},

_resizeWindow: function(resizeElement, event)
{
WebInspector.elementDragStart(resizeElement, this._windowResizeDragging.bind(this, resizeElement), this._endWindowDragging.bind(this), event, "col-resize");
},

_windowResizeDragging: function(resizeElement, event)
{
if (resizeElement === this._leftResizeElement)
this._resizeWindowLeft(event.pageX - this._overviewGrid.element.offsetLeft);
else
this._resizeWindowRight(event.pageX - this._overviewGrid.element.offsetLeft);
event.preventDefault();
},

_dragWindow: function(event)
{
var node = event.target;
while (node) {
if (node === this._overviewGrid._dividersLabelBarElement) {
WebInspector.elementDragStart(this._overviewWindowElement, this._windowDragging.bind(this, event.pageX,
this._leftResizeElement.offsetLeft, this._rightResizeElement.offsetLeft), this._endWindowDragging.bind(this), event, "ew-resize");
break;
} else if (node === this._overviewGrid.element) {
var position = event.pageX - this._overviewGrid.element.offsetLeft;
this._overviewWindowSelector = new WebInspector.TimelinePanel.WindowSelector(this._overviewGrid.element, position, event);
WebInspector.elementDragStart(null, this._windowSelectorDragging.bind(this), this._endWindowSelectorDragging.bind(this), event, "col-resize");
break;
} else if (node === this._leftResizeElement || node === this._rightResizeElement) {
this._resizeWindow(node, event);
break;
}
node = node.parentNode;
}
},

_windowSelectorDragging: function(event)
{
this._overviewWindowSelector._updatePosition(event.pageX - this._overviewGrid.element.offsetLeft);
event.preventDefault();
},

_endWindowSelectorDragging: function(event)
{
WebInspector.elementDragEnd(event);
var window = this._overviewWindowSelector._close(event.pageX - this._overviewGrid.element.offsetLeft);
delete this._overviewWindowSelector;
if (window.end - window.start < WebInspector.TimelineOverviewPane.minSelectableSize)
if (this._overviewGrid.itemsGraphsElement.offsetWidth - window.end > WebInspector.TimelineOverviewPane.minSelectableSize)
window.end = window.start + WebInspector.TimelineOverviewPane.minSelectableSize;
else
window.start = window.end - WebInspector.TimelineOverviewPane.minSelectableSize;
this._setWindowPosition(window.start, window.end);
},

_windowDragging: function(startX, windowLeft, windowRight, event)
{
var delta = event.pageX - startX;
var start = windowLeft + delta;
var end = windowRight + delta;
var windowSize = windowRight - windowLeft;

if (start < 0) {
start = 0;
end = windowSize;
}

if (end > this._overviewGrid.element.clientWidth) {
end = this._overviewGrid.element.clientWidth;
start = end - windowSize;
}
this._setWindowPosition(start, end);

event.preventDefault();
},

_resizeWindowLeft: function(start)
{

if (start < 10)
start = 0;
else if (start > this._rightResizeElement.offsetLeft -  4)
start = this._rightResizeElement.offsetLeft - 4;
this._setWindowPosition(start, null);
},

_resizeWindowRight: function(end)
{

if (end > this._overviewGrid.element.clientWidth - 10)
end = this._overviewGrid.element.clientWidth;
else if (end < this._leftResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.minSelectableSize)
end = this._leftResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.minSelectableSize;
this._setWindowPosition(null, end);
},

_setWindowPosition: function(start, end)
{
const rulerAdjustment = 1 / this._overviewGrid.element.clientWidth;
if (typeof start === "number") {
this.windowLeft = start / this._overviewGrid.element.clientWidth;
this._leftResizeElement.style.left = this.windowLeft * 100 + "%";
this._overviewWindowElement.style.left = this.windowLeft * 100 + "%";
this._overviewWindowBordersElement.style.left = (this.windowLeft - rulerAdjustment) * 100 + "%";
}
if (typeof end === "number") {
this.windowRight = end / this._overviewGrid.element.clientWidth;
this._rightResizeElement.style.left = this.windowRight * 100 + "%";
}
this._overviewWindowElement.style.width = (this.windowRight - this.windowLeft) * 100 + "%";
this._overviewWindowBordersElement.style.right = (1 - this.windowRight + 2 * rulerAdjustment) * 100 + "%";
this.dispatchEventToListeners("window changed");
},

_endWindowDragging: function(event)
{
WebInspector.elementDragEnd(event);
},

_createTimelineCategoryStatusBarCheckbox: function(category, onCheckboxClicked)
{
var labelContainer = document.createElement("div");
labelContainer.addStyleClass("timeline-category-statusbar-item");
labelContainer.addStyleClass("timeline-category-" + category.name);
labelContainer.addStyleClass("status-bar-item");

var label = document.createElement("label");
var checkElement = document.createElement("input");
checkElement.type = "checkbox";
checkElement.className = "timeline-category-checkbox";
checkElement.checked = true;
checkElement.addEventListener("click", onCheckboxClicked);
label.appendChild(checkElement);

var typeElement = document.createElement("span");
typeElement.className = "type";
typeElement.textContent = category.title;
label.appendChild(typeElement);

labelContainer.appendChild(label);
return labelContainer;
}

}

WebInspector.TimelineOverviewPane.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.TimelineOverviewCalculator = function()
{
}

WebInspector.TimelineOverviewCalculator.prototype = {
computeBarGraphPercentages: function(record)
{
var start = (record.startTime - this.minimumBoundary) / this.boundarySpan * 100;
var end = (record.endTime - this.minimumBoundary) / this.boundarySpan * 100;
return {start: start, end: end};
},

reset: function()
{
delete this.minimumBoundary;
delete this.maximumBoundary;
},

updateBoundaries: function(record)
{
if (typeof this.minimumBoundary === "undefined" || record.startTime < this.minimumBoundary) {
this.minimumBoundary = record.startTime;
return true;
}
if (typeof this.maximumBoundary === "undefined" || record.endTime > this.maximumBoundary) {
this.maximumBoundary = record.endTime;
return true;
}
return false;
},

get boundarySpan()
{
return this.maximumBoundary - this.minimumBoundary;
},

formatValue: function(value)
{
return Number.secondsToString(value);
}
}


WebInspector.TimelineCategoryGraph = function(category, isEven)
{
this._category = category;

this._graphElement = document.createElement("div");
this._graphElement.className = "timeline-graph-side timeline-overview-graph-side" + (isEven ? " even" : "");

this._barAreaElement = document.createElement("div");
this._barAreaElement.className = "timeline-graph-bar-area timeline-category-" + category.name;
this._graphElement.appendChild(this._barAreaElement);
}

WebInspector.TimelineCategoryGraph.prototype = {
get graphElement()
{
return this._graphElement;
},

addChunk: function(start, end)
{
var chunk = document.createElement("div");
chunk.className = "timeline-graph-bar";
this._barAreaElement.appendChild(chunk);
chunk.style.setProperty("left", start + "%");
chunk.style.setProperty("width", (end - start) + "%");
},

clearChunks: function()
{
this._barAreaElement.removeChildren();
},

set dimmed(dimmed)
{
if (dimmed)
this._barAreaElement.removeStyleClass("timeline-category-" + this._category.name);
else
this._barAreaElement.addStyleClass("timeline-category-" + this._category.name);
}
}

WebInspector.TimelinePanel.WindowSelector = function(parent, position, event)
{
this._startPosition = position;
this._width = parent.offsetWidth;
this._windowSelector = document.createElement("div");
this._windowSelector.className = "timeline-window-selector";
this._windowSelector.style.left = this._startPosition + "px";
this._windowSelector.style.right = this._width - this._startPosition +  + "px";
parent.appendChild(this._windowSelector);
}

WebInspector.TimelinePanel.WindowSelector.prototype = {
_createSelectorElement: function(parent, left, width, height)
{
var selectorElement = document.createElement("div");
selectorElement.className = "timeline-window-selector";
selectorElement.style.left = left + "px";
selectorElement.style.width = width + "px";
selectorElement.style.top = "0px";
selectorElement.style.height = height + "px";
parent.appendChild(selectorElement);
return selectorElement;
},

_close: function(position)
{
position = Math.max(0, Math.min(position, this._width));
this._windowSelector.parentNode.removeChild(this._windowSelector);
return this._startPosition < position ? {start: this._startPosition, end: position} : {start: position, end: this._startPosition};
},

_updatePosition: function(position)
{
position = Math.max(0, Math.min(position, this._width));
if (position < this._startPosition) {
this._windowSelector.style.left = position + "px";
this._windowSelector.style.right = this._width - this._startPosition + "px";
} else {
this._windowSelector.style.left = this._startPosition + "px";
this._windowSelector.style.right = this._width - position + "px";
}
}
}

WebInspector.HeapGraph = function() {
this._canvas = document.createElement("canvas");

this._maxHeapSizeLabel = document.createElement("div");
this._maxHeapSizeLabel.addStyleClass("memory-graph-label");

this._element = document.createElement("div");
this._element.addStyleClass("hidden");
this._element.appendChild(this._canvas);
this._element.appendChild(this._maxHeapSizeLabel);
}

WebInspector.HeapGraph.prototype = {
get element() {

return this._element;
},

get visible() {
return !this.element.hasStyleClass("hidden");
},

show: function() {
this.element.removeStyleClass("hidden");
},

hide: function() {
this.element.addStyleClass("hidden");
},

setSize: function(w, h) {
this._canvas.width = w;
this._canvas.height = h - 5;
},

update: function(records)
{
if (!records.length)
return;

var maxTotalHeapSize = 0;
var minTime;
var maxTime;
this._forAllRecords(records, function(r) {
if (r.totalHeapSize && r.totalHeapSize > maxTotalHeapSize)
maxTotalHeapSize = r.totalHeapSize;

if (typeof minTime === "undefined" || r.startTime < minTime)
minTime = r.startTime;
if (typeof maxTime === "undefined" || r.endTime > maxTime)
maxTime = r.endTime;
});

var width = this._canvas.width;
var height = this._canvas.height;
var xFactor = width / (maxTime - minTime);
var yFactor = height / maxTotalHeapSize;

var histogram = new Array(width);
this._forAllRecords(records, function(r) {
if (!r.usedHeapSize)
return;
var x = Math.round((r.endTime - minTime) * xFactor);
var y = Math.round(r.usedHeapSize * yFactor);
histogram[x] = Math.max(histogram[x] || 0, y);
});

var ctx = this._canvas.getContext("2d");
this._clear(ctx);


height = height + 1;

ctx.beginPath();
var initialY = 0;
for (var k = 0; k < histogram.length; k++) {
if (histogram[k]) {
initialY = histogram[k];
break;
}
}
ctx.moveTo(0, height - initialY);

for (var x = 0; x < histogram.length; x++) {
if (!histogram[x])
continue;
ctx.lineTo(x, height - histogram[x]);
}

ctx.lineWidth = 0.5;
ctx.strokeStyle = "rgba(20,0,0,0.8)";
ctx.stroke();

ctx.fillStyle = "rgba(214,225,254, 0.8);";
ctx.lineTo(width, 60);
ctx.lineTo(0, 60);
ctx.lineTo(0, height - initialY);
ctx.fill();
ctx.closePath();

this._maxHeapSizeLabel.textContent = Number.bytesToString(maxTotalHeapSize);
},

_clear: function(ctx) {
ctx.fillStyle = "rgba(255,255,255,0.8)";
ctx.fillRect(0, 0, this._canvas.width, this._canvas.height);
},

_forAllRecords: WebInspector.TimelineOverviewPane.prototype._forAllRecords
}





WebInspector.TestController = function()
{
}

WebInspector.TestController.prototype = {
notifyDone: function(callId, result)
{
var message = typeof result === "undefined" ? "\"<undefined>\"" : JSON.stringify(result);
RuntimeAgent.evaluate("didEvaluateForTestInFrontend(" + callId + ", " + message + ")", "test");
}
}

WebInspector.evaluateForTestInFrontend = function(callId, script)
{
function invokeMethod()
{
try {
var result;
if (window[script] && typeof window[script] === "function")
result = window[script].call(WebInspector, controller);
else
result = window.eval(script);

WebInspector.TestController.prototype.notifyDone(callId, result);
} catch (e) {
WebInspector.testController.prototype.notifyDone(callId, e.toString());
}
}
InspectorBackend.runAfterPendingDispatches(invokeMethod);
}





WebInspector.HelpScreen = function(title)
{
this._element = document.createElement("div");
this._element.className = "help-window-outer";
this._element.addEventListener("keydown", this._onKeyDown.bind(this), false);

var mainWindow = this._element.createChild("div", "help-window-main");
var captionWindow = mainWindow.createChild("div", "help-window-caption");
var closeButton = captionWindow.createChild("button", "help-close-button");
this.contentElement = mainWindow.createChild("div", "help-content");
this.contentElement.tabIndex = 0;
this.contentElement.addEventListener("blur", this._onBlur.bind(this), false);
captionWindow.createChild("h1", "help-window-title").textContent = title;

closeButton.textContent = "\u2716"; 
closeButton.addEventListener("click", this._hide.bind(this), false);
this._closeKeys = [
WebInspector.KeyboardShortcut.Keys.Enter.code,
WebInspector.KeyboardShortcut.Keys.Esc.code,
WebInspector.KeyboardShortcut.Keys.Space.code,
];
document.body.appendChild(this._element);
}

WebInspector.HelpScreen.prototype = {
show: function()
{
if (this._isShown)
return;

this._element.style.visibility = "visible";
this._isShown = true;
this._previousFocusElement = WebInspector.currentFocusElement;
WebInspector.currentFocusElement = this.contentElement;
},

_hide: function()
{
this._isShown = false;
this._element.style.visibility = "hidden";
WebInspector.currentFocusElement = this._previousFocusElement;
},

_onKeyDown: function(event)
{
if (this._isShown && this._closeKeys.indexOf(event.keyCode) >= 0) {
this._hide();
event.stopPropagation();
}
},

_onBlur: function()
{

if (this._isShown)
WebInspector.currentFocusElement = this.contentElement;
}
}





WebInspector.GoToLineDialog = function(view)
{
this._element = document.createElement("div");
this._element.className = "go-to-line-dialog";
this._element.addEventListener("keydown", this._onKeyDown.bind(this), false);
this._closeKeys = [
WebInspector.KeyboardShortcut.Keys.Enter.code,
WebInspector.KeyboardShortcut.Keys.Esc.code,
];

var dialogWindow = this._element;

dialogWindow.createChild("label").textContent = WebInspector.UIString("Go to line: ");

this._input = dialogWindow.createChild("input");
this._input.setAttribute("type", "text");
this._input.setAttribute("size", 6);
var blurHandler = this._onBlur.bind(this);
this._input.addEventListener("blur", blurHandler, false);


var go = dialogWindow.createChild("button");
go.textContent = WebInspector.UIString("Go");
go.addEventListener("click", this._onClick.bind(this), false);
go.addEventListener("mousedown", function(e) {


this._input.removeEventListener("blur", blurHandler, false);
}.bind(this), false);

this._view = view;
view.element.appendChild(this._element);

this._previousFocusElement = WebInspector.currentFocusElement;
WebInspector.currentFocusElement = this._input;
this._input.select();
}

WebInspector.GoToLineDialog.show = function(sourceView)
{
if (!sourceView || typeof sourceView.highlightLine !== "function")
return;
if (this._instance)
return;
this._instance = new WebInspector.GoToLineDialog(sourceView);
}

WebInspector.GoToLineDialog.createShortcut = function()
{
var isMac = WebInspector.isMac();
var shortcut;
if (isMac)
return WebInspector.KeyboardShortcut.makeDescriptor("l", WebInspector.KeyboardShortcut.Modifiers.Meta);
return WebInspector.KeyboardShortcut.makeDescriptor("g", WebInspector.KeyboardShortcut.Modifiers.Ctrl);
}

WebInspector.GoToLineDialog.prototype = {
_hide: function()
{
if (this._isHiding)
return;
this._isHiding = true;

WebInspector.currentFocusElement = this._previousFocusElement;
WebInspector.GoToLineDialog._instance = null;
this._element.parentElement.removeChild(this._element);
},

_onBlur: function(event)
{
this._hide();
},

_onKeyDown: function(event)
{
if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Tab.code) {
event.preventDefault();
return;
}

if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Enter.code)
this._highlightSelectedLine();

if (this._closeKeys.indexOf(event.keyCode) >= 0) {
this._hide();
event.preventDefault();
event.stopPropagation();
}
},

_onClick: function(event)
{
this._highlightSelectedLine();
this._hide();
},

_highlightSelectedLine: function()
{
var value = this._input.value;
var lineNumber = parseInt(value, 10) - 1;
if (!isNaN(lineNumber) && lineNumber >= 0)
this._view.highlightLine(lineNumber);
}
};





WebInspector.ShortcutsHelp = function()
{
this._sections = {};
}

WebInspector.ShortcutsHelp.prototype = {
section: function(name)
{
var section = this._sections[name];
if (!section)
this._sections[name] = section = new WebInspector.ShortcutsSection(name);
return section;
},

show: function()
{
if (!this._helpScreen) {
this._helpScreen = new WebInspector.HelpScreen(WebInspector.UIString("Keyboard Shortcuts"));
this._buildTable(this._helpScreen.contentElement, 2);
}
this._helpScreen.show();
},

_buildTable: function(parent, nColumns)
{
var height = 0;
var orderedSections = [];
for (var section in this._sections) {
height += this._sections[section]._height;
orderedSections.push(this._sections[section])
}
function compareSections(a, b)
{
return a.order - b.order;
}
orderedSections = orderedSections.sort(compareSections);

const wrapAfter = height / nColumns;
var table = document.createElement("table");
table.className = "help-table";
var row = table.createChild("tr");



for (var section = 0; section < orderedSections.length;) {
var td = row.createChild("td");
td.style.width = (100 / nColumns) + "%";
var column = td.createChild("table");
for (var columnHeight = 0;
columnHeight < wrapAfter && section < orderedSections.length;
columnHeight += orderedSections[section]._height, section++) {
orderedSections[section].renderSection(column);
}
}
parent.appendChild(table);
}
};

WebInspector.shortcutsHelp = new WebInspector.ShortcutsHelp();

WebInspector.ShortcutsSection = function(name)
{
this.name = name;
this._lines = [];
this.order = ++WebInspector.ShortcutsSection._sequenceNumber;
};

WebInspector.ShortcutsSection._sequenceNumber = 0;

WebInspector.ShortcutsSection.prototype = {
addKey: function(key, description)
{
this.addLine(this._renderKey(key), description);
},

addRelatedKeys: function(keys, description)
{
this.addLine(this._renderSequence(keys,"/"), description);
},

addAlternateKeys: function(keys, description)
{
this.addLine(this._renderSequence(keys,WebInspector.UIString("or")), description);
},

addLine: function(htmlKey, description)
{
this._lines.push({ key: htmlKey, text: description })
},

renderSection: function(parent)
{
this._renderHeader(parent);

for (var line = 0; line < this._lines.length; ++line) {
var tr = parent.createChild("tr");
tr.createChild("td", "help-key-cell").innerHTML = this._lines[line].key + " : ";
tr.createChild("td").textContent = this._lines[line].text;
}
},

_renderHeader: function(parent)
{
var trHead = parent.createChild("tr");

trHead.createChild("th");
trHead.createChild("th").textContent = this.name;
},

_renderSequence: function(sequence, delimiter)
{
var delimiterHtml = '<span class="help-key-delimiter">' + delimiter.escapeHTML() + '</span>'
return sequence.map(this._renderKey).join(delimiterHtml);
},

_renderKey: function(key)
{
function renderLabel(label)
{
return '<span class="help-key monospace">' + label.escapeHTML() + '</span>';
}
return key.split(" + ").map(renderLabel).join('<span class="help-combine-keys">+</span>');
},

get _height()
{
return this._lines.length + 2; 
}
};











WebInspector.HAREntry = function(resource)
{
this._resource = resource;
}

WebInspector.HAREntry.prototype = {
build: function()
{
return {
pageref: this._resource.documentURL,
startedDateTime: new Date(this._resource.startTime * 1000),
time: WebInspector.HAREntry._toMilliseconds(this._resource.duration),
request: this._buildRequest(),
response: this._buildResponse(),
cache: { }, 
timings: this._buildTimings()
};
},

_buildRequest: function()
{
var res = {
method: this._resource.requestMethod,
url: this._resource.url,

headers: this._buildHeaders(this._resource.requestHeaders),
queryString: this._buildParameters(this._resource.queryParameters || []),
cookies: this._buildCookies(this._resource.requestCookies || []),
headersSize: -1, 
bodySize: -1 
};
if (this._resource.requestFormData)
res.postData = this._buildPostData();
return res;
},

_buildResponse: function()
{
return {
status: this._resource.statusCode,
statusText: this._resource.statusText,

headers: this._buildHeaders(this._resource.responseHeaders),
cookies: this._buildCookies(this._resource.responseCookies || []),
content: this._buildContent(),
redirectURL: this._resource.responseHeaderValue("Location") || "",
headersSize: -1, 
bodySize: this._resource.resourceSize
};
},

_buildContent: function()
{
return {
size: this._resource.resourceSize,

mimeType: this._resource.mimeType,

};
},

_buildTimings: function()
{
var waitForConnection = this._interval("connectStart", "connectEnd");
var blocked;
var connect;
var dns = this._interval("dnsStart", "dnsEnd");
var send = this._interval("sendStart", "sendEnd");
var ssl = this._interval("sslStart", "sslEnd");

if (ssl !== -1 && send !== -1)
send -= ssl;

if (this._resource.connectionReused) {
connect = -1;
blocked = waitForConnection;
} else {
blocked = 0;
connect = waitForConnection;
if (dns !== -1)
connect -= dns;
}

return {
blocked: blocked,
dns: dns,
connect: connect,
send: send,
wait: this._interval("sendEnd", "receiveHeadersEnd"),
receive: WebInspector.HAREntry._toMilliseconds(this._resource.receiveDuration),
ssl: ssl
};
},

_buildHeaders: function(headers)
{
var result = [];
for (var name in headers)
result.push({ name: name, value: headers[name] });
return result;
},

_buildPostData: function()
{
var res = {
mimeType: this._resource.requestHeaderValue("Content-Type"),
text: this._resource.requestFormData
};
if (this._resource.formParameters)
res.params = this._buildParameters(this._resource.formParameters);
return res;
},

_buildParameters: function(parameters)
{
return parameters.slice();
},

_buildCookies: function(cookies)
{
return cookies.map(this._buildCookie.bind(this));
},

_buildCookie: function(cookie)
{

return {
name: cookie.name,
value: cookie.value,
path: cookie.path,
domain: cookie.domain,
expires: cookie.expires(new Date(this._resource.startTime * 1000)),
httpOnly: cookie.httpOnly,
secure: cookie.secure
};
},

_interval: function(start, end)
{
var timing = this._resource.timing;
if (!timing)
return -1;
var startTime = timing[start];
return typeof startTime !== "number" || startTime === -1 ? -1 : Math.round(timing[end] - startTime);
}
}

WebInspector.HAREntry._toMilliseconds = function(time)
{
return time === -1 ? -1 : Math.round(time * 1000);
}

WebInspector.HARLog = function()
{
}

WebInspector.HARLog.prototype = {
build: function()
{
var webKitVersion = /AppleWebKit\/([^ ]+)/.exec(window.navigator.userAgent);

return {
version: "1.2",
creator: {
name: "WebInspector",
version: webKitVersion ? webKitVersion[1] : "n/a"
},
pages: this._buildPages(),
entries: WebInspector.networkResources.map(this._convertResource.bind(this))
}
},

_buildPages: function()
{
return [
{
startedDateTime: new Date(WebInspector.mainResource.startTime * 1000),
id: WebInspector.mainResource.documentURL,
title: "",
pageTimings: this.buildMainResourceTimings()
}
];
},

buildMainResourceTimings: function()
{
return {
onContentLoad: this._pageEventTime(WebInspector.mainResourceDOMContentTime),
onLoad: this._pageEventTime(WebInspector.mainResourceLoadTime),
}
},

_convertResource: function(resource)
{
return (new WebInspector.HAREntry(resource)).build();
},

_pageEventTime: function(time)
{
var startTime = WebInspector.mainResource.startTime;
if (time === -1 || startTime === -1)
return -1;
return WebInspector.HAREntry._toMilliseconds(time - startTime);
}
}












WebInspector.CookieParser = function()
{
}

WebInspector.CookieParser.prototype = {
get cookies()
{
return this._cookies;
},

parseCookie: function(cookieHeader)
{
if (!this._initialize(cookieHeader))
return;

for (var kv = this._extractKeyValue(); kv; kv = this._extractKeyValue()) {
if (kv.key.charAt(0) === "$" && this._lastCookie)
this._lastCookie.addAttribute(kv.key.slice(1), kv.value);
else if (kv.key.toLowerCase() !== "$version" && typeof kv.value === "string")
this._addCookie(kv, WebInspector.Cookie.Type.Request);
this._advanceAndCheckCookieDelimiter();
}
this._flushCookie();
return this._cookies;
},

parseSetCookie: function(setCookieHeader)
{
if (!this._initialize(setCookieHeader))
return;
for (var kv = this._extractKeyValue(); kv; kv = this._extractKeyValue()) {
if (this._lastCookie)
this._lastCookie.addAttribute(kv.key, kv.value);
else 
this._addCookie(kv, WebInspector.Cookie.Type.Response);
if (this._advanceAndCheckCookieDelimiter())
this._flushCookie();
}
this._flushCookie();
return this._cookies;
},

_initialize: function(headerValue)
{
this._input = headerValue;
if (typeof headerValue !== "string")
return false;
this._cookies = [];
this._lastCookie = null;
this._originalInputLength = this._input.length;
return true;
},

_flushCookie: function()
{
if (this._lastCookie)
this._lastCookie.size = this._originalInputLength - this._input.length - this._lastCookiePosition;
this._lastCookie = null;
},

_extractKeyValue: function()
{
if (!this._input || !this._input.length)
return null;





var keyValueMatch = /^[ \t]*([^\s=;]+)[ \t]*(?:=[ \t]*([^;\n]*))?/.exec(this._input);
        if (!keyValueMatch) {
            console.log("Failed parsing cookie header before: " + this._input);
            return null;
        }

        var result = {
            key: keyValueMatch[1],
            value: keyValueMatch[2] && keyValueMatch[2].trim(),
            position: this._originalInputLength - this._input.length
        };
        this._input = this._input.slice(keyValueMatch[0].length);
        return result;
    },

    _advanceAndCheckCookieDelimiter: function()
    {
        var match = /^\s*[\n;]\s*/.exec(this._input);
if (!match)
return false;
this._input = this._input.slice(match[0].length);
return match[0].match("\n") !== null;
},

_addCookie: function(keyValue, type)
{
if (this._lastCookie)
this._lastCookie.size = keyValue.position - this._lastCookiePosition;


this._lastCookie = keyValue.value ? new WebInspector.Cookie(keyValue.key, keyValue.value, type) :
new WebInspector.Cookie("", keyValue.key, type);
this._lastCookiePosition = keyValue.position;
this._cookies.push(this._lastCookie);
}
};

WebInspector.CookieParser.parseCookie = function(header)
{
return (new WebInspector.CookieParser()).parseCookie(header);
}

WebInspector.CookieParser.parseSetCookie = function(header)
{
return (new WebInspector.CookieParser()).parseSetCookie(header);
}

WebInspector.Cookie = function(name, value, type)
{
this.name = name;
this.value = value;
this.type = type;
this._attributes = {};
}

WebInspector.Cookie.prototype = {
get httpOnly()
{
return "httponly" in this._attributes;
},

get secure()
{
return "secure" in this._attributes;
},

get session()
{


return  !("expries" in this._attributes || "max-age" in this._attributes);
},

get path()
{
return this._attributes.path;
},

get domain()
{
return this._attributes.domain;
},

expires: function(requestDate)
{
return this._attributes.expires ? new Date(this._attributes.expires) :
(this._attributes["max-age"] ? new Date(requestDate.getTime() + 1000 * this._attributes["max-age"]) : null);
},

get attributes()
{
return this._attributes;
},

addAttribute: function(key, value)
{
this._attributes[key.toLowerCase()] = value;
}
}

WebInspector.Cookie.Type = {
Request: 0,
Response: 1
};





WebInspector.Toolbar = function()
{
this.element = document.getElementById("toolbar");
this.element.addEventListener("mousedown", this._toolbarDragStart.bind(this), true);

this._dropdownButton = document.getElementById("toolbar-dropdown-arrow");
this._dropdownButton.addEventListener("click", this._toggleDropdown.bind(this), false);

document.getElementById("close-button-left").addEventListener("click", this._onClose, true);
document.getElementById("close-button-right").addEventListener("click", this._onClose, true);
}

WebInspector.Toolbar.prototype = {
set attached(attached)
{
if (attached)
this.element.addStyleClass("toolbar-small");
else
this.element.removeStyleClass("toolbar-small");
this._updateDropdownButtonAndHideDropdown();
},

resize: function()
{
this._updateDropdownButtonAndHideDropdown();
},

addPanel: function(panel)
{
this.element.appendChild(panel.toolbarItem);
this.resize();
},

_toolbarDragStart: function(event)
{
if ((!WebInspector.attached && WebInspector.platformFlavor !== WebInspector.PlatformFlavor.MacLeopard && WebInspector.platformFlavor !== WebInspector.PlatformFlavor.MacSnowLeopard) || WebInspector.port == "qt")
return;

var target = event.target;
if (target.hasStyleClass("toolbar-item") && target.hasStyleClass("toggleable"))
return;

if (target !== this.element && !target.hasStyleClass("toolbar-item"))
return;

this.element.lastScreenX = event.screenX;
this.element.lastScreenY = event.screenY;

WebInspector.elementDragStart(this.element, this._toolbarDrag.bind(this), this._toolbarDragEnd.bind(this), event, (WebInspector.attached ? "row-resize" : "default"));
},

_toolbarDragEnd: function(event)
{
WebInspector.elementDragEnd(event);

delete this.element.lastScreenX;
delete this.element.lastScreenY;
},

_toolbarDrag: function(event)
{
if (WebInspector.attached) {
var height = window.innerHeight - (event.screenY - this.element.lastScreenY);

InspectorFrontendHost.setAttachedWindowHeight(height);
} else {
var x = event.screenX - this.element.lastScreenX;
var y = event.screenY - this.element.lastScreenY;



InspectorFrontendHost.moveWindowBy(x, y);
}

this.element.lastScreenX = event.screenX;
this.element.lastScreenY = event.screenY;

event.preventDefault();
},

_onClose: function()
{
WebInspector.close();
},

_setDropdownVisible: function(visible)
{
if (!this._dropdown) {
if (!visible)
return;
this._dropdown = new WebInspector.ToolbarDropdown();
}
if (visible)
this._dropdown.show();
else
this._dropdown.hide();
},

_toggleDropdown: function()
{
this._setDropdownVisible(!this._dropdown || !this._dropdown.visible);
},

_updateDropdownButtonAndHideDropdown: function()
{
this._setDropdownVisible(false);

var toolbar = document.getElementById("toolbar");
if (this.element.scrollHeight > this.element.clientHeight)
this._dropdownButton.removeStyleClass("hidden");
else
this._dropdownButton.addStyleClass("hidden");
}
};

WebInspector.Toolbar.createPanelToolbarItem = function(panel)
{
var toolbarItem = document.createElement("button");
toolbarItem.className = "toolbar-item toggleable";
toolbarItem.panel = panel;
toolbarItem.addStyleClass(panel._panelName);
function onToolbarItemClicked()
{
WebInspector.toolbar._updateDropdownButtonAndHideDropdown();
WebInspector.currentPanel = panel;
}
toolbarItem.addEventListener("click", onToolbarItemClicked);

var iconElement = toolbarItem.createChild("div", "toolbar-icon");

if ("toolbarItemLabel" in panel)
toolbarItem.createChild("div", "toolbar-label").textContent = panel.toolbarItemLabel;

if (panel === WebInspector.currentPanel)
toolbarItem.addStyleClass("toggled-on");

return toolbarItem;
}

WebInspector.ToolbarDropdown = function()
{
this._toolbar = document.getElementById("toolbar");
this._arrow = document.getElementById("toolbar-dropdown-arrow");
this.element = document.createElement("div");
this.element.id = "toolbar-dropdown";
this.element.className = "toolbar-small";
this._contentElement = this.element.createChild("div", "scrollable-content");
this._contentElement.tabIndex = 0;
this._contentElement.addEventListener("keydown", this._onKeyDown.bind(this), true);
}

WebInspector.ToolbarDropdown.prototype = {
show: function()
{
if (this.visible)
return;
var style = this.element.style;
this._populate();
var top = this._arrow.totalOffsetTop + this._arrow.clientHeight;
this._arrow.addStyleClass("dropdown-visible");
this.element.style.top = top + "px";
this.element.style.left = this._arrow.totalOffsetLeft + "px";
this._contentElement.style.maxHeight = window.innerHeight - top - 20 + "px";
this._toolbar.appendChild(this.element);
WebInspector.currentFocusElement = this.contentElement;
},

hide: function()
{
if (!this.visible)
return;
this._arrow.removeStyleClass("dropdown-visible");
this.element.parentNode.removeChild(this.element);
this._contentElement.removeChildren();
},

get visible()
{
return !!this.element.parentNode;
},

_populate: function()
{
var toolbarItems = this._toolbar.querySelectorAll(".toolbar-item.toggleable");

for (var i = 0; i < toolbarItems.length; ++i) {
if (toolbarItems[i].offsetTop > 0)
this._contentElement.appendChild(WebInspector.Toolbar.createPanelToolbarItem(toolbarItems[i].panel));
}
},

_onKeyDown: function(event)
{
if (event.keyCode !== WebInspector.KeyboardShortcut.Keys.Esc.code)
return;
event.stopPropagation();
this.hide();
}
};





WebInspector.SearchController = function()
{
this.element = document.getElementById("search");
this._matchesElement = document.getElementById("search-results-matches");
this._toolbarLabelElement = document.getElementById("search-toolbar-label");

this.element.addEventListener("search", this._onSearch.bind(this), false); 
this.element.addEventListener("mousedown", this._onSearchFieldManualFocus.bind(this), false); 
this.element.addEventListener("keydown", this._onKeyDown.bind(this), true);
}

WebInspector.SearchController.prototype = {
updateSearchMatchesCount: function(matches, panel)
{
if (!panel)
panel = WebInspector.currentPanel;

panel.currentSearchMatches = matches;

if (panel === WebInspector.currentPanel)
this._updateSearchMatchesCount(WebInspector.currentPanel.currentQuery && matches);
},

updateSearchLabel: function()
{
var panelName = WebInspector.currentPanel && WebInspector.currentPanel.toolbarItemLabel;
if (!panelName)
return;
var newLabel = WebInspector.UIString("Search %s", panelName);
if (WebInspector.attached)
this.element.setAttribute("placeholder", newLabel);
else {
this.element.removeAttribute("placeholder");
this._toolbarLabelElement.textContent = newLabel;
}
},

cancelSearch: function()
{
this.element.value = "";
this._performSearch("");
},

handleShortcut: function(event)
{
var isMac = WebInspector.isMac();

switch (event.keyIdentifier) {
case "U+0046": 
if (isMac)
var isFindKey = event.metaKey && !event.ctrlKey && !event.altKey && !event.shiftKey;
else
var isFindKey = event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey;

if (isFindKey) {
this.focusSearchField();
event.handled = true;
}
break;


case "F3":
if (!isMac) {
this.focusSearchField();
event.handled = true;
}
break;

case "U+0047": 
var currentPanel = WebInspector.currentPanel;

if (isMac && event.metaKey && !event.ctrlKey && !event.altKey) {
if (event.shiftKey) {
if (currentPanel.jumpToPreviousSearchResult)
currentPanel.jumpToPreviousSearchResult();
} else if (currentPanel.jumpToNextSearchResult)
currentPanel.jumpToNextSearchResult();
event.handled = true;
}
break;
}
},

activePanelChanged: function()
{
this.updateSearchLabel();

if (!this._currentQuery)
return;

panel = WebInspector.currentPanel;
if (panel.performSearch) {
function performPanelSearch()
{
this._updateSearchMatchesCount();

panel.currentQuery = this._currentQuery;
panel.performSearch(this._currentQuery);
}


setTimeout(performPanelSearch.bind(this), 0);
} else {

this._updateSearchMatchesCount();
}
},

_updateSearchMatchesCount: function(matches)
{
if (matches == null) {
this._matchesElement.addStyleClass("hidden");
return;
}

if (matches) {
if (matches === 1)
var matchesString = WebInspector.UIString("1 match");
else
var matchesString = WebInspector.UIString("%d matches", matches);
} else
var matchesString = WebInspector.UIString("Not Found");

this._matchesElement.removeStyleClass("hidden");
this._matchesElement.textContent = matchesString;
WebInspector.toolbar.resize();
},

focusSearchField: function()
{
this.element.focus();
this.element.select();
},

_onSearchFieldManualFocus: function(event)
{
WebInspector.currentFocusElement = event.target;
},

_onKeyDown: function(event)
{

if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {



if (event.target.value === "" && this.currentFocusElement === this.previousFocusElement)
return;
event.preventDefault();
event.stopPropagation();

this.cancelSearch(event);
WebInspector.currentFocusElement = WebInspector.previousFocusElement;
if (WebInspector.currentFocusElement === event.target)
WebInspector.currentFocusElement.currentFocusElement.select();
return false;
}

if (!isEnterKey(event))
return false;


event.target.select();




this._onSearch(event);



event.preventDefault();
},

_onSearch: function(event)
{
var forceSearch = event.keyIdentifier === "Enter";
this._performSearch(event.target.value, forceSearch, event.shiftKey, false);
},

_performSearch: function(query, forceSearch, isBackwardSearch, repeatSearch)
{
var isShortSearch = (query.length < 3);


if (isShortSearch && this._shortSearchWasForcedByKeyEvent && this._currentQuery !== query)
delete this._shortSearchWasForcedByKeyEvent;


if (isShortSearch && forceSearch)
this._shortSearchWasForcedByKeyEvent = true;

if (!query || !query.length || (!forceSearch && isShortSearch)) {

if (this._shortSearchWasForcedByKeyEvent) {
delete this._shortSearchWasForcedByKeyEvent;
return;
}

delete this._currentQuery;

for (var panelName in WebInspector.panels) {
var panel = WebInspector.panels[panelName];
var hadCurrentQuery = !!panel.currentQuery;
delete panel.currentQuery;
if (hadCurrentQuery && panel.searchCanceled)
panel.searchCanceled();
}

this._updateSearchMatchesCount();

return;
}

var currentPanel = WebInspector.currentPanel;
if (!repeatSearch && query === currentPanel.currentQuery && currentPanel.currentQuery === this._currentQuery) {


if (forceSearch) {
if (!isBackwardSearch && currentPanel.jumpToNextSearchResult)
currentPanel.jumpToNextSearchResult();
else if (isBackwardSearch && currentPanel.jumpToPreviousSearchResult)
currentPanel.jumpToPreviousSearchResult();
}
return;
}

this._currentQuery = query;

this._updateSearchMatchesCount();

if (!currentPanel.performSearch)
return;

currentPanel.currentQuery = query;
currentPanel.performSearch(query);
}
}





WebInspector.WorkerManager = function()
{
}

WebInspector.WorkerManager.isWorkerFrontend = function()
{
return !!WebInspector.queryParamsObject["workerId"];
}

WebInspector.WorkerManager.loaded = function()
{
var workerId = WebInspector.queryParamsObject["workerId"];
if (!workerId) {
InspectorBackend.registerDomainDispatcher("Worker", new WebInspector.WorkerMessageForwarder());
return;
}


function receiveMessage(event)
{
var message = event.data;
InspectorBackend.dispatch(message);
}
window.addEventListener("message", receiveMessage, true);


InspectorBackend.sendMessageObjectToBackend = function(message)
{
window.opener.postMessage({workerId: workerId, command: "sendMessageToBackend", message: message}, "*");
}

InspectorFrontendHost.loaded = function()
{
window.opener.postMessage({workerId: workerId, command: "loaded"}, "*");
}
}


WebInspector.WorkerMessageForwarder = function()
{
window.addEventListener("message", this._receiveMessage.bind(this), true);
this._workerIdToWindow = {};
}

WebInspector.WorkerMessageForwarder.prototype = {
_receiveMessage: function(event)
{
var workerId = event.data.workerId;
workerId = parseInt(workerId);
var command = event.data.command;
var message = event.data.message;

if (command == "sendMessageToBackend")
WorkerAgent.sendMessageToWorker(workerId, message);
},

workerCreated: function(workerId)
{
var url = location.href + "&workerId=" + workerId;
url = url.replace("docked=true&", "");
this._workerIdToWindow[workerId] = window.open(url);
},

dispatchMessageFromWorker: function(workerId, message)
{
var win = this._workerIdToWindow[workerId];
if (win)
win.postMessage(message, "*");
}
}







var context = {};  

(function () {
Preferences.ignoreWhitespace = false;
Preferences.samplingCPUProfiler = true;
Preferences.heapProfilerPresent = true;
Preferences.detailedHeapProfiles = true;
Preferences.debuggerAlwaysEnabled = true;
Preferences.profilerAlwaysEnabled = true;
Preferences.canEditScriptSource = true;
Preferences.onlineDetectionEnabled = false;
Preferences.nativeInstrumentationEnabled = true;
Preferences.fileSystemEnabled = false;
Preferences.showTimingTab = true;
Preferences.showCookiesTab = true;
Preferences.saveAsAvailable = true;
Preferences.useLowerCaseMenuTitlesOnWindows = true;
})();


WebInspector.MIMETypes["image/webp"] = {2: true};

var devtools = devtools || {};

devtools.domContentLoaded = function()
{
WebInspector.setAttachedWindow(WebInspector.queryParamsObject.docked === "true");
if (WebInspector.queryParamsObject.toolbar_color && WebInspector.queryParamsObject.text_color)
WebInspector.setToolbarColors(WebInspector.queryParamsObject.toolbar_color, WebInspector.queryParamsObject.text_color);
}
document.addEventListener("DOMContentLoaded", devtools.domContentLoaded, false);



(function InterceptProfilesPanelEvents()
{
var oldShow = WebInspector.ProfilesPanel.prototype.show;
WebInspector.ProfilesPanel.prototype.show = function()
{
this.enableToggleButton.visible = false;
oldShow.call(this);


WebInspector.ProfilesPanel.prototype.show = oldShow;
};
})();



WebInspector.UIString = function(string)
{
return String.vsprintf(string, Array.prototype.slice.call(arguments, 1));
};



(function()
{
var originalDragStart = WebInspector.elementDragStart;
WebInspector.elementDragStart = function(element)
{
if (element) {
var glassPane = document.createElement("div");
glassPane.style.cssText = "position:absolute;width:100%;height:100%;opacity:0;z-index:1";
glassPane.id = "glass-pane-for-drag";
element.parentElement.appendChild(glassPane);
}

originalDragStart.apply(this, arguments);
};

var originalDragEnd = WebInspector.elementDragEnd;
WebInspector.elementDragEnd = function()
{
originalDragEnd.apply(this, arguments);

var glassPane = document.getElementById("glass-pane-for-drag");
if (glassPane)
glassPane.parentElement.removeChild(glassPane);
};
})();







WebInspector.setToolbarColors = function(backgroundColor, color)
{
if (!WebInspector._themeStyleElement) {
WebInspector._themeStyleElement = document.createElement("style");
document.head.appendChild(WebInspector._themeStyleElement);
}
WebInspector._themeStyleElement.textContent =
"#toolbar {\
             background-image: none !important;\
             background-color: " + backgroundColor + " !important;\
         }\
         \
         .toolbar-label {\
             color: " + color + " !important;\
             text-shadow: none;\
         }";
}

WebInspector.resetToolbarColors = function()
{
if (WebInspector._themeStyleElement)
WebInspector._themeStyleElement.textContent = "";

}





WebInspector.platformExtensionAPI = function(tabId)
{
function getTabId()
{
return tabId;
}
webInspector.inspectedWindow.__proto__.__defineGetter__("tabId", getTabId);
chrome = window.chrome || {};
chrome.experimental = chrome.experimental || {};
chrome.experimental.devtools = chrome.experimental.devtools || {};
for (var property in webInspector)
chrome.experimental.devtools[property] = webInspector[property];
}

WebInspector.buildPlatformExtensionAPI = function()
{
return "(" + WebInspector.platformExtensionAPI + ")(" + WebInspector._inspectedTabId + ");";
}

WebInspector.setInspectedTabId = function(tabId)
{
WebInspector._inspectedTabId = tabId;
}

if (WebInspector.InspectorFrontendHostStub) {
WebInspector.InspectorFrontendHostStub.prototype.inspectedURLChanged = function(url)
{
document.title = "Developer Tools - " + url;
}
}








if (window.domAutomationController) {

var ___interactiveUiTestsMode = true;


TestSuite = function()
{
this.controlTaken_ = false;
this.timerId_ = -1;
};



TestSuite.prototype.fail = function(message)
{
if (this.controlTaken_)
this.reportFailure_(message);
else
throw message;
};



TestSuite.prototype.assertEquals = function(expected, actual, opt_message)
{
if (expected !== actual) {
var message = "Expected: '" + expected + "', but was '" + actual + "'";
if (opt_message)
message = opt_message + "(" + message + ")";
this.fail(message);
}
};


TestSuite.prototype.assertTrue = function(value, opt_message)
{
this.assertEquals(true, !!value, opt_message);
};



TestSuite.prototype.assertContains = function(string, substring)
{
if (string.indexOf(substring) === -1)
this.fail("Expected to: '" + string + "' to contain '" + substring + "'");
};



TestSuite.prototype.takeControl = function()
{
this.controlTaken_ = true;

var self = this;
this.timerId_ = setTimeout(function() {
self.reportFailure_("Timeout exceeded: 20 sec");
}, 20000);
};



TestSuite.prototype.releaseControl = function()
{
if (this.timerId_ !== -1) {
clearTimeout(this.timerId_);
this.timerId_ = -1;
}
this.reportOk_();
};



TestSuite.prototype.reportOk_ = function()
{
window.domAutomationController.send("[OK]");
};



TestSuite.prototype.reportFailure_ = function(error)
{
if (this.timerId_ !== -1) {
clearTimeout(this.timerId_);
this.timerId_ = -1;
}
window.domAutomationController.send("[FAILED] " + error);
};



TestSuite.prototype.runTest = function(testName)
{
try {
this[testName]();
if (!this.controlTaken_)
this.reportOk_();
} catch (e) {
this.reportFailure_(e);
}
};



TestSuite.prototype.showPanel = function(panelName)
{

var toolbar = document.getElementById("toolbar");
var button = toolbar.getElementsByClassName(panelName)[0];
button.click();
this.assertEquals(WebInspector.panels[panelName], WebInspector.currentPanel);
};



TestSuite.prototype.addSniffer = function(receiver, methodName, override, opt_sticky)
{
var orig = receiver[methodName];
if (typeof orig !== "function")
this.fail("Cannot find method to override: " + methodName);
var test = this;
receiver[methodName] = function(var_args) {
try {
var result = orig.apply(this, arguments);
} finally {
if (!opt_sticky)
receiver[methodName] = orig;
}

try {
override.apply(this, arguments);
} catch (e) {
test.fail("Exception in overriden method '" + methodName + "': " + e);
}
return result;
};
};


TestSuite.prototype.testEnableResourcesTab = function()
{

}

TestSuite.prototype.testCompletionOnPause = function()
{

}





TestSuite.prototype.testShowScriptsTab = function()
{
this.showPanel("scripts");
var test = this;

this._waitUntilScriptsAreParsed(["debugger_test_page.html"],
function() {
test.releaseControl();
});

this.takeControl();
};



TestSuite.prototype.testScriptsTabIsPopulatedOnInspectedPageRefresh = function()
{
var test = this;
this.assertEquals(WebInspector.panels.elements, WebInspector.currentPanel, "Elements panel should be current one.");

this.addSniffer(WebInspector.panels.scripts, "reset", waitUntilScriptIsParsed);


test.evaluateInConsole_(
"window.location.reload(true);",
function(resultText) {});

function waitUntilScriptIsParsed() {
test.showPanel("scripts");
test._waitUntilScriptsAreParsed(["debugger_test_page.html"],
function() {
test.releaseControl();
});
}


this.takeControl();
};



TestSuite.prototype.testContentScriptIsPresent = function()
{
this.showPanel("scripts");
var test = this;

test._waitUntilScriptsAreParsed(
["page_with_content_script.html", "simple_content_script.js"],
function() {
test.releaseControl();
});


this.takeControl();
};



TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch = function()
{
var test = this;




var expectedScriptsCount = 2;
var parsedScripts = [];

this.showPanel("scripts");


function switchToElementsTab() {
test.showPanel("elements");
setTimeout(switchToScriptsTab, 0);
}

function switchToScriptsTab() {
test.showPanel("scripts");
setTimeout(checkScriptsPanel, 0);
}

function checkScriptsPanel() {
test.assertTrue(!!WebInspector.panels.scripts.visibleView, "No visible script view.");
test.assertTrue(test._scriptsAreParsed(["debugger_test_page.html"]), "Some scripts are missing.");
checkNoDuplicates();
test.releaseControl();
}

function checkNoDuplicates() {
var scriptSelect = document.getElementById("scripts-files");
var options = scriptSelect.options;
for (var i = 0; i < options.length; i++) {
var scriptName = options[i].text;
for (var j = i + 1; j < options.length; j++)
test.assertTrue(scriptName !== options[j].text, "Found script duplicates: " + test.optionsToString_(options));
}
}

test._waitUntilScriptsAreParsed(
["debugger_test_page.html"],
function() {
checkNoDuplicates();
setTimeout(switchToElementsTab, 0);
});



this.takeControl();
};




TestSuite.prototype.testPauseWhenLoadingDevTools = function()
{
this.showPanel("scripts");
var test = this;

var expectations = {
functionsOnStack: ["callDebugger"],
lineNumber: 8,
lineText: "  debugger;"
};



if (WebInspector.currentPanel.paused) {
var callFrame = WebInspector.currentPanel._presentationModel.selectedCallFrame;
this.assertEquals(expectations.functionsOnStack[0], callFrame.functionName);
var callbackInvoked = false;
this._checkSourceFrameWhenLoaded(expectations, function() {
callbackInvoked = true;
if (test.controlTaken_)
test.releaseControl();
});
if (!callbackInvoked) {
test.takeControl();
}
return;
}

this._waitForScriptPause(
{
functionsOnStack: ["callDebugger"],
lineNumber: 8,
lineText: "  debugger;"
},
function() {
test.releaseControl();
});
this.takeControl();
};




TestSuite.prototype.testPauseWhenScriptIsRunning = function()
{
this.showPanel("scripts");
var test = this;

test.evaluateInConsole_(
'setTimeout("handleClick()" , 0)',
function(resultText) {
test.assertTrue(!isNaN(resultText), "Failed to get timer id: " + resultText);
testScriptPauseAfterDelay();
});



function testScriptPauseAfterDelay() {
setTimeout(testScriptPause, 300);
}

function testScriptPause() {


WebInspector.panels.scripts.pauseButton.click();

test._waitForScriptPause(
{
functionsOnStack: ["handleClick", ""],
lineNumber: 5,
lineText: "  while(true) {"
},
function() {
test.releaseControl();
});
}

this.takeControl();
};



TestSuite.prototype.testNetworkSize = function()
{
var test = this;

function finishResource(resource, finishTime)
{
test.assertEquals(219, resource.transferSize, "Incorrect total encoded data length");
test.assertEquals(25, resource.resourceSize, "Incorrect total data length");
test.releaseControl();
}

this.addSniffer(WebInspector.NetworkDispatcher.prototype, "_finishResource", finishResource);


test.evaluateInConsole_("window.location.reload(true);", function(resultText) {});

this.takeControl();
};



TestSuite.prototype.testNetworkSyncSize = function()
{
var test = this;

function finishResource(resource, finishTime)
{
test.assertEquals(219, resource.transferSize, "Incorrect total encoded data length");
test.assertEquals(25, resource.resourceSize, "Incorrect total data length");
test.releaseControl();
}

this.addSniffer(WebInspector.NetworkDispatcher.prototype, "_finishResource", finishResource);


test.evaluateInConsole_("var xhr = new XMLHttpRequest(); xhr.open(\"GET\", \"chunked\", false); xhr.send(null);", function() {});

this.takeControl();
};



TestSuite.prototype.testNetworkRawHeadersText = function()
{
var test = this;

function finishResource(resource, finishTime)
{
if (!resource.responseHeadersText)
test.fail("Failure: resource does not have response headers text");
test.assertEquals(164, resource.responseHeadersText.length, "Incorrect response headers text length");
test.releaseControl();
}

this.addSniffer(WebInspector.NetworkDispatcher.prototype, "_finishResource", finishResource);


test.evaluateInConsole_("window.location.reload(true);", function(resultText) {});

this.takeControl();
};



TestSuite.prototype.testNetworkTiming = function()
{
var test = this;

function finishResource(resource, finishTime)
{



test.assertTrue(resource.timing.receiveHeadersEnd - resource.timing.connectStart >= 70, 
"Time between receiveHeadersEnd and connectStart should be >=70ms, but was " +
"receiveHeadersEnd=" + resource.timing.receiveHeadersEnd + ", connectStart=" + resource.timing.connectStart + ".");
test.assertTrue(resource.responseReceivedTime - resource.startTime >= 0.07, 
"Time between responseReceivedTime and startTime should be >=0.07s, but was " +
"responseReceivedTime=" + resource.responseReceivedTime + ", startTime=" + resource.startTime + ".");
test.assertTrue(resource.endTime - resource.startTime >= 0.14, 
"Time between endTime and startTime should be >=0.14s, but was " +
"endtime=" + resource.endTime + ", startTime=" + resource.startTime + ".");

test.releaseControl();
}

this.addSniffer(WebInspector.NetworkDispatcher.prototype, "_finishResource", finishResource);


test.evaluateInConsole_("window.location.reload(true);", function(resultText) {});

this.takeControl();
};



TestSuite.prototype.optionsToString_ = function(options)
{
var names = [];
for (var i = 0; i < options.length; i++)
names.push('"' + options[i].text + '"');
return names.join(",");
};



TestSuite.prototype.showMainPageScriptSource_ = function(scriptName, callback)
{
var test = this;

var scriptSelect = document.getElementById("scripts-files");
var options = scriptSelect.options;

test.assertTrue(options.length, "Scripts list is empty");


var scriptResource;
if (options[scriptSelect.selectedIndex].text === scriptName)
scriptResource = options[scriptSelect.selectedIndex].representedObject;
else {
var pageScriptIndex = -1;
for (var i = 0; i < options.length; i++) {
if (options[i].text === scriptName) {
pageScriptIndex = i;
break;
}
}
test.assertTrue(-1 !== pageScriptIndex, "Script with url " + scriptName + " not found among " + test.optionsToString_(options));
scriptResource = options[pageScriptIndex].representedObject;


WebInspector.currentPanel._showScriptOrResource(scriptResource);
test.assertEquals(pageScriptIndex, scriptSelect.selectedIndex, "Unexpected selected option index.");
}

test.assertTrue(scriptResource instanceof WebInspector.Resource,
"Unexpected resource class.");
test.assertTrue(!!scriptResource.url, "Resource URL is null.");
test.assertTrue(scriptResource.url.search(scriptName + "$") !== -1, "Main HTML resource should be selected.");

var scriptsPanel = WebInspector.panels.scripts;

var view = scriptsPanel.visibleView;
test.assertTrue(view instanceof WebInspector.SourceView);

if (!view.sourceFrame._loaded) {
test.addSniffer(view, "_sourceFrameSetupFinished", function(event) {
callback(view, scriptResource.url);
});
} else
callback(view, scriptResource.url);
};



TestSuite.prototype.evaluateInConsole_ = function(code, callback)
{
WebInspector.showConsole();
WebInspector.console.prompt.text = code;
WebInspector.console.promptElement.dispatchEvent( TestSuite.createKeyEvent("Enter"));

this.addSniffer(WebInspector.ConsoleView.prototype, "addMessage",
function(commandResult) {
callback(commandResult.toMessageElement().textContent);
});
};



TestSuite.prototype._checkExecutionLine = function(sourceFrame, lineNumber, lineContent)
{
this.assertEquals(lineNumber, sourceFrame._executionLineNumber + 1, "Unexpected execution line number.");
this.assertEquals(lineContent, sourceFrame._textModel.line(lineNumber - 1), "Unexpected execution line text.");
}



TestSuite.prototype._scriptsAreParsed = function(expected)
{
var scriptSelect = document.getElementById("scripts-files");
var options = scriptSelect.options;


var missing = expected.slice(0);
for (var i = 0 ; i < options.length; i++) {
for (var j = 0; j < missing.length; j++) {
if (options[i].text.search(missing[j]) !== -1) {
missing.splice(j, 1);
break;
}
}
}
return missing.length === 0;
};



TestSuite.prototype._waitForScriptPause = function(expectations, callback)
{
var test = this;

test.addSniffer(
WebInspector.debuggerModel,
"_pausedScript",
function(details) {
var callFrames = details.callFrames;
var functionsOnStack = [];
for (var i = 0; i < callFrames.length; i++)
functionsOnStack.push(callFrames[i].functionName);

test.assertEquals(expectations.functionsOnStack.join(","), functionsOnStack.join(","), "Unexpected stack.");



test._checkSourceFrameWhenLoaded(expectations, callback);
});
};



TestSuite.prototype._checkSourceFrameWhenLoaded = function(expectations, callback)
{
var test = this;

var frame = WebInspector.currentPanel.visibleView;

if (frame._textViewer)
checkExecLine();
else {
setTimeout(function() {
test._checkSourceFrameWhenLoaded(expectations, callback);
}, 100);
}
function checkExecLine() {
test._checkExecutionLine(frame, expectations.lineNumber, expectations.lineText);
callback();
}
};



TestSuite.prototype._executeCodeWhenScriptsAreParsed = function(code, expectedScripts)
{
var test = this;

function executeFunctionInInspectedPage() {


test.evaluateInConsole_(
'setTimeout("' + code + '" , 0)',
function(resultText) {
test.assertTrue(!isNaN(resultText), "Failed to get timer id: " + resultText + ". Code: " + code);
});
}

test._waitUntilScriptsAreParsed(expectedScripts, executeFunctionInInspectedPage);
};



TestSuite.prototype._waitUntilScriptsAreParsed = function(expectedScripts, callback)
{
var test = this;

function waitForAllScripts() {
if (test._scriptsAreParsed(expectedScripts))
callback();
else
test.addSniffer(WebInspector.panels.scripts, "_addOptionToFilesSelect", waitForAllScripts);
}

waitForAllScripts();
};



TestSuite.createKeyEvent = function(keyIdentifier)
{
var evt = document.createEvent("KeyboardEvent");
evt.initKeyboardEvent("keydown", true  , true  , null  , keyIdentifier, "");
return evt;
};



var uiTests = {};



uiTests.runAllTests = function()
{

for (var name in TestSuite.prototype) {
if (name.substring(0, 4) === "test" && typeof TestSuite.prototype[name] === "function")
uiTests.runTest(name);
}
};



uiTests.runTest = function(name)
{
if (uiTests._populatedInterface)
new TestSuite().runTest(name);
else
uiTests._pendingTestName = name;
};

(function() {

function runTests()
{
uiTests._populatedInterface = true;
var name = uiTests._pendingTestName;
delete uiTests._pendingTestName;
if (name)
new TestSuite().runTest(name);
}

var oldShowElementsPanel = WebInspector.showElementsPanel;
WebInspector.showElementsPanel = function()
{
oldShowElementsPanel.call(this);
runTests();
}

var oldShowPanel = WebInspector.showPanel;
WebInspector.showPanel = function(name)
{
oldShowPanel.call(this, name);
runTests();
}

})();

}

