




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 = this.ownerDocument.createElement(elementName);
if (className)
element.className = className;
this.appendChild(element);
return element;
}

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


Element.prototype.totalOffsetLeft = function()
{
var total = 0;
for (var element = this; element; element = element.offsetParent) {
total += element.offsetLeft 
if (this !== element)
total += element.clientLeft - element.scrollLeft;
}

return total;
}


Element.prototype.totalOffsetTop = function()
{
var total = 0;
for (var element = this; element; element = element.offsetParent) {
total += element.offsetTop 
if (this !== element)
total += element.clientTop - element.scrollTop;
}

return total;
}


function AnchorBox(x, y, width, height)
{
this.x = x || 0;
this.y = y || 0;
this.width = width || 0;
this.height = height || 0;
}


Element.prototype.offsetRelativeToWindow = function(targetWindow)
{
var elementOffset = new AnchorBox();
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.boxInWindow = function(targetWindow)
{
targetWindow = targetWindow || this.ownerDocument.defaultView;

var anchorBox = this.offsetRelativeToWindow(window);
anchorBox.width = this.offsetWidth;
anchorBox.height = this.offsetHeight;

return anchorBox;
}


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 = this.ownerDocument.defaultView.getSelection();
selection.removeAllRanges();
var range = this.ownerDocument.createRange();
range.setStart(this, start);
range.setEnd(this, end);
selection.addRange(range);
return this;
}

Element.prototype.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;
}

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];

result.lastPathComponent = "";
if (result.path) {

var path = result.path;
var indexOfQuery = path.indexOf("?");
if (indexOfQuery !== -1)
path = path.substring(0, indexOfQuery);


var lastSlashIndex = path.lastIndexOf("/");
if (lastSlashIndex !== -1)
result.lastPathComponent = path.substring(lastSlashIndex + 1);
} 
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);
}

Node.prototype.isAncestor = function(node)
{
if (!node)
return false;

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

Node.prototype.isDescendant = function(descendant)
{
return !!descendant && descendant.isAncestor(this);
}

Node.prototype.traverseNextNode = function(stayWithin)
{
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;
}

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

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

Date.prototype.toISO8601Compact = function()
{
function leadZero(x)
{
return x > 9 ? '' + x : '0' + x
}
return this.getFullYear() +
leadZero(this.getMonth() + 1) +
leadZero(this.getDate()) + 'T' +
leadZero(this.getHours()) +
leadZero(this.getMinutes()) +
leadZero(this.getSeconds());
}

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, var_arg)
{
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), 10);
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), 10);
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)
{
return !isNaN(substitution) ? substitution : 0;
},

f: function(substitution, token)
{
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)
{
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, domChanges)
{
var result = highlightSearchResults(element, [{offset: offset, length: length }], domChanges);
return result.length ? result[0] : null;
}


function highlightSearchResults(element, resultRanges, changes)
{
return highlightRangesWithStyleClass(element, resultRanges, "webkit-search-result", changes);

}


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

var snapshotLength = textNodeSnapshot.snapshotLength;
if (snapshotLength === 0)
return highlightNodes;

var nodeRanges = [];
var rangeEndOffset = 0;
for (var i = 0; i < snapshotLength; ++i) {
var range = {};
range.offset = rangeEndOffset;
range.length = textNodeSnapshot.snapshotItem(i).textContent.length;
rangeEndOffset = range.offset + range.length;
nodeRanges.push(range);
}

var startIndex = 0;
for (var i = 0; i < resultRanges.length; ++i) {
var startOffset = resultRanges[i].offset;
var endOffset = startOffset + resultRanges[i].length;

while (startIndex < snapshotLength && nodeRanges[startIndex].offset + nodeRanges[startIndex].length <= startOffset)
startIndex++;
var endIndex = startIndex; 
while (endIndex < snapshotLength && nodeRanges[endIndex].offset + nodeRanges[endIndex].length < endOffset)
endIndex++;
if (endIndex === snapshotLength)
break;

var highlightNode = ownerDocument.createElement("span");
highlightNode.className = styleClass;
highlightNode.textContent = lineText.substring(startOffset, endOffset);

var lastTextNode = textNodeSnapshot.snapshotItem(endIndex);
var lastText = lastTextNode.textContent;
lastTextNode.textContent = lastText.substring(endOffset - nodeRanges[endIndex].offset);
changes.push({ node: lastTextNode, type: "changed", oldText: lastText, newText: lastTextNode.textContent });

if (startIndex === endIndex) {
lastTextNode.parentElement.insertBefore(highlightNode, lastTextNode);
changes.push({ node: highlightNode, type: "added", nextSibling: lastTextNode, parent: lastTextNode.parentElement });
highlightNodes.push(highlightNode);

var prefixNode = ownerDocument.createTextNode(lastText.substring(0, startOffset - nodeRanges[startIndex].offset));
lastTextNode.parentElement.insertBefore(prefixNode, highlightNode);
changes.push({ node: prefixNode, type: "added", nextSibling: highlightNode, parent: lastTextNode.parentElement });
} else {
var firstTextNode = textNodeSnapshot.snapshotItem(startIndex);
var firstText = firstTextNode.textContent;
var anchorElement = firstTextNode.nextSibling;

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

firstTextNode.textContent = firstText.substring(0, startOffset - nodeRanges[startIndex].offset);
changes.push({ node: firstTextNode, type: "changed", oldText: firstText, newText: firstTextNode.textContent });

for (var j = startIndex + 1; j < endIndex; j++) {
var textNode = textNodeSnapshot.snapshotItem(j);
var text = textNode.textContent;
textNode.textContent = "";
changes.push({ node: textNode, type: "changed", oldText: text, newText: textNode.textContent });
}
}
startIndex = endIndex;
nodeRanges[startIndex].offset = endOffset;
nodeRanges[startIndex].length = lastTextNode.textContent.length;

}
return highlightNodes;
}

function applyDomChanges(domChanges)
{
for (var i = 0, size = domChanges.length; i < size; ++i) {
var entry = domChanges[i];
switch (entry.type) {
case "added":
entry.parent.insertBefore(entry.node, entry.nextSibling);
break;
case "changed":
entry.node.textContent = entry.newText;
break;
}
}
}

function revertDomChanges(domChanges)
{
for (var i = domChanges.length - 1; i >= 0; --i) {
var entry = domChanges[i];
switch (entry.type) {
case "added":
if (entry.node.parentElement)
entry.node.parentElement.removeChild(entry.node);
break;
case "changed":
entry.node.textContent = entry.oldText;
break;
}
}
}


function createSearchRegex(query, caseSensitive, isRegex)
{
var regexFlags = caseSensitive ? "g" : "gi";
var regexObject;

if (isRegex) {
try {
regexObject = new RegExp(query, regexFlags);
} catch (e) {

}
}

if (!regexObject)
regexObject = createPlainTextSearchRegex(query, regexFlags);

return regexObject;
}


function createPlainTextSearchRegex(query, flags)
{

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


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 numberToStringWithSpacesPadding(value, symbolsCount)
{
var numberString = value.toString();
var paddingLength = Math.max(0, symbolsCount - numberString.length);
var paddingString = Array(paddingLength + 1).join("\u00a0");
return paddingString + numberString;
}


function TextDiff()
{
this.added = [];
this.removed = [];
this.changed = [];
} 


TextDiff.compute = function(baseContent, newContent)
{
var oldLines = baseContent.split(/\r?\n/);
var newLines = newContent.split(/\r?\n/);

var diff = Array.diff(oldLines, newLines);

var diffData = new TextDiff();

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;
}
return diffData;
}






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.prototype.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.classList.add("children");
if (this.hidden)
this._childrenListNode.classList.add("hidden");
}

child._attach();

if (this.treeOutline.onadd)
this.treeOutline.onadd(child);
}

TreeOutline.prototype.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.classList.add("children");
if (this.hidden)
this._childrenListNode.classList.add("hidden");
}

child._attach();

if (this.treeOutline.onadd)
this.treeOutline.onadd(child);
}

TreeOutline.prototype.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.prototype.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");

this.removeChildAtIndex.call(this, childIndex);
}

TreeOutline.prototype.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.prototype.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) {
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();
}

return this.getCachedTreeElement(representedObject);
}

TreeOutline.prototype._treeElementDidChange = function(treeElement)
{
if (treeElement.treeOutline !== this)
return;

if (this.onchange)
this.onchange(treeElement);
}

TreeOutline.prototype.treeElementFromPoint = function(x, y)
{
var node = this._childrenListNode.ownerDocument.elementFromPoint(x, y);
if (!node)
return null;

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;
while (nextSelectedElement && !nextSelectedElement.selectable)
nextSelectedElement = nextSelectedElement.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];
while (nextSelectedElement && !nextSelectedElement.selectable)
nextSelectedElement = nextSelectedElement.nextSibling;
handled = nextSelectedElement ? true : false;
} else {
if (event.altKey)
this.selectedTreeElement.expandRecursively();
else
this.selectedTreeElement.expand();
}
}
} else if (event.keyCode === 8   || event.keyCode === 46  ) {
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.revealAndSelect = function(omitFocus)
{

}


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._selectable = true;
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 = {
arrowToggleWidth: 10,

get selectable() {
if (this._hidden)
return false;
return this._selectable;
},

set selectable(x) {
this._selectable = x;
},

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

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

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

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

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

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

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

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

this._hasChildren = x;

if (!this._listItemNode)
return;

if (x)
this._listItemNode.classList.add("parent");
else {
this._listItemNode.classList.remove("parent");
this.collapse();
}

this.didChange();
},

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

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

this._hidden = x;

if (x) {
if (this._listItemNode)
this._listItemNode.classList.add("hidden");
if (this._childrenListNode)
this._childrenListNode.classList.add("hidden");
} else {
if (this._listItemNode)
this._listItemNode.classList.remove("hidden");
if (this._childrenListNode)
this._childrenListNode.classList.remove("hidden");
}
},

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

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

_fireDidChange: function()
{
delete this._didChangeTimeoutIdentifier;

if (this.treeOutline)
this.treeOutline._treeElementDidChange(this);
},

didChange: function()
{
if (!this.treeOutline)
return;


if (!this._didChangeTimeoutIdentifier)
this._didChangeTimeoutIdentifier = setTimeout(this._fireDidChange.bind(this), 0);
},

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

if (typeof this._title === "string")
this._listItemNode.textContent = this._title;
else {
this._listItemNode.removeChildren();
if (this._title)
this._listItemNode.appendChild(this._title);
}
}
}

TreeElement.prototype.appendChild = TreeOutline.prototype.appendChild;
TreeElement.prototype.insertChild = TreeOutline.prototype.insertChild;
TreeElement.prototype.removeChild = TreeOutline.prototype.removeChild;
TreeElement.prototype.removeChildAtIndex = TreeOutline.prototype.removeChildAtIndex;
TreeElement.prototype.removeChildren = TreeOutline.prototype.removeChildren;
TreeElement.prototype.removeChildrenRecursive = TreeOutline.prototype.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.classList.add("hidden");
if (this.hasChildren)
this._listItemNode.classList.add("parent");
if (this.expanded)
this._listItemNode.classList.add("expanded");
if (this.selected)
this._listItemNode.classList.add("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;

var toggleOnClick = element.treeElement.toggleOnClick && !element.treeElement.selectable;
var isInTriangle = element.treeElement.isEventWithinDisclosureTriangle(event);
if (!toggleOnClick && !isInTriangle)
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.classList.remove("expanded");
if (this._childrenListNode)
this._childrenListNode.classList.remove("expanded");

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

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;





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

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.classList.add("children");

if (this.hidden)
this._childrenListNode.classList.add("hidden");

this.onpopulate();

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

delete this._shouldRefreshChildren;
}

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

if (this._childrenListNode)
this._childrenListNode.classList.add("expanded");

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(omitFocus, selectedByUser)
{
if (!this.treeOutline || !this.selectable || this.selected)
return;

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

this.selected = true;

if(!omitFocus)
this.treeOutline._childrenListNode.focus();


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

if (this.onselect)
this.onselect(this, selectedByUser);
}


TreeElement.prototype.revealAndSelect = function(omitFocus)
{
this.reveal();
this.select(omitFocus);
}


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.classList.remove("selected");

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

TreeElement.prototype.onpopulate = function()
{

}


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

if (info)
info.depthChange = 0;

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

if (this === stayWithin)
return null;

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

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

if (!element)
return null;

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


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

while (element && (skipUnrevealed ? (element.revealed() && element.expanded ? element.children[element.children.length - 1] : null) : element.children[element.children.length - 1])) {
if (!dontPopulate && element.hasChildren)
element.onpopulate();
element = (skipUnrevealed ? (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 computedLeftPadding = window.getComputedStyle(this._listItemNode).getPropertyCSSValue("padding-left").getFloatValue(CSSPrimitiveValue.CSS_PX);
var left = this._listItemNode.totalOffsetLeft() + computedLeftPadding;
return event.pageX >= left && event.pageX <= left + this.arrowToggleWidth && this.hasChildren;
}





var WebInspector = {
_createPanels: function()
{
this.panels = {};
WebInspector.inspectorView = new WebInspector.InspectorView();
var parentElement = document.getElementById("main");
WebInspector.inspectorView.show(parentElement);
WebInspector.inspectorView.addEventListener(WebInspector.InspectorView.Events.PanelSelected, this._panelSelected, this);

if (WebInspector.WorkerManager.isWorkerFrontend()) {
this.panels.scripts = new WebInspector.ScriptsPanel(this.debuggerPresentationModel);
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(this.debuggerPresentationModel);
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();
},

_panelSelected: function()
{
this._toggleConsoleButton.disabled = WebInspector.inspectorView.currentPanel() === WebInspector.panels.console;
},

_createGlobalStatusBarItems: function()
{
this._dockToggleButton = new WebInspector.StatusBarButton(this._dockButtonTitle(), "dock-status-bar-item");
this._dockToggleButton.addEventListener("click", this._toggleAttach.bind(this), false);
this._dockToggleButton.toggled = !this.attached;

this._settingsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Settings"), "settings-status-bar-item");
this._settingsButton.addEventListener("click", this._toggleSettings.bind(this), false);

var anchoredStatusBar = document.getElementById("anchored-status-bar-items");
anchoredStatusBar.appendChild(this._dockToggleButton.element);

this._toggleConsoleButton = new WebInspector.StatusBarButton(WebInspector.UIString("Show console."), "console-status-bar-item");
this._toggleConsoleButton.addEventListener("click", this._toggleConsoleButtonClicked.bind(this), false);
anchoredStatusBar.appendChild(this._toggleConsoleButton.element);

if (this.panels.elements)
anchoredStatusBar.appendChild(this.panels.elements.nodeSearchButton.element);
anchoredStatusBar.appendChild(this._settingsButton.element);
},

_dockButtonTitle: function()
{
return this.attached ? WebInspector.UIString("Undock into separate window.") : WebInspector.UIString("Dock to main window.");
},

_toggleAttach: function()
{
if (!this._attached) {
InspectorFrontendHost.requestAttachWindow();
WebInspector.userMetrics.WindowDocked.record();
} else {
InspectorFrontendHost.requestDetachWindow();
WebInspector.userMetrics.WindowUndocked.record();
}
},

_toggleConsoleButtonClicked: function()
{
if (this._toggleConsoleButton.disabled)
return;

this._toggleConsoleButton.toggled = !this._toggleConsoleButton.toggled;

var animationType = window.event && window.event.shiftKey ? WebInspector.Drawer.AnimationType.Slow : WebInspector.Drawer.AnimationType.Normal;
if (this._toggleConsoleButton.toggled) {
this._toggleConsoleButton.title = WebInspector.UIString("Hide console.");
this.drawer.show(this.consoleView, animationType);
this._consoleWasShown = true;
} else {
this._toggleConsoleButton.title = WebInspector.UIString("Show console.");
this.drawer.hide(animationType);
delete this._consoleWasShown;
}
},

_escPressed: function()
{

if (!this._consoleWasShown && WebInspector.drawer.visible)
this.drawer.hide(WebInspector.Drawer.AnimationType.Immediately);
else
this._toggleConsoleButtonClicked();            
},


showViewInDrawer: function(view)
{
this._toggleConsoleButton.title = WebInspector.UIString("Hide console.");
this._toggleConsoleButton.toggled = false;
this.drawer.show(view, WebInspector.Drawer.AnimationType.Immediately);
},

_toggleSettings: function()
{
this._settingsButton.toggled = !this._settingsButton.toggled;
if (this._settingsButton.toggled)
this._showSettingsScreen();
else
this._hideSettingsScreen();
},

_showSettingsScreen: function()
{
function onhide()
{
this._settingsButton.toggled = false;
delete this._settingsScreen;
}

if (!this._settingsScreen) {
this._settingsScreen = new WebInspector.SettingsScreen();
this._settingsScreen.show(onhide.bind(this));
}
},

_hideSettingsScreen: function()
{
if (this._settingsScreen)
this._settingsScreen.hide();
},

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

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

this._attached = x;

var body = document.body;

if (x) {
body.removeStyleClass("detached");
body.addStyleClass("attached");
} else {
body.removeStyleClass("attached");
body.addStyleClass("detached");
}

if (this._dockToggleButton) {
this._dockToggleButton.title = this._dockButtonTitle();
this._dockToggleButton.toggled = !x;
}



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

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

if (WebInspector.drawer)
WebInspector.drawer.resize();
},

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

var errors = WebInspector.console.errors;
var warnings = WebInspector.console.warnings;
if (!errors && !warnings) {
errorWarningElement.addStyleClass("hidden");
return;
}

errorWarningElement.removeStyleClass("hidden");

errorWarningElement.removeChildren();

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

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

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

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

get inspectedPageDomain()
{
var parsedURL = WebInspector.inspectedPageURL && WebInspector.inspectedPageURL.asParsedURL();
return parsedURL ? parsedURL.host : "";
},

_initializeCapability: function(name, callback, error, result)
{
Capabilities[name] = result;
if (callback)
callback();
}
}

WebInspector.Events = {
InspectorClosing: "InspectorClosing"
}

{(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()
{
InspectorBackend.loadFromJSONIfNeeded();
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);
WebInspector.doLoadedDone();
}
return;
}
WebInspector.doLoadedDone();
}

WebInspector.doLoadedDone = function()
{

WebInspector.installPortStyles();
if (WebInspector.socket)
document.body.addStyleClass("remote");

if (WebInspector.queryParamsObject.toolbarColor && WebInspector.queryParamsObject.textColor)
WebInspector.setToolbarColors(WebInspector.queryParamsObject.toolbarColor, WebInspector.queryParamsObject.textColor);

InspectorFrontendHost.loaded();
WebInspector.WorkerManager.loaded();

DebuggerAgent.causesRecompilation(WebInspector._initializeCapability.bind(WebInspector, "debuggerCausesRecompilation", null));
DebuggerAgent.supportsNativeBreakpoints(WebInspector._initializeCapability.bind(WebInspector, "nativeInstrumentationEnabled", null));
ProfilerAgent.causesRecompilation(WebInspector._initializeCapability.bind(WebInspector, "profilerCausesRecompilation", null));
ProfilerAgent.isSampling(WebInspector._initializeCapability.bind(WebInspector, "samplingCPUProfiler", null));
ProfilerAgent.hasHeapProfiler(WebInspector._initializeCapability.bind(WebInspector, "heapProfilerPresent", WebInspector._doLoadedDoneWithCapabilities.bind(WebInspector)));
}

WebInspector._doLoadedDoneWithCapabilities = function()
{
WebInspector.shortcutsScreen = new WebInspector.ShortcutsScreen();
this._registerShortcuts();


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

this.console = new WebInspector.ConsoleModel();
this.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._updateErrorAndWarningCounts, this);
this.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._updateErrorAndWarningCounts, this);
this.console.addEventListener(WebInspector.ConsoleModel.Events.RepeatCountUpdated, this._updateErrorAndWarningCounts, this);

this.debuggerModel = new WebInspector.DebuggerModel();
this.debuggerPresentationModel = new WebInspector.DebuggerPresentationModel();

this.drawer = new WebInspector.Drawer();
this.consoleView = new WebInspector.ConsoleView(WebInspector.WorkerManager.isWorkerFrontend());

this.networkManager = new WebInspector.NetworkManager();
this.resourceTreeModel = new WebInspector.ResourceTreeModel(this.networkManager);
this.networkLog = new WebInspector.NetworkLog();
this.domAgent = new WebInspector.DOMAgent();
new WebInspector.JavaScriptContextManager(this.resourceTreeModel, this.consoleView);

InspectorBackend.registerInspectorDispatcher(this);

this.cssModel = new WebInspector.CSSStyleModel();
this.timelineManager = new WebInspector.TimelineManager();
InspectorBackend.registerDatabaseDispatcher(new WebInspector.DatabaseDispatcher());
InspectorBackend.registerDOMStorageDispatcher(new WebInspector.DOMStorageDispatcher());

this.searchController = new WebInspector.SearchController();
this.advancedSearchController = new WebInspector.AdvancedSearchController();

if (Capabilities.nativeInstrumentationEnabled)
this.domBreakpointsSidebarPane = new WebInspector.DOMBreakpointsSidebarPane();

this._createPanels();
this._createGlobalStatusBarItems();

this.toolbar = new WebInspector.Toolbar();
this.toolbar.attached = WebInspector.attached;

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

this.addMainEventListeners(document);

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

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

var autoselectPanel = WebInspector.UIString("a panel chosen automatically");
var openAnchorLocationSetting = WebInspector.settings.createSetting("openLinkHandler", autoselectPanel);
this.openAnchorLocationRegistry = new WebInspector.HandlerRegistry(openAnchorLocationSetting);
this.openAnchorLocationRegistry.registerHandler(autoselectPanel, function() { return false; });

this.extensionServer.initExtensions();

this.console.enableAgent();

function showInitialPanel()
{
if (!WebInspector.inspectorView.currentPanel())
WebInspector.showPanel(WebInspector.settings.lastActivePanel.get());
}

InspectorAgent.enable(showInitialPanel);
DatabaseAgent.enable();
DOMStorageAgent.enable();


WebInspector.CSSCompletions.requestCSSNameCompletions();
WebInspector.WorkerManager.loadCompleted();
InspectorFrontendAPI.loadCompleted();
}

WebInspector.addPanel = function(panel)
{
WebInspector.inspectorView.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();

WebInspector.setAttachedWindow(WebInspector.queryParamsObject.docked === "true");

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

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







var messagesToDispatch = [];

WebInspector.dispatchQueueIsEmpty = function() {
return messagesToDispatch.length == 0;
}

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)
{
WebInspector.inspectorView.doResize();
WebInspector.drawer.resize();
WebInspector.toolbar.resize();
}

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

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

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.openRequestInNetworkPanel = function(resource)
{
WebInspector.showPanel("network");
WebInspector.panels.network.revealAndHighlightResource(resource);
}

WebInspector._registerShortcuts = function()
{
var shortcut = WebInspector.KeyboardShortcut;
var section = WebInspector.shortcutsScreen.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"));

var advancedSearchShortcut = WebInspector.AdvancedSearchController.createShortcut();
section.addKey(advancedSearchShortcut.name, WebInspector.UIString("Search across all scripts"));

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.shortcutsScreen.show();
event.stopPropagation();
event.preventDefault();
return;
}

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

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

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

if (WebInspector.isEditingAnyField())
return;

var isMac = WebInspector.isMac();
switch (event.keyIdentifier) {
case "U+001B": 
event.preventDefault();
this._escPressed();
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);
event.preventDefault();
}
break;
}
}

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

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

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

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

WebInspector.showConsole = function()
{
if (WebInspector._toggleConsoleButton && !WebInspector._toggleConsoleButton.toggled)
WebInspector._toggleConsoleButtonClicked();
}

WebInspector.showPanel = function(panel)
{
if (!(panel in this.panels)) {
if (WebInspector.WorkerManager.isWorkerFrontend())
panel = "scripts";
else
panel = "elements";
}
WebInspector.inspectorView.setCurrentPanel(this.panels[panel]);
}

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

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

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


WebInspector.log = function(message, messageLevel, showConsole)
{

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 msg = WebInspector.ConsoleMessage.create(
WebInspector.ConsoleMessage.MessageSource.Other,
messageLevel || WebInspector.ConsoleMessage.MessageLevel.Debug,
message);

self.console.addMessage(msg);
if (showConsole)
WebInspector.showConsole();
}


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.inspect = function(payload, hints)
{
var object = WebInspector.RemoteObject.fromPayload(payload);
if (object.subtype === "node") {

WebInspector.inspectorView.setCurrentPanel(WebInspector.panels.elements);
object.pushNodeToFrontend(WebInspector.updateFocusedNode.bind(WebInspector), object.release.bind(object));
return;
}

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

object.release();
}

WebInspector.updateFocusedNode = function(nodeId)
{
this.panels.elements.revealAndSelectNode(nodeId);
}

WebInspector.populateResourceContextMenu = function(contextMenu, url, preferredLineNumber)
{
var registry = WebInspector.openAnchorLocationRegistry;

for (var i = 1; i < registry.handlerNames.length; ++i) {
var handler = registry.handlerNames[i];
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open using %s" : "Open Using %s", handler),
registry.dispatchToHandler.bind(registry, handler, { url: url, preferredLineNumber: preferredLineNumber }));
}
}

WebInspector._showAnchorLocation = function(anchor)
{
if (WebInspector.openAnchorLocationRegistry.dispatch({ url: anchor.href, lineNumber: anchor.lineNumber}))
return true;
var preferedPanel = this.panels[anchor.preferredPanel || "resources"];
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.showPanelForAnchorNavigation(panel);
panel.showAnchorLocation(anchor);
return true;
}

WebInspector.showPanelForAnchorNavigation = function(panel)
{
WebInspector.searchController.disableSearchUntilExplicitAction();
WebInspector.inspectorView.setCurrentPanel(panel);
}

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

WebInspector.evaluateInConsole = function(expression)
{
this.showConsole();
this.consoleView.evaluateUsingTextPrompt(expression);
}

WebInspector.addMainEventListeners = function(doc)
{
doc.addEventListener("keydown", this.documentKeyDown.bind(this), false);
doc.addEventListener("beforecopy", this.documentCanCopy.bind(this), true);
doc.addEventListener("copy", this.documentCopy.bind(this), true);
doc.addEventListener("contextmenu", this.contextMenuEventFired.bind(this), true);
doc.addEventListener("click", this.documentClick.bind(this), true);
}

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

WebInspector._toolbarItemClicked = function(event)
{
var toolbarItem = event.currentTarget;
WebInspector.inspectorView.setCurrentPanel(toolbarItem.panel);
}

WebInspector.installSourceMappingForTest = function(url)
{

var sourceMapping = new WebInspector.ClosureCompilerSourceMapping(url);
var uiSourceCode = WebInspector.panels.scripts.visibleView._uiSourceCode;
uiSourceCode.rawSourceCode.setCompilerSourceMapping(sourceMapping);
}





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

if (element) {

if (WebInspector._elementDraggingGlassPane)
WebInspector._elementDraggingGlassPane.parentElement.removeChild(WebInspector._elementDraggingGlassPane);

var glassPane = document.createElement("div");
glassPane.style.cssText = "position:absolute;top:0;bottom:0;left:0;right:0;opacity:0;z-index:1";
glassPane.id = "glass-pane-for-drag";
element.ownerDocument.body.appendChild(glassPane);
WebInspector._elementDraggingGlassPane = glassPane;
}

WebInspector._elementDraggingEventListener = dividerDrag;
WebInspector._elementEndDraggingEventListener = elementDragEnd;

var targetDocument = event.target.ownerDocument;
targetDocument.addEventListener("mousemove", dividerDrag, true);
targetDocument.addEventListener("mouseup", elementDragEnd, true);

targetDocument.body.style.cursor = cursor;

event.preventDefault();
}

WebInspector.elementDragEnd = function(event)
{
var targetDocument = event.target.ownerDocument;
targetDocument.removeEventListener("mousemove", WebInspector._elementDraggingEventListener, true);
targetDocument.removeEventListener("mouseup", WebInspector._elementEndDraggingEventListener, true);

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

if (WebInspector._elementDraggingGlassPane)
WebInspector._elementDraggingGlassPane.parentElement.removeChild(WebInspector._elementDraggingGlassPane);

delete WebInspector._elementDraggingGlassPane;
delete WebInspector._elementDraggingEventListener;
delete WebInspector._elementEndDraggingEventListener;

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), 10);
animation.start = start;
} else
for (key in start)
element.style.setProperty(key, start[key] + (key in propertyUnit ? propertyUnit[key] : defaultUnit));
}

function animateLoop()
{
if (hasCompleted)
return;


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)
return;

complete = duration;
animateLoop();
}

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

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

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;
}


WebInspector.EditingConfig = function(commitHandler, cancelHandler, context)
{
this.commitHandler = commitHandler;
this.cancelHandler = cancelHandler
this.context = context;


this.pasteHandler;


this.multiline;


this.customFinishHandler;
}

WebInspector.EditingConfig.prototype = {
setPasteHandler: function(pasteHandler)
{
this.pasteHandler = pasteHandler;
},

setMultiline: function(multiline)
{
this.multiline = multiline;
},

setCustomFinishHandler: function(customFinishHandler)
{
this.customFinishHandler = customFinishHandler;
}
}


WebInspector.startEditing = function(element, config)
{
if (!WebInspector.markBeingEdited(element, true))
return;

config = config || new WebInspector.EditingConfig(function() {}, function() {});
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.setCurrentFocusElement(WebInspector.previousFocusElement());
}


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

cleanUpAfterEditing.call(this);

cancelledCallback(this, context);
}


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

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") 
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.setCurrentFocusElement(element);
return {
cancel: editingCancelled.bind(element),
commit: editingCommitted.bind(element)
};
}


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);
}

WebInspector._missingLocalizedStrings = {};


WebInspector.UIString = function(string, vararg)
{
if (Preferences.localizeUI) {
if (window.localizedStrings && string in window.localizedStrings)
string = window.localizedStrings[string];
else {
if (!(string in WebInspector._missingLocalizedStrings)) {
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.useLowerCaseMenuTitles = function()
{
return WebInspector.platform() === "windows" && Preferences.useLowerCaseMenuTitlesOnWindows;
}

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

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

WebInspector.openInNetworkPanelLabel = function()
{
return WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open in network panel" : "Open in Network Panel");
}

WebInspector.copyLinkAddressLabel = function()
{
return WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy link address" : "Copy Link Address");
}

WebInspector.platform = function()
{
if (!WebInspector._platform)
WebInspector._platform = InspectorFrontendHost.platform();
return WebInspector._platform;
}

WebInspector.isMac = function()
{
if (typeof WebInspector._isMac === "undefined")
WebInspector._isMac = WebInspector.platform() === "mac";

return WebInspector._isMac;
}

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

WebInspector.platformFlavor = function()
{
function detectFlavor()
{
const userAgent = navigator.userAgent;

if (WebInspector.platform() === "windows") {
var match = userAgent.match(/Windows NT (\d+)\.(?:\d+)/);
if (match && match[1] >= 6)
return WebInspector.PlatformFlavor.WindowsVista;
return null;
} else if (WebInspector.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;
}
}
}

if (!WebInspector._platformFlavor)
WebInspector._platformFlavor = detectFlavor();

return WebInspector._platformFlavor;
}

WebInspector.port = function()
{
if (!WebInspector._port)
WebInspector._port = InspectorFrontendHost.port();

return WebInspector._port;
}

WebInspector.installPortStyles = function()
{
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);
}

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.previousFocusElement = function()
{
return WebInspector._previousFocusElement;
}

WebInspector.currentFocusElement = function()
{
return WebInspector._currentFocusElement;
}

WebInspector._focusChanged = function(event)
{
WebInspector.setCurrentFocusElement(event.target);
}

WebInspector.setCurrentFocusElement = function(x)
{
if (WebInspector._currentFocusElement !== x)
WebInspector._previousFocusElement = WebInspector._currentFocusElement;
WebInspector._currentFocusElement = x;

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



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

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

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 = "";

}

;(function() {

function windowLoaded()
{
window.addEventListener("focus", WebInspector._windowFocused, false);
window.addEventListener("blur", WebInspector._windowBlurred, false);
document.addEventListener("focus", WebInspector._focusChanged.bind(this), true);
window.removeEventListener("DOMContentLoaded", windowLoaded, false);
}

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

})();






function InspectorBackendClass()
{
this._lastCallbackId = 1;
this._pendingResponsesCount = 0;
this._callbacks = {};
this._domainDispatchers = {};
this._eventArgs = {};
this._replyArgs = {};

this.dumpInspectorTimeStats = false;
this.dumpInspectorProtocolMessages = false;
this._initialized = false;
}

InspectorBackendClass.prototype = {
_wrap: function(callback, method)
{
var callbackId = this._lastCallbackId++;
if (!callback)
callback = function() {};

this._callbacks[callbackId] = callback;
callback.methodName = method;
if (this.dumpInspectorTimeStats)
callback.sendRequestTime = Date.now();

return callbackId;
},

registerCommand: function(method, signature, replyArgs)
{
var domainAndMethod = method.split(".");
var agentName = domainAndMethod[0] + "Agent";
if (!window[agentName])
window[agentName] = {};

window[agentName][domainAndMethod[1]] = this._sendMessageToBackend.bind(this, method, signature);
window[agentName][domainAndMethod[1]]["invoke"] = this._invoke.bind(this, method, signature);
this._replyArgs[method] = replyArgs;

this._initialized = true;
},

registerEvent: function(eventName, params)
{
this._eventArgs[eventName] = params;

this._initialized = true;
},

_invoke: function(method, signature, args, callback)
{
this._wrapCallbackAndSendMessageObject(method, args, callback);
},

_sendMessageToBackend: function(method, signature, vararg)
{
var args = Array.prototype.slice.call(arguments, 2);
var callback = (args.length && typeof args[args.length - 1] === "function") ? args.pop() : null;

var params = {};
var hasParams = false;
for (var i = 0; i < signature.length; ++i) {
var param = signature[i];
var paramName = param["name"];
var typeName = param["type"];
var optionalFlag = param["optional"];

if (!args.length && !optionalFlag) {
console.error("Protocol Error: Invalid number of arguments for method '" + method + "' call. It must have the following arguments '" + JSON.stringify(signature) + "'.");
return;
}

var value = args.shift();
if (optionalFlag && typeof value === "undefined") {
continue;
}

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

params[paramName] = value;
hasParams = true;
}

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

this._wrapCallbackAndSendMessageObject(method, hasParams ? params : null, callback);
},

_wrapCallbackAndSendMessageObject: function(method, params, callback)
{
var messageObject = {};
messageObject.method = method;
if (params)
messageObject.params = params;
messageObject.id = this._wrap(callback, method);

if (this.dumpInspectorProtocolMessages)
console.log("frontend: " + JSON.stringify(messageObject));

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

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

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

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

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

if ("id" in messageObject) { 
if (messageObject.error) {
messageObject.error.__proto__ = {
getDescription: function()
{
switch(this.code) {
case -32700: return "Parse error";
case -32600: return "Invalid Request";
case -32601: return "Method not found";
case -32602: return "Invalid params";
case -32603: return "Internal error";;
case -32000: return "Server error";
}
},

toString: function()
{
var description ="Unknown error code";
return this.getDescription() + "(" + this.code + "): " + this.message + "." + (this.data ? " " + this.data.join(" ") : "");
},

getMessage: function()
{
return this.message;
}
}

if (messageObject.error.code !== -32000)
this.reportProtocolError(messageObject);
}

var callback = this._callbacks[messageObject.id];
if (callback) {
var argumentsArray = [];
if (messageObject.result) {
var paramNames = this._replyArgs[callback.methodName];
if (paramNames) {
for (var i = 0; i < paramNames.length; ++i)
argumentsArray.push(messageObject.result[paramNames[i]]);
}
}

var processingStartTime;
if (this.dumpInspectorTimeStats && callback.methodName)
processingStartTime = Date.now();

argumentsArray.unshift(messageObject.error);
callback.apply(null, argumentsArray);
--this._pendingResponsesCount;
delete this._callbacks[messageObject.id];

if (this.dumpInspectorTimeStats && callback.methodName)
console.log("time-stats: " + callback.methodName + " = " + (processingStartTime - callback.sendRequestTime) + " + " + (Date.now() - processingStartTime));
}

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]]);
}

var processingStartTime;
if (this.dumpInspectorTimeStats)
processingStartTime = Date.now();

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

if (this.dumpInspectorTimeStats)
console.log("time-stats: " + messageObject.method + " = " + (Date.now() - processingStartTime));
}
},

reportProtocolError: function(messageObject)
{
console.error("Request with id = " + messageObject.id + " failed. " + messageObject.error);
},


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);
}
},

loadFromJSONIfNeeded: function()
{
if (this._initialized)
return;

var xhr = new XMLHttpRequest();
xhr.open("GET", "../Inspector.json", false);
xhr.send(null);

var schema = JSON.parse(xhr.responseText);
var jsTypes = { integer: "number", array: "object" };
var rawTypes = {};

var domains = schema["domains"];
for (var i = 0; i < domains.length; ++i) {
var domain = domains[i];
for (var j = 0; domain.types && j < domain.types.length; ++j) {
var type = domain.types[j];
rawTypes[domain.domain + "." + type.id] = jsTypes[type.type] || type.type;
}
}

var result = [];
for (var i = 0; i < domains.length; ++i) {
var domain = domains[i];

var commands = domain["commands"] || [];    
for (var j = 0; j < commands.length; ++j) {
var command = commands[j];
var parameters = command["parameters"];
var paramsText = [];
for (var k = 0; parameters && k < parameters.length; ++k) {
var parameter = parameters[k];

var type;
if (parameter.type)
type = jsTypes[parameter.type] || parameter.type;
else {
var ref = parameter["$ref"];
if (ref.indexOf(".") !== -1)
type = rawTypes[ref];
else
type = rawTypes[domain.domain + "." + ref];
}

var text = "{\"name\": \"" + parameter.name + "\", \"type\": \"" + type + "\", \"optional\": " + (parameter.optional ? "true" : "false") + "}";
paramsText.push(text);
}

var returnsText = [];
var returns = command["returns"] || [];
for (var k = 0; k < returns.length; ++k) {
var parameter = returns[k];
returnsText.push("\"" + parameter.name + "\"");
}
result.push("InspectorBackend.registerCommand(\"" + domain.domain + "." + command.name + "\", [" + paramsText.join(", ") + "], [" + returnsText.join(", ") + "]);");
}

for (var j = 0; domain.events && j < domain.events.length; ++j) {
var event = domain.events[j];
var paramsText = [];
for (var k = 0; event.parameters && k < event.parameters.length; ++k) {
var parameter = event.parameters[k];
paramsText.push("\"" + parameter.name + "\"");
}
result.push("InspectorBackend.registerEvent(\"" + domain.domain + "." + event.name + "\", [" + paramsText.join(", ") + "]);");
}

result.push("InspectorBackend.register" + domain.domain + "Dispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, \"" + domain.domain + "\");");
}
eval(result.join("\n"));
}
}

InspectorBackend = new InspectorBackendClass();







InspectorBackend.registerCommand("Inspector.enable", [], []);
InspectorBackend.registerCommand("Inspector.disable", [], []);
InspectorBackend.registerCommand("Page.enable", [], []);
InspectorBackend.registerCommand("Page.disable", [], []);
InspectorBackend.registerCommand("Page.addScriptToEvaluateOnLoad", [{"name": "scriptSource", "type": "string", "optional": false}], ["identifier"]);
InspectorBackend.registerCommand("Page.removeScriptToEvaluateOnLoad", [{"name": "identifier", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("Page.reload", [{"name": "ignoreCache", "type": "boolean", "optional": true}, {"name": "scriptToEvaluateOnLoad", "type": "string", "optional": true}], []);
InspectorBackend.registerCommand("Page.open", [{"name": "url", "type": "string", "optional": false}, {"name": "newWindow", "type": "boolean", "optional": true}], []);
InspectorBackend.registerCommand("Page.getCookies", [], ["cookies", "cookiesString"]);
InspectorBackend.registerCommand("Page.deleteCookie", [{"name": "cookieName", "type": "string", "optional": false}, {"name": "domain", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("Page.getResourceTree", [], ["frameTree"]);
InspectorBackend.registerCommand("Page.getResourceContent", [{"name": "frameId", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": false}], ["content", "base64Encoded"]);
InspectorBackend.registerCommand("Page.searchInResource", [{"name": "frameId", "type": "string", "optional": false}, {"name": "url", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}], ["result"]);
InspectorBackend.registerCommand("Page.searchInResources", [{"name": "text", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}], ["result"]);
InspectorBackend.registerCommand("Runtime.evaluate", [{"name": "expression", "type": "string", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}, {"name": "includeCommandLineAPI", "type": "boolean", "optional": true}, {"name": "doNotPauseOnExceptions", "type": "boolean", "optional": true}, {"name": "frameId", "type": "string", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}], ["result", "wasThrown"]);
InspectorBackend.registerCommand("Runtime.callFunctionOn", [{"name": "objectId", "type": "string", "optional": false}, {"name": "functionDeclaration", "type": "string", "optional": false}, {"name": "arguments", "type": "object", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}], ["result", "wasThrown"]);
InspectorBackend.registerCommand("Runtime.getProperties", [{"name": "objectId", "type": "string", "optional": false}, {"name": "ownProperties", "type": "boolean", "optional": true}], ["result"]);
InspectorBackend.registerCommand("Runtime.releaseObject", [{"name": "objectId", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("Runtime.releaseObjectGroup", [{"name": "objectGroup", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("Runtime.run", [], []);
InspectorBackend.registerCommand("Console.enable", [], []);
InspectorBackend.registerCommand("Console.disable", [], []);
InspectorBackend.registerCommand("Console.clearMessages", [], []);
InspectorBackend.registerCommand("Console.setMonitoringXHREnabled", [{"name": "enabled", "type": "boolean", "optional": false}], []);
InspectorBackend.registerCommand("Console.addInspectedNode", [{"name": "nodeId", "type": "number", "optional": false}], []);
InspectorBackend.registerCommand("Network.enable", [], []);
InspectorBackend.registerCommand("Network.disable", [], []);
InspectorBackend.registerCommand("Network.setUserAgentOverride", [{"name": "userAgent", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("Network.setExtraHTTPHeaders", [{"name": "headers", "type": "object", "optional": false}], []);
InspectorBackend.registerCommand("Network.getResponseBody", [{"name": "requestId", "type": "string", "optional": false}], ["body", "base64Encoded"]);
InspectorBackend.registerCommand("Network.canClearBrowserCache", [], ["result"]);
InspectorBackend.registerCommand("Network.clearBrowserCache", [], []);
InspectorBackend.registerCommand("Network.canClearBrowserCookies", [], ["result"]);
InspectorBackend.registerCommand("Network.clearBrowserCookies", [], []);
InspectorBackend.registerCommand("Network.setCacheDisabled", [{"name": "cacheDisabled", "type": "boolean", "optional": false}], []);
InspectorBackend.registerCommand("Database.enable", [], []);
InspectorBackend.registerCommand("Database.disable", [], []);
InspectorBackend.registerCommand("Database.getDatabaseTableNames", [{"name": "databaseId", "type": "number", "optional": false}], ["tableNames"]);
InspectorBackend.registerCommand("Database.executeSQL", [{"name": "databaseId", "type": "number", "optional": false}, {"name": "query", "type": "string", "optional": false}], ["success", "transactionId"]);
InspectorBackend.registerCommand("DOMStorage.enable", [], []);
InspectorBackend.registerCommand("DOMStorage.disable", [], []);
InspectorBackend.registerCommand("DOMStorage.getDOMStorageEntries", [{"name": "storageId", "type": "number", "optional": false}], ["entries"]);
InspectorBackend.registerCommand("DOMStorage.setDOMStorageItem", [{"name": "storageId", "type": "number", "optional": false}, {"name": "key", "type": "string", "optional": false}, {"name": "value", "type": "string", "optional": false}], ["success"]);
InspectorBackend.registerCommand("DOMStorage.removeDOMStorageItem", [{"name": "storageId", "type": "number", "optional": false}, {"name": "key", "type": "string", "optional": false}], ["success"]);
InspectorBackend.registerCommand("ApplicationCache.getFramesWithManifests", [], ["frameIds"]);
InspectorBackend.registerCommand("ApplicationCache.enable", [], []);
InspectorBackend.registerCommand("ApplicationCache.getManifestForFrame", [{"name": "frameId", "type": "string", "optional": false}], ["manifestURL"]);
InspectorBackend.registerCommand("ApplicationCache.getApplicationCacheForFrame", [{"name": "frameId", "type": "string", "optional": false}], ["applicationCache"]);
InspectorBackend.registerCommand("FileSystem.enable", [], []);
InspectorBackend.registerCommand("FileSystem.disable", [], []);
InspectorBackend.registerCommand("DOM.getDocument", [], ["root"]);
InspectorBackend.registerCommand("DOM.requestChildNodes", [{"name": "nodeId", "type": "number", "optional": false}], []);
InspectorBackend.registerCommand("DOM.querySelector", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["nodeId"]);
InspectorBackend.registerCommand("DOM.querySelectorAll", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["nodeIds"]);
InspectorBackend.registerCommand("DOM.setNodeName", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}], ["nodeId"]);
InspectorBackend.registerCommand("DOM.setNodeValue", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "value", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("DOM.removeNode", [{"name": "nodeId", "type": "number", "optional": false}], []);
InspectorBackend.registerCommand("DOM.setAttributeValue", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}, {"name": "value", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("DOM.setAttributesAsText", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "text", "type": "string", "optional": false}, {"name": "name", "type": "string", "optional": true}], []);
InspectorBackend.registerCommand("DOM.removeAttribute", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "name", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("DOM.getEventListenersForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["listeners"]);
InspectorBackend.registerCommand("DOM.copyNode", [{"name": "nodeId", "type": "number", "optional": false}], []);
InspectorBackend.registerCommand("DOM.getOuterHTML", [{"name": "nodeId", "type": "number", "optional": false}], ["outerHTML"]);
InspectorBackend.registerCommand("DOM.setOuterHTML", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "outerHTML", "type": "string", "optional": false}], ["nodeId"]);
InspectorBackend.registerCommand("DOM.performSearch", [{"name": "query", "type": "string", "optional": false}], ["searchId", "resultCount"]);
InspectorBackend.registerCommand("DOM.getSearchResults", [{"name": "searchId", "type": "string", "optional": false}, {"name": "fromIndex", "type": "number", "optional": false}, {"name": "toIndex", "type": "number", "optional": false}], ["nodeIds"]);
InspectorBackend.registerCommand("DOM.discardSearchResults", [{"name": "searchId", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("DOM.requestNode", [{"name": "objectId", "type": "string", "optional": false}], ["nodeId"]);
InspectorBackend.registerCommand("DOM.setInspectModeEnabled", [{"name": "enabled", "type": "boolean", "optional": false}, {"name": "highlightConfig", "type": "object", "optional": true}], []);
InspectorBackend.registerCommand("DOM.highlightRect", [{"name": "x", "type": "number", "optional": false}, {"name": "y", "type": "number", "optional": false}, {"name": "width", "type": "number", "optional": false}, {"name": "height", "type": "number", "optional": false}, {"name": "color", "type": "object", "optional": true}, {"name": "outlineColor", "type": "object", "optional": true}], []);
InspectorBackend.registerCommand("DOM.highlightNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "highlightConfig", "type": "object", "optional": false}], []);
InspectorBackend.registerCommand("DOM.hideHighlight", [], []);
InspectorBackend.registerCommand("DOM.highlightFrame", [{"name": "frameId", "type": "string", "optional": false}, {"name": "contentColor", "type": "object", "optional": true}, {"name": "contentOutlineColor", "type": "object", "optional": true}], []);
InspectorBackend.registerCommand("DOM.pushNodeByPathToFrontend", [{"name": "path", "type": "string", "optional": false}], ["nodeId"]);
InspectorBackend.registerCommand("DOM.resolveNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}], ["object"]);
InspectorBackend.registerCommand("DOM.getAttributes", [{"name": "nodeId", "type": "number", "optional": false}], ["attributes"]);
InspectorBackend.registerCommand("DOM.moveTo", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "targetNodeId", "type": "number", "optional": false}, {"name": "insertBeforeNodeId", "type": "number", "optional": true}], ["nodeId"]);
InspectorBackend.registerCommand("CSS.getMatchedStylesForNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "forcedPseudoClasses", "type": "object", "optional": true}, {"name": "includePseudo", "type": "boolean", "optional": true}, {"name": "includeInherited", "type": "boolean", "optional": true}], ["matchedCSSRules", "pseudoElements", "inherited"]);
InspectorBackend.registerCommand("CSS.getInlineStylesForNode", [{"name": "nodeId", "type": "number", "optional": false}], ["inlineStyle", "styleAttributes"]);
InspectorBackend.registerCommand("CSS.getComputedStyleForNode", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "forcedPseudoClasses", "type": "object", "optional": true}], ["computedStyle"]);
InspectorBackend.registerCommand("CSS.getAllStyleSheets", [], ["headers"]);
InspectorBackend.registerCommand("CSS.getStyleSheet", [{"name": "styleSheetId", "type": "string", "optional": false}], ["styleSheet"]);
InspectorBackend.registerCommand("CSS.getStyleSheetText", [{"name": "styleSheetId", "type": "string", "optional": false}], ["text"]);
InspectorBackend.registerCommand("CSS.setStyleSheetText", [{"name": "styleSheetId", "type": "string", "optional": false}, {"name": "text", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("CSS.setPropertyText", [{"name": "styleId", "type": "object", "optional": false}, {"name": "propertyIndex", "type": "number", "optional": false}, {"name": "text", "type": "string", "optional": false}, {"name": "overwrite", "type": "boolean", "optional": false}], ["style"]);
InspectorBackend.registerCommand("CSS.toggleProperty", [{"name": "styleId", "type": "object", "optional": false}, {"name": "propertyIndex", "type": "number", "optional": false}, {"name": "disable", "type": "boolean", "optional": false}], ["style"]);
InspectorBackend.registerCommand("CSS.setRuleSelector", [{"name": "ruleId", "type": "object", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["rule"]);
InspectorBackend.registerCommand("CSS.addRule", [{"name": "contextNodeId", "type": "number", "optional": false}, {"name": "selector", "type": "string", "optional": false}], ["rule"]);
InspectorBackend.registerCommand("CSS.getSupportedCSSProperties", [], ["cssProperties"]);
InspectorBackend.registerCommand("Timeline.start", [{"name": "maxCallStackDepth", "type": "number", "optional": true}], []);
InspectorBackend.registerCommand("Timeline.stop", [], []);
InspectorBackend.registerCommand("Debugger.causesRecompilation", [], ["result"]);
InspectorBackend.registerCommand("Debugger.supportsNativeBreakpoints", [], ["result"]);
InspectorBackend.registerCommand("Debugger.enable", [], []);
InspectorBackend.registerCommand("Debugger.disable", [], []);
InspectorBackend.registerCommand("Debugger.setBreakpointsActive", [{"name": "active", "type": "boolean", "optional": false}], []);
InspectorBackend.registerCommand("Debugger.setBreakpointByUrl", [{"name": "lineNumber", "type": "number", "optional": false}, {"name": "url", "type": "string", "optional": true}, {"name": "urlRegex", "type": "string", "optional": true}, {"name": "columnNumber", "type": "number", "optional": true}, {"name": "condition", "type": "string", "optional": true}], ["breakpointId", "locations"]);
InspectorBackend.registerCommand("Debugger.setBreakpoint", [{"name": "location", "type": "object", "optional": false}, {"name": "condition", "type": "string", "optional": true}], ["breakpointId", "actualLocation"]);
InspectorBackend.registerCommand("Debugger.removeBreakpoint", [{"name": "breakpointId", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("Debugger.continueToLocation", [{"name": "location", "type": "object", "optional": false}], []);
InspectorBackend.registerCommand("Debugger.stepOver", [], []);
InspectorBackend.registerCommand("Debugger.stepInto", [], []);
InspectorBackend.registerCommand("Debugger.stepOut", [], []);
InspectorBackend.registerCommand("Debugger.pause", [], []);
InspectorBackend.registerCommand("Debugger.resume", [], []);
InspectorBackend.registerCommand("Debugger.searchInContent", [{"name": "scriptId", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}, {"name": "caseSensitive", "type": "boolean", "optional": true}, {"name": "isRegex", "type": "boolean", "optional": true}], ["result"]);
InspectorBackend.registerCommand("Debugger.canSetScriptSource", [], ["result"]);
InspectorBackend.registerCommand("Debugger.setScriptSource", [{"name": "scriptId", "type": "string", "optional": false}, {"name": "scriptSource", "type": "string", "optional": false}, {"name": "preview", "type": "boolean", "optional": true}], ["callFrames", "result"]);
InspectorBackend.registerCommand("Debugger.getScriptSource", [{"name": "scriptId", "type": "string", "optional": false}], ["scriptSource"]);
InspectorBackend.registerCommand("Debugger.getFunctionLocation", [{"name": "functionId", "type": "string", "optional": false}], ["location"]);
InspectorBackend.registerCommand("Debugger.setPauseOnExceptions", [{"name": "state", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("Debugger.evaluateOnCallFrame", [{"name": "callFrameId", "type": "string", "optional": false}, {"name": "expression", "type": "string", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}, {"name": "includeCommandLineAPI", "type": "boolean", "optional": true}, {"name": "returnByValue", "type": "boolean", "optional": true}], ["result", "wasThrown"]);
InspectorBackend.registerCommand("DOMDebugger.setDOMBreakpoint", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "type", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("DOMDebugger.removeDOMBreakpoint", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "type", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("DOMDebugger.setEventListenerBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("DOMDebugger.removeEventListenerBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("DOMDebugger.setXHRBreakpoint", [{"name": "url", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("DOMDebugger.removeXHRBreakpoint", [{"name": "url", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("Profiler.causesRecompilation", [], ["result"]);
InspectorBackend.registerCommand("Profiler.isSampling", [], ["result"]);
InspectorBackend.registerCommand("Profiler.hasHeapProfiler", [], ["result"]);
InspectorBackend.registerCommand("Profiler.enable", [], []);
InspectorBackend.registerCommand("Profiler.disable", [], []);
InspectorBackend.registerCommand("Profiler.start", [], []);
InspectorBackend.registerCommand("Profiler.stop", [], []);
InspectorBackend.registerCommand("Profiler.getProfileHeaders", [], ["headers"]);
InspectorBackend.registerCommand("Profiler.getProfile", [{"name": "type", "type": "string", "optional": false}, {"name": "uid", "type": "number", "optional": false}], ["profile"]);
InspectorBackend.registerCommand("Profiler.removeProfile", [{"name": "type", "type": "string", "optional": false}, {"name": "uid", "type": "number", "optional": false}], []);
InspectorBackend.registerCommand("Profiler.clearProfiles", [], []);
InspectorBackend.registerCommand("Profiler.takeHeapSnapshot", [], []);
InspectorBackend.registerCommand("Profiler.collectGarbage", [], []);
InspectorBackend.registerCommand("Profiler.getObjectByHeapObjectId", [{"name": "objectId", "type": "number", "optional": false}], ["result"]);
InspectorBackend.registerCommand("Worker.setWorkerInspectionEnabled", [{"name": "value", "type": "boolean", "optional": false}], []);
InspectorBackend.registerCommand("Worker.sendMessageToWorker", [{"name": "workerId", "type": "number", "optional": false}, {"name": "message", "type": "object", "optional": false}], []);
InspectorBackend.registerCommand("Worker.connectToWorker", [{"name": "workerId", "type": "number", "optional": false}], []);
InspectorBackend.registerCommand("Worker.disconnectFromWorker", [{"name": "workerId", "type": "number", "optional": false}], []);
InspectorBackend.registerCommand("Worker.setAutoconnectToWorkers", [{"name": "value", "type": "boolean", "optional": false}], []);

InspectorBackend.registerEvent("Inspector.evaluateForTestInFrontend", ["testCallId", "script"]);
InspectorBackend.registerEvent("Inspector.inspect", ["object", "hints"]);
InspectorBackend.registerEvent("Inspector.didCreateWorker", ["id", "url", "isShared"]);
InspectorBackend.registerEvent("Inspector.didDestroyWorker", ["id"]);
InspectorBackend.registerEvent("Page.domContentEventFired", ["timestamp"]);
InspectorBackend.registerEvent("Page.loadEventFired", ["timestamp"]);
InspectorBackend.registerEvent("Page.frameNavigated", ["frame"]);
InspectorBackend.registerEvent("Page.frameDetached", ["frameId"]);
InspectorBackend.registerEvent("Console.messageAdded", ["message"]);
InspectorBackend.registerEvent("Console.messageRepeatCountUpdated", ["count"]);
InspectorBackend.registerEvent("Console.messagesCleared", []);
InspectorBackend.registerEvent("Network.requestWillBeSent", ["requestId", "frameId", "loaderId", "documentURL", "request", "timestamp", "initiator", "stackTrace", "redirectResponse"]);
InspectorBackend.registerEvent("Network.requestServedFromCache", ["requestId"]);
InspectorBackend.registerEvent("Network.responseReceived", ["requestId", "frameId", "loaderId", "timestamp", "type", "response"]);
InspectorBackend.registerEvent("Network.dataReceived", ["requestId", "timestamp", "dataLength", "encodedDataLength"]);
InspectorBackend.registerEvent("Network.loadingFinished", ["requestId", "timestamp"]);
InspectorBackend.registerEvent("Network.loadingFailed", ["requestId", "timestamp", "errorText", "canceled"]);
InspectorBackend.registerEvent("Network.requestServedFromMemoryCache", ["requestId", "frameId", "loaderId", "documentURL", "timestamp", "initiator", "resource"]);
InspectorBackend.registerEvent("Network.webSocketWillSendHandshakeRequest", ["requestId", "timestamp", "request"]);
InspectorBackend.registerEvent("Network.webSocketHandshakeResponseReceived", ["requestId", "timestamp", "response"]);
InspectorBackend.registerEvent("Network.webSocketCreated", ["requestId", "url"]);
InspectorBackend.registerEvent("Network.webSocketClosed", ["requestId", "timestamp"]);
InspectorBackend.registerEvent("Database.addDatabase", ["database"]);
InspectorBackend.registerEvent("Database.sqlTransactionSucceeded", ["transactionId", "columnNames", "values"]);
InspectorBackend.registerEvent("Database.sqlTransactionFailed", ["transactionId", "sqlError"]);
InspectorBackend.registerEvent("DOMStorage.addDOMStorage", ["storage"]);
InspectorBackend.registerEvent("DOMStorage.updateDOMStorage", ["storageId"]);
InspectorBackend.registerEvent("ApplicationCache.applicationCacheStatusUpdated", ["frameId", "manifestURL", "status"]);
InspectorBackend.registerEvent("ApplicationCache.networkStateUpdated", ["isNowOnline"]);
InspectorBackend.registerEvent("DOM.documentUpdated", []);
InspectorBackend.registerEvent("DOM.setChildNodes", ["parentId", "nodes"]);
InspectorBackend.registerEvent("DOM.attributeModified", ["nodeId", "name", "value"]);
InspectorBackend.registerEvent("DOM.attributeRemoved", ["nodeId", "name"]);
InspectorBackend.registerEvent("DOM.inlineStyleInvalidated", ["nodeIds"]);
InspectorBackend.registerEvent("DOM.characterDataModified", ["nodeId", "characterData"]);
InspectorBackend.registerEvent("DOM.childNodeCountUpdated", ["nodeId", "childNodeCount"]);
InspectorBackend.registerEvent("DOM.childNodeInserted", ["parentNodeId", "previousNodeId", "node"]);
InspectorBackend.registerEvent("DOM.childNodeRemoved", ["parentNodeId", "nodeId"]);
InspectorBackend.registerEvent("Timeline.eventRecorded", ["record"]);
InspectorBackend.registerEvent("Debugger.globalObjectCleared", []);
InspectorBackend.registerEvent("Debugger.scriptParsed", ["scriptId", "url", "startLine", "startColumn", "endLine", "endColumn", "isContentScript"]);
InspectorBackend.registerEvent("Debugger.scriptFailedToParse", ["url", "scriptSource", "startLine", "errorLine", "errorMessage"]);
InspectorBackend.registerEvent("Debugger.breakpointResolved", ["breakpointId", "location"]);
InspectorBackend.registerEvent("Debugger.paused", ["callFrames", "reason", "data"]);
InspectorBackend.registerEvent("Debugger.resumed", []);
InspectorBackend.registerEvent("Profiler.addProfileHeader", ["header"]);
InspectorBackend.registerEvent("Profiler.addHeapSnapshotChunk", ["uid", "chunk"]);
InspectorBackend.registerEvent("Profiler.finishHeapSnapshot", ["uid"]);
InspectorBackend.registerEvent("Profiler.setRecordingProfile", ["isProfiling"]);
InspectorBackend.registerEvent("Profiler.resetProfiles", []);
InspectorBackend.registerEvent("Profiler.reportHeapSnapshotProgress", ["done", "total"]);
InspectorBackend.registerEvent("Worker.workerCreated", ["workerId", "url", "inspectorConnected"]);
InspectorBackend.registerEvent("Worker.workerTerminated", ["workerId"]);
InspectorBackend.registerEvent("Worker.dispatchMessageFromWorker", ["workerId", "message"]);
InspectorBackend.registerEvent("Worker.disconnectedFromWorker", []);

InspectorBackend.registerInspectorDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Inspector");
InspectorBackend.registerPageDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Page");
InspectorBackend.registerConsoleDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Console");
InspectorBackend.registerNetworkDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Network");
InspectorBackend.registerDatabaseDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Database");
InspectorBackend.registerDOMStorageDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "DOMStorage");
InspectorBackend.registerApplicationCacheDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "ApplicationCache");
InspectorBackend.registerFileSystemDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "FileSystem");
InspectorBackend.registerDOMDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "DOM");
InspectorBackend.registerTimelineDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Timeline");
InspectorBackend.registerDebuggerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Debugger");
InspectorBackend.registerProfilerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Profiler");
InspectorBackend.registerWorkerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Worker");






if (!window.InspectorExtensionRegistry) {


WebInspector.InspectorExtensionRegistryStub = function()
{
}

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

var InspectorExtensionRegistry = new WebInspector.InspectorExtensionRegistryStub();

}





InspectorFrontendAPI = {
_pendingCommands: [],

isDebuggingEnabled: function()
{
return WebInspector.panels.scripts.debuggingEnabled;
},

setDebuggingEnabled: function(enabled)
{
if (enabled) {
WebInspector.panels.scripts.enableDebugging();
WebInspector.inspectorView.setCurrentPanel(WebInspector.panels.scripts);
} else
WebInspector.panels.scripts.disableDebugging();
},

isTimelineProfilingEnabled: function()
{
return WebInspector.panels.timeline.timelineProfilingEnabled;
},

setTimelineProfilingEnabled: function(enabled)
{
WebInspector.panels.timeline.setTimelineProfilingEnabled(enabled);
},

isProfilingJavaScript: function()
{
return WebInspector.CPUProfileType.instance && WebInspector.CPUProfileType.instance.isRecordingProfile();
},

startProfilingJavaScript: function()
{
WebInspector.panels.profiles.enableProfiler();
WebInspector.inspectorView.setCurrentPanel(WebInspector.panels.profiles);
if (WebInspector.CPUProfileType.instance)
WebInspector.CPUProfileType.instance.startRecordingProfile();
},

stopProfilingJavaScript: function()
{
if (WebInspector.CPUProfileType.instance)
WebInspector.CPUProfileType.instance.stopRecordingProfile();
WebInspector.inspectorView.setCurrentPanel(WebInspector.panels.profiles);
},

setAttachedWindow: function(attached)
{
WebInspector.attached = attached;
},

showConsole: function()
{
WebInspector.inspectorView.setCurrentPanel(WebInspector.panels.console);
},

dispatch: function(signature)
{
if (WebInspector.panels) {
var methodName = signature.shift();
return InspectorFrontendAPI[methodName].apply(InspectorFrontendAPI, signature);
}
InspectorFrontendAPI._pendingCommands.push(signature);
},

loadCompleted: function()
{
for (var i = 0; i < InspectorFrontendAPI._pendingCommands.length; ++i)
InspectorFrontendAPI.dispatch(InspectorFrontendAPI._pendingCommands[i]);
InspectorFrontendAPI._pendingCommands = [];
}
}






WebInspector.Object = function() {
}

WebInspector.Object.prototype = {

addEventListener: function(eventType, listener, thisObject)
{
console.assert(listener);

if (!this._listeners)
this._listeners = {};
if (!this._listeners[eventType])
this._listeners[eventType] = [];
this._listeners[eventType].push({ thisObject: thisObject, listener: listener });
},


removeEventListener: function(eventType, listener, thisObject)
{
console.assert(listener);

if (!this._listeners || !this._listeners[eventType])
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 (!this._listeners || !this._listeners[eventType])
return false;
return true;
},


dispatchEventToListeners: function(eventType, eventData)
{
if (!this._listeners || !this._listeners[eventType])
return false;

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

return event.defaultPrevented;
}
}


WebInspector.Event = function(target, type, data)
{
this.target = target;
this.type = type;
this.data = data;
this.defaultPrevented = false;
this._stoppedPropagation = false;
}

WebInspector.Event.prototype = {
stopPropagation: function()
{
this._stoppedPropagation = true;
},

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

WebInspector.notifications = new WebInspector.Object();






var Preferences = {
maxInlineTextChildLength: 80,
minConsoleHeight: 75,
minSidebarWidth: 100,
minElementsSidebarWidth: 200,
minScriptsSidebarWidth: 200,
styleRulesExpandedState: {},
showMissingLocalizedStrings: false,
useLowerCaseMenuTitlesOnWindows: false,
sharedWorkersDebugNote: undefined,
localizeUI: true,
exposeDisableCache: false,
exposeWorkersInspection: false,
applicationTitle: "Web Inspector - %s"
}

var Capabilities = {
samplingCPUProfiler: false,
debuggerCausesRecompilation: true,
profilerCausesRecompilation: true,
nativeInstrumentationEnabled: false,
heapProfilerPresent: false
}


WebInspector.Settings = function()
{
this._eventSupport = new WebInspector.Object();

this.colorFormat = this.createSetting("colorFormat", "hex");
this.consoleHistory = this.createSetting("consoleHistory", []);
this.debuggerEnabled = this.createSetting("debuggerEnabled", false);
this.domWordWrap = this.createSetting("domWordWrap", true);
this.profilerEnabled = this.createSetting("profilerEnabled", false);
this.eventListenersFilter = this.createSetting("eventListenersFilter", "all");
this.lastActivePanel = this.createSetting("lastActivePanel", "elements");
this.lastViewedScriptFile = this.createSetting("lastViewedScriptFile", "application");
this.monitoringXHREnabled = this.createSetting("monitoringXHREnabled", false);
this.preserveConsoleLog = this.createSetting("preserveConsoleLog", false);
this.resourcesLargeRows = this.createSetting("resourcesLargeRows", true);
this.resourcesSortOptions = this.createSetting("resourcesSortOptions", {timeOption: "responseTime", sizeOption: "transferSize"});
this.resourceViewTab = this.createSetting("resourceViewTab", "preview");
this.showInheritedComputedStyleProperties = this.createSetting("showInheritedComputedStyleProperties", false);
this.showUserAgentStyles = this.createSetting("showUserAgentStyles", true);
this.watchExpressions = this.createSetting("watchExpressions", []);
this.breakpoints = this.createSetting("breakpoints", []);
this.eventListenerBreakpoints = this.createSetting("eventListenerBreakpoints", []);
this.domBreakpoints = this.createSetting("domBreakpoints", []);
this.xhrBreakpoints = this.createSetting("xhrBreakpoints", []);
this.cacheDisabled = this.createSetting("cacheDisabled", false);
this.overrideUserAgent = this.createSetting("overrideUserAgent", "");
this.userAgent = this.createSetting("userAgent", "");
this.showScriptFolders = this.createSetting("showScriptFolders", true);



if (window.localStorage.breakpoints && window.localStorage.breakpoints.length > 500000)
delete window.localStorage.breakpoints;
}

WebInspector.Settings.prototype = {

createSetting: function(key, defaultValue)
{
return new WebInspector.Setting(key, defaultValue, this._eventSupport);
}
}


WebInspector.Setting = function(name, defaultValue, eventSupport)
{
this._name = name;
this._defaultValue = defaultValue;
this._eventSupport = eventSupport;
}

WebInspector.Setting.prototype = {
addChangeListener: function(listener, thisObject)
{
this._eventSupport.addEventListener(this._name, listener, thisObject);
},

removeChangeListener: function(listener, thisObject)
{
this._eventSupport.removeEventListener(this._name, listener, thisObject);
},

get name()
{
return this._name;
},

get: function()
{
var value = this._defaultValue;
if (window.localStorage != null && this._name in window.localStorage) {
try {
value = JSON.parse(window.localStorage[this._name]);
} catch(e) {
window.localStorage.removeItem(this._name);
}
}
return value;
},

set: function(value)
{
if (window.localStorage != null) {
try {
window.localStorage[this._name] = JSON.stringify(value);
} catch(e) {
console.error("Error saving setting with name:" + this._name);
}
}
this._eventSupport.dispatchEventToListeners(this._name, value);
}
}

WebInspector.settings = new WebInspector.Settings();





if (!window.InspectorFrontendHost) {


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

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;
},

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)
{
document.title = WebInspector.UIString(Preferences.applicationTitle, url);
},

copyText: function()
{
},

canSaveAs: function(fileName, content)
{
return true;
},

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) {

window.location = this.result;
}
fr.readAsDataURL(blob);
},

canAttachWindow: function()
{
return false;
},

sendMessageToBackend: function(message)
{
},

recordActionTaken: function(actionCode)
{
},

recordPanelShown: function(panelCode)
{
},

recordSettingChanged: function(settingCode)
{
},

loadResourceSynchronously: function(url)
{
return "";
}
}

var InspectorFrontendHost = new WebInspector.InspectorFrontendHostStub();
Preferences.localizeUI = false;

}






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);
}
}






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

WebInspector.ContextMenu.prototype = {
show: function(event)
{

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()
{

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()
{


}





if (!InspectorFrontendHost.showContextMenu) {


WebInspector.SoftContextMenu = function(items)
{
this._items = items;
}

WebInspector.SoftContextMenu.prototype = {
show: function(event)
{
this._x = event.x;
this._y = event.y;
this._time = new Date().getTime();


var absoluteX = event.pageX;
var absoluteY = event.pageY;
var targetElement = event.target;
while (targetElement && window !== targetElement.ownerDocument.defaultView) {
var frameElement = targetElement.ownerDocument.defaultView.frameElement;
absoluteY += frameElement.totalOffsetTop();
absoluteX += frameElement.totalOffsetLeft();
targetElement = frameElement;
}


this._glassPaneElement = document.createElement("div");
this._glassPaneElement.className = "soft-context-menu-glass-pane";
this._glassPaneElement.tabIndex = 0;
this._glassPaneElement.addEventListener("mouseup", this._glassPaneMouseUp.bind(this), false);


this._contextMenuElement = document.createElement("div");
this._contextMenuElement.className = "soft-context-menu";
this._contextMenuElement.tabIndex = 0;
this._contextMenuElement.style.top = absoluteY + "px";
this._contextMenuElement.style.left = absoluteX + "px";

this._contextMenuElement.addEventListener("mousedown", this._discardMenu.bind(this), false);
this._contextMenuElement.addEventListener("keydown", this._menuKeyDown.bind(this), false);
this._contextMenuElement.addEventListener("blur", this._discardMenu.bind(this), false);

for (var i = 0; i < this._items.length; ++i)
this._contextMenuElement.appendChild(this._createMenuItem(this._items[i]));

this._glassPaneElement.appendChild(this._contextMenuElement);
document.body.appendChild(this._glassPaneElement);
this._contextMenuElement.focus();


if (document.body.offsetWidth <  this._contextMenuElement.offsetLeft + this._contextMenuElement.offsetWidth)
this._contextMenuElement.style.left = (absoluteX - this._contextMenuElement.offsetWidth) + "px";
if (document.body.offsetHeight < this._contextMenuElement.offsetTop + this._contextMenuElement.offsetHeight)
this._contextMenuElement.style.top = (document.body.offsetHeight - this._contextMenuElement.offsetHeight) + "px";

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

_createMenuItem: function(item)
{
if (item.type === "separator")
return this._createSeparator();

var menuItemElement = document.createElement("div");
menuItemElement.className = "soft-context-menu-item";

var checkMarkElement = document.createElement("span");
checkMarkElement.textContent = "\u2713 "; 
checkMarkElement.className = "soft-context-menu-item-checkmark";
if (!item.checked)
checkMarkElement.style.opacity = "0";

menuItemElement.appendChild(checkMarkElement);
menuItemElement.appendChild(document.createTextNode(item.label));

menuItemElement.addEventListener("mousedown", this._menuItemMouseDown.bind(this), false);
menuItemElement.addEventListener("mouseup", this._menuItemMouseUp.bind(this), false);


menuItemElement.addEventListener("mouseover", this._menuItemMouseOver.bind(this), false);
menuItemElement.addEventListener("mouseout", this._menuItemMouseOut.bind(this), false);

menuItemElement._actionId = item.id;
return menuItemElement;
},

_createSeparator: function()
{
var separatorElement = document.createElement("div");
separatorElement.className = "soft-context-menu-separator";
separatorElement._isSeparator = true;
return separatorElement;
},

_menuItemMouseDown: function(event)
{

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

_menuItemMouseUp: function(event)
{
this._triggerAction(event.target, event);
},

_triggerAction: function(menuItemElement, event)
{
this._discardMenu(event);
if (typeof menuItemElement._actionId !== "undefined") {
WebInspector.contextMenuItemSelected(menuItemElement._actionId);
delete menuItemElement._actionId;
}
},

_menuItemMouseOver: function(event)
{
this._highlightMenuItem(event.target);
},

_menuItemMouseOut: function(event)
{
this._highlightMenuItem(null);
},

_highlightMenuItem: function(menuItemElement)
{
if (this._highlightedMenuItemElement)
this._highlightedMenuItemElement.removeStyleClass("soft-context-menu-item-mouse-over");
this._highlightedMenuItemElement = menuItemElement;
if (this._highlightedMenuItemElement)
this._highlightedMenuItemElement.addStyleClass("soft-context-menu-item-mouse-over");
},

_highlightPrevious: function()
{
var menuItemElement = this._highlightedMenuItemElement ? this._highlightedMenuItemElement.previousSibling : this._contextMenuElement.lastChild;
while (menuItemElement && menuItemElement._isSeparator)
menuItemElement = menuItemElement.previousSibling;
if (menuItemElement)
this._highlightMenuItem(menuItemElement);
},

_highlightNext: function()
{
var menuItemElement = this._highlightedMenuItemElement ? this._highlightedMenuItemElement.nextSibling : this._contextMenuElement.firstChild;
while (menuItemElement && menuItemElement._isSeparator)
menuItemElement = menuItemElement.nextSibling;
if (menuItemElement)
this._highlightMenuItem(menuItemElement);
},

_menuKeyDown: function(event)
{
switch (event.keyIdentifier) {
case "Up":
this._highlightPrevious(); break;
case "Down":
this._highlightNext(); break;
case "U+001B": 
this._discardMenu(event); break;
case "Enter":
if (!isEnterKey(event))
break;

case "U+0020": 
if (this._highlightedMenuItemElement)
this._triggerAction(this._highlightedMenuItemElement, event);
break;
}
event.stopPropagation();
event.preventDefault();
},

_glassPaneMouseUp: function(event)
{

if (event.x === this._x && event.y === this._y && new Date().getTime() - this._time < 300)
return;
this._discardMenu(event);
},

_discardMenu: function(event)
{
if (this._glassPaneElement) {
var glassPane = this._glassPaneElement;
delete this._glassPaneElement;

document.body.removeChild(glassPane);

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

InspectorFrontendHost.showContextMenu = function(event, items)
{
new WebInspector.SoftContextMenu(items).show(event);
}

}






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, modifiers)
{
if (typeof keyCode === "string")
keyCode = keyCode.charCodeAt(0) - 32;
modifiers = modifiers || WebInspector.KeyboardShortcut.Modifiers.None;
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.eventHasCtrlOrMeta = function(event)
{
return WebInspector.isMac() ? event.metaKey && !event.ctrlKey : event.ctrlKey && !event.metaKey;
}


WebInspector.KeyboardShortcut.makeDescriptor = function(key, modifiers)
{
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(completions, stopCharacters)
{

this._proxyElement;
this._proxyElementDisplay = "inline-block";
this._loadCompletions = completions;
this._completionStopCharacters = stopCharacters;
this._suggestForceable = true;
}

WebInspector.TextPrompt.Events = {
ItemApplied: "text-prompt-item-applied",
ItemAccepted: "text-prompt-item-accepted"
};

WebInspector.TextPrompt.prototype = {
get proxyElement()
{
return this._proxyElement;
},

setSuggestForceable: function(x)
{
this._suggestForceable = x;
},

setSuggestBoxEnabled: function(className)
{
this._suggestBoxClassName = className;
},

renderAsBlock: function()
{
this._proxyElementDisplay = "block";
},


attach: function(element)
{
return this._attachInternal(element);
},


attachAndStartEditing: function(element, blurListener)
{
this._attachInternal(element);
this._startEditing(blurListener);
return this.proxyElement;
},

_attachInternal: function(element)
{
if (this.proxyElement)
throw "Cannot attach an attached TextPrompt";
this._element = element;

this._boundOnKeyDown = this.onKeyDown.bind(this);
this._boundSelectStart = this._selectStart.bind(this);
this._proxyElement = element.ownerDocument.createElement("span");
this._proxyElement.style.display = this._proxyElementDisplay;
element.parentElement.insertBefore(this.proxyElement, element);
this.proxyElement.appendChild(element);
this._element.addStyleClass("text-prompt");
this._element.addEventListener("keydown", this._boundOnKeyDown, false);
this._element.addEventListener("selectstart", this._selectStart.bind(this), false);

if (typeof this._suggestBoxClassName === "string")
this._suggestBox = new WebInspector.TextPrompt.SuggestBox(this, this._element, this._suggestBoxClassName);

return this.proxyElement;
},

detach: function()
{
this._removeFromElement();
this.proxyElement.parentElement.insertBefore(this._element, this.proxyElement);
this.proxyElement.parentElement.removeChild(this.proxyElement);
delete this._proxyElement;
if (this._element === WebInspector.currentFocusElement() || this._element.isAncestor(WebInspector.currentFocusElement()))
WebInspector.setCurrentFocusElement(WebInspector.previousFocusElement());
},

get text()
{
return this._element.textContent;
},

set text(x)
{
this._removeSuggestionAids();
if (!x) {

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

this.moveCaretToEndOfPrompt();
this._element.scrollIntoView();
},

_removeFromElement: function()
{
this.clearAutoComplete(true);
this._element.removeEventListener("keydown", this._boundOnKeyDown, false);
this._element.removeEventListener("selectstart", this._boundSelectStart, false);
if (this._isEditing)
this._stopEditing();
if (this._suggestBox)
this._suggestBox.removeFromElement();
},

_startEditing: function(blurListener)
{
if (!WebInspector.markBeingEdited(this._element, true))
return;
this._isEditing = true;
this._element.addStyleClass("editing");
if (blurListener) {
this._blurListener = blurListener;
this._element.addEventListener("blur", this._blurListener, false);
}
this._oldTabIndex = this._element.tabIndex;
if (this._element.tabIndex < 0)
this._element.tabIndex = 0;
WebInspector.setCurrentFocusElement(this._element);
},

_stopEditing: function()
{
this._element.tabIndex = this._oldTabIndex;
if (this._blurListener)
this._element.removeEventListener("blur", this._blurListener, false);
this._element.removeStyleClass("editing");
delete this._isEditing;
WebInspector.markBeingEdited(this._element, false);
},

_removeSuggestionAids: function()
{
this.clearAutoComplete();
if (this.isSuggestBoxVisible())
this._suggestBox.hide();
},

_selectStart: function(event)
{
if (this._selectionTimeout)
clearTimeout(this._selectionTimeout);

this._removeSuggestionAids();

function moveBackIfOutside()
{
delete this._selectionTimeout;
if (!this.isCaretInsidePrompt() && window.getSelection().isCollapsed) {
this.moveCaretToEndOfPrompt();
this.autoCompleteSoon();
}
}

this._selectionTimeout = setTimeout(moveBackIfOutside.bind(this), 100);
},


defaultKeyHandler: function(event, force)
{
this.clearAutoComplete();
this.autoCompleteSoon(force);
return false;
},

onKeyDown: function(event)
{
var handled = false;
var invokeDefault = true;

switch (event.keyIdentifier) {
case "Up":
handled = this.upKeyPressed(event);
break;
case "Down":
handled = this.downKeyPressed(event);
break;
case "PageUp":
handled = this.pageUpKeyPressed(event);
break;
case "PageDown":
handled = this.pageDownKeyPressed(event);
break;
case "U+0009": 
handled = this.tabKeyPressed(event);
break;
case "Enter":
handled = this.enterKeyPressed(event);
break;
case "Left":
case "Home":
this._removeSuggestionAids();
invokeDefault = false;
break;
case "Right":
case "End":
if (this.isCaretAtEndOfPrompt())
handled = this.acceptAutoComplete();
else
this._removeSuggestionAids();
invokeDefault = false;
break;
case "U+001B": 
if (this.isSuggestBoxVisible()) {
this._suggestBox.hide();
handled = true;
}
break;
case "U+0020": 
if (this._suggestForceable && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
this.defaultKeyHandler(event, true);
handled = true;
}
break;
case "Alt":
case "Meta":
case "Shift":
case "Control":
invokeDefault = false;
break;
}

if (!handled && invokeDefault)
handled = this.defaultKeyHandler(event);

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

return handled;
},

acceptAutoComplete: function()
{
var result = false;
if (this.isSuggestBoxVisible())
result = this._suggestBox.acceptSuggestion();
if (!result)
result = this.acceptSuggestion();

return result;
},


clearAutoComplete: function(includeTimeout)
{
if (includeTimeout && this._completeTimeout) {
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(force)
{
var immediately = this.isSuggestBoxVisible() || force;
if (!this._completeTimeout)
this._completeTimeout = setTimeout(this.complete.bind(this, true, force), immediately ? 0 : 250);
},


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

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

var shouldExit;


if (auto && isEmptyInput && !force)
shouldExit = true;
else if (!auto && !isEmptyInput && !selectionRange.commonAncestorContainer.isDescendant(this._element))
shouldExit = true;
else if (auto && !force && !this.isCaretAtEndOfPrompt() && !this.isSuggestBoxVisible())
shouldExit = true;
else if (!selection.isCollapsed)
shouldExit = true;
else if (!force) {

var wordSuffixRange = selectionRange.startContainer.rangeOfWord(selectionRange.endOffset, this._completionStopCharacters, this._element, "forward");
if (wordSuffixRange.toString().length)
shouldExit = true;
}
if (shouldExit) {
if (this.isSuggestBoxVisible())
this._suggestBox.hide();
return;
}

var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, this._completionStopCharacters, this._element, "backward");
this._loadCompletions(wordPrefixRange, force, this._completionsReady.bind(this, selection, auto, wordPrefixRange, reverse));
},

_boxForAnchorAtStart: function(selection, textRange)
{
var rangeCopy = selection.getRangeAt(0).cloneRange();
var anchorElement = document.createElement("span");
anchorElement.textContent = "\u200B";
textRange.insertNode(anchorElement);
var box = anchorElement.boxInWindow(window);
anchorElement.parentElement.removeChild(anchorElement);
selection.removeAllRanges();
selection.addRange(rangeCopy);
return box;
},


_completionsReady: function(selection, auto, originalWordPrefixRange, reverse, completions)
{
if (!completions || !completions.length) {
if (this.isSuggestBoxVisible())
this._suggestBox.hide();
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;

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

if (this._suggestBox)
this._suggestBox.updateSuggestions(this._boxForAnchorAtStart(selection, fullWordRange), completions, !this.isCaretAtEndOfPrompt());

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];
}
}
}

if (auto) {
if (this.isCaretAtEndOfPrompt()) {
this._userEnteredRange.deleteContents();
this._element.pruneEmptyTextNodes();
var finalSelectionRange = document.createRange();
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);
selection.removeAllRanges();
selection.addRange(finalSelectionRange);
}
} else
this.applySuggestion(completionText, completions.length > 1, originalWordPrefixRange);
},


applySuggestion: function(completionText, isIntermediateSuggestion, originalPrefixRange)
{
var wordPrefixLength;
if (originalPrefixRange)
wordPrefixLength = originalPrefixRange.toString().length;
else
wordPrefixLength = this._userEnteredText ? this._userEnteredText.length : 0;

this._userEnteredRange.deleteContents();
this._element.pruneEmptyTextNodes();
var finalSelectionRange = document.createRange();
var completionTextNode = document.createTextNode(completionText);
this._userEnteredRange.insertNode(completionTextNode);
if (this.autoCompleteElement && this.autoCompleteElement.parentNode) {
this.autoCompleteElement.parentNode.removeChild(this.autoCompleteElement);
delete this.autoCompleteElement;
}

if (isIntermediateSuggestion)
finalSelectionRange.setStart(completionTextNode, wordPrefixLength);
else
finalSelectionRange.setStart(completionTextNode, completionText.length);

finalSelectionRange.setEnd(completionTextNode, completionText.length);

var selection = window.getSelection();
selection.removeAllRanges();
selection.addRange(finalSelectionRange);
if (isIntermediateSuggestion)
this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemApplied, { itemText: completionText });
},

acceptSuggestion: function()
{
if (this._isAcceptingSuggestion)
return false;

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);

if (this._suggestBox)
this._suggestBox.hide();
this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemAccepted);

return true;
},

isSuggestBoxVisible: function()
{
return this._suggestBox && this._suggestBox.visible;
},

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 && (!this.autoCompleteElement || !this.autoCompleteElement.isAncestor(node)))
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)
{

return true;
},

enterKeyPressed: function(event)
{
if (this.isSuggestBoxVisible())
return this._suggestBox.enterKeyPressed(event);

return false;
},

upKeyPressed: function(event)
{
if (this.isSuggestBoxVisible())
return this._suggestBox.upKeyPressed(event);

return false;
},

downKeyPressed: function(event)
{
if (this.isSuggestBoxVisible())
return this._suggestBox.downKeyPressed(event);

return false;
},

pageUpKeyPressed: function(event)
{
if (this.isSuggestBoxVisible())
return this._suggestBox.pageUpKeyPressed(event);

return false;
},

pageDownKeyPressed: function(event)
{
if (this.isSuggestBoxVisible())
return this._suggestBox.pageDownKeyPressed(event);

return false;
},
}

WebInspector.TextPrompt.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.TextPromptWithHistory = function(completions, stopCharacters)
{
WebInspector.TextPrompt.call(this, completions, stopCharacters);


this._data = [];


this._historyOffset = 1;


this._coalesceHistoryDupes = true;
}

WebInspector.TextPromptWithHistory.prototype = {
get historyData()
{

return this._data;
},

setCoalesceHistoryDupes: function(x)
{
this._coalesceHistoryDupes = x;
},


setHistoryData: function(data)
{
this._data = [].concat(data);
this._historyOffset = 1;
},


pushHistoryItem: function(text)
{
if (this._uncommittedIsTop) {
this._data.pop();
delete this._uncommittedIsTop;
}

this._historyOffset = 1;
if (this._coalesceHistoryDupes && text === this._currentHistoryItem())
return;
this._data.push(text);
},


_pushCurrentText: function()
{
if (this._uncommittedIsTop)
this._data.pop(); 
this._uncommittedIsTop = true;
this.clearAutoComplete(true);
this._data.push(this.text);
},


_previous: function()
{
if (this._historyOffset > this._data.length)
return undefined;
if (this._historyOffset === 1)
this._pushCurrentText();
++this._historyOffset;
return this._currentHistoryItem();
},


_next: function()
{
if (this._historyOffset === 1)
return undefined;
--this._historyOffset;
return this._currentHistoryItem();
},

_currentHistoryItem: function()
{
return this._data[this._data.length - this._historyOffset];
},


defaultKeyHandler: function(event, force)
{
var newText;
var isPrevious;

switch (event.keyIdentifier) {
case "Up":
if (!this.isCaretOnFirstLine())
break;
newText = this._previous();
isPrevious = true;
break;
case "Down":
if (!this.isCaretOnLastLine())
break;
newText = this._next();
break;
case "U+0050": 
if (WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey) {
newText = this._previous();
isPrevious = true;
}
break;
case "U+004E": 
if (WebInspector.isMac() && event.ctrlKey && !event.metaKey && !event.altKey && !event.shiftKey)
newText = this._next();
break;
}

if (newText !== undefined) {
event.stopPropagation();
event.preventDefault();
this.text = newText;

if (isPrevious) {
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);
}
}

return true;
}

return WebInspector.TextPrompt.prototype.defaultKeyHandler.apply(this, arguments);
}
}

WebInspector.TextPromptWithHistory.prototype.__proto__ = WebInspector.TextPrompt.prototype;


WebInspector.TextPrompt.SuggestBox = function(textPrompt, inputElement, className)
{
this._textPrompt = textPrompt;
this._inputElement = inputElement;
this._selectedElement = null;
this._boundOnScroll = this._onscrollresize.bind(this, true);
this._boundOnResize = this._onscrollresize.bind(this, false);
window.addEventListener("scroll", this._boundOnScroll, true);
window.addEventListener("resize", this._boundOnResize, true);

var bodyElement = inputElement.ownerDocument.body;
this._element = bodyElement.createChild("div", "suggest-box " + (className || ""));
this._element.addEventListener("mousedown", this._onboxmousedown.bind(this), true);
this.containerElement = this._element.createChild("div", "container");
this.contentElement = this.containerElement.createChild("div", "content");
}

WebInspector.TextPrompt.SuggestBox.prototype = {
get visible()
{
return this._element.hasStyleClass("visible");
},

get hasSelection()
{
return !!this._selectedElement;
},

_onscrollresize: function(isScroll, event)
{
if (isScroll && this._element.isAncestor(event.target) || !this.visible)
return;
this._updateBoxPositionWithExistingAnchor();
},

_updateBoxPositionWithExistingAnchor: function()
{
this._updateBoxPosition(this._anchorBox);
},


_updateBoxPosition: function(anchorBox)
{

this.contentElement.style.display = "inline-block";
document.body.appendChild(this.contentElement);
this.contentElement.positionAt(0, 0);
var contentWidth = this.contentElement.offsetWidth;
var contentHeight = this.contentElement.offsetHeight;
this.contentElement.style.display = "block";
this.containerElement.appendChild(this.contentElement);


this._anchorBox = anchorBox;
const spacer = 6;

const suggestBoxPaddingX = 21;
var maxWidth = document.body.offsetWidth - anchorBox.x - spacer;
var width = Math.min(contentWidth, maxWidth - suggestBoxPaddingX) + suggestBoxPaddingX;
var paddedWidth = contentWidth + suggestBoxPaddingX;
var boxX = anchorBox.x;
if (width < paddedWidth) {

maxWidth = document.body.offsetWidth - spacer;
width = Math.min(contentWidth, maxWidth - suggestBoxPaddingX) + suggestBoxPaddingX;
boxX = document.body.offsetWidth - width;
}

const suggestBoxPaddingY = 2;
var boxY;
var aboveHeight = anchorBox.y;
var underHeight = document.body.offsetHeight - anchorBox.y - anchorBox.height;
var maxHeight = Math.max(underHeight, aboveHeight) - spacer;
var height = Math.min(contentHeight, maxHeight - suggestBoxPaddingY) + suggestBoxPaddingY;
if (underHeight >= aboveHeight) {

boxY = anchorBox.y + anchorBox.height;
this._element.removeStyleClass("above-anchor");
this._element.addStyleClass("under-anchor");
} else {

boxY = anchorBox.y - height;
this._element.removeStyleClass("under-anchor");
this._element.addStyleClass("above-anchor");
}

this._element.positionAt(boxX, boxY);
this._element.style.width = width + "px";
this._element.style.height = height + "px";
},

_onboxmousedown: function(event)
{
event.preventDefault();
},

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

this._element.removeStyleClass("visible");
delete this._selectedElement;
},

removeFromElement: function()
{
window.removeEventListener("scroll", this._boundOnScroll, true);
window.removeEventListener("resize", this._boundOnResize, true);
this._element.parentElement.removeChild(this._element);
},


_applySuggestion: function(text, isIntermediateSuggestion)
{
if (!this.visible || !(text || this._selectedElement))
return false;

var suggestion = text || this._selectedElement.textContent;
if (!suggestion)
return false;

this._textPrompt.applySuggestion(suggestion, isIntermediateSuggestion);
return true;
},


acceptSuggestion: function(text)
{
var result = this._applySuggestion(text, false);
this.hide();
if (!result)
return false;

this._textPrompt.acceptSuggestion();

return true;
},

_onNextItem: function(event, isPageScroll)
{
var children = this.contentElement.childNodes;
if (!children.length)
return false;

if (!this._selectedElement)
this._selectedElement = this.contentElement.firstChild;
else {
if (!isPageScroll)
this._selectedElement = this._selectedElement.nextSibling || this.contentElement.firstChild;
else {
var candidate = this._selectedElement;

for (var itemsLeft = this._rowCountPerViewport; itemsLeft; --itemsLeft) {
if (candidate.nextSibling)
candidate = candidate.nextSibling;
else
break;
}

this._selectedElement = candidate;
}
}
this._updateSelection();
this._applySuggestion(undefined, true);
return true;
},

_onPreviousItem: function(event, isPageScroll)
{
var children = this.contentElement.childNodes;
if (!children.length)
return false;

if (!this._selectedElement)
this._selectedElement = this.contentElement.lastChild;
else {
if (!isPageScroll)
this._selectedElement = this._selectedElement.previousSibling || this.contentElement.lastChild;
else {
var candidate = this._selectedElement;

for (var itemsLeft = this._rowCountPerViewport; itemsLeft; --itemsLeft) {
if (candidate.previousSibling)
candidate = candidate.previousSibling;
else
break;
}

this._selectedElement = candidate;
}
}
this._updateSelection();
this._applySuggestion(undefined, true);
return true;
},


updateSuggestions: function(anchorBox, completions, canShowForSingleItem)
{
if (this._suggestTimeout) {
clearTimeout(this._suggestTimeout);
delete this._suggestTimeout;
}
this._completionsReady(anchorBox, completions, canShowForSingleItem);
},

_onItemMouseDown: function(text, event)
{
this.acceptSuggestion(text);
event.stopPropagation();
event.preventDefault();
},

_createItemElement: function(prefix, text)
{
var element = document.createElement("div");
element.className = "suggest-box-content-item source-code";
element.tabIndex = -1;
if (prefix && prefix.length && !text.indexOf(prefix)) {
var prefixElement = element.createChild("span", "prefix");
prefixElement.textContent = prefix;
var suffixElement = element.createChild("span", "suffix");
suffixElement.textContent = text.substring(prefix.length);
} else {
var suffixElement = element.createChild("span", "suffix");
suffixElement.textContent = text;
}
element.addEventListener("mousedown", this._onItemMouseDown.bind(this, text), false);
return element;
},


_updateItems: function(items, canShowForSingleItem)
{
this.contentElement.removeChildren();

var userEnteredText = this._textPrompt._userEnteredText;
for (var i = 0; i < items.length; ++i) {
var item = items[i];
var currentItemElement = this._createItemElement(userEnteredText, item);
this.contentElement.appendChild(currentItemElement);
}

this._selectedElement = canShowForSingleItem ? this.contentElement.firstChild : null;
this._updateSelection();
},

_updateSelection: function()
{

for (var child = this.contentElement.firstChild; child; child = child.nextSibling) {
if (child !== this._selectedElement)
child.removeStyleClass("selected");
}
if (this._selectedElement) {
this._selectedElement.addStyleClass("selected");
this._selectedElement.scrollIntoViewIfNeeded(false);
}
},


_canShowBox: function(completions, canShowForSingleItem)
{
if (!completions || !completions.length)
return false;

if (completions.length > 1)
return true;


return canShowForSingleItem && completions[0] !== this._textPrompt._userEnteredText;
},

_rememberRowCountPerViewport: function()
{
if (!this.contentElement.firstChild)
return;

this._rowCountPerViewport = Math.floor(this.containerElement.offsetHeight / this.contentElement.firstChild.offsetHeight);
},


_completionsReady: function(anchorBox, completions, canShowForSingleItem)
{
if (this._canShowBox(completions, canShowForSingleItem)) {
this._updateItems(completions, canShowForSingleItem);
this._updateBoxPosition(anchorBox);
this._element.addStyleClass("visible");
this._rememberRowCountPerViewport();
} else
this.hide();
},

upKeyPressed: function(event)
{
return this._onPreviousItem(event);
},

downKeyPressed: function(event)
{
return this._onNextItem(event);
},

pageUpKeyPressed: function(event)
{
return this._onPreviousItem(event, true);
},

pageDownKeyPressed: function(event)
{
return this._onNextItem(event, true);
},

enterKeyPressed: function(event)
{
var hasSelectedItem = !!this._selectedElement;
this.acceptSuggestion();



return hasSelectedItem;
},

tabKeyPressed: function(event)
{
return this.enterKeyPressed(event);
}
}






WebInspector.Popover = function(popoverHelper)
{
this.element = document.createElement("div");
this.element.className = "popover custom-popup-vertical-scroll custom-popup-horizontal-scroll";

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

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

WebInspector.Popover.prototype = {
show: function(contentElement, anchor, preferredWidth, preferredHeight)
{
if (this._disposed)
return;
this.contentElement = contentElement;


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);
preferredWidth = preferredWidth || this.contentElement.offsetWidth;
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;
if (this._popoverHelper)
contentElement.addEventListener("mousemove", this._popoverHelper._killHidePopoverTimer.bind(this._popoverHelper), true);
},

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

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

get disposed()
{
return this._disposed;
},

dispose: function()
{
if (this.visible)
this.hide();
this._disposed = true;
},

_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 = anchorElement.boxInWindow(window);
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 custom-popup-vertical-scroll custom-popup-horizontal-scroll " + 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, showPopover, onHide, disableOnClick)
{
this._panelElement = panelElement;
this._getAnchor = getAnchor;
this._showPopover = showPopover;
this._onHide = onHide;
this._disableOnClick = !!disableOnClick;
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)
{
if (this._disableOnClick)
this.hidePopover();
else {
this._killHidePopoverTimer();
this._handleMouseAction(event, true);
}
},

_mouseMove: function(event)
{

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


if (this._popover && !this._hidePopoverTimer) {
var self = this;
function doHide()
{
self._hidePopover();
delete self._hidePopoverTimer;
}
this._hidePopoverTimer = setTimeout(doHide, this._timeout / 2);
}

this._handleMouseAction(event, false);
},

_handleMouseAction: function(event, isMouseDown)
{
this._resetHoverTimer();
if (event.which && this._disableOnClick)
return;
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;
}
},

hidePopover: function()
{
this._resetHoverTimer();
this._hidePopover();
},

_hidePopover: function()
{
if (!this._popover)
return;

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

this._popover.dispose();
delete this._popover;
},

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

this._hidePopover();
this._popover = new WebInspector.Popover(this);
this._showPopover(element, this._popover);
},

_killHidePopoverTimer: function()
{
if (this._hidePopoverTimer) {
clearTimeout(this._hidePopoverTimer);
delete this._hidePopoverTimer;



this._resetHoverTimer();
}
}
}






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;
},

discard: function()
{
}
}






WebInspector.View = function()
{
this.element = document.createElement("div");
this.element.__view = this;
this._visible = true;
this._isRoot = false;
this._isShowing = false;
this._children = [];
this._hideOnDetach = false;
this._cssFiles = [];
}

WebInspector.View._cssFileToVisibleViewCount = {};
WebInspector.View._cssFileToStyleElement = {};

WebInspector.View.prototype = {
markAsRoot: function()
{
this._isRoot = true;
},

isShowing: function()
{
return this._isShowing;
},

setHideOnDetach: function()
{
this._hideOnDetach = true;
},

_parentIsShowing: function()
{
return this._isRoot || (this._parentView && this._parentView.isShowing());
},

_callOnVisibleChildren: function(method)
{
for (var i = 0; i < this._children.length; ++i)
if (this._children[i]._visible)
method.call(this._children[i]);
},

_processWillShow: function()
{
this._loadCSSIfNeeded();
this._callOnVisibleChildren(this._processWillShow);
},

_processWasShown: function()
{
this._isShowing = true;
this.restoreScrollPositions();

this.wasShown();
this.onResize();

this._callOnVisibleChildren(this._processWasShown);
},

_processWillHide: function()
{
this.storeScrollPositions();

this._callOnVisibleChildren(this._processWillHide);

this.willHide();
this._isShowing = false;
},

_processWasHidden: function()
{
this._disableCSSIfNeeded();
this._callOnVisibleChildren(this._processWasHidden);
},

_processOnResize: function()
{
if (!this.isShowing())
return;

this.onResize();
this._callOnVisibleChildren(this._processOnResize);
},

wasShown: function()
{
},

willHide: function()
{
},

onResize: function()
{
},


show: function(parentElement, insertBefore)
{
WebInspector.View._assert(parentElement, "Attempt to attach view with no parent element");


if (this.element.parentElement !== parentElement) {
var currentParent = parentElement;
while (currentParent && !currentParent.__view)
currentParent = currentParent.parentElement;

if (currentParent) {
this._parentView = currentParent.__view;
this._parentView._children.push(this);
this._isRoot = false;
} else
WebInspector.View._assert(this._isRoot, "Attempt to attach view to orphan node");
} else if (this._visible)
return;

this._visible = true;
if (this._parentIsShowing())
this._processWillShow();

this.element.addStyleClass("visible");


if (this.element.parentElement !== parentElement) {
WebInspector.View._incrementViewCounter(parentElement, this.element);
if (insertBefore)
WebInspector.View._originalInsertBefore.call(parentElement, this.element, insertBefore);
else
WebInspector.View._originalAppendChild.call(parentElement, this.element);
}

if (this._parentIsShowing())
this._processWasShown();
},


detach: function(overrideHideOnDetach)
{
var parentElement = this.element.parentElement;
if (!parentElement)
return;

if (this._parentIsShowing())
this._processWillHide();

if (this._hideOnDetach && !overrideHideOnDetach) {
this.element.removeStyleClass("visible");
this._visible = false;
if (this._parentIsShowing())
this._processWasHidden();
return;
}


WebInspector.View._decrementViewCounter(parentElement, this.element);
WebInspector.View._originalRemoveChild.call(parentElement, this.element);

this._visible = false;
if (this._parentIsShowing())
this._processWasHidden();


if (this._parentView) {
var childIndex = this._parentView._children.indexOf(this);
WebInspector.View._assert(childIndex >= 0, "Attempt to remove non-child view");
this._parentView._children.splice(childIndex, 1);
this._parentView = null;
} else
WebInspector.View._assert(this._isRoot, "Removing non-root view from DOM");
},

detachChildViews: function()
{
var children = this._children.slice();
for (var i = 0; i < children.length; ++i)
children[i].detach();
},

elementsToRestoreScrollPositionsFor: function()
{
return [this.element];
},

storeScrollPositions: function()
{
var elements = this.elementsToRestoreScrollPositionsFor();
for (var i = 0; i < elements.length; ++i) {
var container = elements[i];
container._scrollTop = container.scrollTop;
container._scrollLeft = container.scrollLeft;
}
},

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;
if (container._scrollLeft)
container.scrollLeft = container._scrollLeft;
}
},

canHighlightLine: function()
{
return false;
},

highlightLine: function(line)
{
},

doResize: function()
{
this._processOnResize();
},

registerRequiredCSS: function(cssFile)
{
this._cssFiles.push(cssFile);
},

_loadCSSIfNeeded: function()
{
for (var i = 0; i < this._cssFiles.length; ++i) {
var cssFile = this._cssFiles[i];

var viewsWithCSSFile = WebInspector.View._cssFileToVisibleViewCount[cssFile];
WebInspector.View._cssFileToVisibleViewCount[cssFile] = (viewsWithCSSFile || 0) + 1;
if (!viewsWithCSSFile)
this._doLoadCSS(cssFile);
}
},

_doLoadCSS: function(cssFile)
{
var styleElement = WebInspector.View._cssFileToStyleElement[cssFile];
if (styleElement) {
styleElement.disabled = false;
return;
}

var xhr = new XMLHttpRequest();
xhr.open("GET", cssFile, false);
xhr.send(null);

styleElement = document.createElement("style");
styleElement.type = "text/css";
styleElement.textContent = xhr.responseText;
document.head.insertBefore(styleElement, document.head.firstChild);

WebInspector.View._cssFileToStyleElement[cssFile] = styleElement;
},

_disableCSSIfNeeded: function()
{
for (var i = 0; i < this._cssFiles.length; ++i) {
var cssFile = this._cssFiles[i];

var viewsWithCSSFile = WebInspector.View._cssFileToVisibleViewCount[cssFile];
viewsWithCSSFile--;
WebInspector.View._cssFileToVisibleViewCount[cssFile] = viewsWithCSSFile;

if (!viewsWithCSSFile)
this._doUnloadCSS(cssFile);
}
},

_doUnloadCSS: function(cssFile)
{
var styleElement = WebInspector.View._cssFileToStyleElement[cssFile];
styleElement.disabled = true;
},

printViewHierarchy: function()
{
var lines = [];
this._collectViewHierarchy("", lines);
console.log(lines.join("\n"));
},

_collectViewHierarchy: function(prefix, lines)
{
lines.push(prefix + "[" + this.element.className + "]" + (this._children.length ? " {" : ""));

for (var i = 0; i < this._children.length; ++i)
this._children[i]._collectViewHierarchy(prefix + "    ", lines);

if (this._children.length)
lines.push(prefix + "}");
}
}

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

WebInspector.View._originalAppendChild = Element.prototype.appendChild;
WebInspector.View._originalInsertBefore = Element.prototype.insertBefore;
WebInspector.View._originalRemoveChild = Element.prototype.removeChild;
WebInspector.View._originalRemoveChildren = Element.prototype.removeChildren;

WebInspector.View._incrementViewCounter = function(parentElement, childElement)
{
var count = (childElement.__viewCounter || 0) + (childElement.__view ? 1 : 0);
if (!count)
return;

while (parentElement) {
parentElement.__viewCounter = (parentElement.__viewCounter || 0) + count;
parentElement = parentElement.parentElement;
}
}

WebInspector.View._decrementViewCounter = function(parentElement, childElement)
{
var count = (childElement.__viewCounter || 0) + (childElement.__view ? 1 : 0);
if (!count)
return;

while (parentElement) {
parentElement.__viewCounter -= count;
parentElement = parentElement.parentElement;
}
}

WebInspector.View._assert = function(condition, message)
{
if (!condition) {
console.trace();
throw new Error(message);
}
}

Element.prototype.appendChild = function(child)
{
WebInspector.View._assert(!child.__view, "Attempt to add view via regular DOM operation.");
return WebInspector.View._originalAppendChild.call(this, child);
}

Element.prototype.insertBefore = function(child, anchor)
{
WebInspector.View._assert(!child.__view, "Attempt to add view via regular DOM operation.");
return WebInspector.View._originalInsertBefore.call(this, child, anchor);
}


Element.prototype.removeChild = function(child)
{
WebInspector.View._assert(!child.__viewCounter && !child.__view, "Attempt to remove element containing view via regular DOM operation");
return WebInspector.View._originalRemoveChild.call(this, child);
}

Element.prototype.removeChildren = function()
{
WebInspector.View._assert(!this.__viewCounter, "Attempt to remove element containing view via regular DOM operation");
WebInspector.View._originalRemoveChildren.call(this);
}






WebInspector.TabbedPane = function()
{
WebInspector.View.call(this);
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._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.detach();
},

canHighlightLine: function()
{
return this._currentTab && this._currentTab.view && this._currentTab.view.canHighlightLine();
},

highlightLine: function(line)
{
if (this.canHighlightLine())
this._currentTab.view.highlightLine(line);
}
}

WebInspector.TabbedPane.prototype.__proto__ = WebInspector.View.prototype;






WebInspector.Drawer = function()
{
this.element = document.getElementById("drawer");
this._savedHeight = 200; 
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._counters = document.getElementById("counters");

this._drawerContentsElement = document.createElement("div");
this._drawerContentsElement.id = "drawer-contents";
this._drawerContentsElement.className = "drawer-contents";
this.element.appendChild(this._drawerContentsElement);

this._drawerStatusBar = document.createElement("div");
this._drawerStatusBar.id = "drawer-status-bar";
this._drawerStatusBar.className = "status-bar";
this.element.appendChild(this._drawerStatusBar);

this._viewStatusBar = document.createElement("div");
this._drawerStatusBar.appendChild(this._viewStatusBar);
}

WebInspector.Drawer.AnimationType = {
Immediately: 0,
Normal: 1,
Slow: 2
}

WebInspector.Drawer.prototype = {
get visible()
{
return !!this._view;
},

_constrainHeight: function(height)
{
return Number.constrain(height, Preferences.minConsoleHeight, window.innerHeight - this._mainElement.totalOffsetTop() - Preferences.minConsoleHeight);
},

show: function(view, animationType)
{
this.immediatelyFinishAnimation();
if (this._view && this._view.counterElement)
this._view.counterElement.parentNode.removeChild(this._view.counterElement);

var drawerWasVisible = this.visible;

if (this._view) {
this._view.detach();
this._drawerContentsElement.removeChildren();
}

this._view = view;

var statusBarItems = this._view.statusBarItems || [];
this._viewStatusBar.removeChildren();
for (var i = 0; i < statusBarItems.length; ++i)
this._viewStatusBar.appendChild(statusBarItems[i]);

if (this._view.counterElement)
this._counters.insertBefore(this._view.counterElement, this._counters.firstChild);

document.body.addStyleClass("drawer-visible");
this._view.markAsRoot();
this._view.show(this._drawerContentsElement);

if (drawerWasVisible)
return;

var anchoredItems = document.getElementById("anchored-status-bar-items");
var height = this._constrainHeight(this._savedHeight || this.element.offsetHeight);
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()
{
WebInspector.inspectorView.currentPanel().statusBarResized();
if (this._view && this._view.afterShow)
this._view.afterShow();
delete this._currentAnimation;
if (this._currentPanelCounters)
this._currentPanelCounters.removeAttribute("style");
}

this._currentAnimation = WebInspector.animateStyle(animations, this._animationDuration(animationType), animationFinished.bind(this));
if (animationType === WebInspector.Drawer.AnimationType.Immediately)
this._currentAnimation.forceComplete();
},

hide: function(animationType)
{
this.immediatelyFinishAnimation();
if (!this.visible)
return;

this._savedHeight = this.element.offsetHeight;

if (this.element === WebInspector.currentFocusElement() || this.element.isAncestor(WebInspector.currentFocusElement()))
WebInspector.setCurrentFocusElement(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");
WebInspector.inspectorView.currentPanel().statusBarResized();
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.inspectorView.currentPanel().doResize();
this._mainStatusBar.insertBefore(anchoredItems, this._mainStatusBar.firstChild);
this._mainStatusBar.style.removeProperty("padding-left");

if (this._view.counterElement)
this._view.counterElement.parentNode.removeChild(this._view.counterElement);

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

this._view.detach();
delete this._view;
this._drawerContentsElement.removeChildren();
document.body.removeStyleClass("drawer-visible");
delete this._currentAnimation;
}

this._currentAnimation = WebInspector.animateStyle(animations, this._animationDuration(animationType), animationFinished.bind(this));
if (animationType === WebInspector.Drawer.AnimationType.Immediately)
this._currentAnimation.forceComplete();
},

resize: function()
{
if (!this.visible)
return;

this._view.storeScrollPositions();
var height = this._constrainHeight(parseInt(this.element.style.height, 10));
this._mainElement.style.bottom = height + "px";
this.element.style.height = height + "px";
this._view.doResize();
},

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);
},

_animationDuration: function(animationType)
{
switch (animationType) {
case WebInspector.Drawer.AnimationType.Slow:
return 2000;
case WebInspector.Drawer.AnimationType.Normal:
return 250;
default:
return 0;
}        
},

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

this._view.storeScrollPositions();
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";
if (WebInspector.inspectorView.currentPanel())
WebInspector.inspectorView.currentPanel().doResize();
this._view.doResize();

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

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

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

event.stopPropagation();
}
}


WebInspector.drawer = null;






WebInspector.ConsoleModel = function()
{
this.messages = [];
this.warnings = 0;
this.errors = 0;
this._interruptRepeatCount = false;
InspectorBackend.registerConsoleDispatcher(new WebInspector.ConsoleDispatcher(this));
}

WebInspector.ConsoleModel.Events = {
ConsoleCleared: "console-cleared",
MessageAdded: "console-message-added",
RepeatCountUpdated: "repeat-count-updated"
}

WebInspector.ConsoleModel.prototype = {
enableAgent: function()
{
if (WebInspector.settings.monitoringXHREnabled.get())
ConsoleAgent.setMonitoringXHREnabled(true);

ConsoleAgent.enable();
},


addMessage: function(msg)
{
this.messages.push(msg);
this._previousMessage = msg;
this._incrementErrorWarningCount(msg);
this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.MessageAdded, msg);
this._interruptRepeatCount = false;
},


_incrementErrorWarningCount: function(msg)
{
switch (msg.level) {
case WebInspector.ConsoleMessage.MessageLevel.Warning:
this.warnings += msg.repeatDelta;
break;
case WebInspector.ConsoleMessage.MessageLevel.Error:
this.errors += msg.repeatDelta;
break;
}
},

requestClearMessages: function()
{
ConsoleAgent.clearMessages();
this.clearMessages();
},

clearMessages: function()
{
this.messages = [];

this.errors = 0;
this.warnings = 0;

this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.ConsoleCleared);
},

interruptRepeatCount: function()
{
this._interruptRepeatCount = true;
},

_messageRepeatCountUpdated: function(count)
{
var msg = this._previousMessage;
if (!msg)
return;

var prevRepeatCount = msg.totalRepeatCount;

if (!this._interruptRepeatCount) {
msg.repeatDelta = count - prevRepeatCount;
msg.repeatCount = msg.repeatCount + msg.repeatDelta;
msg.totalRepeatCount = count;
msg.updateRepeatCount();

this._incrementErrorWarningCount(msg);
this.dispatchEventToListeners(WebInspector.ConsoleModel.Events.RepeatCountUpdated, msg);
} else {
var msgCopy = WebInspector.ConsoleMessage.create(msg.source, msg.level, msg._messageText, msg.type, msg.url, msg.line, count - prevRepeatCount, msg._parameters, msg._stackTrace, msg._request);
msgCopy.totalRepeatCount = count;
this.addMessage(msgCopy);
}
}
}

WebInspector.ConsoleModel.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.ConsoleMessage = function()
{
this.repeatDelta = 0;
this.repeatCount = 0;
this._totalRepeatCount = 0;
}

WebInspector.ConsoleMessage.prototype = {

get totalRepeatCount()
{
return this._totalRepeatCount;
},

set totalRepeatCount(totalRepeatCount)
{
this._totalRepeatCount = totalRepeatCount;
},

updateRepeatCount: function()
{

}
}


WebInspector.ConsoleMessage.create = function(source, level, message, type, url, line, repeatCount, parameters, stackTrace, request)
{
}


WebInspector.ConsoleMessage.MessageSource = {
HTML: "html",
XML: "xml",
JS: "javascript",
Network: "network",
ConsoleAPI: "console-api",
Other: "other"
}

WebInspector.ConsoleMessage.MessageType = {
Log: "log",
Dir: "dir",
DirXML: "dirxml",
Trace: "trace",
StartGroup: "startGroup",
StartGroupCollapsed: "startGroupCollapsed",
EndGroup: "endGroup",
Assert: "assert",
Result: "result"
}

WebInspector.ConsoleMessage.MessageLevel = {
Tip: "tip",
Log: "log",
Warning: "warning",
Error: "error",
Debug: "debug"
}



WebInspector.ConsoleDispatcher = function(console)
{
this._console = console;
}

WebInspector.ConsoleDispatcher.prototype = {

messageAdded: function(payload)
{
var consoleMessage = WebInspector.ConsoleMessage.create(
payload.source,
payload.level,
payload.text,
payload.type,
payload.url,
payload.line,
payload.repeatCount,
payload.parameters,
payload.stackTrace,
payload.networkRequestId ? WebInspector.networkResourceById(payload.networkRequestId) : undefined);
this._console.addMessage(consoleMessage);
},


messageRepeatCountUpdated: function(count)
{
this._console._messageRepeatCountUpdated(count);
},

messagesCleared: function()
{
if (!WebInspector.settings.preserveConsoleLog.get())
this._console.clearMessages();
}
}


WebInspector.console = null;






WebInspector.ConsoleMessageImpl = function(source, level, message, linkifier, type, url, line, repeatCount, parameters, stackTrace, request)
{
WebInspector.ConsoleMessage.call();

this._linkifier = linkifier;
this.source = source;
this.type = type || WebInspector.ConsoleMessage.MessageType.Log;
this.level = level;
this.line = line || 0;
this.url = url || null;
repeatCount = repeatCount || 1;
this.repeatCount = repeatCount;
this.repeatDelta = repeatCount;
this.totalRepeatCount = repeatCount;
this._messageText = message;
this._parameters = parameters;
this._stackTrace = stackTrace;
this._request = request;

this._customFormatters = {
"object": this._formatParameterAsObject,
"array":  this._formatParameterAsArray,
"node":   this._formatParameterAsNode,
"string": this._formatParameterAsString
};
}

WebInspector.ConsoleMessageImpl.prototype = {
_formatMessage: function()
{
this._formattedMessage = document.createElement("span");
this._formattedMessage.className = "console-message-text source-code";

var messageText;
if (this.source === WebInspector.ConsoleMessage.MessageSource.ConsoleAPI) {
switch (this.type) {
case WebInspector.ConsoleMessage.MessageType.Trace:
messageText = document.createTextNode("console.trace()");
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.Dir:
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);
}
} else if (this.source === WebInspector.ConsoleMessage.MessageSource.Network) {
if (this._request) {
this._stackTrace = this._request.stackTrace;
messageText = document.createElement("span");
if (this.level === WebInspector.ConsoleMessage.MessageLevel.Error) {
messageText.appendChild(document.createTextNode(this._request.requestMethod + " "));
messageText.appendChild(WebInspector.linkifyRequestAsNode(this._request));
if (this._request.failed)
messageText.appendChild(document.createTextNode(" " + this._request.localizedFailDescription));
else
messageText.appendChild(document.createTextNode(" " + this._request.statusCode + " (" + this._request.statusText + ")"));
} else {
var fragment = WebInspector.linkifyStringAsFragmentWithCustomLinkifier(this._messageText, WebInspector.linkifyRequestAsNode.bind(null, this._request, ""));
messageText.appendChild(fragment);
}
} else {
if (this.url) {
var isExternal = !WebInspector.resourceForURL(this.url);
var anchor = WebInspector.linkifyURLAsNode(this.url, this.url, "console-message-url", isExternal);
this._formattedMessage.appendChild(anchor);
}
messageText = this._format([this._messageText]);
}
} else {
var args = this._parameters || [this._messageText];
messageText = this._format(args);
}


if (this.source !== WebInspector.ConsoleMessage.MessageSource.Network) {
if (this._stackTrace && this._stackTrace.length && this._stackTrace[0].url) {
var urlElement = this._linkifyCallFrame(this._stackTrace[0]);
this._formattedMessage.appendChild(urlElement);
} else if (this.url && this.url !== "undefined") {
var urlElement = this._linkifyLocation(this.url, this.line, 0);
this._formattedMessage.appendChild(urlElement);
}
}

this._formattedMessage.appendChild(messageText);

var dumpStackTrace = !!this._stackTrace && this._stackTrace.length && (this.source === WebInspector.ConsoleMessage.MessageSource.Network || this.level === WebInspector.ConsoleMessage.MessageLevel.Error || this.type === WebInspector.ConsoleMessage.MessageType.Trace);
if (dumpStackTrace) {
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 = messageText.textContent;
},

get message()
{

var formattedMessage = this.formattedMessage;
return this._message;
},

get formattedMessage()
{
if (!this._formattedMessage)
this._formatMessage();
return this._formattedMessage;
},

_linkifyLocation: function(url, lineNumber, columnNumber)
{

lineNumber = lineNumber ? lineNumber - 1 : 0;
columnNumber = columnNumber ? columnNumber - 1 : 0;
return this._linkifier.linkifyLocation(url, lineNumber, columnNumber, "console-message-url");
},

_linkifyCallFrame: function(callFrame)
{
return this._linkifyLocation(callFrame.url, callFrame.lineNumber, callFrame.columnNumber);
},

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 (parameters[i] instanceof WebInspector.RemoteObject)
continue;

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(this._formatParameter(parameters[i]));
if (i < parameters.length - 1)
formattedResult.appendChild(document.createTextNode(" "));
}
return formattedResult;
},


_formatParameter: function(output, forceObjectFormat)
{
var type;
if (forceObjectFormat)
type = "object";
else if (output instanceof WebInspector.RemoteObject)
type = output.subtype || output.type;
else
type = typeof output;

var formatter = this._customFormatters[type];
if (!formatter) {
formatter = this._formatParameterAsValue;
output = output.description;
}

var span = document.createElement("span");
span.className = "console-formatted-" + type + " source-code";
formatter.call(this, output, span);
return span;
},

_formatParameterAsValue: function(val, elem)
{
elem.appendChild(document.createTextNode(val));
},

_formatParameterAsObject: function(obj, elem)
{
elem.appendChild(new WebInspector.ObjectPropertiesSection(obj, obj.description).element);
},

_formatParameterAsNode: function(object, elem)
{
function printNode(nodeId)
{
if (!nodeId) {


this._formatParameterAsObject(object, elem);
return;
}
var treeOutline = new WebInspector.ElementsTreeOutline(false, false, true);
treeOutline.setVisible(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));
},

_formatParameterAsArray: function(arr, elem)
{
arr.getOwnProperties(this._printArray.bind(this, elem));
},

_formatParameterAsString: 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, 10))
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._formatParameter(output, output.subtype && output.subtype === "array");
},

_formatWithSubstitutionString: function(parameters, formattedResult)
{
var formatters = {}

function parameterFormatter(force, obj)
{
return this._formatParameter(obj, force);
}

function valueFormatter(obj)
{
return obj.description;
}


formatters.o = parameterFormatter.bind(this, false);
formatters.s = valueFormatter;
formatters.f = valueFormatter;

formatters.i = valueFormatter;
formatters.d = valueFormatter;


formatters.O = parameterFormatter.bind(this, 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()
{
if (!this._formattedMessage)
return;

var highlightedMessage = this._formattedMessage;
delete this._formattedMessage;
this._formatMessage();
this._element.replaceChild(this._formattedMessage, highlightedMessage);
},

highlightSearchResults: function(regexObject)
{
if (!this._formattedMessage)
return;

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);

if (frame.url) {
var urlElement = this._linkifyCallFrame(frame);
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.Network:
sourceString = "Network";
break;
case WebInspector.ConsoleMessage.MessageSource.ConsoleAPI:
sourceString = "ConsoleAPI";
break;
case WebInspector.ConsoleMessage.MessageSource.Other:
sourceString = "Other";
break;
}

var typeString;
switch (this.type) {
case WebInspector.ConsoleMessage.MessageType.Log:
typeString = "Log";
break;
case WebInspector.ConsoleMessage.MessageType.Dir:
typeString = "Dir";
break;
case WebInspector.ConsoleMessage.MessageType.DirXML:
typeString = "Dir XML";
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;
},

get text()
{
return this._messageText;
},

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._request === msg._request);
},

get stackTrace()
{
return this._stackTrace;
}
}

WebInspector.ConsoleMessageImpl.prototype.__proto__ = WebInspector.ConsoleMessage.prototype;





const ExpressionStopCharacters = " =:[({;,!+-*/&|^<>";


WebInspector.ConsoleView = function(hideContextSelector)
{
WebInspector.View.call(this);

this.element.id = "console-view";
this.messages = [];

this._clearConsoleButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear console log."), "clear-status-bar-item");
this._clearConsoleButton.addEventListener("click", this._requestClearMessages, this);

this._contextSelectElement = document.createElement("select");
this._contextSelectElement.id = "console-context";
this._contextSelectElement.className = "status-bar-item";

if (hideContextSelector)
this._contextSelectElement.addStyleClass("hidden");

this.messagesElement = document.createElement("div");
this.messagesElement.id = "console-messages";
this.messagesElement.className = "monospace";
this.messagesElement.addEventListener("click", this._messagesClicked.bind(this), true);
this.element.appendChild(this.messagesElement);
this._scrolledToBottom = true;

this.promptElement = document.createElement("div");
this.promptElement.id = "console-prompt";
this.promptElement.className = "source-code";
this.promptElement.spellcheck = false;
this.messagesElement.appendChild(this.promptElement);
this.messagesElement.appendChild(document.createElement("br"));

this.topGroup = new WebInspector.ConsoleGroup(null);
this.messagesElement.insertBefore(this.topGroup.element, this.promptElement);
this.currentGroup = this.topGroup;

this._filterBarElement = document.createElement("div");
this._filterBarElement.id = "console-filter";
this._filterBarElement.className = "scope-bar status-bar-item";

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.registerRequiredCSS("textPrompt.css");

this.messagesElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), false);

WebInspector.settings.monitoringXHREnabled.addChangeListener(this._monitoringXHREnabledSettingChanged.bind(this));

WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this);
WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);

this._linkifier = WebInspector.debuggerPresentationModel.createLinkifier();

this.prompt = new WebInspector.TextPromptWithHistory(this.completions.bind(this), ExpressionStopCharacters + ".");
this.prompt.setSuggestBoxEnabled("generic-suggest");
this.prompt.renderAsBlock();
this.prompt.attach(this.promptElement);
this.prompt.proxyElement.addEventListener("keydown", this._promptKeyDown.bind(this), false);
this.prompt.setHistoryData(WebInspector.settings.consoleHistory.get());
}

WebInspector.ConsoleView.Events = {
ConsoleCleared: "console-cleared",
EntryAdded: "console-entry-added",
}

WebInspector.ConsoleView.prototype = {
get statusBarItems()
{
return [this._clearConsoleButton.element, this._contextSelectElement, this._filterBarElement];
},

addContext: function(context)
{
var option = document.createElement("option");
option.text = context.displayName;
option.title = context.url;
option._context = context;
context._consoleOption = option;
this._contextSelectElement.appendChild(option);
context.addEventListener(WebInspector.FrameEvaluationContext.EventTypes.Updated, this._contextUpdated, this);
},

removeContext: function(context)
{
this._contextSelectElement.removeChild(context._consoleOption);
},

_contextUpdated: function(event)
{
var context = event.data;
var option= context._consoleOption;
option.text = context.displayName;
option.title = context.url;
},

_currentEvaluationContextId: function()
{
if (this._contextSelectElement.selectedIndex === -1)
return undefined;
return this._contextSelectElement[this._contextSelectElement.selectedIndex]._context.frameId;
},

_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);
}
},

wasShown: function()
{
if (!this.prompt.isCaretInsidePrompt())
this.prompt.moveCaretToEndOfPrompt();
},

afterShow: function()
{
WebInspector.setCurrentFocusElement(this.promptElement);
},

storeScrollPositions: function()
{
WebInspector.View.prototype.storeScrollPositions.call(this);
this._scrolledToBottom = this.messagesElement.isScrolledToBottom();
},

restoreScrollPositions: function()
{
if (this._scrolledToBottom)
this._immediatelyScrollIntoView();
else
WebInspector.View.prototype.restoreScrollPositions.call(this);
},

onResize: function()
{
this.restoreScrollPositions();
},

_isScrollIntoViewScheduled: function()
{
return !!this._scrollIntoViewTimer;
},

_scheduleScrollIntoView: function()
{
if (this._scrollIntoViewTimer)
return;

function scrollIntoView()
{
this.promptElement.scrollIntoView(true);
delete this._scrollIntoViewTimer;
}
this._scrollIntoViewTimer = setTimeout(scrollIntoView.bind(this), 20);
},

_immediatelyScrollIntoView: function()
{
this.promptElement.scrollIntoView(true);
this._cancelScheduledScrollIntoView();
},

_cancelScheduledScrollIntoView: function()
{
if (!this._isScrollIntoViewScheduled())
return;

clearTimeout(this._scrollIntoViewTimer);
delete this._scrollIntoViewTimer;
},

_consoleMessageAdded: function(event)
{
this._appendConsoleMessage(event.data);
},

_appendConsoleMessage: function(msg)
{


if (!this._isScrollIntoViewScheduled() && ((msg instanceof WebInspector.ConsoleCommandResult) || this.messagesElement.isScrolledToBottom()))
this._scheduleScrollIntoView();

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);
}

this.dispatchEventToListeners(WebInspector.ConsoleView.Events.EntryAdded, msg);
},

_consoleCleared: function()
{
this._scrolledToBottom = true;
this.messages = [];

this.currentGroup = this.topGroup;
this.topGroup.messagesElement.removeChildren();

this.dispatchEventToListeners(WebInspector.ConsoleView.Events.ConsoleCleared);

this._linkifier.reset();
},

completions: function(wordRange, force, completionsReadyCallback)
{

var expressionRange = wordRange.startContainer.rangeOfWord(wordRange.startOffset, ExpressionStopCharacters, this.promptElement, "backward");
var expressionString = expressionRange.toString();
var prefix = wordRange.toString();
this._completions(expressionString, prefix, force, completionsReadyCallback);
},

_completions: function(expressionString, prefix, force, completionsReadyCallback)
{
var lastIndex = expressionString.length - 1;

var dotNotation = (expressionString[lastIndex] === ".");
var bracketNotation = (expressionString[lastIndex] === "[");

if (dotNotation || bracketNotation)
expressionString = expressionString.substr(0, lastIndex);

if (expressionString && parseInt(expressionString, 10) == expressionString) {

completionsReadyCallback([]);
return;
}

if (!prefix && !expressionString && !force) {
completionsReadyCallback([]);
return;
}

if (!expressionString && WebInspector.debuggerPresentationModel.paused)
WebInspector.debuggerPresentationModel.getSelectedCallFrameVariables(receivedPropertyNames.bind(this));
else
this.evalInInspectedWindow(expressionString, "completion", true, true, false, evaluated.bind(this));

function evaluated(result, wasThrown)
{
if (!result || wasThrown) {
completionsReadyCallback([]);
return;
}

function getCompletions(primitiveType)
{
var object;
if (primitiveType === "string")
object = new String("");
else if (primitiveType === "number")
object = new Number(0);
else if (primitiveType === "boolean")
object = new Boolean(false);
else
object = this;

var resultSet = {};
for (var o = object; o; o = o.__proto__) {
try {
var names = Object.getOwnPropertyNames(o);
for (var i = 0; i < names.length; ++i)
resultSet[names[i]] = true;
} catch (e) {
}
}
return resultSet;
}

if (result.type === "object" || result.type === "function")
result.callFunctionJSON(getCompletions, receivedPropertyNames.bind(this));
else if (result.type === "string" || result.type === "number" || result.type === "boolean")
this.evalInInspectedWindow("(" + getCompletions + ")(\"" + result.type + "\")", "completion", false, true, true, receivedPropertyNamesFromEval.bind(this));
}

function receivedPropertyNamesFromEval(notRelevant, wasThrown, result)
{
if (result && !wasThrown)
receivedPropertyNames.call(this, result.value);
else
completionsReadyCallback([]);
}

function receivedPropertyNames(propertyNames)
{
RuntimeAgent.releaseObjectGroup("completion");
if (!propertyNames) {
completionsReadyCallback([]);
return;
}
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(completionsReadyCallback, dotNotation, bracketNotation, expressionString, prefix, Object.keys(propertyNames));
}
},

_reportCompletions: function(completionsReadyCallback, dotNotation, bracketNotation, expressionString, prefix, properties) {
if (bracketNotation) {
if (prefix.length && prefix[0] === "'")
var quoteUsed = "'";
else
var quoteUsed = "\"";
}

var results = [];

if (!expressionString) {
const keywords = ["break", "case", "catch", "continue", "default", "delete", "do", "else", "finally", "for", "function", "if", "in",
"instanceof", "new", "return", "switch", "this", "throw", "try", "typeof", "var", "void", "while", "with"];
properties = properties.concat(keywords);
}

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 (prefix.length && property.indexOf(prefix) !== 0)
continue;

results.push(property);
}
completionsReadyCallback(results);
},

_handleContextMenuEvent: function(event)
{
if (!window.getSelection().isCollapsed) {


return;
}

var contextMenu = new WebInspector.ContextMenu();

if (WebInspector.populateHrefContextMenu(contextMenu, null, event))
contextMenu.appendSeparator();

function monitoringXHRItemAction()
{
WebInspector.settings.monitoringXHREnabled.set(!WebInspector.settings.monitoringXHREnabled.get());
}
contextMenu.appendCheckboxItem(WebInspector.UIString("Log XMLHttpRequests"), monitoringXHRItemAction.bind(this), WebInspector.settings.monitoringXHREnabled.get());

function preserveLogItemAction()
{
WebInspector.settings.preserveConsoleLog.set(!WebInspector.settings.preserveConsoleLog.get());
}
contextMenu.appendCheckboxItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Preserve log upon navigation" : "Preserve Log upon Navigation"), preserveLogItemAction.bind(this), WebInspector.settings.preserveConsoleLog.get());

contextMenu.appendSeparator();
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Clear console" : "Clear Console"), this._requestClearMessages.bind(this));
contextMenu.show(event);
},

_monitoringXHREnabledSettingChanged: function(event)
{
ConsoleAgent.setMonitoringXHREnabled(event.data);
},

_messagesClicked: function(event)
{
if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
this.prompt.moveCaretToEndOfPrompt();
},

_registerShortcuts: function()
{
this._shortcuts = {};

var shortcut = WebInspector.KeyboardShortcut;

if (WebInspector.isMac()) {
var shortcutK = shortcut.makeDescriptor("k", WebInspector.KeyboardShortcut.Modifiers.Meta);
this._shortcuts[shortcutK.key] = this._requestClearMessages.bind(this);
}

var shortcutL = shortcut.makeDescriptor("l", WebInspector.KeyboardShortcut.Modifiers.Ctrl);
this._shortcuts[shortcutL.key] = this._requestClearMessages.bind(this);

var section = WebInspector.shortcutsScreen.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"));
},

_requestClearMessages: function()
{
WebInspector.console.requestClearMessages();
},

_promptKeyDown: function(event)
{
if (isEnterKey(event)) {
this._enterKeyPressed(event);
return;
}

var shortcut = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
var handler = this._shortcuts[shortcut];
if (handler) {
handler();
event.preventDefault();
return;
}
},


evalInInspectedWindow: function(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptions, returnByValue, callback)
{
if (WebInspector.debuggerPresentationModel.paused) {
WebInspector.debuggerPresentationModel.evaluateInSelectedCallFrame(expression, objectGroup, includeCommandLineAPI, returnByValue, callback);
return;
}

if (!expression) {

expression = "this";
}

function evalCallback(error, result, wasThrown)
{
if (error) {
console.error(error);
callback(null, false);
return;
}

if (returnByValue)
callback(null, wasThrown, wasThrown ? null : result);
else
callback(WebInspector.RemoteObject.fromPayload(result), wasThrown);
}
RuntimeAgent.evaluate(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptions, this._currentEvaluationContextId(), returnByValue, evalCallback);
},

evaluateUsingTextPrompt: function(expression)
{
this._appendCommand(expression, this.prompt.text);
},

_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;
this._appendCommand(str, "");
},

_appendCommand: function(text, newPromptText)
{
var commandMessage = new WebInspector.ConsoleCommand(text);
WebInspector.console.interruptRepeatCount();
this._appendConsoleMessage(commandMessage);

function printResult(result, wasThrown)
{
if (!result)
return;

this.prompt.pushHistoryItem(text);
this.prompt.text = newPromptText;

WebInspector.settings.consoleHistory.set(this.prompt.historyData.slice(-30));

this._appendConsoleMessage(new WebInspector.ConsoleCommandResult(result, wasThrown, commandMessage, this._linkifier));
}
this.evalInInspectedWindow(text, "console", true, false, false, printResult.bind(this));

WebInspector.userMetrics.ConsoleEvaluated.record();
},

elementsToRestoreScrollPositionsFor: function()
{
return [this.messagesElement];
}
}

WebInspector.ConsoleView.prototype.__proto__ = WebInspector.View.prototype;


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, linkifier)
{
var level = (wasThrown ? WebInspector.ConsoleMessage.MessageLevel.Error : WebInspector.ConsoleMessage.MessageLevel.Log);
this.originatingCommand = originatingCommand;
WebInspector.ConsoleMessageImpl.call(this, WebInspector.ConsoleMessage.MessageSource.JS, level, "", linkifier, WebInspector.ConsoleMessage.MessageType.Result, undefined, undefined, undefined, [result]);
}

WebInspector.ConsoleCommandResult.prototype = {
toMessageElement: function()
{
var element = WebInspector.ConsoleMessageImpl.prototype.toMessageElement.call(this);
element.addStyleClass("console-user-command-result");
return element;
}
}

WebInspector.ConsoleCommandResult.prototype.__proto__ = WebInspector.ConsoleMessageImpl.prototype;


WebInspector.ConsoleGroup = function(parentGroup)
{
this.parentGroup = parentGroup;

var element = document.createElement("div");
element.className = "console-group";
element.group = this;
this.element = element;

if (parentGroup) {
var bracketElement = document.createElement("div");
bracketElement.className = "console-group-bracket";
element.appendChild(bracketElement);
}

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.consoleView = null;

WebInspector.ConsoleMessage.create = function(source, level, message, type, url, line, repeatCount, parameters, stackTrace, request)
{
return new WebInspector.ConsoleMessageImpl(source, level, message, WebInspector.consoleView._linkifier, type, url, line, repeatCount, parameters, stackTrace, request);
}






WebInspector.Panel = function(name)
{
WebInspector.View.call(this);

this.element.addStyleClass("panel");
this.element.addStyleClass(name);
this._panelName = name;

this._shortcuts = {};

WebInspector.settings[this._sidebarWidthSettingName()] = WebInspector.settings.createSetting(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, WebInspector.inspectorView.element);
},

wasShown: function()
{
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.setCurrentFocusElement(this.defaultFocusedElement);
},

willHide: function()
{
if (this._statusBarItemContainer && this._statusBarItemContainer.parentNode)
this._statusBarItemContainer.parentNode.removeChild(this._statusBarItemContainer);
delete this._statusBarItemContainer;
if ("_toolbarItem" in this)
this._toolbarItem.removeStyleClass("toggled-on");
},

reset: function()
{
this.searchCanceled();
},

get defaultFocusedElement()
{
return this.sidebarTreeElement || this.element;
},

searchCanceled: function()
{
WebInspector.searchController.updateSearchMatchesCount(0, this);
},

performSearch: function(query)
{

this.searchCanceled();
},

jumpToNextSearchResult: function()
{
},

jumpToPreviousSearchResult: function()
{
},


createSplitView: function(parentElement, position, defaultWidth)
{
if (this.splitView)
return;

if (!parentElement)
parentElement = this.element;

this.splitView = new WebInspector.SplitView(position || WebInspector.SplitView.SidebarPosition.Left, this._sidebarWidthSettingName(), defaultWidth);
this.splitView.show(parentElement);
this.splitView.addEventListener(WebInspector.SplitView.EventTypes.Resized, this.sidebarResized.bind(this));

this.sidebarElement = this.splitView.sidebarElement;
},


createSplitViewWithSidebarTree: function(parentElement, position, defaultWidth)
{
if (this.splitView)
return;

this.createSplitView(parentElement, position);

this.sidebarTreeElement = document.createElement("ol");
this.sidebarTreeElement.className = "sidebar-tree";
this.splitView.sidebarElement.appendChild(this.sidebarTreeElement);
this.splitView.sidebarElement.addStyleClass("sidebar");

this.sidebarTree = new TreeOutline(this.sidebarTreeElement);
this.sidebarTree.panel = this;
},

_sidebarWidthSettingName: function()
{
return this._panelName + "SidebarWidth";
},



get toolbarItemLabel()
{
},

get statusBarItems()
{
},

sidebarResized: function(width)
{
},

statusBarResized: function()
{
},

canShowAnchorLocation: function(anchor)
{
return false;
},

showAnchorLocation: function(anchor)
{
return false;
},

elementsToRestoreScrollPositionsFor: function()
{
return [];
},

handleShortcut: function(event)
{
var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(event);
var handler = this._shortcuts[shortcutKey];
if (handler) {
handler(event);
event.handled = true;
}
},

registerShortcut: function(key, handler)
{
this._shortcuts[key] = handler;
}
}

WebInspector.Panel.prototype.__proto__ = WebInspector.View.prototype;






WebInspector.InspectorView = function()
{
WebInspector.View.call(this);
this.markAsRoot();
this.element.id = "main-panels";
this.element.setAttribute("spellcheck", false);
this._history = [];
this._historyIterator = -1;
document.addEventListener("keydown", this._keyDown.bind(this), false);
this._panelOrder = [];
}

WebInspector.InspectorView.Events = {
PanelSelected: "panel-selected"
}

WebInspector.InspectorView.prototype = {
addPanel: function(panel)
{
this._panelOrder.push(panel);
WebInspector.toolbar.addPanel(panel);
},

currentPanel: function()
{
return this._currentPanel;
},

setCurrentPanel: function(x)
{
if (this._currentPanel === x)
return;

if (this._currentPanel)
this._currentPanel.detach();

this._currentPanel = x;

if (x) {
x.show();
this.dispatchEventToListeners(WebInspector.InspectorView.Events.PanelSelected);

WebInspector.searchController.activePanelChanged();
}
for (var panelName in WebInspector.panels) {
if (WebInspector.panels[panelName] === x) {
WebInspector.settings.lastActivePanel.set(panelName);
this._pushToHistory(panelName);
WebInspector.userMetrics.panelShown(panelName);
}
}
},

_keyDown: function(event)
{
var isInEditMode = event.target.enclosingNodeOrSelfWithClass("text-prompt") || WebInspector.isEditingAnyField();

switch (event.keyIdentifier) {
case "Left":
var isBackKey = !isInEditMode && WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event);
if (isBackKey && this._canGoBackInHistory()) {
this._goBackInHistory();
event.preventDefault();
}
break;

case "Right":
var isForwardKey = !isInEditMode && WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event);
if (isForwardKey && this._canGoForwardInHistory()) {
this._goForwardInHistory();
event.preventDefault();
}
break;


case "U+005B":
case "U+00DB": 
var isRotateLeft = WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && !event.shiftKey && !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":  
var isRotateRight = WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && !event.shiftKey && !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;
}
},

_canGoBackInHistory: function()
{
return this._historyIterator > 0;
},

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

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

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

_pushToHistory: 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;
}
}

WebInspector.InspectorView.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.inspectorView = null;






WebInspector.AdvancedSearchController = function()
{
this._shortcut = WebInspector.AdvancedSearchController.createShortcut();
this._searchId = 0;

WebInspector.settings.advancedSearchConfig = WebInspector.settings.createSetting("advancedSearchConfig", new WebInspector.SearchConfig("", true, false));

WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this);
}

WebInspector.AdvancedSearchController.createShortcut = function()
{
if (WebInspector.isMac())
return WebInspector.KeyboardShortcut.makeDescriptor("f", WebInspector.KeyboardShortcut.Modifiers.Meta | WebInspector.KeyboardShortcut.Modifiers.Alt);
else
return WebInspector.KeyboardShortcut.makeDescriptor("f", WebInspector.KeyboardShortcut.Modifiers.Ctrl | WebInspector.KeyboardShortcut.Modifiers.Shift);
}

WebInspector.AdvancedSearchController.prototype = {

handleShortcut: function(event)
{
if (WebInspector.KeyboardShortcut.makeKeyFromEvent(event) === this._shortcut.key) {
this.show();
event.handled = true;
}
},

_frameNavigated: function()
{
this.resetSearch();
},


registerSearchScope: function(searchScope)
{

this._searchScope = searchScope;
},

show: function()
{
if (!this._searchView)
this._searchView = new WebInspector.SearchView(this);

if (this._searchView.isShowing())
this._searchView.focus();
else
WebInspector.showViewInDrawer(this._searchView);
},


_onSearchResult: function(searchId, searchResult)
{
if (searchId !== this._searchId)
return;

this._searchView.addSearchResult(searchResult);
if (!searchResult.searchMatches.length)
return;

if (!this._searchResultsPane) 
this._searchResultsPane = this._currentSearchScope.createSearchResultsPane(this._searchConfig);        
this._searchView.resultsPane = this._searchResultsPane; 
this._searchResultsPane.addSearchResult(searchResult);
},


_onSearchFinished: function(searchId, finished)
{
if (searchId !== this._searchId)
return;

if (!this._searchResultsPane)
this._searchView.nothingFound();

this._searchView.searchFinished(finished);
},


startSearch: function(searchConfig)
{
this.resetSearch();
++this._searchId;

this._searchConfig = searchConfig;

this._currentSearchScope = this._searchScope;

var totalSearchResultsCount = this._currentSearchScope.performSearch(searchConfig, this._onSearchResult.bind(this, this._searchId), this._onSearchFinished.bind(this, this._searchId));
this._searchView.searchStarted(totalSearchResultsCount);
},

resetSearch: function()
{
this.stopSearch();

if (this._searchResultsPane) {
this._searchView.resetResults();
delete this._searchResultsPane;
}
},

stopSearch: function()
{
if (this._currentSearchScope)
this._currentSearchScope.stopSearch();
}
}


WebInspector.SearchView = function(controller)
{
WebInspector.View.call(this);
this.registerRequiredCSS("textViewer.css");

this._controller = controller;

this.element.className = "search-view";

this._searchPanelElement = this.element.createChild("div");
this._searchPanelElement.tabIndex = 0;
this._searchPanelElement.className = "search-panel";
this._searchPanelElement.addEventListener("keydown", this._onKeyDown.bind(this), false);

this._searchResultsElement = this.element.createChild("div");
this._searchResultsElement.className = "search-results";

this._search = this._searchPanelElement.createChild("input");
this._search.setAttribute("type", "search");
this._search.addStyleClass("search-config-search");
this._search.setAttribute("results", "0");
this._search.setAttribute("size", 20);

this._ignoreCaseLabel = this._searchPanelElement.createChild("label");
this._ignoreCaseLabel.addStyleClass("search-config-label");
this._ignoreCaseCheckbox = this._ignoreCaseLabel.createChild("input");
this._ignoreCaseCheckbox.setAttribute("type", "checkbox");
this._ignoreCaseCheckbox.addStyleClass("search-config-checkbox");
this._ignoreCaseLabel.appendChild(document.createTextNode(WebInspector.UIString("Ignore case")));

this._regexLabel = this._searchPanelElement.createChild("label");
this._regexLabel.addStyleClass("search-config-label");
this._regexCheckbox = this._regexLabel.createChild("input");
this._regexCheckbox.setAttribute("type", "checkbox");
this._regexCheckbox.addStyleClass("search-config-checkbox");
this._regexLabel.appendChild(document.createTextNode(WebInspector.UIString("Regular expression")));

this._searchStatusBarElement = document.createElement("div");
this._searchStatusBarElement.className = "search-status-bar-item";
this._searchMessageElement = this._searchStatusBarElement.createChild("div");
this._searchMessageElement.className = "search-status-bar-message";
this._searchProgressElement = document.createElement("progress");
this._searchProgressElement.className = "search-status-bar-progress";

this._searchStopButtonItem = document.createElement("div");
this._searchStopButtonItem.className = "search-status-bar-stop-button-item";
this._searchStopStatusBarButton = new WebInspector.StatusBarButton(WebInspector.UIString("Stop search"), "search-status-bar-stop-button");
this._searchStopButtonItem.appendChild(this._searchStopStatusBarButton.element);
this._searchStopStatusBarButton.addEventListener("click", this._searchStopButtonPressed, this);

this._searchResultsMessageElement = document.createElement("span");
this._searchResultsMessageElement.className = "search-results-status-bar-message";

this._load();
}


WebInspector.SearchView.maxQueriesCount = 20;

WebInspector.SearchView.prototype = {

get statusBarItems()
{
return [this._searchStatusBarElement];
},


get counterElement()
{
return this._searchResultsMessageElement;
},


get searchConfig()
{
var searchConfig = {};
searchConfig.query = this._search.value;
searchConfig.ignoreCase = this._ignoreCaseCheckbox.checked;
searchConfig.isRegex = this._regexCheckbox.checked;
return searchConfig;
},


set resultsPane(resultsPane)
{
this.resetResults();
this._searchResultsElement.appendChild(resultsPane.element);
},


searchStarted: function(totalSearchResultsCount)
{
this.resetResults();
this._resetCounters();

this._totalSearchResultsCount = totalSearchResultsCount;

this._searchMessageElement.textContent = WebInspector.UIString("Searching...");
this._searchStatusBarElement.appendChild(this._searchProgressElement);
this._searchStatusBarElement.appendChild(this._searchStopButtonItem);
this._updateSearchProgress();

this._updateSearchResultsMessage();

if (!this._searchingView)
this._searchingView = new WebInspector.EmptyView(WebInspector.UIString("Searching..."));
this._searchingView.show(this._searchResultsElement);
},

_updateSearchResultsMessage: function()
{
if (this._searchMatchesCount && this._searchResultsCount)
this._searchResultsMessageElement.textContent = WebInspector.UIString("Found %d matches in %d files.", this._searchMatchesCount, this._nonEmptySearchResultsCount);
else
this._searchResultsMessageElement.textContent = "";
},

_updateSearchProgress: function()
{
this._searchProgressElement.setAttribute("max", this._totalSearchResultsCount);
this._searchProgressElement.setAttribute("value", this._searchResultsCount);
},

resetResults: function()
{
if (this._searchingView)
this._searchingView.detach();
if (this._notFoundView)
this._notFoundView.detach();
this._searchResultsElement.removeChildren();
},

_resetCounters: function()
{
this._searchMatchesCount = 0;
this._searchResultsCount = 0;
this._nonEmptySearchResultsCount = 0;
},

nothingFound: function()
{
this.resetResults();

if (!this._notFoundView)
this._notFoundView = new WebInspector.EmptyView(WebInspector.UIString("No matches found."));
this._notFoundView.show(this._searchResultsElement);
this._searchResultsMessageElement.textContent = WebInspector.UIString("No matches found.");
},


addSearchResult: function(searchResult)
{
this._searchMatchesCount += searchResult.searchMatches.length;
this._searchResultsCount++;
if (searchResult.searchMatches.length)
this._nonEmptySearchResultsCount++;
this._updateSearchResultsMessage();
this._updateSearchProgress();
},


searchFinished: function(finished)
{
this._searchMessageElement.textContent = finished ? WebInspector.UIString("Search finished.") : WebInspector.UIString("Search interrupted.");
this._searchStatusBarElement.removeChild(this._searchProgressElement);
this._searchStatusBarElement.removeChild(this._searchStopButtonItem);
},

focus: function()
{
WebInspector.setCurrentFocusElement(this._search);
this._search.select();
},

wasShown: function()
{
this.focus();
},

wasHidden: function()
{
this._controller.stopSearch();
},


_onKeyDown: function(event)
{
if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Enter.code)
this._onAction();
},

_save: function()
{
var searchConfig = new WebInspector.SearchConfig(this.searchConfig.query, this.searchConfig.ignoreCase, this.searchConfig.isRegex); 
WebInspector.settings.advancedSearchConfig.set(searchConfig);
},

_load: function()
{
var searchConfig = WebInspector.settings.advancedSearchConfig.get();
this._search.value = searchConfig.query;
this._ignoreCaseCheckbox.checked = searchConfig.ignoreCase;
this._regexCheckbox.checked = searchConfig.isRegex;
},

_searchStopButtonPressed: function()
{
this._controller.stopSearch();
this.focus();
},

_onAction: function()
{
if (!this.searchConfig.query || !this.searchConfig.query.length)
return;

this._save();
this._controller.startSearch(this.searchConfig);
}
}

WebInspector.SearchView.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.SearchConfig = function(query, ignoreCase, isRegex)
{
this.query = query;
this.ignoreCase = ignoreCase;
this.isRegex = isRegex;
}


WebInspector.SearchScope = function()
{
}

WebInspector.SearchScope.prototype = {

performSearch: function(searchConfig, searchResultCallback, searchFinishedCallback) { },

stopSearch: function() { },


createSearchResultsPane: function(searchConfig) { }
}


WebInspector.SearchResultsPane = function(searchConfig)
{
this._searchConfig = searchConfig;
this.element = document.createElement("div");
}

WebInspector.SearchResultsPane.prototype = {

get searchConfig()
{
return this._searchConfig;
},


addSearchResult: function(searchResult) { }
}


WebInspector.FileBasedSearchResultsPane = function(searchConfig)
{
WebInspector.SearchResultsPane.call(this, searchConfig);

this._searchResults = [];

this.element.id ="search-results-pane-file-based";

this._treeOutlineElement = document.createElement("ol");
this._treeOutlineElement.className = "outline-disclosure";
this._treeOutlineElement.addStyleClass("search-results-outline-disclosure");
this.element.appendChild(this._treeOutlineElement);
this._treeOutline = new TreeOutline(this._treeOutlineElement);

this._matchesExpandedCount = 0;
}

WebInspector.FileBasedSearchResultsPane.matchesExpandedByDefaultCount = 20;
WebInspector.FileBasedSearchResultsPane.fileMatchesShownAtOnce = 20;

WebInspector.FileBasedSearchResultsPane.prototype = {

createAnchor: function(file, lineNumber, columnNumber) { },


fileName: function(file) { },


addSearchResult: function(searchResult)
{
this._searchResults.push(searchResult);
var file = searchResult.file;
var fileName = this.fileName(file);
var searchMatches = searchResult.searchMatches;

var fileTreeElement = this._addFileTreeElement(fileName, searchMatches.length, this._searchResults.length - 1);
},


_fileTreeElementExpanded: function(searchResult, fileTreeElement)
{
if (fileTreeElement._initialized)
return;

var toIndex = Math.min(searchResult.searchMatches.length, WebInspector.FileBasedSearchResultsPane.fileMatchesShownAtOnce);
if (toIndex < searchResult.searchMatches.length) {
this._appendSearchMatches(fileTreeElement, searchResult, 0, toIndex - 1);
this._appendShowMoreMatchesElement(fileTreeElement, searchResult, toIndex - 1);
} else
this._appendSearchMatches(fileTreeElement, searchResult, 0, toIndex);

fileTreeElement._initialized = true;
},


_appendSearchMatches: function(fileTreeElement, searchResult, fromIndex, toIndex)
{
var file = searchResult.file;
var fileName = this.fileName(file);
var searchMatches = searchResult.searchMatches;

var regex = createSearchRegex(this._searchConfig.query, !this._searchConfig.ignoreCase, this._searchConfig.isRegex);
for (var i = fromIndex; i < toIndex; ++i) {
var lineNumber = searchMatches[i].lineNumber;
var lineContent = searchMatches[i].lineContent;
var matchRanges = this._regexMatchRanges(lineContent, regex);

var anchor = this.createAnchor(file, lineNumber, matchRanges[0].offset);

var numberString = numberToStringWithSpacesPadding(lineNumber + 1, 4);
var lineNumberSpan = document.createElement("span");
lineNumberSpan.addStyleClass("webkit-line-number");
lineNumberSpan.addStyleClass("search-match-line-number");
lineNumberSpan.textContent = numberString;
anchor.appendChild(lineNumberSpan);

var contentSpan = this._createContentSpan(lineContent, matchRanges);
anchor.appendChild(contentSpan);

var searchMatchElement = new TreeElement("", null, false);
fileTreeElement.appendChild(searchMatchElement);
searchMatchElement.listItemElement.className = "search-match";
searchMatchElement.listItemElement.appendChild(anchor);
}
},


_appendShowMoreMatchesElement: function(fileTreeElement, searchResult, startMatchIndex)
{
var matchesLeftCount = searchResult.searchMatches.length - startMatchIndex;
var showMoreMatchesText = WebInspector.UIString("Show all matches (%d more).", matchesLeftCount);
var showMoreMatchesElement = new TreeElement(showMoreMatchesText, null, false);
fileTreeElement.appendChild(showMoreMatchesElement);
showMoreMatchesElement.listItemElement.addStyleClass("show-more-matches");
showMoreMatchesElement.onselect = this._showMoreMatchesElementSelected.bind(this, searchResult, startMatchIndex);
},


_showMoreMatchesElementSelected: function(searchResult, startMatchIndex, showMoreMatchesElement)
{
var fileTreeElement = showMoreMatchesElement.parent;
fileTreeElement.removeChild(showMoreMatchesElement);
this._appendSearchMatches(fileTreeElement, searchResult, startMatchIndex, searchResult.searchMatches.length);
},


_addFileTreeElement: function(fileName, searchMatchesCount, searchResultIndex)
{
var fileTreeElement = new TreeElement("", null, true);
fileTreeElement.toggleOnClick = true;
fileTreeElement.selectable = false;

this._treeOutline.appendChild(fileTreeElement);
fileTreeElement.listItemElement.addStyleClass("search-result");

var fileNameSpan = document.createElement("span");
fileNameSpan.className = "search-result-file-name";
fileNameSpan.textContent = fileName;
fileTreeElement.listItemElement.appendChild(fileNameSpan);

var matchesCountSpan = document.createElement("span");
matchesCountSpan.className = "search-result-matches-count";
if (searchMatchesCount === 1)
matchesCountSpan.textContent = WebInspector.UIString("(%d match)", searchMatchesCount);
else
matchesCountSpan.textContent = WebInspector.UIString("(%d matches)", searchMatchesCount);

fileTreeElement.listItemElement.appendChild(matchesCountSpan);

var searchResult = this._searchResults[searchResultIndex];
fileTreeElement.onexpand = this._fileTreeElementExpanded.bind(this, searchResult);


if (this._matchesExpandedCount < WebInspector.FileBasedSearchResultsPane.matchesExpandedByDefaultCount)
fileTreeElement.expand();
this._matchesExpandedCount += searchResult.searchMatches.length;

return fileTreeElement; 
},


_regexMatchRanges: function(lineContent, regex)
{
regex.lastIndex = 0;
var match;
var offset = 0;
var matchRanges = [];
while ((regex.lastIndex < lineContent.length) && (match = regex.exec(lineContent)))
matchRanges.push({ offset: match.index, length: match[0].length });

return matchRanges;
},


_createContentSpan: function(lineContent, matchRanges)
{
var contentSpan = document.createElement("span");
contentSpan.className = "search-match-content";
contentSpan.textContent = lineContent;
highlightRangesWithStyleClass(contentSpan, matchRanges, "highlighted-match");
return contentSpan;
}
}

WebInspector.FileBasedSearchResultsPane.prototype.__proto__ = WebInspector.SearchResultsPane.prototype;


WebInspector.FileBasedSearchResultsPane.SearchResult = function(file, searchMatches) {
this.file = file;
this.searchMatches = searchMatches;
}


WebInspector.advancedSearchController = null;





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.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/svg+xml":               {2: true},
"image/vnd.microsoft.icon":    {2: true},
"image/webp":                  {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},
"application/json":            {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.Resource = function(requestId, url, frameId, loaderId)
{
this.requestId = requestId;
this.url = url;
this.frameId = frameId;
this.loaderId = loaderId;
this._startTime = -1;
this._endTime = -1;
this._category = WebInspector.resourceCategories.other;
this._pendingContentCallbacks = [];
this.history = [];

this.statusCode = 0;
this.statusText = "";
this.requestMethod = "";
this.requestTime = 0;
this.receiveHeadersEnd = 0;
}

WebInspector.Resource.displayName = function(url)
{
return new WebInspector.Resource("fake-transient-resource", url, null, null).displayName;
}


WebInspector.Resource.Type = {
Document:   0,
Stylesheet: 1,
Image:      2,
Font:       3,
Script:     4,
XHR:        5,
WebSocket:  7,
Other:      8,

isTextType: function(type)
{
return (type === WebInspector.Resource.Type.Document) || (type === WebInspector.Resource.Type.Stylesheet) || (type === WebInspector.Resource.Type.Script) || (type === WebInspector.Resource.Type.XHR);
},

toUIString: function(type)
{
switch (type) {
case WebInspector.Resource.Type.Document:
return WebInspector.UIString("Document");
case WebInspector.Resource.Type.Stylesheet:
return WebInspector.UIString("Stylesheet");
case WebInspector.Resource.Type.Image:
return WebInspector.UIString("Image");
case WebInspector.Resource.Type.Font:
return WebInspector.UIString("Font");
case WebInspector.Resource.Type.Script:
return WebInspector.UIString("Script");
case WebInspector.Resource.Type.XHR:
return WebInspector.UIString("XHR");
case WebInspector.Resource.Type.WebSocket:
return WebInspector.UIString("WebSocket");
case WebInspector.Resource.Type.Other:
default:
return WebInspector.UIString("Other");
}
},



toString: function(type)
{
switch (type) {
case WebInspector.Resource.Type.Document:
return "document";
case WebInspector.Resource.Type.Stylesheet:
return "stylesheet";
case WebInspector.Resource.Type.Image:
return "image";
case WebInspector.Resource.Type.Font:
return "font";
case WebInspector.Resource.Type.Script:
return "script";
case WebInspector.Resource.Type.XHR:
return "xhr";
case WebInspector.Resource.Type.WebSocket:
return "websocket";
case WebInspector.Resource.Type.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: "revision-added",
MessageAdded: "message-added",
MessagesCleared: "messages-cleared",
}

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.urlFragment = parsedURL ? parsedURL.fragment : "";
this.lastPathComponent = parsedURL ? parsedURL.lastPathComponent : "";
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.inspectedPageDomain ? WebInspector.inspectedPageDomain : "");
if (this._displayName === "/")
this._displayName = this.url;
return this._displayName;
},

get folder()
{
var path = this.path;
var indexOfQuery = path.indexOf("?");
if (indexOfQuery !== -1)
path = path.substring(0, indexOfQuery);
var lastSlashIndex = path.lastIndexOf("/");
return lastSlashIndex !== -1 ? path.substring(0, lastSlashIndex) : "";
},

get displayDomain()
{

if (this.domain && (!WebInspector.inspectedPageDomain || (WebInspector.inspectedPageDomain && this.domain !== WebInspector.inspectedPageDomain)))
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.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 redirectSource()
{
if (this.redirects && this.redirects.length > 0)
return this.redirects[this.redirects.length - 1];
return this._redirectSource;
},

set redirectSource(x)
{
this._redirectSource = x;
},

get requestHeaders()
{
return this._requestHeaders || {};
},

set requestHeaders(x)
{
this._requestHeaders = x;
delete this._sortedRequestHeaders;
delete this._requestCookies;

this.dispatchEventToListeners("requestHeaders changed");
},

get requestHeadersText()
{
if (this._requestHeadersText === undefined) {
this._requestHeadersText = this.requestMethod + " " + this.url + " HTTP/1.1\r\n";
for (var key in this.requestHeaders)
this._requestHeadersText += key + ": " + this.requestHeaders[key] + "\r\n";
}
return this._requestHeadersText;
},

set requestHeadersText(x)
{
this._requestHeadersText = x;

this.dispatchEventToListeners("requestHeaders changed");
},

get requestHeadersSize()
{
return this.requestHeadersText.length;
},

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 requestHttpVersion()
{
var firstLine = this.requestHeadersText.split(/\r\n/)[0];
var match = firstLine.match(/(HTTP\/\d+\.\d+)$/);
return match ? match[1] : undefined;
},

get responseHeaders()
{
return this._responseHeaders || {};
},

set responseHeaders(x)
{
this._responseHeaders = x;
delete this._sortedResponseHeaders;
delete this._responseCookies;

this.dispatchEventToListeners("responseHeaders changed");
},

get responseHeadersText()
{
if (this._responseHeadersText === undefined) {
this._responseHeadersText = "HTTP/1.1 " + this.statusCode + " " + this.statusText + "\r\n";
for (var key in this.responseHeaders)
this._responseHeadersText += key + ": " + this.responseHeaders[key] + "\r\n";
}
return this._responseHeadersText;
},

set responseHeadersText(x)
{
this._responseHeadersText = x;

this.dispatchEventToListeners("responseHeaders changed");
},

get responseHeadersSize()
{
return this.responseHeadersText.length;
},

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;
queryString = queryString.split("#", 2)[0];
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;
},

get responseHttpVersion()
{
var match = this.responseHeadersText.match(/^(HTTP\/\d+\.\d+)/);
return match ? match[1] : undefined;
},

_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];
}
},

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(WebInspector.Resource.Events.MessageAdded, 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(WebInspector.Resource.Events.MessagesCleared);
},

get content()
{
return this._content;
},

get contentEncoded()
{
return this._contentEncoded;
},

get contentTimestamp()
{
return this._contentTimestamp;
},

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()) {
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();
WebInspector.resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceContentCommitted, { resource: this, content: newContent });
},

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

searchInContent: function(query, caseSensitive, isRegex, callback)
{
function callbackWrapper(error, searchMatches)
{
callback(searchMatches || []);
}

if (this.frameId)
PageAgent.searchInResource(this.frameId, this.url, query, caseSensitive, isRegex, callbackWrapper);
else
callback([]);
},

populateImageSource: function(image)
{
function onResourceContent()
{
image.src = this._contentURL();
}

this.requestContent(onResourceContent.bind(this));
},

isHttpFamily: function()
{
return this.url.match(/^https?:/i);
},

requestContentType: function()
{
return this.requestHeaderValue("Content-Type");
},

isPingRequest: function()
{
return "text/ping" === this.requestContentType();
},

hasErrorStatusCode: function()
{
return this.statusCode >= 400;
},

_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;

function onResourceContent(data, contentEncoded)
{
this._contentEncoded = contentEncoded;
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, 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, 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: "StyleSheetChanged"
}

WebInspector.CSSStyleModel.prototype = {

getMatchedStylesAsync: function(nodeId, forcedPseudoClasses, needPseudo, needInherited, userCallback)
{

function callback(userCallback, error, matchedPayload, pseudoPayload, inheritedPayload)
{
if (error) {
if (userCallback)
userCallback(null);
return;
}

var result = {};
if (matchedPayload)
result.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleArrayPayload(matchedPayload);

if (pseudoPayload) {
result.pseudoElements = [];
for (var i = 0; i < pseudoPayload.length; ++i) {
var entryPayload = pseudoPayload[i];
result.pseudoElements.push({ pseudoId: entryPayload.pseudoId, rules: WebInspector.CSSStyleModel.parseRuleArrayPayload(entryPayload.rules) });
}
}

if (inheritedPayload) {
result.inherited = [];
for (var i = 0; i < inheritedPayload.length; ++i) {
var entryPayload = inheritedPayload[i];
var entry = {};
if (entryPayload.inlineStyle)
entry.inlineStyle = WebInspector.CSSStyleDeclaration.parsePayload(entryPayload.inlineStyle);
if (entryPayload.matchedCSSRules)
entry.matchedCSSRules = WebInspector.CSSStyleModel.parseRuleArrayPayload(entryPayload.matchedCSSRules);
result.inherited.push(entry);
}
}

if (userCallback)
userCallback(result);
}

CSSAgent.getMatchedStylesForNode(nodeId, forcedPseudoClasses || [], needPseudo, needInherited, callback.bind(null, userCallback));
},


getComputedStyleAsync: function(nodeId, forcedPseudoClasses, userCallback)
{

function callback(userCallback, error, computedPayload)
{
if (error || !computedPayload)
userCallback(null);
else
userCallback(WebInspector.CSSStyleDeclaration.parseComputedStylePayload(computedPayload));
}

CSSAgent.getComputedStyleForNode(nodeId, forcedPseudoClasses || [], callback.bind(null, userCallback));
},


getInlineStylesAsync: function(nodeId, userCallback)
{

function callback(userCallback, error, inlinePayload, attributesPayload)
{
if (error || !inlinePayload)
userCallback(null, null);
else {
var styleAttributes;
if (attributesPayload) {
styleAttributes = {};
for (var i = 0; i < attributesPayload.length; ++i) {
var name = attributesPayload[i].name;
styleAttributes[name] = WebInspector.CSSStyleDeclaration.parsePayload(attributesPayload[i].style);
}
}
userCallback(WebInspector.CSSStyleDeclaration.parsePayload(inlinePayload), styleAttributes || null);
}
}

CSSAgent.getInlineStylesForNode(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, newSelector, error, 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 = 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.parseComputedStylePayload = function(payload)
{
var newPayload = { cssProperties: [], shorthandEntries: [], width: "", height: "" };
if (payload)
newPayload.cssProperties = payload;

return new WebInspector.CSSStyleDeclaration(newPayload);
}

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(this, 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;
if (payload.media)
this.media = WebInspector.CSSMedia.parseMediaArrayPayload(payload.media);
}

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, userCallback ? userCallback.bind(null, style) : null);
else 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(null, 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.CSSMedia = function(payload)
{
this.text = payload.text;
this.source = payload.source;
this.sourceURL = payload.sourceURL || "";
this.sourceLine = typeof payload.sourceLine === "undefined" || this.source === "linkedSheet" ? -1 : payload.sourceLine;
}

WebInspector.CSSMedia.Source = {
LINKED_SHEET: "linkedSheet",
INLINE_SHEET: "inlineSheet",
MEDIA_RULE: "mediaRule",
IMPORT_RULE: "importRule"
};

WebInspector.CSSMedia.parsePayload = function(payload)
{
return new WebInspector.CSSMedia(payload);
}

WebInspector.CSSMedia.parseMediaArrayPayload = function(payload)
{
var result = [];
for (var i = 0; i < payload.length; ++i)
result.push(WebInspector.CSSMedia.parsePayload(payload[i]));
return result;
}


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, null);
return;
}
this._loadStyleSheetHeaders(this._innerSetContent.bind(this, resource.url, content, majorChange, userCallback));
},

canSetContent: function()
{
return true;
},

_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.cssModel = null;






WebInspector.NetworkManager = function()
{
WebInspector.Object.call(this);
this._dispatcher = new WebInspector.NetworkDispatcher(this);
if (WebInspector.settings.cacheDisabled.get())
NetworkAgent.setCacheDisabled(true);
NetworkAgent.enable();

WebInspector.settings.cacheDisabled.addChangeListener(this._cacheDisabledSettingChanged, this);

if (WebInspector.settings.userAgent.get())
this._userAgentSettingChanged();
WebInspector.settings.userAgent.addChangeListener(this._userAgentSettingChanged, this);
}

WebInspector.NetworkManager.EventTypes = {
ResourceStarted: "ResourceStarted",
ResourceUpdated: "ResourceUpdated",
ResourceFinished: "ResourceFinished",
ResourceUpdateDropped: "ResourceUpdateDropped"
}

WebInspector.NetworkManager.prototype = {
requestContent: function(resource, callback)
{
function callbackWrapper(error, content, contentEncoded)
{
if (error)
callback(null, false);
else
callback(content, content && contentEncoded);
}


if (resource.requestId)
NetworkAgent.getResponseBody(resource.requestId, callbackWrapper);
else
PageAgent.getResourceContent(resource.frameId, resource.url, callbackWrapper);
},

inflightResourceForURL: function(url)
{
return this._dispatcher._inflightResourcesByURL[url];
},

_cacheDisabledSettingChanged: function(event)
{
NetworkAgent.setCacheDisabled(event.data);
},

_userAgentSettingChanged: function()
{
NetworkAgent.setUserAgentOverride(WebInspector.settings.userAgent.get());
}
}

WebInspector.NetworkManager.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.NetworkDispatcher = function(manager)
{
this._manager = manager;
this._inflightResourcesById = {};
this._inflightResourcesByURL = {};
InspectorBackend.registerNetworkDispatcher(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;

if (response.url && resource.url !== response.url)
resource.url = response.url;
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;

if (!this._mimeTypeIsConsistentWithType(resource)) {
WebInspector.console.addMessage(WebInspector.ConsoleMessage.create(WebInspector.ConsoleMessage.MessageSource.Network,
WebInspector.ConsoleMessage.MessageLevel.Warning,
WebInspector.UIString("Resource interpreted as %s but transferred with MIME type %s: \"%s\".", WebInspector.Resource.Type.toUIString(resource.type), resource.mimeType, resource.url),
WebInspector.ConsoleMessage.MessageType.Log,
"",
0,
1,
[],
null,
resource));
}
},

_mimeTypeIsConsistentWithType: function(resource)
{






if (resource.hasErrorStatusCode() || resource.statusCode === 304)
return true;

if (typeof resource.type === "undefined"
|| resource.type === WebInspector.Resource.Type.Other
|| resource.type === WebInspector.Resource.Type.XHR
|| resource.type === WebInspector.Resource.Type.WebSocket)
return true;

if (!resource.mimeType)
return true; 

if (resource.mimeType in WebInspector.MIMETypes)
return resource.type in WebInspector.MIMETypes[resource.mimeType];

return false;
},

_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(requestId, frameId, loaderId, documentURL, request, time, initiator, stackTrace, redirectResponse)
{
var resource = this._inflightResourcesById[requestId];
if (resource) {

if (!redirectResponse)
return;
this.responseReceived(requestId, frameId, loaderId, time, "Other", redirectResponse);
resource = this._appendRedirect(requestId, time, request.url);
} else
resource = this._createResource(requestId, frameId, loaderId, request.url, documentURL, initiator, stackTrace);
resource.hasNetworkData = true;
this._updateResourceWithRequest(resource, request);
resource.startTime = time;

this._startResource(resource);
},

requestServedFromCache: function(requestId)
{
var resource = this._inflightResourcesById[requestId];
if (!resource)
return;

resource.cached = true;
},

responseReceived: function(requestId, frameId, loaderId, time, resourceType, response)
{

if (this._isNull(response))
return;

var resource = this._inflightResourcesById[requestId];
if (!resource) {

var eventData = {};
eventData.url = response.url;
eventData.frameId = frameId;
eventData.loaderId = loaderId;
eventData.resourceType = resourceType;
eventData.mimeType = response.mimeType;
this._manager.dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceUpdateDropped, eventData);
return;
}

resource.responseReceivedTime = time;
resource.type = WebInspector.Resource.Type[resourceType];

this._updateResourceWithResponse(resource, response);

this._updateResource(resource);
},

dataReceived: function(requestId, time, dataLength, encodedDataLength)
{
var resource = this._inflightResourcesById[requestId];
if (!resource)
return;

resource.resourceSize += dataLength;
if (encodedDataLength != -1)
resource.increaseTransferSize(encodedDataLength);
resource.endTime = time;

this._updateResource(resource);
},

loadingFinished: function(requestId, finishTime)
{
var resource = this._inflightResourcesById[requestId];
if (!resource)
return;
this._finishResource(resource, finishTime);
},

loadingFailed: function(requestId, time, localizedDescription, canceled)
{
var resource = this._inflightResourcesById[requestId];
if (!resource)
return;

resource.failed = true;
resource.canceled = canceled;
resource.localizedFailDescription = localizedDescription;
this._finishResource(resource, time);
},

requestServedFromMemoryCache: function(requestId, frameId, loaderId, documentURL, time, initiator, cachedResource)
{
var resource = this._createResource(requestId, frameId, loaderId, cachedResource.url, documentURL, initiator, null);
this._updateResourceWithCachedResource(resource, cachedResource);
resource.cached = true;
resource.requestMethod = "GET";
this._startResource(resource);
resource.startTime = resource.responseReceivedTime = time;
this._finishResource(resource, time);
},

webSocketCreated: function(requestId, requestURL)
{
var resource = new WebInspector.Resource(requestId, requestURL, null, null);
resource.type = WebInspector.Resource.Type.WebSocket;
this._startResource(resource);
},

webSocketWillSendHandshakeRequest: function(requestId, time, request)
{
var resource = this._inflightResourcesById[requestId];
if (!resource)
return;

resource.requestMethod = "GET";
resource.requestHeaders = request.headers;
resource.webSocketRequestKey3 = request.requestKey3;
resource.startTime = time;

this._updateResource(resource);
},

webSocketHandshakeResponseReceived: function(requestId, time, response)
{
var resource = this._inflightResourcesById[requestId];
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(requestId, time)
{
var resource = this._inflightResourcesById[requestId];
if (!resource)
return;
this._finishResource(resource, time);
},

_appendRedirect: function(requestId, time, redirectURL)
{
var originalResource = this._inflightResourcesById[requestId];
var previousRedirects = originalResource.redirects || [];
originalResource.requestId = "redirected:" + requestId + "." + previousRedirects.length;
delete originalResource.redirects;
if (previousRedirects.length > 0)
originalResource.redirectSource = previousRedirects[previousRedirects.length - 1];
this._finishResource(originalResource, time);
var newResource = this._createResource(requestId, originalResource.frameId, originalResource.loaderId,
redirectURL, originalResource.documentURL, originalResource.initiator, originalResource.stackTrace);
newResource.redirects = previousRedirects.concat(originalResource);
return newResource;
},

_startResource: function(resource)
{
this._inflightResourcesById[resource.requestId] = 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.requestId];
delete this._inflightResourcesByURL[resource.url];
},

_dispatchEventToListeners: function(eventType, resource)
{
this._manager.dispatchEventToListeners(eventType, resource);
},


_createResource: function(requestId, frameId, loaderId, url, documentURL, initiator, stackTrace)
{
var resource = new WebInspector.Resource(requestId, url, frameId, loaderId);
resource.documentURL = documentURL;
resource.initiator = initiator;
resource.stackTrace = stackTrace;
return resource;
}
}


WebInspector.networkManager = null;






WebInspector.NetworkLog = function()
{
this._resources = [];
WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceStarted, this._onResourceStarted, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameNavigated, this);
}

WebInspector.NetworkLog.prototype = {

get resources()
{
return this._resources;
},

_mainFrameNavigated: function(event)
{

var oldResources = this._resources.splice(0, this._resources.length);
for (var i = 0; i < oldResources.length; ++i) {
if (oldResources[i].loaderId === event.data.loaderId)
this._resources.push(oldResources[i]);
}
},


_onResourceStarted: function(event)
{
var resource =   event.data;
this._resources.push(resource);
}
}


WebInspector.networkLog = null;






WebInspector.ResourceTreeModel = function(networkManager)
{
networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceUpdated, this._onResourceUpdated, this);
networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceFinished, this._onResourceUpdated, this);
networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceUpdateDropped, this._onResourceUpdateDropped, this);

WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this);
WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.RepeatCountUpdated, this._consoleMessageAdded, this);
WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);

PageAgent.enable();

this._fetchResourceTree();
InspectorBackend.registerPageDispatcher(new WebInspector.PageDispatcher(this));

this._pendingConsoleMessages = {};
}

WebInspector.ResourceTreeModel.EventTypes = {
FrameAdded: "FrameAdded",
FrameNavigated: "FrameNavigated",
FrameDetached: "FrameDetached",
MainFrameNavigated: "MainFrameNavigated",
ResourceAdded: "ResourceAdded",
ResourceContentCommitted: "resource-content-committed",
WillLoadCachedResources: "WillLoadCachedResources",
CachedResourcesLoaded: "CachedResourcesLoaded",
DOMContentLoaded: "DOMContentLoaded",
OnLoad: "OnLoad",
InspectedURLChanged: "InspectedURLChanged"
}

WebInspector.ResourceTreeModel.prototype = {
_fetchResourceTree: function()
{
this._frames = {};
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);
WebInspector.inspectedPageURL = mainFramePayload.frame.url;
this._addFramesRecursively(null, mainFramePayload);
this._dispatchInspectedURLChanged();
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded);
WebInspector.Resource.restoreRevisions();

this._cachedResourcesProcessed = true;
},

_dispatchInspectedURLChanged: function()
{
InspectorFrontendHost.inspectedURLChanged(WebInspector.inspectedPageURL);
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, WebInspector.inspectedPageURL);
},


_addFrame: function(frame)
{
this._frames[frame.id] = frame;
if (frame.isMainFrame())
this.mainFrame = frame;
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, frame);
},


_frameNavigated: function(framePayload)
{
if (this._frontendReused(framePayload))
return;


if (!this._cachedResourcesProcessed)
return;
var frame = this._frames[framePayload.id];
if (frame) {

frame._navigate(framePayload);
} else {

var parentFrame = this._frames[framePayload.parentId];
frame = new WebInspector.ResourceTreeFrame(this, parentFrame, framePayload);
if (frame.isMainFrame() && this.mainFrame) {

this._frameDetached(this.mainFrame.id);
}
this._addFrame(frame);
}

if (frame.isMainFrame())
WebInspector.inspectedPageURL = frame.url;

this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, frame);
if (frame.isMainFrame())
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, frame);


var resources = frame.resources();
for (var i = 0; i < resources.length; ++i)
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resources[i]);

if (frame.isMainFrame())
this._dispatchInspectedURLChanged();
},

_frontendReused: function(framePayload)
{
if (!framePayload.parentId && !WebInspector.networkLog.resources.length) {

this._fetchResourceTree();
return true;
}
return false;
},

_frameDetached: function(frameId)
{

if (!this._cachedResourcesProcessed)
return;

var frame = this._frames[frameId];
if (!frame)
return;

if (frame.parentFrame)
frame.parentFrame._removeChildFrame(frame);
else {

frame._removeChildFrames();
this.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, frame);
}
},

_onResourceUpdated: function(event)
{
if (!this._cachedResourcesProcessed)
return;

this._addPendingConsoleMessagesToResource(event.data);

var resource = event.data;
if (resource.failed || resource.type === WebInspector.Resource.Type.XHR)
return;

var frame = this._frames[resource.frameId];
if (frame)
frame._addResource(resource);
},

_onResourceUpdateDropped: function(event)
{
if (!this._cachedResourcesProcessed)
return;

var frameId = event.data.frameId;
var frame = this._frames[frameId];
if (!frame)
return;

var url = event.data.url;
if (frame._resourcesMap[url])
return;

var resource = this._createResource(url, frame.url, frameId, event.data.loaderId);
resource.type = WebInspector.Resource.Type[event.data.resourceType];
resource.mimeType = event.data.mimeType;
resource.finished = true;
frame._addResource(resource);
},

frameForId: function(frameId)
{
return this._frames[frameId];
},

forAllResources: function(callback)
{
if (this.mainFrame)
return this.mainFrame._callForFrameResources(callback);
return false;
},

_consoleMessageAdded: function(event)
{
var msg = event.data;
var resource = this.resourceForURL(msg.url);
if (resource)
this._addConsoleMessageToResource(msg, resource);
else
this._addPendingConsoleMessage(msg);
},

_addPendingConsoleMessage: function(msg)
{
if (!msg.url)
return;
if (!this._pendingConsoleMessages[msg.url])
this._pendingConsoleMessages[msg.url] = [];
this._pendingConsoleMessages[msg.url].push(msg);
},

_addPendingConsoleMessagesToResource: function(resource)
{
var messages = this._pendingConsoleMessages[resource.url];
if (messages) {
for (var i = 0; i < messages.length; i++)
this._addConsoleMessageToResource(messages[i], resource);
delete this._pendingConsoleMessages[resource.url];
}
},

_addConsoleMessageToResource: function(msg, resource)
{
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._pendingConsoleMessages = {};
this.forAllResources(callback);
},

resourceForURL: function(url)
{

return this.mainFrame ? this.mainFrame.resourceForURL(url) : null;
},

_addFramesRecursively: function(parentFrame, frameTreePayload)
{
var framePayload = frameTreePayload.frame;
var frame = new WebInspector.ResourceTreeFrame(this, parentFrame, framePayload);


var frameResource = this._createResourceFromFramePayload(framePayload, framePayload.url);
frameResource.mimeType = framePayload.mimeType;
frameResource.type = WebInspector.Resource.Type.Document;
frameResource.finished = true;

if (frame.isMainFrame())
WebInspector.inspectedPageURL = frameResource.url;

this._addFrame(frame);
frame._addResource(frameResource);

for (var i = 0; frameTreePayload.childFrames && i < frameTreePayload.childFrames.length; ++i)
this._addFramesRecursively(frame, frameTreePayload.childFrames[i]);

if (!frameTreePayload.resources)
return;


for (var i = 0; i < frameTreePayload.resources.length; ++i) {
var subresource = frameTreePayload.resources[i];
var resource = this._createResourceFromFramePayload(framePayload, subresource.url);
resource.type = WebInspector.Resource.Type[subresource.type];
resource.mimeType = subresource.mimeType;
resource.finished = true;
frame._addResource(resource);
}
},


_createResourceFromFramePayload: function(frame, url)
{
return this._createResource(url, frame.url, frame.id, frame.loaderId);
},


_createResource: function(url, documentURL, frameId, loaderId)
{
var resource = new WebInspector.Resource("", url, frameId, loaderId);
resource.documentURL = documentURL;
return resource;
}
}

WebInspector.ResourceTreeModel.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.ResourceTreeFrame = function(model, parentFrame, payload)
{
this._model = model;
this._parentFrame = parentFrame; 

this._id = payload.id;
this._loaderId = payload.loaderId;
this._name = payload.name;
this._url = payload.url;
this._mimeType = payload.mimeType;


this._childFrames = [];


this._resourcesMap = {};

if (this._parentFrame)
this._parentFrame._childFrames.push(this);
}

WebInspector.ResourceTreeFrame.prototype = {
get id()
{
return this._id;
},

get name()
{
return this._name;
},

get url()
{
return this._url;
},

get loaderId()
{
return this._loaderId;
},

get parentFrame()
{
return this._parentFrame;
},

get childFrames()
{
return this._childFrames;
},


isMainFrame: function()
{
return !this._parentFrame;
},


_navigate: function(framePayload)
{
this._loaderId = framePayload.loaderId;
this._name = framePayload.name;
this._url = framePayload.url;
this._mimeType = framePayload.mimeType;

var mainResource = this._resourcesMap[this._url];
this._resourcesMap = {};
this._removeChildFrames();
if (mainResource && mainResource.loaderId === this._loaderId)
this._addResource(mainResource);
},

get mainResource()
{
return this._resourcesMap[this._url];
},


_removeChildFrame: function(frame)
{
frame._removeChildFrames();
this._childFrames.remove(frame);
this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, frame);
},

_removeChildFrames: function()
{
var copy = this._childFrames.slice();
for (var i = 0; i < copy.length; ++i)
this._removeChildFrame(copy[i]); 
},


_addResource: function(resource)
{
if (this._resourcesMap[resource.url] === resource) {

return;
}
this._resourcesMap[resource.url] = resource;
this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resource);
},


resources: function()
{
var result = [];
for (var url in this._resourcesMap)
result.push(this._resourcesMap[url]);
return result;
},


resourceForURL: function(url)
{
var result;
function filter(resource)
{
if (resource.url === url) {
result = resource;
return true;
}
}
this._callForFrameResources(filter);
return result;
},


_callForFrameResources: function(callback)
{
for (var url in this._resourcesMap) {
if (callback(this._resourcesMap[url]))
return true;
}

for (var i = 0; i < this._childFrames.length; ++i) {
if (this._childFrames[i]._callForFrameResources(callback))
return true;
}
return false;
}
}


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)
{
this._resourceTreeModel._frameNavigated(frame);
},

frameDetached: function(frameId)
{
this._resourceTreeModel._frameDetached(frameId);
}
}


WebInspector.resourceTreeModel = null;






WebInspector.resourceForURL = function(url)
{
return WebInspector.resourceTreeModel.resourceForURL(url);
}


WebInspector.forAllResources = function(callback)
{
WebInspector.resourceTreeModel.forAllResources(callback);
}


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

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

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

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

return url.trimURL(parsedURL.host);
}


WebInspector.linkifyStringAsFragmentWithCustomLinkifier = function(string, linkifier)
{
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 linkIndex = string.indexOf(linkString);
        var nonLink = string.substring(0, linkIndex);
        container.appendChild(document.createTextNode(nonLink));

        var title = linkString;
        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 linkNode = linkifier(title, realURL, lineColumnMatch ? lineColumnMatch[1] : undefined);
        container.appendChild(linkNode);
        string = string.substring(linkIndex + linkString.length, string.length);
    }

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

    return container;
}

WebInspector._linkifierPlugins = [];

/**
 * @param {function(string):string} plugin
 */
WebInspector.registerLinkifierPlugin = function(plugin)
{
    WebInspector._linkifierPlugins.push(plugin);
}

/**
 * @param {string} string
 * @return {DocumentFragment}
 */
WebInspector.linkifyStringAsFragment = function(string)
{
    function linkifier(title, url, lineNumber)
    {
        for (var i = 0; i < WebInspector._linkifierPlugins.length; ++i)
            title = WebInspector._linkifierPlugins[i](title);

        var isExternal = !WebInspector.resourceForURL(url);
        var urlNode = WebInspector.linkifyURLAsNode(url, title, undefined, isExternal);
        if (typeof(lineNumber) !== "undefined") {
            urlNode.lineNumber = lineNumber;
            urlNode.preferredPanel = "scripts";
        }
        
        return urlNode; 
    }
    
    return WebInspector.linkifyStringAsFragmentWithCustomLinkifier(string, linkifier);
}

/**
 * @param {string} url
 * @param {string=} linkText
 * @param {string=} classes
 * @param {boolean=} isExternal
 * @param {string=} tooltipText
 * @return {Element}
 */
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;
}

/**
 * @param {string} url
 * @param {number=} lineNumber
 * @return {string}
 */
WebInspector.formatLinkText = function(url, lineNumber)
{
    var text = WebInspector.displayNameForURL(url);
    if (typeof lineNumber === "number")
        text += ":" + (lineNumber + 1);
    return text;
}

/**
 * @param {string} url
 * @param {number} lineNumber
 * @param {string=} classes
 * @param {string=} tooltipText
 * @return {Element}
 */
WebInspector.linkifyResourceAsNode = function(url, lineNumber, classes, tooltipText)
{
    var linkText = WebInspector.formatLinkText(url, lineNumber);
    var anchor = WebInspector.linkifyURLAsNode(url, linkText, classes, false, tooltipText);
    anchor.preferredPanel = "resources";
    anchor.lineNumber = lineNumber;
    return anchor;
}

/**
 * @param {WebInspector.Resource} request
 * @param {string=} classes
 */
WebInspector.linkifyRequestAsNode = function(request, classes)
{
    var anchor = WebInspector.linkifyURLAsNode(request.url);
    anchor.preferredPanel = "network";
    anchor.requestId  = request.requestId;
    return anchor;
}

/**
 * @return {?string} null if the specified resource MUST NOT have a URL (e.g. "javascript:...")
 */
WebInspector.resourceURLForRelatedNode = function(node, url)
{
    if (!url || url.indexOf("://") > 0)
        return url;

    if (url.trim().indexOf("javascript:") === 0)
        return null; // Do not provide a resource URL for security.

    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;
}

/**
 * @param {WebInspector.ContextMenu} contextMenu
 * @param {Node} contextNode
 * @param {Event} event
 */
WebInspector.populateHrefContextMenu = function(contextMenu, contextNode, event)
{
    var anchorElement = event.target.enclosingNodeOrSelfWithClass("webkit-html-resource-link") || event.target.enclosingNodeOrSelfWithClass("webkit-html-external-link");
    if (!anchorElement)
        return false;

    var resourceURL = WebInspector.resourceURLForRelatedNode(contextNode, anchorElement.href);
    if (!resourceURL)
        return false;

    // Add resource-related actions.
    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));
    contextMenu.appendItem(WebInspector.copyLinkAddressLabel(), InspectorFrontendHost.copyText.bind(InspectorFrontendHost, resourceURL));
    return true;
}

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

        // Return special URLs as-is.
        var trimmedHref = href.trim();
        if (trimmedHref.indexOf("data:") === 0 || trimmedHref.indexOf("javascript:") === 0)
            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;
}

/* ResourceCategory.js */

/*
 * Copyright (C) 2007, 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.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
 */

/**
 * @constructor
 */
WebInspector.ResourceCategory = function(name, title, color)
{
    this.name = name;
    this._title = title;
    this.color = color;
}

WebInspector.ResourceCategory.prototype = {
    toString: function()
    {
        return this.title;
    },

    get title()
    {
        return WebInspector.UIString(this._title);
    }
}

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

/* TimelineManager.js */

/*
 * Copyright (C) 2011 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.
 */

/**
 * @constructor
 * @extends {WebInspector.Object}
 */
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 = {
    /**
     * @param {number=} maxCallStackDepth
     */
    start: function(maxCallStackDepth)
    {
        this._enablementCount++;
        if (this._enablementCount === 1)
            TimelineAgent.start(maxCallStackDepth, this._started.bind(this));
    },

    stop: function()
    {
        if (!this._enablementCount) {
            console.error("WebInspector.TimelineManager start/stop calls are unbalanced");
            return;
        }
        this._enablementCount--;
        if (!this._enablementCount)
            TimelineAgent.stop(this._stopped.bind(this));
    },

    _started: function()
    {
        this.dispatchEventToListeners(WebInspector.TimelineManager.EventTypes.TimelineStarted);
    },

    _stopped: function()
    {
        this.dispatchEventToListeners(WebInspector.TimelineManager.EventTypes.TimelineStopped);
    }
}

WebInspector.TimelineManager.prototype.__proto__ = WebInspector.Object.prototype;

/**
 * @constructor
 * @implements {TimelineAgent.Dispatcher}
 */
WebInspector.TimelineDispatcher = function(manager)
{
    this._manager = manager;
    InspectorBackend.registerTimelineDispatcher(this);
}

WebInspector.TimelineDispatcher.prototype = {
    eventRecorded: function(record)
    {
        this._manager.dispatchEventToListeners(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded, record);
    }
}

/**
 * @type {WebInspector.TimelineManager}
 */
WebInspector.timelineManager;

/* Database.js */

/*
 * Copyright (C) 2007, 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.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 APPLE AND ITS 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 APPLE OR ITS 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.
 */

/**
 * @constructor
 */
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);
    }
}

/**
 * @constructor
 * @implements {DatabaseAgent.Dispatcher}
 */
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);
    }
}

/* DOMStorage.js */

/*
 * Copyright (C) 2008 Nokia 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.
 * 3.  Neither the name of Apple Computer, Inc. ("Apple") 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 "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 OR ITS 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.
 */

/**
 * @constructor
 */
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);
    }
}

/**
 * @constructor
 * @implements {DOMStorageAgent.Dispatcher}
 */
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);
    }
}

/* DOMStorageItemsView.js */

/*
 * Copyright (C) 2008 Nokia 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 ``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.
 */

/**
 * @constructor
 * @extends {WebInspector.View}
 */
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, this);

    this.refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
    this.refreshButton.addEventListener("click", this._refreshButtonClicked, this);
}

WebInspector.DOMStorageItemsView.prototype = {
    get statusBarItems()
    {
        return [this.refreshButton.element, this.deleteButton.element];
    },

    wasShown: function()
    {
        this.update();
    },

    willHide: function()
    {
        this.deleteButton.visible = false;
    },

    update: function()
    {
        this.detachChildViews();
        this.domStorage.getEntries(this._showDOMStorageEntries.bind(this));
    },

    _showDOMStorageEntries: function(error, entries)
    {
        if (error)
            return;

        this._dataGrid = this._dataGridForDOMStorageEntries(entries);
        this._dataGrid.show(this.element);
        this._dataGrid.autoSizeColumns(10);
        this.deleteButton.visible = true;
    },

    _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));
        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;

/* DataGrid.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.
 */

/**
 * @constructor
 * @extends {WebInspector.View}
 * @param {function(WebInspector.DataGridNode, number, string, string)=} editCallback
 * @param {function(WebInspector.DataGridNode)=} deleteCallback
 */
WebInspector.DataGrid = function(columns, editCallback, deleteCallback)
{
    WebInspector.View.call(this);
    this.registerRequiredCSS("dataGrid.css");

    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);

    // FIXME: Add a createCallback which is different from editCallback and has different
    // behavior when creating a new node.
    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 td = document.createElement("td");
        td.className = columnIdentifier + "-column";
        fillerRow.appendChild(td);
    }

    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;
}

/**
 * @param {Array.<string>} columnNames
 * @param {Array.<string>} values
 */
WebInspector.DataGrid.createSortableDataGrid = 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", sortDataGrid, this);

    function sortDataGrid()
    {
        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) {
                // Sort numbers based on comparing their values rather than a lexicographical comparison.
                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]);
    }
    return dataGrid;
}

WebInspector.DataGrid.prototype = {
    get refreshCallback()
    {
        return this._refreshCallback;
    },

    set refreshCallback(refreshCallback)
    {
        this._refreshCallback = refreshCallback;
    },

    _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, this._startEditingConfig(element));
        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;
        }

        // Force editing the 1st column when editing the creation node
        if (this._editingNode.isCreationNode)
            return this._startEditingColumnOfDataGridNode(this._editingNode, 0);

        this._editing = true;
        WebInspector.startEditing(element, this._startEditingConfig(element));

        window.getSelection().setBaseAndExtent(element, 0, element, 1);
    },


    _startEditingConfig: function(element)
    {
        return new WebInspector.EditingConfig(this._editingCommitted.bind(this), this._editingCancelled.bind(this), element.textContent);
    },

    _editingCommitted: function(element, newText, oldText, context, moveDirection)
    {
        // FIXME: We need more column identifiers here throughout this function.
        // Not needed yet since only editable DataGrid is DOM Storage, which is Key - Value.

        // FIXME: Better way to do this than regular expressions?
        var columnIdentifier = parseInt(element.className.match(/\b(\d+)-column\b/)[1], 10);

        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) {
                    this.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;
        }

        // Update the text in the datagrid that we typed
        this._editingNode.data[columnIdentifier] = newText;

        // Make the callback - expects an editing node (table row), the column number that is being edited,
        // the text that used to be there, and the new text.
        this._editCallback(this._editingNode, columnIdentifier, textBeforeEditing, newText);

        if (this._editingNode.isCreationNode)
            this.addCreationNode(false);

        this._editingCancelled(element);
        moveToNextIfNeeded.call(this, true);
    },

    _editingCancelled: function(element)
    {
        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;
    },

    /**
     * @param {number=} maxDescentLevel
     */
    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;
    },

    onResize: function()
    {
        this.updateWidths();
    },

    // Updates the widths of the table, including the positions of the column
    // resizers.
    //
    // IMPORTANT: This function MUST be called once after the element of the
    // DataGrid is attached to its parent element and every subsequent time the
    // width of the parent element is changed in order to make it possible to
    // resize the columns.
    //
    // If this function is not called after the DataGrid is attached to its
    // parent element, then the DataGrid's columns will not be resizable.
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) {
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(true);
handled = nextSelectedNode ? true : false;
} else if (event.keyIdentifier === "Down" && !event.altKey) {
nextSelectedNode = this.selectedNode.traverseNextNode(true);
while (nextSelectedNode && !nextSelectedNode.selectable)
nextSelectedNode = nextSelectedNode.traverseNextNode(true);
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()
{

},

revealAndSelect: 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 contextMenu = new WebInspector.ContextMenu();

var gridNode = this.dataGridNodeFromNode(event.target);
if (this.dataGrid._refreshCallback && (!gridNode || gridNode !== this.creationNode))
contextMenu.appendItem(WebInspector.UIString("Refresh"), this._refreshCallback.bind(this));

if (gridNode && gridNode.selectable && !gridNode.isEventWithinDisclosureTriangle(event)) {

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._currentResizer, 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.View.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 leftPadding()
{
if (typeof(this._leftPadding) === "number")
return this._leftPadding;

this._leftPadding = this.depth * this.dataGrid.indentWidth;
return this._leftPadding;
},

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.leftPadding)
cell.style.setProperty("padding-left", this.leftPadding + "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");
},

revealAndSelect: function()
{
this.reveal();
this.select();
},


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 left = cell.totalOffsetLeft() + this.leftPadding;
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)
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, refreshCallback)
{
WebInspector.View.call(this);
this.element.className = "fill";

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, undefined, deleteCallback ? this._onDeleteFromGrid.bind(this, deleteCallback) : undefined);
this._dataGrid.addEventListener("sorting changed", this._rebuildTable, this);
this._dataGrid.refreshCallback = refreshCallback;

this._dataGrid.show(this.element);
this._data = [];
}

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, 10)) {
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(deleteCallback, node)
{
deleteCallback(node.cookie);
}
}

WebInspector.CookiesTable.prototype.__proto__ = WebInspector.View.prototype;






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, this);

this._refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
this._refreshButton.addEventListener("click", this._refreshButtonClicked, this);

this._treeElement = treeElement;
this._cookieDomain = cookieDomain;

this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("This site has no cookies."));
this._emptyView.show(this.element);

this.element.addEventListener("contextmenu", this._contextMenu.bind(this), true);
}

WebInspector.CookieItemsView.prototype = {
get statusBarItems()
{
return [this._refreshButton.element, this._deleteButton.element];
},

wasShown: function()
{
this._update();
},

willHide: function()
{
this._deleteButton.visible = false;
},

_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._emptyView.show(this.element);
this._deleteButton.visible = false;
if (this._cookiesTable)
this._cookiesTable.detach();
return;
}

if (!this._cookiesTable)
this._cookiesTable = isAdvanced ? new WebInspector.CookiesTable(this._cookieDomain, false, this._deleteCookie.bind(this), this._update.bind(this)) : new WebInspector.SimpleCookiesTable();

this._cookiesTable.setCookies(this._cookies);
this._emptyView.detach();
this._cookiesTable.show(this.element);
if (isAdvanced) {
this._treeElement.subtitle = String.sprintf(WebInspector.UIString("%d cookies (%s)"), this._cookies.length,
Number.bytesToString(this._totalSize));
this._deleteButton.visible = true;
}
},

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

_contextMenu: function(event)
{
if (!this._cookies.length) {
var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendItem(WebInspector.UIString("Refresh"), this._update.bind(this));
contextMenu.show(event);
}
}
}

WebInspector.CookieItemsView.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.SimpleCookiesTable = function()
{
WebInspector.View.call(this);

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._dataGrid.show(this.element);
}

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;
}
}

WebInspector.SimpleCookiesTable.prototype.__proto__ = WebInspector.View.prototype;

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 || !WebInspector.Cookies.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.ApplicationCacheModel = function()
{
ApplicationCacheAgent.enable();
InspectorBackend.registerApplicationCacheDispatcher(new WebInspector.ApplicationCacheDispatcher(this));

WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this._frameDetached, this);

this._statuses = {};
this._manifestURLsByFrame = {};

this._mainFrameNavigated();

this._onLine = true;
}

WebInspector.ApplicationCacheModel.EventTypes = {
FrameManifestStatusUpdated: "FrameManifestStatusUpdated",
FrameManifestAdded: "FrameManifestAdded",
FrameManifestRemoved: "FrameManifestRemoved",
NetworkStateChanged: "NetworkStateChanged"
}

WebInspector.ApplicationCacheModel.prototype = {
_frameNavigated: function(event)
{
var frame =   event.data;
if (frame.isMainFrame()) {
this._mainFrameNavigated();
return;
}

ApplicationCacheAgent.getManifestForFrame(frame.id, this._manifestForFrameLoaded.bind(this, frame.id));
},

_frameDetached: function(event)
{
var frame =   event.data;
this._frameManifestRemoved(frame.id);
},

_mainFrameNavigated: function()
{
ApplicationCacheAgent.getFramesWithManifests(this._framesWithManifestsLoaded.bind(this));
},


_manifestForFrameLoaded: function(frameId, error, manifestURL)
{
if (error) {
console.error(error);
return;
}

if (!manifestURL)
this._frameManifestRemoved(frameId);
},


_framesWithManifestsLoaded: function(error, framesWithManifests)
{
if (error) {
console.error(error);
return;
}

for (var i = 0; i < framesWithManifests.length; ++i)
this._frameManifestUpdated(framesWithManifests[i].frameId, framesWithManifests[i].manifestURL, framesWithManifests[i].status);
},


_frameManifestUpdated: function(frameId, manifestURL, status)
{
if (status === applicationCache.UNCACHED) {
this._frameManifestRemoved(frameId);
return;
}

if (!manifestURL)
return;

if (this._manifestURLsByFrame[frameId] && manifestURL !== this._manifestURLsByFrame[frameId])
this._frameManifestRemoved(frameId);

var statusChanged = this._statuses[frameId] !== status;
this._statuses[frameId] = status;

if (!this._manifestURLsByFrame[frameId]) {
this._manifestURLsByFrame[frameId] = manifestURL;
this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestAdded, frameId);
}

if (statusChanged)
this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestStatusUpdated, frameId);
},


_frameManifestRemoved: function(frameId)
{
if (!this._manifestURLsByFrame[frameId])
return;

var manifestURL = this._manifestURLsByFrame[frameId];
delete this._manifestURLsByFrame[frameId];
delete this._statuses[frameId];

this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestRemoved, frameId);
},


frameManifestURL: function(frameId)
{
return this._manifestURLsByFrame[frameId] || "";
},


frameManifestStatus: function(frameId)
{
return this._statuses[frameId] || applicationCache.UNCACHED;
},


get onLine()
{
return this._onLine;
},


_statusUpdated: function(frameId, manifestURL, status)
{
this._frameManifestUpdated(frameId, manifestURL, status);
},


requestApplicationCache: function(frameId, callback)
{
function callbackWrapper(error, applicationCache)
{
if (error) {
console.error(error);
callback(null);
return;
}

callback(applicationCache);
}

ApplicationCacheAgent.getApplicationCacheForFrame(frameId, callbackWrapper.bind(this));
},


_networkStateUpdated: function(isNowOnline)
{
this._onLine = isNowOnline;
this.dispatchEventToListeners(WebInspector.ApplicationCacheModel.EventTypes.NetworkStateChanged, isNowOnline);
}
}

WebInspector.ApplicationCacheModel.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.ApplicationCacheDispatcher = function(applicationCacheModel)
{
this._applicationCacheModel = applicationCacheModel;
}

WebInspector.ApplicationCacheDispatcher.prototype = {

applicationCacheStatusUpdated: function(frameId, manifestURL, status)
{
this._applicationCacheModel._statusUpdated(frameId, manifestURL, status);
},


networkStateUpdated: function(isNowOnline)
{
this._applicationCacheModel._networkStateUpdated(isNowOnline);
},
}






WebInspector.ApplicationCacheItemsView = function(model, frameId)
{
WebInspector.View.call(this);

this._model = model;

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, this);

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._frameId = frameId;

this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("No Application Cache information available."));
this._emptyView.show(this.element);

this._markDirty();

var status = this._model.frameManifestStatus(frameId);
this.updateStatus(status);

this.updateNetworkState(this._model.onLine);



this.deleteButton.element.style.display = "none";
}

WebInspector.ApplicationCacheItemsView.prototype = {
get statusBarItems()
{
return [
this.deleteButton.element,
this.connectivityIcon, this.connectivityMessage, this.divider,
this.statusIcon, this.statusMessage
];
},

wasShown: function()
{
this._maybeUpdate();
},

willHide: function()
{
this.deleteButton.visible = false;
},

_maybeUpdate: function()
{
if (!this.isShowing() || !this._viewDirty)
return;

this._update();
this._viewDirty = false;
},

_markDirty: function()
{
this._viewDirty = true;
},


updateStatus: function(status)
{
var oldStatus = this._status;
this._status = status;

var statusInformation = {};

statusInformation[applicationCache.UNCACHED]    = { src: "Images/errorRedDot.png", text: "UNCACHED" };
statusInformation[applicationCache.IDLE]        = { src: "Images/successGreenDot.png", text: "IDLE" };
statusInformation[applicationCache.CHECKING]    = { src: "Images/warningOrangeDot.png",  text: "CHECKING" };
statusInformation[applicationCache.DOWNLOADING] = { src: "Images/warningOrangeDot.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] || statusInformation[applicationCache.UNCACHED];

this.statusIcon.src = info.src;
this.statusMessage.textContent = info.text;

if (this.isShowing() && this._status === applicationCache.IDLE && (oldStatus === applicationCache.UPDATEREADY || !this._resources))
this._markDirty();
this._maybeUpdate();
},


updateNetworkState: function(isNowOnline)
{
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()
{
this._model.requestApplicationCache(this._frameId, this._updateCallback.bind(this));
},


_updateCallback: function(applicationCache)
{
if (!applicationCache || !applicationCache.manifestURL) {
delete this._manifest;
delete this._creationTime;
delete this._updateTime;
delete this._size;
delete this._resources;

this._emptyView.show(this.element);
this.deleteButton.visible = false;
if (this._dataGrid)
this._dataGrid.element.addStyleClass("hidden");
return;
}

this._manifest = applicationCache.manifestURL;
this._creationTime = applicationCache.creationTime;
this._updateTime = applicationCache.updateTime;
this._size = applicationCache.size;
this._resources = applicationCache.resources;

var lastPathComponent = applicationCache.lastPathComponent;

if (!this._dataGrid)
this._createDataGrid();

this._populateDataGrid();
this._dataGrid.autoSizeColumns(20, 80);
this._dataGrid.element.removeStyleClass("hidden");
this._emptyView.detach();
this.deleteButton.visible = true;




},

_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._dataGrid.show(this.element);
this._dataGrid.addEventListener("sorting changed", this._populateDataGrid, this);
},

_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, 10)) {
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.url;
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.length)
this._dataGrid.children[0].selected = true;
},

_deleteButtonClicked: function(event)
{
if (!this._dataGrid || !this._dataGrid.selectedNode)
return;


this._deleteCallback(this._dataGrid.selectedNode);
},

_deleteCallback: function(node)
{



},
}

WebInspector.ApplicationCacheItemsView.prototype.__proto__ = WebInspector.View.prototype;






WebInspector.Script = function(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript)
{
this.scriptId = scriptId;
this.sourceURL = sourceURL;
this.lineOffset = startLine;
this.columnOffset = startColumn;
this.endLine = endLine;
this.endColumn = endColumn;
this.isContentScript = isContentScript;
}

WebInspector.Script.prototype = {

requestSource: function(callback)
{
if (this._source) {
callback(this._source);
return;
}


function didGetScriptSource(error, source)
{
this._source = error ? "" : source;
callback(this._source);
}
if (this.scriptId) {

DebuggerAgent.getScriptSource(this.scriptId, didGetScriptSource.bind(this));
} else
callback("");
},


searchInContent: function(query, caseSensitive, isRegex, callback)
{

function innerCallback(error, searchMatches)
{
if (error)
console.error(error);
var result = [];
for (var i = 0; i < searchMatches.length; ++i) {
var searchMatch = new WebInspector.ContentProvider.SearchMatch(searchMatches[i].lineNumber, searchMatches[i].lineContent);
result.push(searchMatch);
}
callback(result || []);
}

if (this.scriptId) {

DebuggerAgent.searchInContent(this.scriptId, query, caseSensitive, isRegex, innerCallback.bind(this));
} else
callback([]);
},


editSource: function(newSource, callback)
{

function didEditScriptSource(error, callFrames)
{
if (!error)
this._source = newSource;
callback(error, callFrames);
}
if (this.scriptId) {

DebuggerAgent.setScriptSource(this.scriptId, newSource, undefined, didEditScriptSource.bind(this));
} else
callback("Script failed to parse");
},

isInlineScript: function()
{
return this.sourceURL && this.lineOffset !== 0 && this.columnOffset !== 0;
}
}






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(omitRootDOMNode, selectEnabled, showInElementsPanelEnabled, contextMenuCallback)
{
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);
this.element.addEventListener("dragstart", this._ondragstart.bind(this), false);
this.element.addEventListener("dragover", this._ondragover.bind(this), false);
this.element.addEventListener("dragleave", this._ondragleave.bind(this), false);
this.element.addEventListener("drop", this._ondrop.bind(this), false);
this.element.addEventListener("dragend", this._ondragend.bind(this), false);

TreeOutline.call(this, this.element);

this._includeRootDOMNode = !omitRootDOMNode;
this._selectEnabled = selectEnabled;
this._showInElementsPanelEnabled = showInElementsPanelEnabled;
this._rootDOMNode = null;
this._selectDOMNode = null;
this._eventSupport = new WebInspector.Object();
this._editing = false;

this._visible = false;

this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true);
this._contextMenuCallback = contextMenuCallback;
}

WebInspector.ElementsTreeOutline.Events = {
SelectedNodeChanged: "SelectedNodeChanged"
}

WebInspector.ElementsTreeOutline.prototype = {
wireToDomAgent: function()
{
this._elementsTreeUpdater = new WebInspector.ElementsTreeUpdater(this);
},

setVisible: function(visible)
{
this._visible = visible;
if (!this._visible)
return;

this._updateModifiedNodes();
if (this._selectedDOMNode)
this._revealAndSelectNode(this._selectedDOMNode, false);
},

addEventListener: function(eventType, listener, thisObject)
{
this._eventSupport.addEventListener(eventType, listener, thisObject);
},

removeEventListener: function(eventType, listener, thisObject)
{
this._eventSupport.removeEventListener(eventType, listener, thisObject);
},

get rootDOMNode()
{
return this._rootDOMNode;
},

set rootDOMNode(x)
{
if (this._rootDOMNode === x)
return;

this._rootDOMNode = x;

this._isXMLMimeType = x && x.isXMLNode();

this.update();
},

get isXMLMimeType()
{
return this._isXMLMimeType;
},

selectedDOMNode: function()
{
return this._selectedDOMNode;
},

selectDOMNode: function(node, focus)
{
if (this._selectedDOMNode === node) {
this._revealAndSelectNode(node, !focus);
return;
}

this._selectedDOMNode = node;
this._revealAndSelectNode(node, !focus);





if (this._selectedDOMNode === node)
this._selectedNodeChanged();
},

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, true);
},

updateSelection: function()
{
if (!this.selectedTreeElement)
return;
var element = this.treeOutline.selectedTreeElement;
element.updateSelection();
},

_selectedNodeChanged: function()
{
this._eventSupport.dispatchEventToListeners(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged);
},

findTreeElement: function(node)
{
function isAncestorNode(ancestor, node)
{
return ancestor.isAncestor(node);
}

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

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;

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, omitFocus)
{
if (!node || this._suppressRevealAndSelect)
return;

var treeElement = this.createTreeElementFor(node);
if (!treeElement)
return;

treeElement.revealAndSelect(omitFocus);
},

_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.domAgent.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.domAgent.hideDOMNodeHighlight();
},

_ondragstart: function(event)
{
var treeElement = this._treeElementFromEvent(event);
if (!treeElement)
return false;

if (!this._isValidDragSourceOrTarget(treeElement))
return false;

if (treeElement.representedObject.nodeName() === "BODY" || treeElement.representedObject.nodeName() === "HEAD")
return false;

event.dataTransfer.setData("text/plain", treeElement.listItemElement.textContent);
event.dataTransfer.effectAllowed = "copyMove";
this._nodeBeingDragged = treeElement.representedObject;

WebInspector.domAgent.hideDOMNodeHighlight();

return true;
},

_ondragover: function(event)
{
if (!this._nodeBeingDragged)
return false;

var treeElement = this._treeElementFromEvent(event);
if (!this._isValidDragSourceOrTarget(treeElement))
return false;

var node = treeElement.representedObject;
while (node) {
if (node === this._nodeBeingDragged)
return false;
node = node.parentNode;
}

treeElement.updateSelection();
treeElement.listItemElement.addStyleClass("elements-drag-over");
this._dragOverTreeElement = treeElement;
event.preventDefault();
event.dataTransfer.dropEffect = 'move';
return false;
},

_ondragleave: function(event)
{
this._clearDragOverTreeElementMarker();
event.preventDefault();
return false;
},

_isValidDragSourceOrTarget: function(treeElement)
{
if (!treeElement)
return false;

var node = treeElement.representedObject;
if (!(node instanceof WebInspector.DOMNode))
return false;

if (!node.parentNode || node.parentNode.nodeType() !== Node.ELEMENT_NODE)
return false;

return true;
},

_ondrop: function(event)
{
event.preventDefault();
var treeElement = this._treeElementFromEvent(event);
if (this._nodeBeingDragged && treeElement) {
var parentNode;
var anchorNode;

if (treeElement._elementCloseTag) {

parentNode = treeElement.representedObject;
} else {
var dragTargetNode = treeElement.representedObject;
parentNode = dragTargetNode.parentNode;
anchorNode = dragTargetNode;
}

function callback(error, newNodeId)
{
if (error)
return;

this._updateModifiedNodes();
var newNode = WebInspector.domAgent.nodeForId(newNodeId);
if (newNode)
this.selectDOMNode(newNode, true);
}
this._nodeBeingDragged.moveTo(parentNode, anchorNode, callback.bind(this));
}

delete this._nodeBeingDragged;
},

_ondragend: function(event)
{
event.preventDefault();
this._clearDragOverTreeElementMarker();
delete this._nodeBeingDragged;
},

_clearDragOverTreeElementMarker: function()
{
if (this._dragOverTreeElement) {
this._dragOverTreeElement.updateSelection();
this._dragOverTreeElement.listItemElement.removeStyleClass("elements-drag-over");
delete this._dragOverTreeElement;
}
},

_contextMenuEventFired: function(event)
{
if (!this._showInElementsPanelEnabled)
return;

var treeElement = this._treeElementFromEvent(event);
if (!treeElement)
return;

function focusElement()
{
WebInspector.domAgent.inspectElement(treeElement.representedObject.id);
}
var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendItem(WebInspector.UIString("Reveal in Elements Panel"), focusElement.bind(this));
contextMenu.show(event);
},

populateContextMenu: function(contextMenu, event)
{
var treeElement = this._treeElementFromEvent(event);
if (!treeElement)
return false;

var tag = event.target.enclosingNodeOrSelfWithClass("webkit-html-tag");
var textNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-text-node");
var commentNode = event.target.enclosingNodeOrSelfWithClass("webkit-html-comment");
var populated = WebInspector.populateHrefContextMenu(contextMenu, this.selectedDOMNode(), event);
if (tag && treeElement._populateTagContextMenu) {
if (populated)
contextMenu.appendSeparator();
treeElement._populateTagContextMenu(contextMenu, event);
populated = true;
} else if (textNode && treeElement._populateTextContextMenu) {
if (populated)
contextMenu.appendSeparator();
treeElement._populateTextContextMenu(contextMenu, textNode);
populated = true;
} else if (commentNode && treeElement._populateNodeContextMenu) {
if (populated)
contextMenu.appendSeparator();
treeElement._populateNodeContextMenu(contextMenu, textNode);
populated = true;
}

return populated;
},

adjustCollapsedRange: function()
{
},

_updateModifiedNodes: function()
{
if (this._elementsTreeUpdater)
this._elementsTreeUpdater._updateModifiedNodes();
},

_populateContextMenu: function(contextMenu, node)
{
if (this._contextMenuCallback)
this._contextMenuCallback(contextMenu, node);
}
}

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(result)
{
if (!result || 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;

function dimensions()
{
return "[" + this.offsetWidth + "," + this.offsetHeight + "," + this.naturalWidth + "," + this.naturalHeight + "]";
}

object.callFunction(dimensions, 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();
this.listItemElement.draggable = true;
},

_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 || !this.treeOutline._visible)
return;

this._updateChildrenInProgress = true;
var selectedNode = this.treeOutline.selectedDOMNode();
var originalScrollTop = 0;
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 === selectedNode)
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();

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 button = document.createElement("button");
button.className = "show-all-nodes";
button.value = "";
var item = new TreeElement(button, null, false);
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.selectDOMNode(this.representedObject, selectedByUser);
if (selectedByUser)
WebInspector.domAgent.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");
this.treeOutline.selectDOMNode(this.representedObject, true);
}


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.selectedDOMNode() != 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();

this._populateNodeContextMenu(contextMenu);
this.treeOutline._populateContextMenu(contextMenu, this.representedObject);
},

_populateTextContextMenu: function(contextMenu, textNode)
{
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Edit text" : "Edit Text"), this._startEditingTextNode.bind(this, textNode));
this._populateNodeContextMenu(contextMenu);
},

_populateNodeContextMenu: function(contextMenu)
{

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));
},

_startEditing: function()
{
if (this.treeOutline.selectedDOMNode() !== 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);

var config = new WebInspector.EditingConfig(this._attributeEditingCommitted.bind(this), this._editingCancelled.bind(this), attributeName);
this._editing = WebInspector.startEditing(attribute, config);

window.getSelection().setBaseAndExtent(elementForSelection, 0, elementForSelection, 1);

return true;
},

_startEditingTextNode: function(textNode)
{
if (WebInspector.isBeingEdited(textNode))
return true;

var config = new WebInspector.EditingConfig(this._textNodeEditingCommitted.bind(this), this._editingCancelled.bind(this));
this._editing = WebInspector.startEditing(textNode, config);
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);

var config = new WebInspector.EditingConfig(editingComitted.bind(this), editingCancelled.bind(this), tagName);
this._editing = WebInspector.startEditing(tagNameElement, config);
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()
{
this._editing = false;


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

var config = new WebInspector.EditingConfig(commit.bind(this), dispose.bind(this));
config.setMultiline(true);
this._editing = WebInspector.startEditing(this._htmlEditElement, config);
},

_attributeEditingCommitted: function(element, newText, oldText, attributeName, moveDirection)
{
this._editing = false;

var treeOutline = this.treeOutline;
function moveToNextAttributeIfNeeded(error)
{
if (error)
this._editingCancelled(element, attributeName);

if (!moveDirection)
return;

treeOutline._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)
{
this._editing = false;
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;
}

var node = WebInspector.domAgent.nodeForId(nodeId);


treeOutline._updateModifiedNodes();
treeOutline.selectDOMNode(node, true);

var newTreeItem = treeOutline.findTreeElement(node);
if (wasExpanded)
newTreeItem.expand();

moveToNextAttributeIfNeeded.call(newTreeItem);
}

this.representedObject.setNodeName(newText, changeTagNameCallback);
},

_textNodeEditingCommitted: function(element, newText)
{
this._editing = false;

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)
{
this._editing = false;


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;

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");
if (rewrittenHref === null) {
var attrValueElement = attrSpanElement.createChild("span", "webkit-html-attribute-value");
attrValueElement.textContent = value;
} else {
if (value.indexOf("data:") === 0)
value = value.trimMiddle(60);
attrSpanElement.appendChild(linkify(rewrittenHref, value, "webkit-html-attribute-value", node.nodeName().toLowerCase() === "a"));
}
} else {
value = value.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 = node.nodeNameInCorrectCase();
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);
}




if (showInlineText) {
var textNodeElement = info.titleDOM.createChild("span", "webkit-html-text-node");
textNodeElement.textContent = textChild.nodeValue();
info.titleDOM.appendChild(document.createTextNode("\u200B"));
this._buildTagDOM(info.titleDOM, tagName, true, false);
info.hasChildren = false;
}
break;

case Node.TEXT_NODE:
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();
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() + "-->"));
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() + "]]>"));
break;
default:
var defaultElement = info.titleDOM.appendChild(document.createTextNode(node.nodeNameInCorrectCase().collapseWhitespace()));
}

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

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;

var node = WebInspector.domAgent.nodeForId(nodeId);

treeOutline._updateModifiedNodes();
treeOutline.selectDOMNode(node, true);

if (wasExpanded) {
var newTreeItem = treeOutline.findTreeElement(node);
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 = createPlainTextSearchRegex(this._searchQuery, "gi");

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.ElementsTreeUpdater = function(treeOutline)
{
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.AttrRemoved, 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._treeOutline = treeOutline;
this._recentlyModifiedNodes = [];
}

WebInspector.ElementsTreeUpdater.prototype = {
_documentUpdated: function(event)
{
var inspectedRootDocument = event.data;

this._reset();

if (!inspectedRootDocument)
return;

this._treeOutline.rootDOMNode = inspectedRootDocument;
},

_attributesUpdated: function(event)
{
this._recentlyModifiedNodes.push({node: event.data.node, updated: true});
if (this._treeOutline._visible)
this._updateModifiedNodesSoon();
},

_characterDataModified: function(event)
{
this._recentlyModifiedNodes.push({node: event.data, updated: true});
if (this._treeOutline._visible)
this._updateModifiedNodesSoon();
},

_nodeInserted: function(event)
{
this._recentlyModifiedNodes.push({node: event.data, parent: event.data.parentNode, inserted: true});
if (this._treeOutline._visible)
this._updateModifiedNodesSoon();
},

_nodeRemoved: function(event)
{
this._recentlyModifiedNodes.push({node: event.data.node, parent: event.data.parent, removed: true});
if (this._treeOutline._visible)
this._updateModifiedNodesSoon();
},

_childNodeCountUpdated: function(event)
{
var treeElement = this._treeOutline.findTreeElement(event.data);
if (treeElement)
treeElement.hasChildren = event.data.hasChildNodes();
},

_updateModifiedNodesSoon: function()
{
if (this._updateModifiedNodesTimeout)
return;
this._updateModifiedNodesTimeout = setTimeout(this._updateModifiedNodes.bind(this), 0);
},

_updateModifiedNodes: function()
{
if (this._updateModifiedNodesTimeout) {
clearTimeout(this._updateModifiedNodesTimeout);
delete this._updateModifiedNodesTimeout;
}

var updatedParentTreeElements = [];

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);
}
}

for (var i = 0; i < updatedParentTreeElements.length; ++i)
delete updatedParentTreeElements[i].alreadyUpdatedChildren;

this._recentlyModifiedNodes = [];
},

_reset: function()
{
this._treeOutline.rootDOMNode = null;
this._treeOutline.selectDOMNode(null, false);
WebInspector.domAgent.hideDOMNodeHighlight();
this._recentlyModifiedNodes = [];
}
}





WebInspector.DOMPresentationUtils = {}

WebInspector.DOMPresentationUtils.decorateNodeLabel = function(node, parentElement)
{
var title = node.nodeNameInCorrectCase();

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;
}

WebInspector.DOMPresentationUtils.linkifyNodeReference = function(node)
{
var link = document.createElement("span");
link.className = "node-link";
WebInspector.DOMPresentationUtils.decorateNodeLabel(node, link);

link.addEventListener("click", WebInspector.domAgent.inspectElement.bind(WebInspector.domAgent, node.id), false);
link.addEventListener("mouseover", WebInspector.domAgent.highlightDOMNode.bind(WebInspector.domAgent, node.id, ""), false);
link.addEventListener("mouseout", WebInspector.domAgent.hideDOMNodeHighlight.bind(WebInspector.domAgent), false);

return link;
}

WebInspector.DOMPresentationUtils.linkifyNodeById = function(nodeId)
{
var node = WebInspector.domAgent.nodeForId(nodeId);
if (!node)
return document.createTextNode(WebInspector.UIString("<node>"));
return WebInspector.DOMPresentationUtils.linkifyNodeReference(node);
}






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;
},

set wait(x)
{
if (x)
this._listItemNode.addStyleClass("wait");
else
this._listItemNode.removeStyleClass("wait");
},

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._expanded) {
this.onpopulate();
this._populated = true;
}
},

onpopulate: function()
{

},

get firstSibling()
{
var parent = this.element.parentElement;
if (!parent)
return null;

var childElement = parent.firstChild;
while (childElement) {
if (childElement._section)
return childElement._section;
childElement = childElement.nextSibling;
}

return null;
},

get lastSibling()
{
var parent = this.element.parentElement;
if (!parent)
return null;

var childElement = parent.lastChild;
while (childElement) {
if (childElement._section)
return childElement._section;
childElement = childElement.previousSibling;
}

return null;
},

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._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, subtype, value, description)
{
this._type = type;
this._subtype = subtype;
if (objectId) {

this._objectId = objectId;
this._description = description;
this._hasChildren = true;
} else {

console.assert(type !== "object" || value === null);
this._description = description || (value + "");
this._hasChildren = false;
this.value = value;
}
}

WebInspector.RemoteObject.fromPrimitiveValue = function(value)
{
return new WebInspector.RemoteObject(null, typeof value, null, value);
}

WebInspector.RemoteObject.fromLocalObject = function(value)
{
return new WebInspector.LocalJSONObject(value);
}

WebInspector.RemoteObject.resolveNode = function(node, objectGroup, callback)
{
function mycallback(error, object)
{
if (!callback)
return;

if (error || !object)
callback(null);
else
callback(WebInspector.RemoteObject.fromPayload(object));
}
DOMAgent.resolveNode(node.id, objectGroup, mycallback);
}

WebInspector.RemoteObject.fromPayload = function(payload)
{
console.assert(typeof payload === "object", "Remote object payload should only be an object");

return new WebInspector.RemoteObject(payload.objectId, payload.type, payload.subtype, payload.value, payload.description);
}

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 subtype()
{
return this._subtype;
},

get description()
{
return this._description;
},

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

getOwnProperties: function(callback)
{
this._getProperties(true, callback);
},

getAllProperties: function(callback)
{
this._getProperties(false, callback);
},

_getProperties: function(ownProperties, callback)
{
if (!this._objectId) {
callback([]);
return;
}
function remoteObjectBinder(error, properties)
{
if (error) {
callback(null);
return;
}
var result = [];
for (var i = 0; properties && i < properties.length; ++i) {
var property = properties[i];
if (property.get || property.set) {
if (property.get)
result.push(new WebInspector.RemoteObjectProperty("get " + property.name, WebInspector.RemoteObject.fromPayload(property.get), property));
if (property.set)
result.push(new WebInspector.RemoteObjectProperty("set " + property.name, WebInspector.RemoteObject.fromPayload(property.set), property));
} else
result.push(new WebInspector.RemoteObjectProperty(property.name, WebInspector.RemoteObject.fromPayload(property.value), property));
}
callback(result);
}
RuntimeAgent.getProperties(this._objectId, ownProperties, remoteObjectBinder);
},

setPropertyValue: function(name, value, callback)
{
if (!this._objectId) {
callback("Can't set a property of non-object.");
return;
}

RuntimeAgent.evaluate.invoke({expression:value, doNotPauseOnExceptions:true}, evaluatedCallback.bind(this));

function evaluatedCallback(error, result, wasThrown)
{
if (error || wasThrown) {
callback(error || result);
return;
}

function setPropertyValue(propertyName, propertyValue)
{
this[propertyName] = propertyValue;
}

delete result.description; 
RuntimeAgent.callFunctionOn(this._objectId, setPropertyValue.toString(), [{ value:name }, result], undefined, propertySetCallback.bind(this));
if (result._objectId)
RuntimeAgent.releaseObject(result._objectId);
}

function propertySetCallback(error, result, wasThrown) {
if (error || wasThrown) {
callback(error || result);
return;
}
callback();
}
},

pushNodeToFrontend: function(callback)
{
if (this._objectId)
WebInspector.domAgent.pushNodeToFrontend(this._objectId, callback);
else
callback(0);
},

callFunction: function(functionDeclaration, callback)
{
function mycallback(error, result, wasThrown)
{
callback((error || wasThrown) ? null : WebInspector.RemoteObject.fromPayload(result));
}

RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), undefined, undefined, mycallback);
},

callFunctionJSON: function(functionDeclaration, callback)
{
function mycallback(error, result, wasThrown)
{
callback((error || wasThrown) ? null : result.value);
}

RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), undefined, true, mycallback);
},

release: function()
{
RuntimeAgent.releaseObject(this._objectId);
}
}


WebInspector.RemoteObjectProperty = function(name, value, descriptor)
{
this.name = name;
this.value = value;
this.enumerable = descriptor ? !!descriptor.enumerable : true;
this.writable = descriptor ? !!descriptor.writable : true;
if (descriptor && descriptor.wasThrown)
this.wasThrown = true;
}

WebInspector.RemoteObjectProperty.fromPrimitiveValue = function(name, value)
{
return new WebInspector.RemoteObjectProperty(name, WebInspector.RemoteObject.fromPrimitiveValue(value));
}








WebInspector.LocalJSONObject = function(value)
{
this._value = value;
}

WebInspector.LocalJSONObject.prototype = {
get description()
{
if (this._cachedDescription)
return this._cachedDescription;

if (this.type === "object") {
switch (this.subtype) {
case "array":
function formatArrayItem(property)
{
return property.value.description;
}
this._cachedDescription = this._concatenate("[", "]", formatArrayItem);
break;
case "null":
this._cachedDescription = "null";
break;
default:
function formatObjectItem(property)
{
return property.name + ":" + property.value.description;
}
this._cachedDescription = this._concatenate("{", "}", formatObjectItem);
}
} else
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()
{
return typeof this._value;
},

get subtype()
{
if (this._value === null)
return "null";

if (this._value instanceof Array)
return "array";

return undefined;
},

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()
{
if (!this.hasChildren)
return [];

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 = document.createElement("div");
title.className = "info";
title.textContent = this.emptyPlaceholder;
var infoElement = new TreeElement(title, null, false);
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);
this.toggleOnClick = true;
this.selectable = 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)
{
if (this.property.writable)
this.startEditing();
},

onattach: function()
{
this.update();
},

update: function()
{
this.nameElement = document.createElement("span");
this.nameElement.className = "name";
this.nameElement.textContent = this.property.name;
if (!this.property.enumerable)
this.nameElement.addStyleClass("dimmed");

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.value.type === "function")
this.valueElement.addEventListener("contextmenu", this._functionContextMenuEventFired.bind(this), false);

if (this.property.wasThrown)
this.valueElement.addStyleClass("error");
if (this.property.value.subtype)
this.valueElement.addStyleClass("console-formatted-" + this.property.value.subtype);
else if (this.property.value.type)
this.valueElement.addStyleClass("console-formatted-" + this.property.value.type);
if (this.property.value.subtype === "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(event)
{
function selectNode(nodeId)
{
if (nodeId)
WebInspector.domAgent.inspectElement(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);
},

_functionContextMenuEventFired: function(event)
{
function didGetLocation(error, response)
{
if (error) {
console.error(error);
return;
}
WebInspector.panels.scripts.showFunctionDefinition(response);
}

function revealFunction()
{
DebuggerAgent.getFunctionLocation(this.property.value.objectId, didGetLocation.bind(this));
}

var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendItem(WebInspector.UIString("Show function definition"), revealFunction.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;

var config = new WebInspector.EditingConfig(this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
WebInspector.startEditing(this.valueElement, config);
},

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.ObjectPopoverHelper = function(panelElement, getAnchor, queryObject, onHide, disableOnClick)
{
WebInspector.PopoverHelper.call(this, panelElement, getAnchor, this._showObjectPopover.bind(this), onHide, disableOnClick);
this._queryObject = queryObject;
panelElement.addEventListener("scroll", this.hidePopover.bind(this), true);
};

WebInspector.ObjectPopoverHelper.prototype = {
_showObjectPopover: function(element, popover)
{
function showObjectPopover(result, wasThrown)
{
if (popover.disposed)
return;
if (wasThrown) {
this.hidePopover();
return;
}
var popoverContentElement = null;
if (result.type !== "object") {
popoverContentElement = document.createElement("span");
popoverContentElement.className = "monospace console-formatted-" + result.type;
popoverContentElement.style.whiteSpace = "pre";
popoverContentElement.textContent = result.description;
if (result.type === "string")
popoverContentElement.textContent = "\"" + popoverContentElement.textContent + "\"";
popover.show(popoverContentElement, element);
} else {
popoverContentElement = document.createElement("div");

this._titleElement = document.createElement("div");
this._titleElement.className = "source-frame-popover-title monospace";
this._titleElement.textContent = result.description;
popoverContentElement.appendChild(this._titleElement);

var section = new WebInspector.ObjectPropertiesSection(result);

if (result.description.substr(0, 4) === "HTML") {
this._sectionUpdateProperties = section.updateProperties.bind(section);
section.updateProperties = this._updateHTMLId.bind(this);
}
section.expanded = true;
section.element.addStyleClass("source-frame-popover-tree");
section.headerElement.addStyleClass("hidden");
popoverContentElement.appendChild(section.element);

const popoverWidth = 300;
const popoverHeight = 250;
popover.show(popoverContentElement, element, popoverWidth, popoverHeight);
}
}
this._queryObject(element, showObjectPopover.bind(this));
},

_updateHTMLId: function(properties, rootTreeElementConstructor, rootPropertyComparer)
{
for (var i = 0; i < properties.length; ++i) {
if (properties[i].name === "id") {
if (properties[i].value.description)
this._titleElement.textContent += "#" + properties[i].value.description;
break;
}
}
this._sectionUpdateProperties(properties, rootTreeElementConstructor, rootPropertyComparer);
}
}

WebInspector.ObjectPopoverHelper.prototype.__proto__ = WebInspector.PopoverHelper.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 breakpointItemId = this._createBreakpointItemId(breakpoint.uiSourceCode, breakpoint.lineNumber);
if (breakpointItemId in this._items)
return;

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 url = breakpoint.uiSourceCode.url;
var displayName = url ? WebInspector.displayNameForURL(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);
function didRequestContent(mimeType, content)
{
var lineEndings = content.lineEndings();
if (breakpoint.lineNumber < lineEndings.length)
snippetElement.textContent = content.substring(lineEndings[breakpoint.lineNumber - 1], lineEndings[breakpoint.lineNumber]);
}
breakpoint.uiSourceCode.requestContent(didRequestContent.bind(this));

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[breakpointItemId] = breakpointItem;

if (!this.expanded)
this.expanded = true;
},

removeBreakpoint: function(uiSourceCode, lineNumber)
{
var breakpointItemId = this._createBreakpointItemId(uiSourceCode, lineNumber);
var breakpointItem = this._items[breakpointItemId];
if (!breakpointItem)
return;
delete this._items[breakpointItemId];
this._removeListElement(breakpointItem.element);
},

highlightBreakpoint: function(uiSourceCode, lineNumber)
{
var breakpointItem = this._items[this._createBreakpointItemId(uiSourceCode, 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(uiSourceCode, lineNumber)
{
return uiSourceCode.id + ":" + lineNumber;
},

_breakpointClicked: function(breakpoint, event)
{
this._showSourceLineDelegate(breakpoint.uiSourceCode, breakpoint.lineNumber);
},

_breakpointCheckboxClicked: function(breakpoint, event)
{

event.stopPropagation();

this._model.setBreakpointEnabled(breakpoint.uiSourceCode, breakpoint.lineNumber, event.target.checked);
},

_contextMenu: function(breakpoint, event)
{
var contextMenu = new WebInspector.ContextMenu();

var removeHandler = this._model.removeBreakpoint.bind(this._model, breakpoint.uiSourceCode, 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();
}
}

var config = new WebInspector.EditingConfig(finishEditing.bind(this, true), finishEditing.bind(this, false));
WebInspector.startEditing(inputElement, config);
},

_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, new WebInspector.EditingConfig(finishEditing.bind(this, true), 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.set(breakpoints);
},

_restoreBreakpoints: function()
{
var breakpoints = WebInspector.settings.xhrBreakpoints.get();
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.set(breakpoints);
},

_restoreBreakpoints: function()
{
var breakpoints = WebInspector.settings.eventListenerBreakpoints.get();
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: "subtree-modified",
AttributeModified: "attribute-modified",
NodeRemoved: "node-removed"
};
this._breakpointTypeLabels = {};
this._breakpointTypeLabels[this._breakpointTypes.SubtreeModified] = WebInspector.UIString("Subtree Modified");
this._breakpointTypeLabels[this._breakpointTypes.AttributeModified] = WebInspector.UIString("Attribute Modified");
this._breakpointTypeLabels[this._breakpointTypes.NodeRemoved] = WebInspector.UIString("Node Removed");

this._contextMenuLabels = {};
this._contextMenuLabels[this._breakpointTypes.SubtreeModified] = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Break on subtree modifications" : "Break on Subtree Modifications");
this._contextMenuLabels[this._breakpointTypes.AttributeModified] = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Break on attributes modifications" : "Break on Attributes Modifications");
this._contextMenuLabels[this._breakpointTypes.NodeRemoved] = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Break on node removal" : "Break on Node Removal");

WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged, this._inspectedURLChanged, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.NodeRemoved, this._nodeRemoved, 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 key in this._breakpointTypes) {
var type = this._breakpointTypes[key];
var label = this._contextMenuLabels[type];
contextMenu.appendCheckboxItem(label, toggleBreakpoint.bind(this, type), nodeBreakpoints[type]);
}
},

createBreakpointHitStatusMessage: function(auxData, callback)
{
if (auxData.type === this._breakpointTypes.SubtreeModified) {
var targetNodeObject = WebInspector.RemoteObject.fromPayload(auxData["targetNode"]);
function didPushNodeToFrontend(targetNodeId)
{
if (targetNodeId)
targetNodeObject.release();
this._doCreateBreakpointHitStatusMessage(auxData, targetNodeId, callback);
}
targetNodeObject.pushNodeToFrontend(didPushNodeToFrontend.bind(this));
} else
this._doCreateBreakpointHitStatusMessage(auxData, null, callback);
},

_doCreateBreakpointHitStatusMessage: function (auxData, targetNodeId, callback)
{
var message;
var typeLabel = this._breakpointTypeLabels[auxData.type];
var linkifiedNode = WebInspector.DOMPresentationUtils.linkifyNodeById(auxData.nodeId);
var substitutions = [typeLabel, linkifiedNode];
var targetNode = "";
if (targetNodeId)
targetNode = WebInspector.DOMPresentationUtils.linkifyNodeById(targetNodeId);

if (auxData.type === this._breakpointTypes.SubtreeModified) {
if (auxData.insertion) {
if (targetNodeId !== auxData.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(event)
{
var node = event.data.node;
this._removeBreakpointsForNode(event.data.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.DOMPresentationUtils.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(auxData)
{
var breakpointId = this._createBreakpointId(auxData.nodeId, auxData.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.get();
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.set(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.get();
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)
{
this.bodyElement.removeChildren();

if (this.placards) {
for (var i = 0; i < this.placards.length; ++i)
this.placards[i].discard();
}
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 placard = this._model.createPlacard(callFrame);
placard.callFrame = callFrame;
placard.element.addEventListener("click", this._placardSelected.bind(this, placard), false);
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)
{
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 + "\n";
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 details = WebInspector.debuggerModel.debuggerPausedDetails;
var exception = details.reason === WebInspector.DebuggerModel.BreakReason.Exception ? details.auxData : 0;
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"));
}

WebInspector.WatchExpressionsSidebarPane.prototype = {
show: function()
{
this._visible = true;


if (this._wasShown) {
this._refreshExpressionsIfNeeded();
return;
}

this._wasShown = true;

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._requiresUpdate = true;

if (WebInspector.settings.watchExpressions.get().length > 0)
this.expanded = true;
},

hide: function()
{
this._visible = false;
},

reset: function()
{
this.refreshExpressions();
},

refreshExpressions: function()
{
this._requiresUpdate = true;
this._refreshExpressionsIfNeeded();
},

addExpression: function(expression)
{
this.section.addExpression(expression);
this.expanded = true;
},

_refreshExpressionsIfNeeded: function()
{
if (this._requiresUpdate && this._visible) {
this.section.update();
delete this._requiresUpdate;
} else
this._requiresUpdate = true;
},

_addButtonClicked: function(event)
{
event.stopPropagation();
this.expanded = true;
this.section.addNewExpressionAndEdit();
},

_refreshButtonClicked: function(event)
{
event.stopPropagation();
this.refreshExpressions();
}
}

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.get();

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)
{
if (e)
e.stopPropagation();

function appendResult(expression, watchIndex, result, wasThrown)
{
if (!result)
return;

var property = new WebInspector.RemoteObjectProperty(expression, result);
property.watchIndex = watchIndex;
property.wasThrown = wasThrown;








properties.push(property);

if (properties.length == propertyCount) {
this.updateProperties(properties, WebInspector.WatchExpressionTreeElement, WebInspector.WatchExpressionsSection.CompareProperties);



if (this._newExpressionAdded) {
delete this._newExpressionAdded;

var 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.consoleView.evalInInspectedWindow(expression, this._watchObjectGroupId, false, true, 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(expression)
{
this.watchExpressions.push(expression);
this.saveExpressions();
this.update();
},

addNewExpressionAndEdit: 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.set(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.wasThrown)
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, new WebInspector.EditingConfig(this.editingCommitted.bind(this), this.editingCancelled.bind(this), context));
},

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.linkifyURLAsNode(url, WebInspector.displayNameForURL(url), "worker-item", true, url);
this._treeOutline.appendChild(new TreeElement(title, worker, false));
},

removeWorker: function(id)
{
if (id in this._workers) {
this._treeOutline.removeChild(this._treeOutline.getCachedTreeElement(this._workers[id]));
delete this._workers[id];
}
},

_setInstrumentation: function(enabled)
{
if (!enabled === !this._fakeWorkersScriptIdentifier)
return;

if (enabled) {
this._enableWorkersCheckbox.disabled = true;
function callback(error, identifier)
{
this._fakeWorkersScriptIdentifier = identifier;
this._enableWorkersCheckbox.disabled = false;
}
PageAgent.addScriptToEvaluateOnLoad("(" + InjectedFakeWorker + ")", callback.bind(this));
} else {
PageAgent.removeScriptToEvaluateOnLoad(this._fakeWorkersScriptIdentifier);
this._fakeWorkersScriptIdentifier = null;
}
},

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.WorkerListSidebarPane = function(workerManager)
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Workers"));

this._enableWorkersCheckbox = new WebInspector.Checkbox(
WebInspector.UIString("Pause on start"),
"sidebar-label",
WebInspector.UIString("Automatically attach to new workers and pause them. Enabling this option will force opening inspector for all new workers."));
this._enableWorkersCheckbox.element.id = "pause-workers-checkbox";
this.bodyElement.appendChild(this._enableWorkersCheckbox.element);
this._enableWorkersCheckbox.addEventListener(this._autoattachToWorkersClicked.bind(this));
this._enableWorkersCheckbox.checked = false;

if (Preferences.sharedWorkersDebugNote) {
var note = this.bodyElement.createChild("div");
note.id = "shared-workers-list";
note.addStyleClass("sidebar-label")
note.textContent = Preferences.sharedWorkersDebugNote;
}

var separator = this.bodyElement.createChild("div", "sidebar-separator");
separator.textContent = WebInspector.UIString("Dedicated worker inspectors");

this._workerListElement = document.createElement("ol");
this._workerListElement.tabIndex = 0;
this._workerListElement.addStyleClass("properties-tree");
this._workerListElement.addStyleClass("sidebar-label");
this.bodyElement.appendChild(this._workerListElement);

this._idToWorkerItem = {};
this._workerManager = workerManager;

workerManager.addEventListener(WebInspector.WorkerManager.Events.WorkerAdded, this._workerAdded, this);
workerManager.addEventListener(WebInspector.WorkerManager.Events.WorkerRemoved, this._workerRemoved, this);
workerManager.addEventListener(WebInspector.WorkerManager.Events.WorkersCleared, this._workersCleared, this);
}

WebInspector.WorkerListSidebarPane.prototype = {
_workerAdded: function(event)
{
this._addWorker(event.data.workerId, event.data.url, event.data.inspectorConnected);
},

_workerRemoved: function(event)
{
var workerItem = this._idToWorkerItem[event.data];
delete this._idToWorkerItem[event.data];
workerItem.parentElement.removeChild(workerItem);
},

_workersCleared: function(event)
{
this._idToWorkerItem = {};
this._workerListElement.removeChildren();
},

_addWorker: function(workerId, url, inspectorConnected)
{
var item = this._workerListElement.createChild("div", "dedicated-worker-item");
var link = item.createChild("a");
link.textContent = url;
link.href = "#";
link.target = "_blank";
link.addEventListener("click", this._workerItemClicked.bind(this, workerId), true);
this._idToWorkerItem[workerId] = item;
},

_workerItemClicked: function(workerId, event)
{
event.preventDefault();
this._workerManager.openWorkerInspector(workerId);
},

_autoattachToWorkersClicked: function(event)
{
WorkerAgent.setAutoconnectToWorkers(event.target.checked);
}
}

WebInspector.WorkerListSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;






WebInspector.MetricsSidebarPane = function()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Metrics"));

WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetChanged, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrModified, this._attributesUpdated, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrRemoved, this._attributesUpdated, this);
}

WebInspector.MetricsSidebarPane.prototype = {

update: function(node)
{
if (node)
this.node = node;
this._innerUpdate();
},

_innerUpdate: function()
{


if (this._isEditingMetrics)
return;


var node = this.node;

if (!node || node.nodeType() !== Node.ELEMENT_NODE) {
this.bodyElement.removeChildren();
return;
}

function callback(style)
{
if (!style || this.node !== node)
return;
this._updateMetrics(style);
}
WebInspector.cssModel.getComputedStyleAsync(node.id, WebInspector.panels.elements.sidebarPanes.styles.forcedPseudoClasses, callback.bind(this));

function inlineStyleCallback(style)
{
if (!style || this.node !== node)
return;
this.inlineStyle = style;
}
WebInspector.cssModel.getInlineStylesAsync(node.id, inlineStyleCallback.bind(this));
},

_styleSheetChanged: function()
{
this._innerUpdate();
},

_attributesUpdated: function(event)
{
if (this.node !== event.data.node)
return;

this._innerUpdate();
},

_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)
{
event.stopPropagation();
var nodeId = showHighlight && this.node ? this.node.id : 0;
if (nodeId) {
if (this._highlightMode === mode)
return;
this._highlightMode = mode;
WebInspector.domAgent.highlightDOMNode(nodeId, mode);
} else {
delete this._highlightMode;
WebInspector.domAgent.hideDOMNodeHighlight();
}

for (var i = 0; this._boxElements && i < this._boxElements.length; ++i) {
var element = this._boxElements[i];
if (!nodeId || mode === "all" || element._name === mode)
element.style.backgroundColor = element._backgroundColor;
else
element.style.backgroundColor = "";
}
},

_updateMetrics: 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 boxColors = [
WebInspector.Color.PageHighlight.Content,
WebInspector.Color.PageHighlight.Padding,
WebInspector.Color.PageHighlight.Border,
WebInspector.Color.PageHighlight.Margin,
WebInspector.Color.fromRGBA(0, 0, 0, 0)
];
var boxLabels = [WebInspector.UIString("content"), WebInspector.UIString("padding"), WebInspector.UIString("border"), WebInspector.UIString("margin"), WebInspector.UIString("position")];
var previousBox = null;
this._boxElements = [];
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._backgroundColor = boxColors[i].toString("original");
boxElement._name = name;
boxElement.style.backgroundColor = boxElement._backgroundColor;
boxElement.addEventListener("mouseover", this._highlightDOMNode.bind(this, true, name === "position" ? "all" : name), false);
this._boxElements.push(boxElement);

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, false, ""), false);
this.bodyElement.removeChildren();
this.bodyElement.appendChild(metricsElement);
},

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);

this._isEditingMetrics = true;

var config = new WebInspector.EditingConfig(this.editingCommitted.bind(this), this.editingCancelled.bind(this), context);
WebInspector.startEditing(targetElement, config);

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) {
var prefix = matches[1];
var suffix = matches[3];
var 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);
delete this._isEditingMetrics;
},

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) {

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, true);
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 (typeof self._highlightMode !== "undefined") {
WebInspector.domAgent.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._objectGroupName = "properties-sidebar-pane";

WebInspector.PropertiesSidebarPane.prototype = {
update: function(node)
{
var body = this.bodyElement;

if (!node) {
body.removeChildren();
this.sections = [];
return;
}

WebInspector.RemoteObject.resolveNode(node, WebInspector.PropertiesSidebarPane._objectGroupName, nodeResolved.bind(this));

function nodeResolved(object)
{
if (!object)
return;
function protoList()
{
var proto = this;
var result = {};
var counter = 1;
while (proto) {
result[counter++] = proto;
proto = proto.__proto__;
}
return result;
}
object.callFunction(protoList, nodePrototypesReady.bind(this));
object.release();
}

function nodePrototypesReady(object)
{
if (!object)
return;
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, 10))
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");
this.settingsSelectElement.className = "select-filter";

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.get();
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);

this._linkifier = WebInspector.debuggerPresentationModel.createLinkifier();
}

WebInspector.EventListenersSidebarPane._objectGroupName = "event-listeners-sidebar-pane";

WebInspector.EventListenersSidebarPane.prototype = {
update: function(node)
{
RuntimeAgent.releaseObjectGroup(WebInspector.EventListenersSidebarPane._objectGroupName);
this._linkifier.reset();

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.handlerBody.toString()))
continue; 
var type = eventListener.type;
var section = sectionMap[type];
if (!section) {
section = new WebInspector.EventListenersSection(type, node.id, self._linkifier);
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.set(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, linkifier)
{
this.eventListeners = [];
this._nodeId = nodeId;
this._linkifier = linkifier;
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.get() == "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._linkifier);
this.eventBars.appendChild(eventListenerBar.element);
}
},

addListener: function(eventListener)
{
this.eventListeners.push(eventListener);
}
}

WebInspector.EventListenersSection.prototype.__proto__ = WebInspector.PropertiesSection.prototype;


WebInspector.EventListenerBar = function(eventListener, nodeId, linkifier)
{
WebInspector.ObjectPropertiesSection.call(this);

this.eventListener = eventListener;
this._nodeId = nodeId;
this._setNodeTitle();
this._setFunctionSubtitle(linkifier);
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 (this.eventListener.type)
properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("type", this.eventListener.type));
if (typeof this.eventListener.useCapture !== "undefined")
properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("useCapture", this.eventListener.useCapture));
if (typeof this.eventListener.isAttribute !== "undefined")
properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("isAttribute", this.eventListener.isAttribute));
if (nodeObject)
properties.push(new WebInspector.RemoteObjectProperty("node", nodeObject));
if (typeof this.eventListener.handlerBody !== "undefined")
properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("listenerBody", this.eventListener.handlerBody));
if (this.eventListener.location) {
properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("sourceName", this.eventListener.location.scriptId));
properties.push(WebInspector.RemoteObjectProperty.fromPrimitiveValue("lineNumber", this.eventListener.location.lineNumber));
}

this.updateProperties(properties);
}
WebInspector.RemoteObject.resolveNode(this.eventListener.node, WebInspector.EventListenersSidebarPane._objectGroupName, 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.DOMPresentationUtils.linkifyNodeReference(this.eventListener.node));
},

_setFunctionSubtitle: function(linkifier)
{

if (this.eventListener.location) {
this.subtitleElement.removeChildren();

var url = this.eventListener.location.scriptId;
var lineNumber = this.eventListener.location.lineNumber - 1;
var columnNumber = 0;
var urlElement = linkifier.linkifyLocation(url, lineNumber, columnNumber);
this.subtitleElement.appendChild(urlElement);
} else {
var match = this.eventListener.handlerBody.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.fromRGBA = function(r, g, b, a)
{
return new WebInspector.Color("rgba(" + r + "," + g + "," + b + "," + (typeof a === "undefined" ? 1 : a) + ")");
}

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";
},

toProtocolRGBA: function()
{
if (this._protocolRGBA)
return this._protocolRGBA;

var components = this.rgba;
if (components)
this._protocolRGBA = { r: Number(components[0]), g: Number(components[1]), b: Number(components[2]), a: Number(components[3]) };
else {
components = this.rgb;
this._protocolRGBA = { r: Number(components[0]), g: Number(components[1]), b: Number(components[2]) };
}
return this._protocolRGBA;
},

_clamp: function(value, min, max)
{
if (value < min)
return min;
if (value > max)
return max;
return value;
},

_individualRGBValueToFloatValue: function(rgbValue)
{
if (typeof rgbValue === "number")
return this._clamp(rgbValue, 0, 255);

if (rgbValue.indexOf("%") === -1) {
var intValue = parseInt(rgbValue, 10);
return this._clamp(rgbValue, 0, 255);
}

var percentValue = parseFloat(rgbValue);
return this._clamp(percentValue, 0, 100) * 2.55;
},

_individualRGBValueToHexValue: function(rgbValue)
{
var floatValue = this._individualRGBValueToFloatValue(rgbValue);
var hex = Math.round(floatValue).toString(16);
if (hex.length === 1)
hex = "0" + hex;
return hex;
},

_rgbToHex: function(rgb)
{
var r = this._individualRGBValueToHexValue(rgb[0]);
var g = this._individualRGBValueToHexValue(rgb[1]);
var b = this._individualRGBValueToHexValue(rgb[2]);
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 = this._individualRGBValueToFloatValue(rgb[0]) / 255;
var g = this._individualRGBValueToFloatValue(rgb[1]) / 255;
var b = this._individualRGBValueToFloatValue(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 (s < 0)
s = 0;

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, alpha)
{
var hsl = this._rgbToHSL(rgba)
hsl.push(alpha);
return hsl;
},

_hslaToRGBA: function(hsla, alpha)
{
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.rgba[3] = this.alpha = this._clamp(this.rgba[3], 0, 1);
this.hsla = this._rgbaToHSLA(this.rgba, this.alpha);
} else if (match[2]) { 
this.format = "hsla";
this.hsla = match[2].replace(/%/g, "").split(/\s*,\s*/);
this.hsla[3] = this.alpha = this._clamp(this.hsla[3], 0, 1);
this.rgba = this._hslaToRGBA(this.hsla, this.alpha);
}

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.Color.PageHighlight = {
Content: WebInspector.Color.fromRGBA(111, 168, 220, .66),
ContentLight: WebInspector.Color.fromRGBA(111, 168, 220, .5),
ContentOutline: WebInspector.Color.fromRGBA(9, 83, 148),
Padding: WebInspector.Color.fromRGBA(147, 196, 125, .55),
PaddingLight: WebInspector.Color.fromRGBA(147, 196, 125, .4),
Border: WebInspector.Color.fromRGBA(255, 229, 153, .66),
BorderLight: WebInspector.Color.fromRGBA(255, 229, 153, .5),
Margin: WebInspector.Color.fromRGBA(246, 178, 107, .66),
MarginLight: WebInspector.Color.fromRGBA(246, 178, 107, .5)
}






WebInspector.CSSCompletions = function(values, acceptEmptyPrefix)
{
this._values = values.slice();
this._values.sort();
this._acceptEmptyPrefix = acceptEmptyPrefix;
}



WebInspector.CSSCompletions.cssNameCompletions = null;

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

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()
{
if (!this._keySet)
this._keySet = this._values.keySet();
return this._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 = {}

WebInspector.CSSKeywordCompletions.forProperty = function(propertyName)
{
var acceptedKeywords = ["initial"];
if (propertyName in WebInspector.CSSKeywordCompletions._propertyKeywordMap)
acceptedKeywords = acceptedKeywords.concat(WebInspector.CSSKeywordCompletions._propertyKeywordMap[propertyName]);
if (propertyName in WebInspector.CSSKeywordCompletions._colorAwareProperties)
acceptedKeywords = acceptedKeywords.concat(WebInspector.CSSKeywordCompletions._colors);
if (propertyName in WebInspector.CSSKeywordCompletions.InheritedProperties)
acceptedKeywords.push("inherit");
return new WebInspector.CSSCompletions(acceptedKeywords, true);
}

WebInspector.CSSKeywordCompletions.isColorAwareProperty = function(propertyName)
{
return WebInspector.CSSKeywordCompletions._colorAwareProperties[propertyName] === true;
}


WebInspector.CSSKeywordCompletions.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.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", "background-image", "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", "-webkit-pictograph"
],
"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", "-webkit-pictograph"
],
"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");
this.settingsSelectElement.className = "select-settings";

var option = document.createElement("option");
option.value = WebInspector.StylesSidebarPane.ColorFormat.Original;
option.label = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "As authored" : "As Authored");
this.settingsSelectElement.appendChild(option);

option = document.createElement("option");
option.value = WebInspector.StylesSidebarPane.ColorFormat.HEX;
option.label = WebInspector.UIString("Hex Colors");
this.settingsSelectElement.appendChild(option);

option = document.createElement("option");
option.value = WebInspector.StylesSidebarPane.ColorFormat.RGB;
option.label = WebInspector.UIString("RGB Colors");
this.settingsSelectElement.appendChild(option);

option = document.createElement("option");
option.value = WebInspector.StylesSidebarPane.ColorFormat.HSL;
option.label = WebInspector.UIString("HSL Colors");
this.settingsSelectElement.appendChild(option);


var muteEventListener = function(event) { event.stopPropagation(); event.preventDefault(); };

this.settingsSelectElement.addEventListener("click", muteEventListener, true);
this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false);
this._updateColorFormatFilter();

this.titleElement.appendChild(this.settingsSelectElement);

this._elementStateButton = document.createElement("button");
this._elementStateButton.className = "pane-title-button element-state";
this._elementStateButton.title = WebInspector.UIString("Toggle Element State");
this._elementStateButton.addEventListener("click", this._toggleElementStatePane.bind(this), false);
this.titleElement.appendChild(this._elementStateButton);

var addButton = document.createElement("button");
addButton.className = "pane-title-button add";
addButton.id = "add-style-button-test-id";
addButton.title = WebInspector.UIString("New Style Rule");
addButton.addEventListener("click", this._createNewRule.bind(this), false);
this.titleElement.appendChild(addButton);

this._computedStylePane = computedStylePane;
this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true);
WebInspector.settings.colorFormat.addChangeListener(this._colorFormatSettingChanged.bind(this));

this._createElementStatePane();
this.bodyElement.appendChild(this._elementStatePane);
this._sectionsContainer = document.createElement("div");
this.bodyElement.appendChild(this._sectionsContainer);

WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetChanged, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrModified, this._attributesModified, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.AttrRemoved, this._attributesRemoved, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.StyleInvalidated, this._styleInvalidated, this);
WebInspector.settings.showUserAgentStyles.addChangeListener(this._showUserAgentStylesSettingChanged.bind(this));
}

WebInspector.StylesSidebarPane.ColorFormat = {
Original: "original",
Nickname: "nickname",
HEX: "hex",
ShortHEX: "shorthex",
RGB: "rgb",
RGBA: "rgba",
HSL: "hsl",
HSLA: "hsla"
}

WebInspector.StylesSidebarPane.StyleValueDelimiters = " \xA0\t\n\"':;,/()";






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 changeAmount = 1;
if (event.shiftKey && !arrowKeyPressed)
changeAmount = 100;
else if (event.shiftKey || !arrowKeyPressed)
changeAmount = 10;
else if (event.altKey)
changeAmount = 0.1;

if (event.keyIdentifier === "Down" || event.keyIdentifier === "PageDown")
changeAmount *= -1;



var 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 contextMenu = new WebInspector.ContextMenu();
if (WebInspector.populateHrefContextMenu(contextMenu, this.node, event))
contextMenu.show(event);
},

get forcedPseudoClasses()
{
return this._forcedPseudoClasses;
},

update: function(node, forceUpdate)
{
var refresh = false;

if (forceUpdate)
delete this.node;

if (!forceUpdate && (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;

this._innerUpdate(refresh);
},

_executeRebuildUpdate: function(node, callback)
{
var resultStyles = {};

function stylesCallback(matchedResult)
{
if (matchedResult) {
resultStyles.matchedCSSRules = matchedResult.matchedCSSRules;
resultStyles.pseudoElements = matchedResult.pseudoElements;
resultStyles.inherited = matchedResult.inherited;
this._rebuildUpdate(node, resultStyles);
}
if (callback)
callback();
}

function inlineCallback(inlineStyle, styleAttributes)
{
resultStyles.inlineStyle = inlineStyle;
resultStyles.styleAttributes = styleAttributes;
}

function computedCallback(computedStyle)
{
resultStyles.computedStyle = computedStyle;
}

WebInspector.cssModel.getComputedStyleAsync(node.id, this._forcedPseudoClasses, computedCallback.bind(this));
WebInspector.cssModel.getInlineStylesAsync(node.id, inlineCallback.bind(this));
WebInspector.cssModel.getMatchedStylesAsync(node.id, this._forcedPseudoClasses, true, true, stylesCallback.bind(this));
},


_innerUpdate: function(refresh, editedSection, userCallback)
{
var node = this.node;
if (!node) {
this._sectionsContainer.removeChildren();
this._computedStylePane.bodyElement.removeChildren();
this.sections = {};
if (userCallback)
userCallback();
return;
}

function computedStyleCallback(computedStyle)
{
if (this.node === node && computedStyle)
this._refreshUpdate(node, computedStyle, editedSection);
if (userCallback)
userCallback();
}

if (refresh)
WebInspector.cssModel.getComputedStyleAsync(node.id, this._forcedPseudoClasses, computedStyleCallback.bind(this));
else
this._executeRebuildUpdate(node, userCallback);
},

_styleSheetChanged: function()
{
if (this._userOperation || this._isEditingStyle)
return;

this._innerUpdate(false);
},

_attributesModified: function(event)
{
if (this.node !== event.data.node)
return;


if (event.data.name === "style")
return;


if (!this._isEditingStyle && !this._userOperation)
this._innerUpdate(false);
},

_attributesRemoved: function(event)
{
if (this.node !== event.data.node)
return;


if (!this._isEditingStyle && !this._userOperation)
this._innerUpdate(false);
},

_styleInvalidated: function(event)
{
if (this.node !== event.data)
return;

if (!this._isEditingStyle && !this._userOperation)
this._innerUpdate(false);
},

_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]);

this._nodeStylesUpdatedForTest(node, true);
},

_rebuildUpdate: function(node, styles)
{
this._sectionsContainer.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, null);
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, media: rule.media, 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);
}

this._nodeStylesUpdatedForTest(node, false);
},

_nodeStylesUpdatedForTest: function(node, refresh)
{

},

_refreshStyleRules: function(sections, computedStyle)
{
var nodeComputedStyle = computedStyle;
var styleRules = [];
for (var i = 0; sections && i < sections.length; ++i) {
var section = sections[i];
if (section.isBlank)
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 = [];

function addStyleAttributes()
{
for (var name in styles.styleAttributes) {
var attrStyle = { style: styles.styleAttributes[name], editable: false };
attrStyle.selectorText = node.nodeNameInCorrectCase() + "[" + name;
if (node.getAttribute(name))
attrStyle.selectorText += "=" + node.getAttribute(name);
attrStyle.selectorText += "]";
styleRules.push(attrStyle);
}
}

styleRules.push({ computedStyle: true, selectorText: "", style: nodeComputedStyle, editable: false });


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") });
var addedStyleAttributes;
for (var i = styles.matchedCSSRules.length - 1; i >= 0; --i) {
var rule = styles.matchedCSSRules[i];
if (!WebInspector.settings.showUserAgentStyles.get() && (rule.isUser || rule.isUserAgent))
continue;
if ((rule.isUser || rule.isUserAgent) && !addedStyleAttributes) {

addedStyleAttributes = true;
addStyleAttributes();
}
styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, sourceURL: rule.sourceURL, rule: rule, editable: !!(rule.style && rule.style.id) });
}

if (!addedStyleAttributes)
addStyleAttributes();


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 (!WebInspector.settings.showUserAgentStyles.get() && (rule.isUser || rule.isUserAgent))
continue;

if (!separatorInserted) {
insertInheritedNodeSeparator(parentNode);
separatorInserted = true;
}
styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, 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;
}



for (var name in styleRules[i].usedProperties)
usedProperties[name] = true;
}

if (priorityUsed) {

var foundPriorityProperties = [];



for (var i = 0; i < styleRules.length; ++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 = "sidebar-separator";
if (styleRule.node) {
var link = WebInspector.DOMPresentationUtils.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._sectionsContainer.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);
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._sectionsContainer.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.CSSKeywordCompletions.InheritedProperties)
return true;
}
return false;
},

_colorFormatSettingChanged: function(event)
{
this._updateColorFormatFilter();
for (var pseudoId in this.sections) {
var sections = this.sections[pseudoId];
for (var i = 0; i < sections.length; ++i)
sections[i].update(true);
}
},

_updateColorFormatFilter: function()
{

var selectedIndex = 0;
var value = WebInspector.settings.colorFormat.get();
var options = this.settingsSelectElement.options;
for (var i = 0; i < options.length; ++i) {
if (options[i].value === value) {
selectedIndex = i;
break;
}
}
this.settingsSelectElement.selectedIndex = selectedIndex;
},

_changeSetting: function(event)
{
var options = this.settingsSelectElement.options;
var selectedOption = options[this.settingsSelectElement.selectedIndex];
WebInspector.settings.colorFormat.set(selectedOption.value);
},

_createNewRule: function(event)
{
event.stopPropagation();
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._sectionsContainer.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.shortcutsScreen.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));
},

_toggleElementStatePane: function(event)
{
event.stopPropagation();
if (!this._elementStateButton.hasStyleClass("toggled")) {
this.expand();
this._elementStateButton.addStyleClass("toggled");
this._elementStatePane.addStyleClass("expanded");
} else {
this._elementStateButton.removeStyleClass("toggled");
this._elementStatePane.removeStyleClass("expanded");

if (this._forcedPseudoClasses) {
for (var i = 0; i < this._elementStatePane.inputs.length; ++i)
this._elementStatePane.inputs[i].checked = false;
delete this._forcedPseudoClasses;
this._innerUpdate(false);
}
}
},

_createElementStatePane: function()
{
this._elementStatePane = document.createElement("div");
this._elementStatePane.className = "styles-element-state-pane source-code";
var table = document.createElement("table");

var inputs = [];
this._elementStatePane.inputs = inputs;

function clickListener(event)
{
var pseudoClasses = [];
for (var i = 0; i < inputs.length; ++i) {
if (inputs[i].checked)
pseudoClasses.push(inputs[i].state);
}
this._forcedPseudoClasses = pseudoClasses.length ? pseudoClasses : undefined;
this._innerUpdate(false);
}

function createCheckbox(state)
{
var td = document.createElement("td");
var label = document.createElement("label");
var input = document.createElement("input");
input.type = "checkbox";
input.state = state;
input.addEventListener("click", clickListener.bind(this), false);
inputs.push(input);
label.appendChild(input);
label.appendChild(document.createTextNode(":" + state));
td.appendChild(label);
return td;
}

var tr = document.createElement("tr");
tr.appendChild(createCheckbox.call(this, "active"));
tr.appendChild(createCheckbox.call(this, "hover"));
table.appendChild(tr);

tr = document.createElement("tr");
tr.appendChild(createCheckbox.call(this, "focus"));
tr.appendChild(createCheckbox.call(this, "visited"));
table.appendChild(tr);

this._elementStatePane.appendChild(table);
},

_showUserAgentStylesSettingChanged: function()
{
this._innerUpdate(false);
}
}

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.get()) {
this.bodyElement.addStyleClass("show-inherited");
showInheritedCheckbox.checked = true;
}

function showInheritedToggleFunction(event)
{
WebInspector.settings.showInheritedComputedStyleProperties.set(showInheritedCheckbox.checked);
if (WebInspector.settings.showInheritedComputedStyleProperties.get())
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" : "");

if (styleRule.media) {
for (var i = styleRule.media.length - 1; i >= 0; --i) {
var media = styleRule.media[i];
var mediaDataElement = this.titleElement.createChild("div", "media");
var mediaText;
switch (media.source) {
case WebInspector.CSSMedia.Source.LINKED_SHEET:
case WebInspector.CSSMedia.Source.INLINE_SHEET:
mediaText = "media=\"" + media.text + "\"";
break;
case WebInspector.CSSMedia.Source.MEDIA_RULE:
mediaText = "@media " + media.text;
break;
case WebInspector.CSSMedia.Source.IMPORT_RULE:
mediaText = "@import " + media.text;
break;
}

if (media.sourceURL) {
var refElement = mediaDataElement.createChild("div", "subtitle");
var anchor = WebInspector.linkifyResourceAsNode(media.sourceURL, media.sourceLine < 0 ? undefined : media.sourceLine, "subtitle");
anchor.style.float = "right";
refElement.appendChild(anchor);
}

var mediaTextElement = mediaDataElement.createChild("span");
mediaTextElement.textContent = mediaText;
mediaTextElement.title = media.text;
}
}

var selectorContainer = document.createElement("div");
this._selectorElement = document.createElement("span");
this._selectorElement.textContent = styleRule.selectorText;
selectorContainer.appendChild(this._selectorElement);

var openBrace = document.createElement("span");
openBrace.textContent = " {";
selectorContainer.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;

if (this.rule) {

if (this.rule.isUserAgent || this.rule.isUser)
this.editable = false;
this.titleElement.addStyleClass("styles-selector");
}

this._usedProperties = styleRule.usedProperties;

this._selectorRefElement = document.createElement("div");
this._selectorRefElement.className = "subtitle";
this._selectorRefElement.appendChild(this._createRuleOriginNode());
selectorContainer.insertBefore(this._selectorRefElement, selectorContainer.firstChild);
this.titleElement.appendChild(selectorContainer);

if (isInherited)
this.element.addStyleClass("show-inherited"); 

if (!this.editable)
this.element.addStyleClass("read-only");
}

WebInspector.StylePropertiesSection.prototype = {
collapse: function(dontRememberState)
{

},

isPropertyInherited: function(propertyName)
{
if (this.isInherited) {


return !(propertyName in WebInspector.CSSKeywordCompletions.InheritedProperties);
}
return false;
},

isPropertyOverloaded: function(propertyName, shorthand)
{
if (!this._usedProperties || this.noAffect)
return false;

if (this.isInherited && !(propertyName in WebInspector.CSSKeywordCompletions.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);

if (!curSection) {
curSection = this.firstSibling;
while (curSection && !curSection.editable)
curSection = curSection.nextSibling;
}

return (curSection && curSection.editable) ? curSection : null;
},

previousEditableSibling: function()
{
var curSection = this;
do {
curSection = curSection.previousSibling;
} while (curSection && !curSection.editable);

if (!curSection) {
curSection = this.lastSibling;
while (curSection && !curSection.editable)
curSection = curSection.previousSibling;
}

return (curSection && curSection.editable) ? curSection : null;
},

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, "", undefined);
}


if (!shorthand && this.editable && property.styleBased)
continue;

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;
},

_createRuleOriginNode: function()
{
function linkifyUncopyable(url, line)
{
var link = WebInspector.linkifyResourceAsNode(url, line);
link.classList.add("webkit-html-resource-link");
link.setAttribute("data-uncopyable", link.textContent);
link.textContent = "";
return link;
}

if (this.styleRule.sourceURL)
return linkifyUncopyable(this.styleRule.sourceURL, this.rule.sourceLine);
if (!this.rule)
return document.createTextNode("");

var origin = "";
if (this.rule.isUserAgent)
origin = WebInspector.UIString("user agent stylesheet");
else if (this.rule.isUser)
origin = WebInspector.UIString("user stylesheet");
else if (this.rule.isViaInspector)
origin = WebInspector.UIString("via inspector");
return document.createTextNode(origin);
},

_handleEmptySpaceDoubleClick: function(event)
{
if (event.target.hasStyleClass("header") || this.element.hasStyleClass("read-only") || event.target.enclosingNodeOrSelfWithClass("media")) {
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;

this._selectorElement.scrollIntoViewIfNeeded(false);

var config = new WebInspector.EditingConfig(this.editingSelectorCommitted.bind(this), this.editingSelectorCancelled.bind(this));
WebInspector.startEditing(this._selectorElement, config);

window.getSelection().setBaseAndExtent(element, 0, element, 1);
},

_moveEditorFromSelector: function(moveDirection)
{
if (!moveDirection)
return;

if (moveDirection === "forward") {
this.expand();
var firstChild = this.propertiesTreeOutline.children[0];
if (!firstChild)
this.addNewBlankProperty().startEditing();
else
firstChild.startEditing(firstChild.nameElement);
} else {
var previousSection = this.previousEditableSibling();
if (!previousSection)
return;

previousSection.expand();
previousSection.addNewBlankProperty().startEditing();
}
},

editingSelectorCommitted: function(element, newContent, oldContent, context, moveDirection)
{
if (newContent === oldContent)
return this._moveEditorFromSelector(moveDirection);

function successCallback(newRule, doesAffectSelectedNode)
{
if (!doesAffectSelectedNode) {
this.noAffect = true;
this.element.addStyleClass("no-affect");
} else {
delete this.noAffect;
this.element.removeStyleClass("no-affect");
}

this.rule = newRule;
this.styleRule = { section: this, style: newRule.style, selectorText: newRule.selectorText, media: newRule.media, sourceURL: newRule.sourceURL, rule: newRule };

this.pane.update();

this._moveEditorFromSelector(moveDirection);
}

var selectedNode = WebInspector.panels.elements.selectedDOMNode();
WebInspector.cssModel.setRuleSelector(this.rule.id, selectedNode ? selectedNode.id : 0, newContent, successCallback.bind(this), this._moveEditorFromSelector.bind(this, moveDirection));
},

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(null, 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.isBlank)
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.CSSKeywordCompletions.InheritedProperties))
continue;

var treeElement = this._propertyTreeElements[property.name];
if (treeElement) {
var fragment = document.createDocumentFragment();
var selector = fragment.createChild("span");
selector.style.color = "gray";
selector.textContent = section.styleRule.selectorText;
fragment.appendChild(document.createTextNode(" - " + property.value + " "));
var subtitle = fragment.createChild("span");
subtitle.style.float = "right";
subtitle.appendChild(section._createRuleOriginNode());
var childElement = new TreeElement(fragment, null, false);
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 = {
get isBlank()
{
return !this._normal;
},

expand: function()
{
if (!this.isBlank)
WebInspector.StylePropertiesSection.prototype.expand.call(this);
},

editingSelectorCommitted: function(element, newContent, oldContent, context, moveDirection)
{
if (!this.isBlank) {
WebInspector.StylePropertiesSection.prototype.editingSelectorCommitted.call(this, element, newContent, oldContent, context, moveDirection);
return;
}

function successCallback(newRule, doesSelectorAffectSelectedNode)
{
var styleRule = { section: this, style: newRule.style, selectorText: newRule.selectorText, sourceURL: newRule.sourceURL, rule: newRule };
this.makeNormal(styleRule);

if (!doesSelectorAffectSelectedNode) {
this.noAffect = true;
this.element.addStyleClass("no-affect");
}

this._selectorRefElement.textContent = WebInspector.UIString("via inspector");
this.expand();
if (this.element.parentElement) 
this._moveEditorFromSelector(moveDirection);
}

WebInspector.cssModel.addRule(this.pane.node.id, newContent, successCallback.bind(this), this.editingSelectorCancelled.bind(this));
},

editingSelectorCancelled: function()
{
if (!this.isBlank) {
WebInspector.StylePropertiesSection.prototype.editingSelectorCancelled.call(this);
return;
}

this.pane.removeSection(this);
},

makeNormal: function(styleRule)
{
this.element.removeStyleClass("blank-section");
this.styleRule = styleRule;
this.rule = styleRule.rule;


this._normal = true;
}
}

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;

var cf = WebInspector.StylesSidebarPane.ColorFormat;

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.selectedDOMNode())
hrefUrl = WebInspector.resourceURLForRelatedNode(WebInspector.panels.elements.selectedDOMNode(), hrefUrl);
var hasResource = !!WebInspector.resourceForURL(hrefUrl);

container.appendChild(WebInspector.linkifyURLAsNode(hrefUrl, url, undefined, !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;
var formatSetting = WebInspector.settings.colorFormat.get();
if (formatSetting === cf.Original)
format = cf.Original;
else if (color.nickname)
format = cf.Nickname;
else if (formatSetting === cf.RGB)
format = (color.simple ? cf.RGB : cf.RGBA);
else if (formatSetting === cf.HSL)
format = (color.simple ? cf.HSL : cf.HSLA);
else if (color.simple)
format = (color.hasShortHex() ? cf.ShortHEX : cf.HEX);
else
format = cf.RGBA;

var colorValueElement = document.createElement("span");
colorValueElement.textContent = color.toString(format);

function nextFormat(curFormat)
{








switch (curFormat) {
case cf.Original:
return color.simple ? cf.RGB : cf.RGBA;

case cf.RGB:
case cf.RGBA:
return color.simple ? cf.HSL : cf.HSLA;

case cf.HSL:
case cf.HSLA:
if (color.nickname)
return cf.Nickname;
if (color.simple)
return color.hasShortHex() ? cf.ShortHEX : cf.HEX;
else
return cf.Original;

case cf.ShortHEX:
return cf.HEX;

case cf.HEX:
return cf.Original;

case cf.Nickname:
if (color.simple)
return color.hasShortHex() ? cf.ShortHEX : cf.HEX;
else
return cf.Original;

default:
return null;
}
}

function changeColorDisplay(event)
{
do {
format = nextFormat(format);
var currentValue = color.toString(format || "");
} while (format && currentValue === color.value && format !== cf.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");


var exclamationElement = document.createElement("img");
exclamationElement.className = "exclamation-mark";
exclamationElement.title = WebInspector.CSSCompletions.cssNameCompletions.keySet()[this.property.name.toLowerCase()] ? WebInspector.UIString("Invalid property value.") : WebInspector.UIString("Unknown property name.");
this.listItemElement.insertBefore(exclamationElement, this.listItemElement.firstChild);
}
if (this.property.inactive)
this.listItemElement.addStyleClass("inactive");

this.tooltip = this.property.propertyText;
},

_updatePane: function(userCallback)
{
if (this.treeOutline && this.treeOutline.section && this.treeOutline.section.pane)
this.treeOutline.section.pane._innerUpdate(true, this.treeOutline.section, userCallback);
else  {
if (userCallback)
userCallback();
}
},

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._updatePane();

delete this._parentPane._userOperation;
}

this._parentPane._userOperation = 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,
isEditingName: isEditingName,
previousContent: selectElement.textContent
};


this.hasChildren = false;

if (selectElement.parentElement)
selectElement.parentElement.addStyleClass("child-editing");
selectElement.textContent = selectElement.textContent; 

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();

this.editingCommitted(null, event.target.textContent, context.previousContent, context, "forward");
}

function blurListener(context, event)
{
this.editingCommitted(null, event.target.textContent, context.previousContent, context, "");
}

delete this.originalPropertyText;

this._parentPane._isEditingStyle = true;
if (selectElement.parentElement)
selectElement.parentElement.scrollIntoViewIfNeeded(false);

var applyItemCallback = !isEditingName ? this._applyFreeFlowStyleTextEdit.bind(this, true) : undefined;
this._prompt = new WebInspector.StylesSidebarPane.CSSPropertyPrompt(isEditingName ? WebInspector.CSSCompletions.cssNameCompletions : WebInspector.CSSKeywordCompletions.forProperty(this.nameElement.textContent), this, isEditingName);
if (applyItemCallback) {
this._prompt.addEventListener(WebInspector.TextPrompt.Events.ItemApplied, applyItemCallback, this);
this._prompt.addEventListener(WebInspector.TextPrompt.Events.ItemAccepted, applyItemCallback, this);
}
var proxyElement = this._prompt.attachAndStartEditing(selectElement, blurListener.bind(this, context));

proxyElement.addEventListener("keydown", this.editingNameValueKeyDown.bind(this, context), false);
if (isEditingName)
proxyElement.addEventListener("paste", pasteHandler.bind(this, context));

window.getSelection().setBaseAndExtent(selectElement, 0, selectElement, 1);
},

editingNameValueKeyDown: function(context, event)
{
if (event.handled)
return;

var isEditingName = context.isEditingName;
var result;

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;
}


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();
result = "forward";
} else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code || event.keyIdentifier === "U+001B")
result = "cancel";
else if (!isEditingName && this._newProperty && event.keyCode === WebInspector.KeyboardShortcut.Keys.Backspace.code) {

var selection = window.getSelection();
if (selection.isCollapsed && !selection.focusOffset) {
event.preventDefault();
result = "backward";
}
} else if (event.keyIdentifier === "U+0009") { 
result = event.shiftKey ? "backward" : "forward";
event.preventDefault();
}

if (result) {
switch (result) {
case "cancel":
this.editingCancelled(null, context);
break;
case "forward":
case "backward":
this.editingCommitted(null, event.target.textContent, context.previousContent, context, result);
break;
}

event.stopPropagation();
return;
}

if (!isEditingName)
this._applyFreeFlowStyleTextEdit(false);
},

_applyFreeFlowStyleTextEdit: function(now)
{
if (this._applyFreeFlowStyleTextEditTimer)
clearTimeout(this._applyFreeFlowStyleTextEditTimer);

function apply()
{
this.applyStyleText(this.nameElement.textContent + ": " + this.valueElement.textContent, false, false, false);
}
if (now)
apply.call(this);
else
this._applyFreeFlowStyleTextEditTimer = setTimeout(apply.bind(this), 100);
},

kickFreeFlowStyleEditForTest: function()
{
this._applyFreeFlowStyleTextEdit(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 (editedElement.parentElement)
editedElement.parentElement.removeStyleClass("child-editing");

delete this._parentPane._isEditingStyle;
},

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")
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) {
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, false);
} 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)
{
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) {
if (sectionToEdit.rule)
sectionToEdit.startEditingSelector();
else
sectionToEdit._moveEditorFromSelector(moveDirection);
}
return;
}

if (moveToSelector) {
if (section.rule)
section.startEditingSelector();
else
section._moveEditorFromSelector(moveDirection);
}
}
},

_removePrompt: function()
{

if (this._prompt) {
this._prompt.detach();
delete this._prompt;
}
},

_hasBeenModifiedIncrementally: function()
{


return typeof this.originalPropertyText === "string" || (!!this.property.propertyText && this._newProperty);
},

applyStyleText: function(styleText, updateInterface, majorChange, isRevert)
{
function userOperationFinishedCallback(parentPane, updateInterface)
{
if (updateInterface)
delete parentPane._userOperation;
}


if (!isRevert && !updateInterface && !this._hasBeenModifiedIncrementally()) {


this.originalPropertyText = this.property.propertyText;
}

if (!this.treeOutline)
return;

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;
}

var currentNode = this._parentPane.node;
if (updateInterface)
this._parentPane._userOperation = true;

function callback(userCallback, originalPropertyText, newStyle)
{
if (!newStyle) {
if (updateInterface) {

this._revertStyleUponEditingCanceled(originalPropertyText);
}
userCallback();
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 && currentNode === section.pane.node) {
this._updatePane(userCallback);
return;
}

userCallback();
}



if (styleText.length && !/;\s*$/.test(styleText))
styleText += ";";
this.property.setText(styleText, majorChange, callback.bind(this, userOperationFinishedCallback.bind(null, this._parentPane, updateInterface), this.originalPropertyText));
}
}

WebInspector.StylePropertyTreeElement.prototype.__proto__ = TreeElement.prototype;


WebInspector.StylesSidebarPane.CSSPropertyPrompt = function(cssCompletions, sidebarPane, isEditingName, acceptCallback)
{

WebInspector.TextPrompt.call(this, this._buildPropertyCompletions.bind(this), WebInspector.StylesSidebarPane.StyleValueDelimiters);
this.setSuggestBoxEnabled("generic-suggest");
this._cssCompletions = cssCompletions;
this._sidebarPane = sidebarPane;
this._isEditingName = isEditingName;
}

WebInspector.StylesSidebarPane.CSSPropertyPrompt.prototype = {
onKeyDown: function(event)
{
switch (event.keyIdentifier) {
case "Up":
case "Down":
case "PageUp":
case "PageDown":
if (this._handleNameOrValueUpDown(event)) {
event.preventDefault();
return;
}
break;
}

WebInspector.TextPrompt.prototype.onKeyDown.call(this, event);
},

tabKeyPressed: function()
{
this.acceptAutoComplete();


return false;
},

_handleNameOrValueUpDown: function(event)
{

if (!this._isEditingName && this._handleUpOrDownValue(event))
return true;

return false;
},

_handleUpOrDownValue: 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._sidebarPane.valueElement && !selectionRange.commonAncestorContainer.isDescendant(this._sidebarPane.valueElement))
return false;

var wordRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, WebInspector.StylesSidebarPane.StyleValueDelimiters, this._sidebarPane.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._sidebarPane.applyStyleText(this._sidebarPane.nameElement.textContent + ": " + this._sidebarPane.valueElement.textContent, false, false, false);

return true;
}
return false;
},

_buildPropertyCompletions: function(wordRange, force, completionsReadyCallback)
{
var prefix = wordRange.toString().toLowerCase();
if (!prefix && !force)
return;

var results = this._cssCompletions.startsWith(prefix);
completionsReadyCallback(results);
}
}

WebInspector.StylesSidebarPane.CSSPropertyPrompt.prototype.__proto__ = WebInspector.TextPrompt.prototype;






WebInspector.PanelEnablerView = function(identifier, headingText, disclaimerText, buttonTitle)
{
WebInspector.View.call(this);
this.registerRequiredCSS("panelEnablerView.css");

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"), false);

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");
},

onResize: 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.registerRequiredCSS("panelEnablerView.css");

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.textContent = 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.ElementsPanel = function()
{
WebInspector.Panel.call(this, "elements");
this.registerRequiredCSS("elementsPanel.css");
this.registerRequiredCSS("textPrompt.css");
this.setHideOnDetach();

const initialSidebarWidth = 325;
const minimalContentWidthPercent = 34;
this.createSplitView(this.element, WebInspector.SplitView.SidebarPosition.Right, initialSidebarWidth);
this.splitView.minimalSidebarWidth = Preferences.minElementsSidebarWidth;
this.splitView.minimalMainWidthPercent = minimalContentWidthPercent;

this.contentElement = this.splitView.mainElement;
this.contentElement.id = "elements-content";
this.contentElement.addStyleClass("outline-disclosure");
this.contentElement.addStyleClass("source-code");
if (!WebInspector.settings.domWordWrap.get())
this.contentElement.classList.add("nowrap");
WebInspector.settings.domWordWrap.addChangeListener(this._domWordWrapSettingChanged.bind(this));

this.contentElement.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true);

this.treeOutline = new WebInspector.ElementsTreeOutline(true, true, false, this._populateContextMenu.bind(this));
this.treeOutline.wireToDomAgent();

this.treeOutline.addEventListener(WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged, this._selectedNodeChanged, this);

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 (Capabilities.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);

for (var pane in this.sidebarPanes) {
this.sidebarElement.appendChild(this.sidebarPanes[pane].element);
if (this.sidebarPanes[pane].onattach)
this.sidebarPanes[pane].onattach();
}

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, this);

this._registerShortcuts();

WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.NodeRemoved, this._nodeRemoved, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.DocumentUpdated, this._documentUpdated, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.InspectElementRequested, this._inspectElementRequested, this);
}

WebInspector.ElementsPanel.prototype = {
get toolbarItemLabel()
{
return WebInspector.UIString("Elements");
},

get statusBarItems()
{
return [this.crumbsElement];
},

get defaultFocusedElement()
{
return this.treeOutline.element;
},

statusBarResized: function()
{
this.updateBreadcrumbSizes();
},

wasShown: function()
{
WebInspector.Panel.prototype.wasShown.call(this);


if (this.treeOutline.element.parentElement !== this.contentElement)
this.contentElement.appendChild(this.treeOutline.element);

this.updateBreadcrumb();
this.treeOutline.updateSelection();
this.treeOutline.setVisible(true);

if (!this.treeOutline.rootDOMNode)
WebInspector.domAgent.requestDocument();

if (Capabilities.nativeInstrumentationEnabled)
this.sidebarElement.insertBefore(this.sidebarPanes.domBreakpoints.element, this.sidebarPanes.eventListeners.element);
},

willHide: function()
{
WebInspector.domAgent.hideDOMNodeHighlight();
this.setSearchingForNode(false);
this.treeOutline.setVisible(false);


this.contentElement.removeChild(this.treeOutline.element);

WebInspector.Panel.prototype.willHide.call(this);
},

onResize: function()
{
this.treeOutline.updateSelection();
this.updateBreadcrumbSizes();
},

_selectedNodeChanged: function()
{
var selectedNode = this.selectedDOMNode();
if (!selectedNode && this._lastValidSelectedNode)
this._selectedPathOnReset = this._lastValidSelectedNode.path();

this.updateBreadcrumb(false);

for (var pane in this.sidebarPanes)
this.sidebarPanes[pane].needsUpdate = true;

this.updateStyles(true);
this.updateMetrics();
this.updateProperties();
this.updateEventListeners();

if (selectedNode) {
ConsoleAgent.addInspectedNode(selectedNode.id);
this._lastValidSelectedNode = selectedNode;
}
},

_reset: function()
{
delete this.currentQuery;
},

_documentUpdated: function(event)
{
var inspectedRootDocument = event.data;

this._reset();
this.searchCanceled();

this.treeOutline.rootDOMNode = inspectedRootDocument;

if (!inspectedRootDocument) {
if (this.isShowing())
WebInspector.domAgent.requestDocument();
return;
}

if (Capabilities.nativeInstrumentationEnabled)
this.sidebarPanes.domBreakpoints.restoreBreakpoints();


function selectNode(candidateFocusNode)
{
if (!candidateFocusNode)
candidateFocusNode = inspectedRootDocument.body || inspectedRootDocument.documentElement;

if (!candidateFocusNode)
return;

this.selectDOMNode(candidateFocusNode);
if (this.treeOutline.selectedTreeElement)
this.treeOutline.selectedTreeElement.expand();
}

function selectLastSelectedNode(nodeId)
{
if (this.selectedDOMNode()) {

return;
}
var node = nodeId ? WebInspector.domAgent.nodeForId(nodeId) : null;
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;
delete this._searchResults;
WebInspector.domAgent.cancelSearch();
},

performSearch: function(query)
{

this.searchCanceled();

const whitespaceTrimmedQuery = query.trim();
if (!whitespaceTrimmedQuery.length)
return;

this._searchQuery = query;


function resultCountCallback(resultCount)
{
WebInspector.searchController.updateSearchMatchesCount(resultCount, this);
if (!resultCount)
return;

this._searchResults = new Array(resultCount);
this._currentSearchResultIndex = -1;
this.jumpToNextSearchResult();
}
WebInspector.domAgent.performSearch(whitespaceTrimmedQuery, resultCountCallback.bind(this));
},

_contextMenuEventFired: function(event)
{
function toggleWordWrap()
{
WebInspector.settings.domWordWrap.set(!WebInspector.settings.domWordWrap.get());
}

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), WebInspector.settings.domWordWrap.get());

contextMenu.show(event);
},

_domWordWrapSettingChanged: function(event)
{
if (event.data)
this.contentElement.removeStyleClass("nowrap");
else
this.contentElement.addStyleClass("nowrap");

var selectedNode = this.selectedDOMNode();
if (!selectedNode)
return;

var treeElement = this.treeOutline.findTreeElement(selectedNode);
if (treeElement)
treeElement.updateSelection(); 
},

switchToAndFocus: function(node)
{

WebInspector.searchController.cancelSearch();
WebInspector.inspectorView.setCurrentPanel(this);
this.selectDOMNode(node, true);
},

_populateContextMenu: function(contextMenu, node)
{
if (Capabilities.nativeInstrumentationEnabled) {

contextMenu.appendSeparator();
var pane = this.sidebarPanes.domBreakpoints;
pane.populateNodeContextMenu(node, contextMenu);
}
},

jumpToNextSearchResult: function()
{
if (!this._searchResults)
return;

this._hideSearchHighlights();
if (++this._currentSearchResultIndex >= this._searchResults.length)
this._currentSearchResultIndex = 0;

this._highlightCurrentSearchResult();
},

jumpToPreviousSearchResult: function()
{
if (!this._searchResults)
return;

this._hideSearchHighlights();
if (--this._currentSearchResultIndex < 0)
this._currentSearchResultIndex = (this._searchResults.length - 1);

this._highlightCurrentSearchResult();
},

_highlightCurrentSearchResult: function()
{
var index = this._currentSearchResultIndex;
var searchResults = this._searchResults;
var searchResult = searchResults[index];

if (searchResult === null) {
WebInspector.searchController.updateCurrentMatchIndex(index, this);
return;
}

if (typeof searchResult === "undefined") {

function callback(node)
{
searchResults[index] = node || null;
this._highlightCurrentSearchResult();
}
WebInspector.domAgent.searchResult(index, callback.bind(this));
return;
}

WebInspector.searchController.updateCurrentMatchIndex(index, this);

var treeElement = this.treeOutline.findTreeElement(searchResult);
if (treeElement) {
treeElement.highlightSearchResults(this._searchQuery);
treeElement.reveal();
}
},

_hideSearchHighlights: function()
{
if (!this._searchResults)
return;
var searchResult = this._searchResults[this._currentSearchResultIndex];
if (!searchResult)
return;
var treeElement = this.treeOutline.findTreeElement(searchResult);
if (treeElement)
treeElement.hideSearchHighlights();
},

selectedDOMNode: function()
{
return this.treeOutline.selectedDOMNode();
},


selectDOMNode: function(node, focus)
{
this.treeOutline.selectDOMNode(node, focus);
},

_nodeRemoved: function(event)
{
if (!this.isShowing())
return;

var crumbs = this.crumbsElement;
for (var crumb = crumbs.firstChild; crumb; crumb = crumb.nextSibling) {
if (crumb.representedObject === event.data.node) {
this.updateBreadcrumb(true);
return;
}
}
},

_stylesPaneEdited: function()
{

this.sidebarPanes.metrics.needsUpdate = true;
this.updateMetrics();
},

_metricsPaneEdited: function()
{

this.sidebarPanes.styles.needsUpdate = true;
this.updateStyles(true);
},

_mouseMovedInCrumbs: function(event)
{
var nodeUnderMouse = document.elementFromPoint(event.pageX, event.pageY);
var crumbElement = nodeUnderMouse.enclosingNodeOrSelfWithClass("crumb");

WebInspector.domAgent.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.domAgent.hideDOMNodeHighlight();

this._mouseOutOfCrumbsTimeout = setTimeout(this.updateBreadcrumbSizes.bind(this), 1000);
},


updateBreadcrumb: function(forceUpdate)
{
if (!this.isShowing())
return;

var crumbs = this.crumbsElement;

var handled = false;
var foundRoot = false;
var crumb = crumbs.firstChild;
while (crumb) {
if (crumb.representedObject === this.treeOutline.rootDOMNode)
foundRoot = true;

if (foundRoot)
crumb.addStyleClass("dimmed");
else
crumb.removeStyleClass("dimmed");

if (crumb.representedObject === this.selectedDOMNode()) {
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
panel.selectDOMNode(crumb.representedObject, true);

event.preventDefault();
}

foundRoot = false;
for (var current = this.selectedDOMNode(); current; current = current.parentNode) {
if (current.nodeType() === Node.DOCUMENT_NODE)
continue;

if (current === this.treeOutline.rootDOMNode)
foundRoot = true;

crumb = document.createElement("span");
crumb.className = "crumb";
crumb.representedObject = current;
crumb.addEventListener("mousedown", selectCrumbFunction, false);

var crumbTitle;
switch (current.nodeType()) {
case Node.ELEMENT_NODE:
WebInspector.DOMPresentationUtils.decorateNodeLabel(current, crumb);
break;

case Node.TEXT_NODE:
crumbTitle = WebInspector.UIString("(text)");
break

case Node.COMMENT_NODE:
crumbTitle = "<!-->";
break;

case Node.DOCUMENT_TYPE_NODE:
crumbTitle = "<!DOCTYPE>";
break;

default:
crumbTitle = current.nodeNameInCorrectCase();
}

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.selectedDOMNode())
crumb.addStyleClass("selected");
if (!crumbs.childNodes.length)
crumb.addStyleClass("end");

crumbs.appendChild(crumb);
}

if (crumbs.hasChildNodes())
crumbs.lastChild.addStyleClass("start");

this.updateBreadcrumbSizes();
},


updateBreadcrumbSizes: function(focusedCrumb)
{
if (!this.isShowing())
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, false);
}

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)
return;

stylesSidebarPane.update(this.selectedDOMNode(), forceUpdate);
stylesSidebarPane.needsUpdate = false;
},

updateMetrics: function()
{
var metricsSidebarPane = this.sidebarPanes.metrics;
if (!metricsSidebarPane.expanded || !metricsSidebarPane.needsUpdate)
return;

metricsSidebarPane.update(this.selectedDOMNode());
metricsSidebarPane.needsUpdate = false;
},

updateProperties: function()
{
var propertiesSidebarPane = this.sidebarPanes.properties;
if (!propertiesSidebarPane.expanded || !propertiesSidebarPane.needsUpdate)
return;

propertiesSidebarPane.update(this.selectedDOMNode());
propertiesSidebarPane.needsUpdate = false;
},

updateEventListeners: function()
{
var eventListenersSidebarPane = this.sidebarPanes.eventListeners;
if (!eventListenersSidebarPane.expanded || !eventListenersSidebarPane.needsUpdate)
return;

eventListenersSidebarPane.update(this.selectedDOMNode());
eventListenersSidebarPane.needsUpdate = false;
},

_registerShortcuts: function()
{
var shortcut = WebInspector.KeyboardShortcut;
var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("Elements Panel"));
var keys = [
shortcut.shortcutToString(shortcut.Keys.Up),
shortcut.shortcutToString(shortcut.Keys.Down)
];
section.addRelatedKeys(keys, WebInspector.UIString("Navigate elements"));

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.selectedDOMNode().copyNode();
},

sidebarResized: function(event)
{
this.treeOutline.updateSelection();
},

_inspectElementRequested: function(event)
{
var node = event.data;
this.revealAndSelectNode(node.id);
},

revealAndSelectNode: function(nodeId)
{
WebInspector.inspectorView.setCurrentPanel(this);

var node = WebInspector.domAgent.nodeForId(nodeId);
if (!node)
return;

WebInspector.domAgent.highlightDOMNodeForTwoSeconds(nodeId);
this.selectDOMNode(node, true);
if (this.nodeSearchButton.toggled) {
InspectorFrontendHost.bringToFront();
this.nodeSearchButton.toggled = false;
}
},

setSearchingForNode: function(enabled)
{
function callback(error)
{
if (!error)
this.nodeSearchButton.toggled = enabled;
}
WebInspector.domAgent.setInspectModeEnabled(enabled, callback.bind(this));
},

toggleSearchingForNode: function()
{
this.setSearchingForNode(!this.nodeSearchButton.toggled);
}
}

WebInspector.ElementsPanel.prototype.__proto__ = WebInspector.Panel.prototype;






WebInspector.NetworkLogView = function()
{
WebInspector.View.call(this);
this.registerRequiredCSS("networkLogView.css");

this._allowResourceSelection = false;
this._resources = [];
this._resourcesById = {};
this._resourcesByURL = {};
this._staleResources = {};
this._resourceGridNodes = {};
this._lastResourceGridNodeId = 0;
this._mainResourceLoadTime = -1;
this._mainResourceDOMContentTime = -1;
this._hiddenCategories = {};
this._matchedResources = [];
this._matchedResourcesMap = {};
this._currentMatchedResourceIndex = -1;

this._categories = WebInspector.resourceCategories;

this._createStatusbarButtons();
this._createFilterStatusBarItems();
this._linkifier = WebInspector.debuggerPresentationModel.createLinkifier();

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.MainFrameNavigated, this._mainFrameNavigated, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.OnLoad, this._onLoadEventFired, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, this._domContentLoadedEventFired, this);

this._initializeView();
function onCanClearBrowserCache(error, result)
{
this._canClearBrowserCache = result;
}
NetworkAgent.canClearBrowserCache(onCanClearBrowserCache.bind(this));

function onCanClearBrowserCookies(error, result)
{
this._canClearBrowserCookies = result;
}
NetworkAgent.canClearBrowserCache(onCanClearBrowserCookies.bind(this));
}

WebInspector.NetworkLogView.prototype = {
_initializeView: function()
{
this.element.id = "network-container";

this._createSortingFunctions();
this._createTable();
this._createTimelineGrid();
this._createSummaryBar();

if (!this.useLargeRows)
this._setLargerResources(this.useLargeRows);

this._allowPopover = true;
this._popoverHelper = new WebInspector.PopoverHelper(this.element, this._getPopoverAnchor.bind(this), this._showPopover.bind(this));

this._popoverHelper.setTimeout(100);

this.calculator = new WebInspector.NetworkTransferTimeCalculator();
this._filter(this._filterAllElement, false);

this.switchToDetailedView();
},

get statusBarItems()
{
return [this._largerResourcesButton.element, this._preserveLogToggle.element, this._clearButton.element, this._filterBarElement];
},

get useLargeRows()
{
return WebInspector.settings.resourcesLargeRows.get();
},

set allowPopover(flag)
{
this._allowPopover = flag;
},

get allowResourceSelection()
{
return this._allowResourceSelection;
},

set allowResourceSelection(flag)
{
this._allowResourceSelection = !!flag;
},

elementsToRestoreScrollPositionsFor: function()
{
if (!this._dataGrid) 
return [];
return [this._dataGrid.scrollContainer];
},

onResize: function()
{
this._updateOffscreenRows();
},

_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;
if (Capabilities.nativeInstrumentationEnabled)
columns = {name: {}, method: {}, status: {}, type: {}, initiator: {}, size: {}, time: {}, timeline: {}};
else
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%";

if (Capabilities.nativeInstrumentationEnabled) {
columns.initiator.title = WebInspector.UIString("Initiator");
columns.initiator.sortable = true;
columns.initiator.width = "10%";
}

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;
if (Capabilities.nativeInstrumentationEnabled)
columns.timeline.width = "40%";
else
columns.timeline.width = "50%";
columns.timeline.sort = "ascending";

this._dataGrid = new WebInspector.DataGrid(columns);
this._dataGrid.resizeMethod = WebInspector.DataGrid.ResizeMethod.Last;
this._dataGrid.element.addStyleClass("network-log-grid");
this._dataGrid.element.addEventListener("contextmenu", this._contextMenu.bind(this), true);
this._dataGrid.show(this.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.initiator = WebInspector.NetworkDataGridNode.InitiatorComparator;
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()
{
this._removeAllNodeHighlights();
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();

this.performSearch(null, true);
},

_sortByTimeline: function()
{
this._removeAllNodeHighlights();
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 requestsNumber = this._resources.length;

if (!requestsNumber) {
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 selectedRequestsNumber = 0;
var selectedTransferSize = 0;
var baseTime = -1;
var maxTime = -1;
for (var i = 0; i < this._resources.length; ++i) {
var resource = this._resources[i];
var resourceTransferSize = (resource.cached || !resource.transferSize) ? 0 : resource.transferSize;
transferSize += resourceTransferSize;
if (!this._hiddenCategories.all || !this._hiddenCategories[resource.category.name]) {
selectedRequestsNumber++;
selectedTransferSize += resourceTransferSize;
}
if (resource.url === WebInspector.inspectedPageURL) {
baseTime = resource.startTime;
WebInspector.mainResourceStartTime = resource.startTime;
}
if (resource.endTime > maxTime)
maxTime = resource.endTime;
}
var text = "";
if (this._hiddenCategories.all) {
text += String.sprintf(WebInspector.UIString("%d / %d requests"), selectedRequestsNumber, requestsNumber);
text += "  \u2758  " + String.sprintf(WebInspector.UIString("%s / %s transferred"), Number.bytesToString(selectedTransferSize), Number.bytesToString(transferSize));
} else {
text += String.sprintf(WebInspector.UIString("%d requests"), requestsNumber);
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)
{
this._removeAllNodeHighlights();
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);
this.performSearch(null, true);
this._updateSummaryBar();
},

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

_defaultRefreshDelay: 500,

_scheduleRefresh: function()
{
if (this._needsRefresh)
return;

this._needsRefresh = true;

if (this.isShowing() && !this._refreshTimeout)
this._refreshTimeout = setTimeout(this.refresh.bind(this), this._defaultRefreshDelay);
},

_updateDividersIfNeeded: function(force)
{
if (!this._dataGrid)
return;
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.isShowing()) {
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()
{
for (var i = 0; i < this._resources.length; ++i) {
var resource = this._resources[i];
this._staleResources[resource.requestId] = resource;
}
},

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;
},

_createStatusbarButtons: function()
{
this._preserveLogToggle = new WebInspector.StatusBarButton(WebInspector.UIString("Preserve Log upon Navigation"), "record-profile-status-bar-item");
this._preserveLogToggle.addEventListener("click", this._onPreserveLogClicked, this);

this._clearButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear"), "clear-status-bar-item");
this._clearButton.addEventListener("click", this._reset, this);

this._largerResourcesButton = new WebInspector.StatusBarButton(WebInspector.UIString("Use small resource rows."), "network-larger-resources-status-bar-item");
this._largerResourcesButton.toggled = WebInspector.settings.resourcesLargeRows.get();
this._largerResourcesButton.addEventListener("click", this._toggleLargerResources, this);
},

_onLoadEventFired: function(event)
{
this._mainResourceLoadTime = event.data || -1;

this._scheduleRefresh();
},

_domContentLoadedEventFired: function(event)
{
this._mainResourceDOMContentTime = event.data || -1;

this._scheduleRefresh();
},

wasShown: function()
{
this._refreshIfNeeded();
},

willHide: function()
{
this._popoverHelper.hidePopover();
},

refresh: function()
{
this._needsRefresh = false;
if (this._refreshTimeout) {
clearTimeout(this._refreshTimeout);
delete this._refreshTimeout;
}

this._removeAllNodeHighlights();
var wasScrolledToLastRow = this._dataGrid.isScrolledToLastRow();
var boundariesChanged = false;
if (this.calculator.updateBoundariesForEventTime) {
boundariesChanged = this.calculator.updateBoundariesForEventTime(this._mainResourceLoadTime) || boundariesChanged;
boundariesChanged = this.calculator.updateBoundariesForEventTime(this._mainResourceDOMContentTime) || boundariesChanged;
}

for (var resourceId in this._staleResources) {
var resource = this._staleResources[resourceId];
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 (!node.isFilteredOut())
this._updateHighlightIfMatched(resource);
}

if (boundariesChanged) {

this._invalidateAllItems();
}

for (var resourceId in this._staleResources)
this._resourceGridNode(this._staleResources[resourceId]).refreshGraph(this.calculator);

this._staleResources = {};
this._sortItems();
this._updateSummaryBar();
this._dataGrid.updateWidths();

if (wasScrolledToLastRow)
this._dataGrid.scrollToLastRow();
},

_onPreserveLogClicked: function(e)
{
this._preserveLogToggle.toggled = !this._preserveLogToggle.toggled;
},

_reset: function()
{
this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.ViewCleared);

this._clearSearchMatchedList();
if (this._popoverHelper)
this._popoverHelper.hidePopover();

if (this._calculator)
this._calculator.reset();

this._resources = [];
this._resourcesById = {};
this._resourcesByURL = {};
this._staleResources = {};
this._resourceGridNodes = {};

if (this._dataGrid) {
this._dataGrid.removeChildren();
this._updateDividersIfNeeded(true);
this._updateSummaryBar();
}

this._mainResourceLoadTime = -1;
this._mainResourceDOMContentTime = -1;
this._linkifier.reset();
},

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);



if (this._resourcesById[resource.requestId]) {
var oldResource = resource.redirects[resource.redirects.length - 1];
this._resourcesById[oldResource.requestId] = oldResource;

this._updateSearchMatchedListAfterRequestIdChanged(resource.requestId, oldResource.requestId);
}
this._resourcesById[resource.requestId] = 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[resource.requestId] = resource;
this._scheduleRefresh();
},

clear: function()
{
if (this._preserveLogToggle.toggled)
return;
this._reset();
},

_mainFrameNavigated: function(event)
{
if (this._preserveLogToggle.toggled)
return;

var frame =   event.data;
var loaderId = frame.loaderId;


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]);
},

switchToDetailedView: function()
{
if (!this._dataGrid)
return;
if (this._dataGrid.selectedNode)
this._dataGrid.selectedNode.selected = false;

this.element.removeStyleClass("brief-mode");

this._dataGrid.showColumn("method");
this._dataGrid.showColumn("status");
this._dataGrid.showColumn("type");
if (Capabilities.nativeInstrumentationEnabled)
this._dataGrid.showColumn("initiator");
this._dataGrid.showColumn("size");
this._dataGrid.showColumn("time");
this._dataGrid.showColumn("timeline");

var widths = {};
widths.name = 20;
widths.method = 6;
widths.status = 6;
widths.type = 6;
if (Capabilities.nativeInstrumentationEnabled)
widths.initiator = 10;
widths.size = 6;
widths.time = 6;
if (Capabilities.nativeInstrumentationEnabled)
widths.timeline = 40;
else
widths.timeline = 50;

this._dataGrid.applyColumnWidthsMap(widths);
},

switchToBriefView: function()
{
this.element.addStyleClass("brief-mode");
this._removeAllNodeHighlights();

this._dataGrid.hideColumn("method");
this._dataGrid.hideColumn("status");
this._dataGrid.hideColumn("type");
if (Capabilities.nativeInstrumentationEnabled)
this._dataGrid.hideColumn("initiator");
this._dataGrid.hideColumn("size");
this._dataGrid.hideColumn("time");
this._dataGrid.hideColumn("timeline");

var widths = {};
widths.name = 100;
this._dataGrid.applyColumnWidthsMap(widths);

this._popoverHelper.hidePopover();
},

_toggleLargerResources: function()
{
WebInspector.settings.resourcesLargeRows.set(!WebInspector.settings.resourcesLargeRows.get());
this._setLargerResources(WebInspector.settings.resourcesLargeRows.get());
},

_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");
} else {
this._largerResourcesButton.title = WebInspector.UIString("Use small resource rows.");
this._dataGrid.element.removeStyleClass("small");
this._timelineGrid.element.removeStyleClass("small");
}
this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.RowSizeChanged, { largeRows: enabled });
this._updateOffscreenRows();
},

_getPopoverAnchor: function(element)
{
if (!this._allowPopover)
return;
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, popover)
{
var resource = anchor.parentElement.resource;
var tableElement = WebInspector.ResourceTimingView.createTimingTable(resource);
popover.show(tableElement, anchor);
},

_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.copyLinkAddressLabel(), 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 (InspectorFrontendHost.canSaveAs()) {
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));
}

if (this._canClearBrowserCache || this._canClearBrowserCookies)
contextMenu.appendSeparator();
if (this._canClearBrowserCache)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Clear browser cache" : "Clear Browser Cache"), this._clearBrowserCache.bind(this));
if (this._canClearBrowserCookies)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Clear browser cookies" : "Clear Browser Cookies"), this._clearBrowserCookies.bind(this));

contextMenu.show(event);
},

_copyAll: function()
{
var harArchive = {
log: (new WebInspector.HARLog(this._resources)).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(this._resources)).build()
};

InspectorFrontendHost.saveAs(WebInspector.inspectedPageDomain + ".har", JSON.stringify(harArchive));
},

_exportResource: function(resource)
{
var har = (new WebInspector.HAREntry(resource)).build();
InspectorFrontendHost.saveAs(resource.displayName + ".har", JSON.stringify(har));
},

_clearBrowserCache: function(event)
{
if (confirm(WebInspector.UIString("Are you sure you want to clear browser cache?")))
NetworkAgent.clearBrowserCache();
},

_clearBrowserCookies: function(event)
{
if (confirm(WebInspector.UIString("Are you sure you want to clear browser cookies?")))
NetworkAgent.clearBrowserCookies();
},

_updateOffscreenRows: function()
{
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++;
}
},

_matchResource: function(resource)
{
if (!this._searchRegExp)
return -1;

if ((!resource.displayName || !resource.displayName.match(this._searchRegExp)) && !resource.folder.match(this._searchRegExp))
return -1;

if (resource.requestId in this._matchedResourcesMap)
return this._matchedResourcesMap[resource.requestId];

var matchedResourceIndex = this._matchedResources.length;
this._matchedResourcesMap[resource.requestId] = matchedResourceIndex;
this._matchedResources.push(resource.requestId);

return matchedResourceIndex;
},

_clearSearchMatchedList: function()
{
this._matchedResources = [];
this._matchedResourcesMap = {};
this._highlightNthMatchedResource(-1, false);
},

_updateSearchMatchedListAfterRequestIdChanged: function(oldRequestId, newRequestId)
{
var resourceIndex = this._matchedResourcesMap[oldRequestId];
if (resourceIndex) {
delete this._matchedResourcesMap[oldRequestId];
this._matchedResourcesMap[newRequestId] = resourceIndex;
this._matchedResources[resourceIndex] = newRequestId;
}
},

_updateHighlightIfMatched: function(resource)
{
var matchedResourceIndex = this._matchResource(resource);
if (matchedResourceIndex === -1)
return;

this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.SearchCountUpdated, this._matchedResources.length);

if (this._currentMatchedResourceIndex !== -1 && this._currentMatchedResourceIndex !== matchedResourceIndex)
return;

this._highlightNthMatchedResource(matchedResourceIndex, false);
},

_highlightNthMatchedResource: function(matchedResourceIndex, reveal)
{
if (this._highlightedSubstringChanges) {
revertDomChanges(this._highlightedSubstringChanges);
this._highlightedSubstringChanges = null;
}

if (matchedResourceIndex === -1) {
this._currentMatchedResourceIndex = matchedResourceIndex;
return;
}

var resource = this._resourcesById[this._matchedResources[matchedResourceIndex]];
if (!resource)
return;

var nameMatched = resource.displayName && resource.displayName.match(this._searchRegExp);
var pathMatched = resource.path && resource.folder.match(this._searchRegExp);
if (!nameMatched && pathMatched && !this._largerResourcesButton.toggled)
this._toggleLargerResources();

var node = this._resourceGridNode(resource);
if (node) {
this._highlightedSubstringChanges = node._highlightMatchedSubstring(this._searchRegExp);
if (reveal)
node.reveal();
this._currentMatchedResourceIndex = matchedResourceIndex;
}
this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.SearchIndexUpdated, this._currentMatchedResourceIndex);
},

performSearch: function(searchQuery, sortOrFilterApplied)
{
var newMatchedResourceIndex = 0;
var currentMatchedRequestId;
if (this._currentMatchedResourceIndex !== -1)
currentMatchedRequestId = this._matchedResources[this._currentMatchedResourceIndex];

if (!sortOrFilterApplied)
this._searchRegExp = createPlainTextSearchRegex(searchQuery, "i");

this._clearSearchMatchedList();

var childNodes = this._dataGrid.dataTableBody.childNodes;
var resourceNodes = Array.prototype.slice.call(childNodes, 0, childNodes.length - 1); 

for (var i = 0; i < resourceNodes.length; ++i) {
var dataGridNode = this._dataGrid.dataGridNodeFromNode(resourceNodes[i]);
if (dataGridNode.isFilteredOut())
continue;

if (this._matchResource(dataGridNode._resource) !== -1 && dataGridNode._resource.requestId === currentMatchedRequestId)
newMatchedResourceIndex = this._matchedResources.length - 1;
}

this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.SearchCountUpdated, this._matchedResources.length);
this._highlightNthMatchedResource(newMatchedResourceIndex, !sortOrFilterApplied);
},

jumpToPreviousSearchResult: function()
{
if (!this._matchedResources.length)
return;
this._highlightNthMatchedResource((this._currentMatchedResourceIndex + this._matchedResources.length - 1) % this._matchedResources.length, true);
},

jumpToNextSearchResult: function()
{
if (!this._matchedResources.length)
return;
this._highlightNthMatchedResource((this._currentMatchedResourceIndex + 1) % this._matchedResources.length, true);
},

searchCanceled: function()
{
this._clearSearchMatchedList();
this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.SearchCountUpdated, 0);
},

revealAndHighlightResource: function(resource)
{
this._removeAllNodeHighlights();

var node = this._resourceGridNode(resource);
if (node) {
this._dataGrid.element.focus();
node.reveal();
this._highlightNode(node);
}
},

_removeAllNodeHighlights: function()
{
if (this._highlightedNode) {
this._highlightedNode.element.removeStyleClass("highlighted-row");
delete this._highlightedNode;
}
},

_highlightNode: function(node)
{
node.element.addStyleClass("highlighted-row");
this._highlightedNode = node;
}
};

WebInspector.NetworkLogView.prototype.__proto__ = WebInspector.View.prototype;

WebInspector.NetworkLogView.EventTypes = {
ViewCleared: "ViewCleared",
RowSizeChanged: "RowSizeChanged",
ResourceSelected: "ResourceSelected",
SearchCountUpdated: "SearchCountUpdated",
SearchIndexUpdated: "SearchIndexUpdated"
};


WebInspector.NetworkPanel = function()
{
WebInspector.Panel.call(this, "network");
this.registerRequiredCSS("networkPanel.css");

this.createSplitView();
this.splitView.hideMainElement();

this._networkLogView = new WebInspector.NetworkLogView();
this._networkLogView.show(this.sidebarElement);

this._viewsContainerElement = this.splitView.mainElement;
this._viewsContainerElement.id = "network-views";
this._viewsContainerElement.addStyleClass("hidden");
if (!this._networkLogView.useLargeRows)
this._viewsContainerElement.addStyleClass("small");

this._networkLogView.addEventListener(WebInspector.NetworkLogView.EventTypes.ViewCleared, this._onViewCleared, this);
this._networkLogView.addEventListener(WebInspector.NetworkLogView.EventTypes.RowSizeChanged, this._onRowSizeChanged, this);
this._networkLogView.addEventListener(WebInspector.NetworkLogView.EventTypes.ResourceSelected, this._onResourceSelected, this);
this._networkLogView.addEventListener(WebInspector.NetworkLogView.EventTypes.SearchCountUpdated, this._onSearchCountUpdated, this);
this._networkLogView.addEventListener(WebInspector.NetworkLogView.EventTypes.SearchIndexUpdated, this._onSearchIndexUpdated, this);

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);

function viewGetter()
{
return this.visibleView;
}
WebInspector.GoToLineDialog.install(this, viewGetter.bind(this));
}

WebInspector.NetworkPanel.prototype = {
get toolbarItemLabel()
{
return WebInspector.UIString("Network");
},

get statusBarItems()
{
return this._networkLogView.statusBarItems;
},

elementsToRestoreScrollPositionsFor: function()
{
return this._networkLogView.elementsToRestoreScrollPositionsFor();
},


_reset: function()
{
this._networkLogView._reset();
},

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);
},

wasShown: function()
{
WebInspector.Panel.prototype.wasShown.call(this);
},

get resources()
{
return this._networkLogView.resources;
},

resourceById: function(id)
{
return this._networkLogView.resourceById(id);
},

_resourceByAnchor: function(anchor)
{
return anchor.requestId ? this.resourceById(anchor.requestId) : this._networkLogView._resourcesByURL[anchor.href];
},

canShowAnchorLocation: function(anchor)
{
return !!this._resourceByAnchor(anchor);
},

showAnchorLocation: function(anchor)
{
var resource = this._resourceByAnchor(anchor);
this.revealAndHighlightResource(resource)
},

revealAndHighlightResource: function(resource)
{
this._toggleGridMode();
if (resource)
this._networkLogView.revealAndHighlightResource(resource);
},

_onViewCleared: function(event)
{
this._closeVisibleResource();
this._toggleGridMode();
this._viewsContainerElement.removeChildren();
this._viewsContainerElement.appendChild(this._closeButtonElement);
},

_onRowSizeChanged: function(event)
{
if (event.data.largeRows)
this._viewsContainerElement.removeStyleClass("small");
else
this._viewsContainerElement.addStyleClass("small");
},

_onSearchCountUpdated: function(event)
{
WebInspector.searchController.updateSearchMatchesCount(event.data, this);
},

_onSearchIndexUpdated: function(event)
{
WebInspector.searchController.updateCurrentMatchIndex(event.data, this);
},

_onResourceSelected: function(event)
{
this._showResource(event.data);
},

_showResource: function(resource)
{
if (!resource)
return;

this._toggleViewingResourceMode();

if (this.visibleView) {
this.visibleView.detach();
delete this.visibleView;
}

var view = new WebInspector.NetworkItemView(resource);
view.show(this._viewsContainerElement);
this.visibleView = view;
},

_closeVisibleResource: function()
{
this.element.removeStyleClass("viewing-resource");

if (this.visibleView) {
this.visibleView.detach();
delete this.visibleView;
}
},

_toggleGridMode: function()
{
if (this._viewingResourceMode) {
this._viewingResourceMode = false;
this.element.removeStyleClass("viewing-resource");
this.splitView.hideMainElement();
}

this._networkLogView.switchToDetailedView();
this._networkLogView.allowPopover = true;
this._networkLogView.allowResourceSelection = false;
},

_toggleViewingResourceMode: function()
{
if (this._viewingResourceMode)
return;
this._viewingResourceMode = true;

this.element.addStyleClass("viewing-resource");
this.splitView.showMainElement();
this._networkLogView.allowPopover = false;
this._networkLogView.allowResourceSelection = true;
this._networkLogView.switchToBriefView();
},

performSearch: function(searchQuery, sortOrFilterApplied)
{
this._networkLogView.performSearch(searchQuery, sortOrFilterApplied);
},

jumpToPreviousSearchResult: function()
{
this._networkLogView.jumpToPreviousSearchResult();
},

jumpToNextSearchResult: function()
{
this._networkLogView.jumpToNextSearchResult();
},

searchCanceled: function()
{
this._networkLogView.searchCanceled();
}
}

WebInspector.NetworkPanel.prototype.__proto__ = WebInspector.Panel.prototype;


WebInspector.NetworkBaseCalculator = function()
{
}

WebInspector.NetworkBaseCalculator.prototype = {
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 = {
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;
},

updateBoundariesForEventTime: function(eventTime)
{
if (eventTime === -1 || this.startAtZero)
return false;

if (typeof this.maximumBoundary === "undefined" || eventTime > this.maximumBoundary) {
this.maximumBoundary = eventTime;
return true;
}
return false;
},

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(parentView, resource)
{
WebInspector.DataGridNode.call(this, {});
this._parentView = parentView;
this._resource = resource;
}

WebInspector.NetworkDataGridNode.prototype = {
createCells: function()
{

this._element.addStyleClass("offscreen");
this._nameCell = this._createDivInTD("name");
this._methodCell = this._createDivInTD("method");
this._statusCell = this._createDivInTD("status");
this._typeCell = this._createDivInTD("type");
if (Capabilities.nativeInstrumentationEnabled)
this._initiatorCell = this._createDivInTD("initiator");
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._parentView._hiddenCategories.all)
return false;
return this._resource.category.name in this._parentView._hiddenCategories;
},

select: function()
{
this._parentView.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.ResourceSelected, this._resource);
WebInspector.DataGridNode.prototype.select.apply(this, arguments);
},

_highlightMatchedSubstring: function(regexp)
{
var domChanges = [];
var matchInfo = this._nameCell.textContent.match(regexp);
highlightSearchResult(this._nameCell, matchInfo.index, matchInfo[0].length, domChanges);
return domChanges;
},

_openInNewTab: function()
{
PageAgent.open(this._resource.url, true);
},

get selectable()
{
return this._parentView.allowResourceSelection && !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();
if (Capabilities.nativeInstrumentationEnabled)
this._refreshInitiatorCell();
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)
subtitle += this._resource.folder;

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");
this.element.addStyleClass("network-error-row");
return;
}

this._statusCell.removeStyleClass("network-dim-cell");
this.element.removeStyleClass("network-error-row");

if (this._resource.statusCode) {
this._statusCell.appendChild(document.createTextNode(this._resource.statusCode));
this._appendSubtitle(this._statusCell, this._resource.statusText);
this._statusCell.title = this._resource.statusCode + " " + this._resource.statusText;
if (this._resource.statusCode >= 400)
this.element.addStyleClass("network-error-row");
if (this._resource.cached)
this._statusCell.addStyleClass("network-dim-cell");
} else {
if (!this._resource.isHttpFamily() && this._resource.finished)
this._statusCell.setTextAndTitle(WebInspector.UIString("Success"));
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"));
}
},

_refreshInitiatorCell: function()
{
var initiator = this._resource.initiator;
if ((initiator && initiator.type !== "other") || this._resource.redirectSource) {
this._initiatorCell.removeStyleClass("network-dim-cell");
this._initiatorCell.removeChildren();
if (this._resource.redirectSource) {
var redirectSource = this._resource.redirectSource;
this._initiatorCell.title = redirectSource.url;
this._initiatorCell.appendChild(WebInspector.linkifyRequestAsNode(redirectSource));
this._appendSubtitle(this._initiatorCell, WebInspector.UIString("Redirect"));
} else if (initiator.type === "script") {
var topFrame = initiator.stackTrace[0];

if (!topFrame.url) {
this._initiatorCell.addStyleClass("network-dim-cell");
this._initiatorCell.setTextAndTitle(WebInspector.UIString("Other"));
return;
}
this._initiatorCell.title = topFrame.url + ":" + topFrame.lineNumber;
var urlElement = this._parentView._linkifier.linkifyLocation(topFrame.url, topFrame.lineNumber - 1, 0);
this._initiatorCell.appendChild(urlElement);
this._appendSubtitle(this._initiatorCell, WebInspector.UIString("Script"));
} else { 
this._initiatorCell.title = initiator.url + ":" + initiator.lineNumber;
this._initiatorCell.appendChild(WebInspector.linkifyResourceAsNode(initiator.url, initiator.lineNumber - 1));
this._appendSubtitle(this._initiatorCell, WebInspector.UIString("Parser"));
}
} else {
this._initiatorCell.addStyleClass("network-dim-cell");
this._initiatorCell.setTextAndTitle(WebInspector.UIString("Other"));
}
},

_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.InitiatorComparator = function(a, b)
{
if (!a._resource.initiator || a._resource.initiator.type === "Other")
return -1;
if (!b._resource.initiator || b._resource.initiator.type === "Other")
return 1;

if (a._resource.initiator.url < b._resource.initiator.url)
return -1;
if (a._resource.initiator.url > b._resource.initiator.url)
return 1;

return a._resource.initiator.lineNumber - b._resource.initiator.lineNumber;
}

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.registerRequiredCSS("textViewer.css");

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);
var syncLineHeightListener = this._syncLineHeight.bind(this);
this._mainPanel = new WebInspector.TextEditorMainPanel(this._textModel, url, syncScrollListener, syncDecorationsForLineListener, enterTextChangeMode, exitTextChangeMode);
this._gutterPanel = new WebInspector.TextEditorGutterPanel(this._textModel, syncDecorationsForLineListener, syncLineHeightListener);
this.element.appendChild(this._mainPanel.element);
this.element.appendChild(this._gutterPanel.element);


function forwardWheelEvent(event)
{
var clone = document.createEvent("WheelEvent");
clone.initWebKitWheelEvent(event.wheelDeltaX, event.wheelDeltaY,
event.view,
event.screenX, event.screenY,
event.clientX, event.clientY,
event.ctrlKey, event.altKey, event.shiftKey, event.metaKey);
this._mainPanel.element.dispatchEvent(clone);
}
this._gutterPanel.element.addEventListener("mousewheel", forwardWheelEvent.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;
},

focus: function()
{
this._mainPanel.element.focus();
},

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();
},

elementsToRestoreScrollPositionsFor: function()
{
return [this._mainPanel.element];
},

inheritScrollPositions: function(textViewer)
{
this._mainPanel.element._scrollTop = textViewer._mainPanel.element.scrollTop;
this._mainPanel.element._scrollLeft = textViewer._mainPanel.element.scrollLeft;
},

beginUpdates: function()
{
this._mainPanel.beginUpdates();
this._gutterPanel.beginUpdates();
},

endUpdates: function()
{
this._mainPanel.endUpdates();
this._gutterPanel.endUpdates();
this._updatePanelOffsets();
},

onResize: 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()
{
var mainElement = this._mainPanel.element;
var gutterElement = this._gutterPanel.element;

this._gutterPanel.syncClientHeight(mainElement.clientHeight);
gutterElement.scrollTop = mainElement.scrollTop;
},

_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");
}
},

_syncLineHeight: function(gutterRow) {
if (this._lineHeightSynced)
return;
if (gutterRow && gutterRow.offsetHeight) {

this.element.style.setProperty("line-height", gutterRow.offsetHeight + "px");
this._lineHeightSynced = true;
}
},

_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 handleEnterKey = this._mainPanel.handleEnterKey.bind(this._mainPanel);
this._shortcuts[WebInspector.KeyboardShortcut.makeKey(keys.Enter.code, WebInspector.KeyboardShortcut.Modifiers.None)] = handleEnterKey;

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)
{
if (this.readOnly)
return;

var shortcutKey = WebInspector.KeyboardShortcut.makeKeyFromEvent(e);
var handler = this._shortcuts[shortcutKey];
if (handler && handler()) {
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(contextMenu, target.lineNumber);
else {
target = this._mainPanel._enclosingLineRowOrSelf(event.target);
this._delegate.populateTextAreaContextMenu(contextMenu, target && target.lineNumber);
}
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, lineNumber) { },

populateTextAreaContextMenu: function(contextMenu, lineNumber) { },

suggestedFileName: function() { }
}


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, syncLineHeightListener)
{
WebInspector.TextEditorChunkedPanel.call(this, textModel);

this._syncDecorationsForLineListener = syncDecorationsForLineListener;
this._syncLineHeightListener = syncLineHeightListener;

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);
this._textViewer._syncLineHeightListener(this._expandedLineRows[0]);
} 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._updateSelectionOnStartEditing();
}
this.endDomUpdates();
},

get readOnly()
{
return this._readOnly;
},

_updateSelectionOnStartEditing: function()
{




this._container.focus();
var selection = window.getSelection();
if (selection.rangeCount) {
var commonAncestorContainer = selection.getRangeAt(0).commonAncestorContainer;
if (this._container === commonAncestorContainer || this._container.isAncestor(commonAncestorContainer))
return;
}

selection.removeAllRanges();
var range = document.createRange();
range.setStart(this._container, 0);
range.setEnd(this._container, 0);
selection.addRange(range);
},

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._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._dirtyLines)
return false;

var selection = this._getSelection();
if (!selection)
return false;

var range = selection.normalize();

this.beginUpdates();
this._enterTextChangeMode();

var newRange;
if (shiftKey)
newRange = this._unindentLines(range);
else {
if (range.isEmpty()) {
newRange = this._setText(range, WebInspector.settings.textEditorIndent.get());
newRange.startColumn = newRange.endColumn;
} else
newRange = this._indentLines(range);

}

this._exitTextChangeMode(range, newRange);
this.endUpdates();
this._restoreSelection(newRange, true);
return true;
},

_indentLines: function(range)
{
var indent = WebInspector.settings.textEditorIndent.get();

if (this._lastEditedRange)
this._textModel.markUndoableState();

for (var lineNumber = range.startLine; lineNumber <= range.endLine; lineNumber++)
this._textModel.setText(new WebInspector.TextRange(lineNumber, 0, lineNumber, 0), indent);

var newRange = range.clone();
newRange.startColumn += indent.length;
newRange.endColumn += indent.length;
this._lastEditedRange = newRange;

return newRange;
},

_unindentLines: function(range)
{
if (this._lastEditedRange)
this._textModel.markUndoableState();

var indent = WebInspector.settings.textEditorIndent.get();
var indentLength = indent === WebInspector.TextEditorModel.Indent.TabCharacter ? 4 : indent.length;
var lineIndentRegex = new RegExp("^ {1," + indentLength + "}");
var newRange = range.clone();

for (var lineNumber = range.startLine; lineNumber <= range.endLine; lineNumber++) {
var line = this._textModel.line(lineNumber);
var firstCharacter = line.charAt(0);
var lineIndentLength;

if (firstCharacter === " ")
lineIndentLength = line.match(lineIndentRegex)[0].length;
else if (firstCharacter === "\t")
lineIndentLength = 1;
else
continue;

this._textModel.setText(new WebInspector.TextRange(lineNumber, 0, lineNumber, lineIndentLength), "");

if (lineNumber === range.startLine)
newRange.startColumn = Math.max(0, newRange.startColumn - lineIndentLength);
}

if (lineIndentLength)
newRange.endColumn = Math.max(0, newRange.endColumn - lineIndentLength);

this._lastEditedRange = newRange;

return newRange;
},

handleEnterKey: function()
{
if (this._dirtyLines)
return false;

var range = this._getSelection();
if (!range)
return false;

range.normalize();

if (range.endColumn === 0)
return false;

var line = this._textModel.line(range.startLine);
var linePrefix = line.substring(0, range.startColumn);
var indentMatch = linePrefix.match(/^\s+/);
var currentIndent = indentMatch ? indentMatch[0] : "";

var textEditorIndent = WebInspector.settings.textEditorIndent.get();
var indent = WebInspector.TextEditorModel.endsWithBracketRegex.test(linePrefix) ? currentIndent + textEditorIndent : currentIndent;

if (!indent)
return false;

this.beginUpdates();
this._enterTextChangeMode();

var lineBreak = this._textModel.lineBreak;
var newRange;
if (range.isEmpty() && line.substr(range.endColumn - 1, 2) === '{}') {





newRange = this._setText(range, lineBreak + indent + lineBreak + currentIndent);
newRange.endLine--;
newRange.endColumn += textEditorIndent.length;
} else
newRange = this._setText(range, lineBreak + indent);

newRange = newRange.collapseToEnd();

this._exitTextChangeMode(range, newRange);
this.endUpdates();
this._restoreSelection(newRange, 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;

if (!this._container.isAncestor(selection.anchorNode) || !this._container.isAncestor(selection.focusNode))
return null;
var start = this._selectionToPosition(selection.anchorNode, selection.anchorOffset);
var end = selection.isCollapsed ? start : this._selectionToPosition(selection.focusNode, selection.focusOffset);
return new WebInspector.TextRange(start.line, start.column, end.line, end.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 (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, undefined, 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);

line1 = this._textModel.line(endLine - 1);
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;
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(url)
{
WebInspector.View.call(this);
this.element.addStyleClass("script-view");

this._url = url;

this._textModel = new WebInspector.TextEditorModel();

var textViewerDelegate = new WebInspector.TextViewerDelegateForSourceFrame(this);
this._textViewer = new WebInspector.TextViewer(this._textModel, WebInspector.platform(), this._url, textViewerDelegate);

this._editButton = new WebInspector.StatusBarButton(WebInspector.UIString("Edit"), "edit-source-status-bar-item");
this._editButton.addEventListener("click", this._editButtonClicked.bind(this), this);

this._currentSearchResultIndex = -1;
this._searchResults = [];

this._messages = [];
this._rowMessages = {};
this._messageBubbles = {};
}

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 = createPlainTextSearchRegex(query, "i");

return regex;
}

WebInspector.SourceFrame.prototype = {
wasShown: function()
{
this._ensureContentLoaded();
this._textViewer.show(this.element);
if (this._wasHiddenWhileEditing)
this.setReadOnly(false);
},

willHide: function()
{
WebInspector.View.prototype.willHide.call(this);
if (this.loaded)
this._textViewer.freeCachedElements();

this._clearLineHighlight();
if (!this._textViewer.readOnly)
this._wasHiddenWhileEditing = true;
this.setReadOnly(true);
},

focus: function()
{
this._textViewer.focus();
},

get statusBarItems()
{
return [this._editButton.element];
},

get loaded()
{
return this._loaded;
},

hasContent: function()
{
return true;
},

get textViewer()
{
return this._textViewer;
},

_ensureContentLoaded: function()
{
if (!this._contentRequested) {
this._contentRequested = true;
this.requestContent(this.setContent.bind(this));
}
},

requestContent: function(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.doResize();
},

get textModel()
{
return this._textModel;
},

canHighlightLine: function(line)
{
return true;
},

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,
messages: this._messages,
diffLines: this._diffLines,
};
},

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

delete this._viewerState;
},

beforeTextChanged: function()
{
if (!this._viewerState)
this._saveViewerState();

WebInspector.searchController.cancelSearch();
this.clearMessages();
},

afterTextChanged: function(oldRange, newRange)
{
},

setContent: function(mimeType, content)
{
this._textViewer.mimeType = mimeType;

this._loaded = true;
this._textModel.setText(null, content);

this._textViewer.beginUpdates();

this._setTextViewerDecorations();

if (typeof this._lineToHighlight === "number") {
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.canEditSource())
this._editButton.disabled = true;
},

_setTextViewerDecorations: function()
{
this._rowMessages = {};
this._messageBubbles = {};

this._textViewer.beginUpdates();

this._addExistingMessagesToSource();
this._updateDiffDecorations();

this._textViewer.doResize();

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);
},

get currentSearchResultIndex()
{
return this._currentSearchResultIndex;
},

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;
},

_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].consoleMessage.isEqual(msg)) {
rowMessages[i].repeatCount = msg.totalRepeatCount;
this._updateMessageRepeatCount(rowMessages[i]);
return;
}
}

var rowMessage = { consoleMessage: msg };
rowMessages.push(rowMessage);

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));

rowMessage.element = messageLineElement;
rowMessage.repeatCount = msg.totalRepeatCount;
this._updateMessageRepeatCount(rowMessage);
},

_updateMessageRepeatCount: function(rowMessage)
{
if (rowMessage.repeatCount < 2)
return;

if (!rowMessage.repeatCountElement) {
var repeatCountElement = document.createElement("span");
rowMessage.element.appendChild(repeatCountElement);
rowMessage.repeatCountElement = repeatCountElement;
}

rowMessage.repeatCountElement.textContent = WebInspector.UIString(" (repeated %d times)", rowMessage.repeatCount);
},

populateLineGutterContextMenu: function(contextMenu, lineNumber)
{
},

populateTextAreaContextMenu: function(contextMenu, lineNumber)
{
if (!window.getSelection().isCollapsed)
return;
WebInspector.populateResourceContextMenu(contextMenu, this._url, lineNumber);
},

suggestedFileName: function()
{
},

inheritScrollPositions: function(sourceFrame)
{
this._textViewer.inheritScrollPositions(sourceFrame._textViewer);
},

_editButtonClicked: function()
{
if (!this.canEditSource())
return;

const shouldStartEditing = !this._editButton.toggled;
if (shouldStartEditing)
this.startEditing();
else
this.commitEditing();
},

canEditSource: function()
{
return false;
},

startEditing: function()
{
if (!this.canEditSource())
return false;

if (this._commitEditingInProgress)
return false;

this.setReadOnly(false);
return true;
},

commitEditing: function()
{
if (!this._viewerState) {

this.setReadOnly(true);
return;
}

this._commitEditingInProgress = true;
this._textViewer.readOnly = true;
this._editButton.toggled = false;
this.editContent(this._textModel.text, this.didEditContent.bind(this));
},

didEditContent: function(error)
{
this._commitEditingInProgress = false;
this._textViewer.readOnly = false;

if (error) {
if (error.message)
WebInspector.log(error.message, WebInspector.ConsoleMessage.MessageLevel.Error, true);
return;
}

delete this._viewerState;
},

editContent: function(newContent, callback)
{
},

cancelEditing: function()
{
this._restoreViewerState();
this.setReadOnly(true);
},

get readOnly()
{
return this._textViewer.readOnly;
},

setReadOnly: function(readOnly)
{
this._textViewer.readOnly = readOnly;
this._editButton.toggled = !readOnly;
WebInspector.markBeingEdited(this._textViewer.element, !readOnly);
}
}

WebInspector.SourceFrame.prototype.__proto__ = WebInspector.View.prototype;



WebInspector.TextViewerDelegateForSourceFrame = function(sourceFrame)
{
this._sourceFrame = sourceFrame;
}

WebInspector.TextViewerDelegateForSourceFrame.prototype = {
doubleClick: function(lineNumber)
{
this._sourceFrame.startEditing(lineNumber);
},

beforeTextChanged: function()
{
this._sourceFrame.beforeTextChanged();
},

afterTextChanged: function(oldRange, newRange)
{
this._sourceFrame.afterTextChanged(oldRange, newRange);
},

commitEditing: function()
{
this._sourceFrame.commitEditing();
},

cancelEditing: function()
{
this._sourceFrame.cancelEditing();
},

populateLineGutterContextMenu: function(contextMenu, lineNumber)
{
this._sourceFrame.populateLineGutterContextMenu(contextMenu, lineNumber);
},

populateTextAreaContextMenu: function(contextMenu, lineNumber)
{
this._sourceFrame.populateTextAreaContextMenu(contextMenu, lineNumber);
},

suggestedFileName: function()
{
return this._sourceFrame.suggestedFileName();
}
}

WebInspector.TextViewerDelegateForSourceFrame.prototype.__proto__ = WebInspector.TextViewerDelegate.prototype;






WebInspector.ResourceView = function(resource)
{
WebInspector.View.call(this);
this.registerRequiredCSS("resourceView.css");

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;
case WebInspector.resourceCategories.other:
return resource.content && !resource.contentEncoded;
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, 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 = {
canEditSource: function()
{
return this.resource.isEditable() && !this._commitEditingInProgress;
},

editContent: function(newText, callback)
{
this._clearIncrementalUpdateTimer();
var majorChange = true;
this.resource.setContent(newText, majorChange, callback);
},

cancelEditing: function()
{
this._clearIncrementalUpdateTimer();
const majorChange = false;
if (this._viewerState)
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.JavaScriptSourceFrame = function(scriptsPanel, model, uiSourceCode)
{
WebInspector.SourceFrame.call(this, uiSourceCode.url);

this._scriptsPanel = scriptsPanel;
this._model = model;
this._uiSourceCode = uiSourceCode;
this._popoverObjectGroup = "popover";
this._breakpoints = {};
this._popoverHelper = new WebInspector.ObjectPopoverHelper(this.textViewer.element,
this._getPopoverAnchor.bind(this), this._onShowPopover.bind(this), this._onHidePopover.bind(this), true);

this.textViewer.element.addEventListener("mousedown", this._onMouseDown.bind(this), true);
this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.ContentChanged, this._onContentChanged, this);
this.addEventListener(WebInspector.SourceFrame.Events.Loaded, this._onTextViewerContentLoaded, this);
}

WebInspector.JavaScriptSourceFrame.prototype = {

willHide: function()
{
WebInspector.SourceFrame.prototype.willHide.call(this);
this._popoverHelper.hidePopover();
},


requestContent: function(callback)
{
this._uiSourceCode.requestContent(callback);
},

canEditSource: function()
{
return this._model.canEditScriptSource(this._uiSourceCode);
},

suggestedFileName: function()
{
var names = this._scriptsPanel.folderAndDisplayNameForScriptURL(this._uiSourceCode.url);
return names.displayName || "untitled.js";
},

editContent: function(newContent, callback)
{
this._model.setScriptSource(this._uiSourceCode, newContent, callback);
},

_onContentChanged: function()
{
if (!this.textViewer.readOnly)
return;
this.requestContent(this.setContent.bind(this));
},

setReadOnly: function(readOnly)
{
if (!readOnly)
this._popoverHelper.hidePopover();
WebInspector.SourceFrame.prototype.setReadOnly.call(this, readOnly);
if (readOnly)
this._scriptsPanel.setScriptSourceIsBeingEdited(this._uiSourceCode, false);
},

populateLineGutterContextMenu: function(contextMenu, lineNumber)
{
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Continue to here" : "Continue to Here"), this._model.continueToLine.bind(this._model, this._uiSourceCode, lineNumber));

var breakpoint = this._model.findBreakpoint(this._uiSourceCode, lineNumber);
if (!breakpoint) {

contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add breakpoint" : "Add Breakpoint"), this._setBreakpoint.bind(this, lineNumber, "", true));

function addConditionalBreakpoint()
{
this.addBreakpoint(lineNumber, true, true, true);
function didEditBreakpointCondition(committed, condition)
{
this.removeBreakpoint(lineNumber);
if (committed)
this._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._model.removeBreakpoint.bind(this._model, this._uiSourceCode, lineNumber));

function editBreakpointCondition()
{
function didEditBreakpointCondition(committed, condition)
{
if (committed)
this._model.updateBreakpoint(this._uiSourceCode, 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._model.updateBreakpoint(this._uiSourceCode, 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, lineNumber)
{
WebInspector.SourceFrame.prototype.populateTextAreaContextMenu.call(this, contextMenu, lineNumber);
var selection = window.getSelection();
if (selection.type !== "Range" || selection.isCollapsed)
return;
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add to watch" : "Add to Watch"),
this._scriptsPanel.addToWatch.bind(this._scriptsPanel, selection.toString()));

contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Evaluate in console" : "Evaluate in Console"), WebInspector.evaluateInConsole.bind(WebInspector, selection.toString()));
},

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);
}
}
},

beforeTextChanged: function()
{
if (!this._javaScriptSourceFrameState) {
this._javaScriptSourceFrameState = {
executionLineNumber: this._executionLineNumber,
breakpoints: this._breakpoints
}
this._scriptsPanel.setScriptSourceIsBeingEdited(this._uiSourceCode, true);
}
WebInspector.SourceFrame.prototype.beforeTextChanged.call(this);
},

cancelEditing: function()
{
WebInspector.SourceFrame.prototype.cancelEditing.call(this);

if (!this._javaScriptSourceFrameState)
return;

if (typeof this._javaScriptSourceFrameState.executionLineNumber === "number") {
this.clearExecutionLine();
this.setExecutionLine(this._javaScriptSourceFrameState.executionLineNumber);
}

var oldBreakpoints = this._breakpoints;
this._breakpoints = {};
for (var lineNumber in oldBreakpoints)
this.removeBreakpoint(Number(lineNumber));

var newBreakpoints = this._javaScriptSourceFrameState.breakpoints;
for (var lineNumber in newBreakpoints) {
lineNumber = Number(lineNumber);
var breakpoint = newBreakpoints[lineNumber];
this.addBreakpoint(lineNumber, breakpoint.resolved, breakpoint.conditional, breakpoint.enabled);
}

delete this._javaScriptSourceFrameState;
},

didEditContent: function(error)
{
WebInspector.SourceFrame.prototype.didEditContent.call(this, error);
if (error)
return;

var newBreakpoints = {};
for (var lineNumber in this._breakpoints) {
newBreakpoints[lineNumber] = this._breakpoints[lineNumber];
this.removeBreakpoint(Number(lineNumber));
}

for (var lineNumber in this._javaScriptSourceFrameState.breakpoints)
this._model.removeBreakpoint(this._uiSourceCode, Number(lineNumber));

for (var lineNumber in newBreakpoints) {
var breakpoint = newBreakpoints[lineNumber];
this._setBreakpoint(Number(lineNumber), breakpoint.condition, breakpoint.enabled);
}
this._scriptsPanel.setScriptSourceIsBeingEdited(this._uiSourceCode, false);
delete this._javaScriptSourceFrameState;
},


_shouldShowPopover: function(element)
{
if (!this._model.paused)
return false;
if (!element.enclosingNodeOrSelfWithClass("webkit-line-content"))
return false;
if (window.getSelection().type === "Range")
return false;


if (element.hasStyleClass("webkit-javascript-keyword"))
return element.textContent === "this";

return element.hasStyleClass("webkit-javascript-ident");
},

_getPopoverAnchor: function(element)
{
if (!this._shouldShowPopover(element))
return;
return element;
},

_onShowPopover: function(element, showCallback)
{
if (!this.readOnly) {
this._popoverHelper.hidePopover();
return;
}
this._highlightElement = this._highlightExpression(element);

function showObjectPopover(result, wasThrown)
{
if (!this._model.paused) {
this._popoverHelper.hidePopover();
return;
}
showCallback(WebInspector.RemoteObject.fromPayload(result), wasThrown);

if (this._highlightElement)
this._highlightElement.addStyleClass("source-frame-eval-expression");
}

var selectedCallFrame = this._model.selectedCallFrame;
selectedCallFrame.evaluate(this._highlightElement.textContent, this._popoverObjectGroup, false, false, showObjectPopover.bind(this));
},

_onHidePopover: function()
{

var highlightElement = this._highlightElement;
if (!highlightElement)
return;


var parentElement = highlightElement.parentElement;
if (parentElement) {
var child = highlightElement.firstChild;
while (child) {
var nextSibling = child.nextSibling;
parentElement.insertBefore(child, highlightElement);
child = nextSibling;
}
parentElement.removeChild(highlightElement);
}
delete this._highlightElement;
RuntimeAgent.releaseObjectGroup(this._popoverObjectGroup);
},

_highlightExpression: function(element)
{

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);
return container;
},

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();
},

_setBreakpoint: function(lineNumber, condition, enabled)
{
this._model.setBreakpoint(this._uiSourceCode, lineNumber, condition, enabled);
this._scriptsPanel.activateBreakpoints();
},

_onMouseDown: function(event)
{
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._model.findBreakpoint(this._uiSourceCode, lineNumber);
if (breakpoint) {
if (event.shiftKey)
this._model.updateBreakpoint(this._uiSourceCode, lineNumber, breakpoint.condition, !breakpoint.enabled);
else
this._model.removeBreakpoint(this._uiSourceCode, lineNumber);
} else
this._setBreakpoint(lineNumber, "", true);
event.preventDefault();
},

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

var config = new WebInspector.EditingConfig(finishEditing.bind(this, true), finishEditing.bind(this, false));
WebInspector.startEditing(this._conditionEditorElement, config);
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;
},


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;
},

_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;
},

_onTextViewerContentLoaded: function()
{
if (typeof this._executionLineNumber === "number")
this.setExecutionLine(this._executionLineNumber);
}
}

WebInspector.JavaScriptSourceFrame.prototype.__proto__ = WebInspector.SourceFrame.prototype;






WebInspector.SplitView = function(sidebarPosition, sidebarWidthSettingName, defaultSidebarWidth)
{
WebInspector.View.call(this);
this.registerRequiredCSS("splitView.css");

this.element.className = "split-view";

this._leftElement = document.createElement("div");
this._leftElement.className = "split-view-contents";
this.element.appendChild(this._leftElement);

this._rightElement = document.createElement("div");
this._rightElement.className = "split-view-contents";
this.element.appendChild(this._rightElement);

this.sidebarResizerElement = document.createElement("div");
this.sidebarResizerElement.className = "split-view-resizer";
this.installResizer(this.sidebarResizerElement);
this._resizable = true;
this.element.appendChild(this.sidebarResizerElement);

defaultSidebarWidth = defaultSidebarWidth || 200;
this._savedSidebarWidth = defaultSidebarWidth;

this._sidebarWidthSettingName = sidebarWidthSettingName;
if (this._sidebarWidthSettingName)
WebInspector.settings[this._sidebarWidthSettingName] = WebInspector.settings.createSetting(this._sidebarWidthSettingName, undefined);

this._minimalSidebarWidth = Preferences.minSidebarWidth;
this._minimalMainWidth = 0;
this._minimalSidebarWidthPercent = 0;
this._minimalMainWidthPercent = 50;

this._mainElementHidden = false;
this._sidebarElementHidden = false;

this._innerSetSidebarPosition(sidebarPosition || WebInspector.SplitView.SidebarPosition.Left);
}

WebInspector.SplitView.EventTypes = {
Resized: "Resized",
}


WebInspector.SplitView.SidebarPosition = {
Left: "Left",
Right: "Right"
}

WebInspector.SplitView.prototype = {

get hasLeftSidebar()
{
return this._sidebarPosition === WebInspector.SplitView.SidebarPosition.Left;
},


get mainElement()
{
return this.hasLeftSidebar ? this._rightElement : this._leftElement;
},


get sidebarElement()
{
return this.hasLeftSidebar ? this._leftElement : this._rightElement;
},


get resizable()
{
return this._resizable && !this._mainElementHidden && !this._sidebarElementHidden
},


set resizable(resizable)
{
if (this._resizable === resizable)
return;
this._resizable = resizable;
this._updateResizer(resizable);
},

_updateResizer: function()
{
if (this.resizable)
this.sidebarResizerElement.removeStyleClass("hidden");
else
this.sidebarResizerElement.addStyleClass("hidden");
},


set sidebarPosition(sidebarPosition)
{
if (this._sidebarPosition === sidebarPosition)
return;
this._innerSetSidebarPosition(sidebarPosition);
this._restoreSidebarWidth();
},


_innerSetSidebarPosition: function(sidebarPosition)
{
this._sidebarPosition = sidebarPosition;

this._leftElement.style.left = 0;
this._rightElement.style.right = 0;
if (this.hasLeftSidebar) {
this._leftElement.addStyleClass("split-view-sidebar-left");
this._rightElement.removeStyleClass("split-view-sidebar-right");
this._leftElement.style.removeProperty("right");
this._rightElement.style.removeProperty("width");
this.sidebarResizerElement.style.removeProperty("right");
} else {
this._rightElement.addStyleClass("split-view-sidebar-right");
this._leftElement.removeStyleClass("split-view-sidebar-left");
this._leftElement.style.removeProperty("width");
this._rightElement.style.removeProperty("left");
this.sidebarResizerElement.style.removeProperty("left");
}
},


set minimalSidebarWidth(width)
{
this._minimalSidebarWidth = width;
},


set minimalMainWidth(width)
{
this._minimalMainWidth = width;
},


set minimalSidebarWidthPercent(widthPercent)
{
this._minimalSidebarWidthPercent = widthPercent;
},


set minimalMainWidthPercent(widthPercent)
{
this._minimalMainWidthPercent = widthPercent;
},


setMainWidth: function(width)
{
this.setSidebarWidth(this._totalWidth - width);
},


setSidebarWidth: function(width)
{
if (this._sidebarWidth === width)
return;

this._innerSetSidebarWidth(width);
this.saveSidebarWidth();
},


_innerSetSidebarWidth: function(width)
{
if (this.hasLeftSidebar)
this._innerSetLeftSidebarWidth(width);
else
this._innerSetRightSidebarWidth(width);
this._sidebarWidth = width;
this.doResize();
this.dispatchEventToListeners(WebInspector.SplitView.EventTypes.Resized, this._sidebarWidth);
},


_innerSetLeftSidebarWidth: function(width)
{
this._leftElement.style.width = width + "px";
this._rightElement.style.left = width + "px";
this.sidebarResizerElement.style.left = (width - 3) + "px";
},


_innerSetRightSidebarWidth: function(width)
{
this._rightElement.style.width = width + "px";
this._leftElement.style.right = width + "px";
this.sidebarResizerElement.style.right = (width - 3) + "px";
},


_setSidebarWidthEnsuringConstraints: function(width)
{
var minWidth = Math.max(this._minimalSidebarWidth, this._totalWidth * this._minimalSidebarWidthPercent);
var maxWidth = Math.min(this._totalWidth - this._minimalMainWidth, this._totalWidth * (100 - this._minimalMainWidthPercent) / 100 );
width = Number.constrain(width, minWidth, maxWidth);

this.setSidebarWidth(width);
},

hideMainElement: function()
{
if (this._mainElementHidden)
return;

if (this._sidebarElementHidden)
this.showSidebarElement();

this.mainElement.addStyleClass("hidden");
this.sidebarElement.addStyleClass("maximized");

if (this.hasLeftSidebar)
this.sidebarElement.style.right = "0px";
else
this.sidebarElement.style.left = "0px";

this._mainElementHidden = true;
this._updateResizer();
this._restoreSidebarWidth();
},

showMainElement: function()
{
if (!this._mainElementHidden)
return;

this.mainElement.removeStyleClass("hidden");
this.sidebarElement.removeStyleClass("maximized");

if (this.hasLeftSidebar)
this.sidebarElement.style.right = "";
else
this.sidebarElement.style.left = "";

this._mainElementHidden = false;
this._updateResizer();
this._restoreSidebarWidth();
},

hideSidebarElement: function()
{
if (this._sidebarElementHidden)
return;

if (this._mainElementHidden)
this.showMainElement();

this.sidebarElement.addStyleClass("hidden");
this._sidebarElementHidden = true;
this._updateResizer();
this._restoreSidebarWidth();
},

showSidebarElement: function()
{
if (!this._sidebarElementHidden)
return;

this.sidebarElement.removeStyleClass("hidden");
this._sidebarElementHidden = false;
this._updateResizer();
this._restoreSidebarWidth();
},

wasShown: function()
{
this._totalWidth = this.element.offsetWidth;
this._restoreSidebarWidth();
},

onResize: function()
{
this._totalWidth = this.element.offsetWidth;

if (this._mainElementHidden)
this._sidebarWidth = this._totalWidth;
},


_startResizerDragging: function(event)
{
if (!this._resizable)
return;

var leftWidth = this.hasLeftSidebar ? this._sidebarWidth : this._totalWidth - this._sidebarWidth;
this._dragOffset = leftWidth - event.pageX;

WebInspector.elementDragStart(this.sidebarResizerElement, this._resizerDragging.bind(this), this._endResizerDragging.bind(this), event, "ew-resize");
},


_resizerDragging: function(event)
{
var leftWidth = event.pageX + this._dragOffset
var rightWidth = this._totalWidth - leftWidth;
var sidebarWidth = this.hasLeftSidebar ? leftWidth : rightWidth;

this._setSidebarWidthEnsuringConstraints(sidebarWidth);
event.preventDefault();
},


_endResizerDragging: function(event)
{
delete this._dragOffset;
WebInspector.elementDragEnd(event);
},


installResizer: function(resizerElement)
{
resizerElement.addEventListener("mousedown", this._startResizerDragging.bind(this), false);
},


preferredSidebarWidth: function()
{
if (!this._sidebarWidthSettingName)
return this._savedSidebarWidth;

return WebInspector.settings[this._sidebarWidthSettingName].get() || this._savedSidebarWidth;
},

_restoreSidebarWidth: function()
{
if (this._mainElementHidden) {
this.sidebarElement.style.width = "";
this._sidebarWidth = this._totalWidth;
return;
}

if (this._sidebarElementHidden) {
this._innerSetSidebarWidth(0);
return;
}


this._setSidebarWidthEnsuringConstraints(this.preferredSidebarWidth());
},

saveSidebarWidth: function()
{
this._savedSidebarWidth = this._sidebarWidth;
if (!this._sidebarWidthSettingName)
return;

WebInspector.settings[this._sidebarWidthSettingName].set(this._sidebarWidth);
},


elementsToRestoreScrollPositionsFor: function()
{
return [ this.mainElement, this.sidebarElement ];
}
}

WebInspector.SplitView.prototype.__proto__ = WebInspector.View.prototype;






WebInspector.ScriptsPanel = function(presentationModel)
{
WebInspector.Panel.call(this, "scripts");
this.registerRequiredCSS("scriptsPanel.css");

WebInspector.settings.pauseOnExceptionStateString = WebInspector.settings.createSetting("pauseOnExceptionStateString", WebInspector.ScriptsPanel.PauseOnExceptionsState.DontPauseOnExceptions);

this._presentationModel = presentationModel;

function viewGetter()
{
return this.visibleView;
}
WebInspector.GoToLineDialog.install(this, viewGetter.bind(this));

this.editorToolbar = this._createEditorToolbar();
this.debugToolbar = this._createDebugToolbar();

const initialSidebarWidth = 225;
const minimalViewsContainerWidthPercent = 34;
this.createSplitView(this.element, WebInspector.SplitView.SidebarPosition.Right, initialSidebarWidth);
this.splitView.element.id = "scripts-split-view";
this.splitView.minimalSidebarWidth = Preferences.minScriptsSidebarWidth;
this.splitView.minimalMainWidthPercent = minimalViewsContainerWidthPercent;

this.sidebarElement.appendChild(this.debugToolbar);
this.splitView.mainElement.appendChild(this.editorToolbar);

this.viewsContainerElement = this.splitView.mainElement;

this.debugSidebarResizeWidgetElement = document.createElement("div");
this.debugSidebarResizeWidgetElement.id = "scripts-debug-sidebar-resizer-widget";
this.splitView.installResizer(this.debugSidebarResizeWidgetElement);
this.editorToolbar.appendChild(this.debugSidebarResizeWidgetElement);

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 (Capabilities.nativeInstrumentationEnabled) {
this.sidebarPanes.domBreakpoints = WebInspector.domBreakpointsSidebarPane;
this.sidebarPanes.xhrBreakpoints = new WebInspector.XHRBreakpointsSidebarPane();
this.sidebarPanes.eventListenerBreakpoints = new WebInspector.EventListenerBreakpointsSidebarPane();
}

if (Preferences.exposeWorkersInspection && !WebInspector.WorkerManager.isWorkerFrontend()) {
WorkerAgent.setWorkerInspectionEnabled(true);
this.sidebarPanes.workerList = new WebInspector.WorkerListSidebarPane(WebInspector.workerManager);
} else
this.sidebarPanes.workers = new WebInspector.WorkersSidebarPane();

this._debugSidebarContentsElement = document.createElement("div");
this._debugSidebarContentsElement.id = "scripts-debug-sidebar-contents";
this.sidebarElement.appendChild(this._debugSidebarContentsElement);    

for (var pane in this.sidebarPanes)
this._debugSidebarContentsElement.appendChild(this.sidebarPanes[pane].element);

this.sidebarPanes.callstack.expanded = true;

this.sidebarPanes.scopechain.expanded = true;
this.sidebarPanes.jsBreakpoints.expanded = true;

var helpSection = WebInspector.shortcutsScreen.section(WebInspector.UIString("Scripts Panel"));
this.sidebarPanes.callstack.registerShortcuts(helpSection, this.registerShortcut.bind(this));
var evaluateInConsoleShortcut = WebInspector.KeyboardShortcut.makeDescriptor("e", WebInspector.KeyboardShortcut.Modifiers.Shift | WebInspector.KeyboardShortcut.Modifiers.Ctrl);
helpSection.addKey(evaluateInConsoleShortcut.name, WebInspector.UIString("Evaluate selection in console"));
this.registerShortcut(evaluateInConsoleShortcut.key, this._evaluateSelectionInConsole.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.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
this.enableToggleButton.addEventListener("click", this.toggleDebugging, this);
if (!Capabilities.debuggerCausesRecompilation)
this.enableToggleButton.element.addStyleClass("hidden");

this._pauseOnExceptionButton = new WebInspector.StatusBarButton("", "scripts-pause-on-exceptions-status-bar-item", 3);
this._pauseOnExceptionButton.addEventListener("click", this._togglePauseOnExceptions, this);

this._toggleFormatSourceButton = new WebInspector.StatusBarButton(WebInspector.UIString("Pretty print"), "scripts-toggle-pretty-print-status-bar-item");
this._toggleFormatSourceButton.toggled = false;
this._toggleFormatSourceButton.addEventListener("click", this._toggleFormatSource, this);

this._scriptViewStatusBarItemsContainer = document.createElement("div");
this._scriptViewStatusBarItemsContainer.style.display = "inline-block";

this._debuggerEnabled = !Capabilities.debuggerCausesRecompilation;

this._reset(false);

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.UISourceCodeAdded, this._uiSourceCodeAdded, this)
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.UISourceCodeReplaced, this._uiSourceCodeReplaced, this);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, 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);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame, this._consoleCommandEvaluatedInSelectedCallFrame, this);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.ExecutionLineChanged, this._executionLineChanged, this);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.DebuggerReset, this._reset.bind(this, false));

var enableDebugger = !Capabilities.debuggerCausesRecompilation || WebInspector.settings.debuggerEnabled.get();
if (enableDebugger)
WebInspector.debuggerModel.enableDebugger();

WebInspector.settings.showScriptFolders.addChangeListener(this._showScriptFoldersSettingChanged.bind(this));

WebInspector.advancedSearchController.registerSearchScope(new WebInspector.ScriptsSearchScope());
}


WebInspector.ScriptsPanel.PauseOnExceptionsState = {
DontPauseOnExceptions : "none",
PauseOnAllExceptions : "all",
PauseOnUncaughtExceptions: "uncaught"
};

WebInspector.ScriptsPanel.prototype = {
get toolbarItemLabel()
{
return WebInspector.UIString("Scripts");
},

get statusBarItems()
{
return [this.enableToggleButton.element, this._pauseOnExceptionButton.element, this._toggleFormatSourceButton.element, this._scriptViewStatusBarItemsContainer];
},

get defaultFocusedElement()
{
return this._filesSelectElement;
},

get paused()
{
return this._paused;
},

wasShown: function()
{
WebInspector.Panel.prototype.wasShown.call(this);
if (Capabilities.nativeInstrumentationEnabled)
this._debugSidebarContentsElement.insertBefore(this.sidebarPanes.domBreakpoints.element, this.sidebarPanes.xhrBreakpoints.element);
this.sidebarPanes.watchExpressions.show();
},

breakpointsActivated: function()
{
return this.toggleBreakpointsButton.toggled;
},

activateBreakpoints: function()
{
if (!this.breakpointsActivated)
this._toggleBreakpointsClicked();
},

_uiSourceCodeAdded: function(event)
{
var uiSourceCode = event.data;

if (!uiSourceCode.url) {

return;
}

this._addOptionToFilesSelect(uiSourceCode);

var lastViewedURL = WebInspector.settings.lastViewedScriptFile.get();
if (!this._filesSelectElement.initialSelectionProcessed) {
this._filesSelectElement.initialSelectionProcessed = true;


this._showSourceFrameAndAddToHistory(uiSourceCode);


WebInspector.settings.lastViewedScriptFile.set(lastViewedURL);
} else if (uiSourceCode.url === lastViewedURL)
this._showSourceFrameAndAddToHistory(uiSourceCode);
},

_uiSourceCodeRemoved: function(event)
{
var uiSourceCode = event.data;
if (uiSourceCode._sourceFrame)
uiSourceCode._sourceFrame.detach();
},

_showScriptFoldersSettingChanged: function()
{
var selectedOption = this._filesSelectElement[this._filesSelectElement.selectedIndex];
var uiSourceCode = selectedOption ? selectedOption._uiSourceCode : null;

var options = Array.prototype.slice.call(this._filesSelectElement);
this._resetFilesSelect();
for (var i = 0; i < options.length; ++i) {
if (options[i]._uiSourceCode)
this._addOptionToFilesSelect(options[i]._uiSourceCode);
}

if (uiSourceCode) {
var index = uiSourceCode._option.index;
if (typeof index === "number")
this._filesSelectElement.selectedIndex = index;
}
},

_addOptionToFilesSelect: function(uiSourceCode)
{
var showScriptFolders = WebInspector.settings.showScriptFolders.get();

var select = this._filesSelectElement;
if (!select.domainOptions)
select.domainOptions = {};
if (!select.folderOptions)
select.folderOptions = {};

var option = document.createElement("option");
option._uiSourceCode = uiSourceCode;
var parsedURL = uiSourceCode.url.asParsedURL();

const indent = WebInspector.isMac() ? "" : "\u00a0\u00a0\u00a0\u00a0";

var names = this.folderAndDisplayNameForScriptURL(uiSourceCode.url);
option.displayName = names.displayName;

var contentScriptPrefix = uiSourceCode.isContentScript ? "2:" : "0:";

if (uiSourceCode.isContentScript && names.domain) {

names.folderName = names.domain + (names.folderName ? names.folderName : "");
delete names.domain;
}

var folderNameForSorting = contentScriptPrefix + (names.domain ? names.domain + "\t\t" : "") + names.folderName;

if (showScriptFolders) {
option.text = indent + (names.displayName ? names.displayName : WebInspector.UIString("(program)"));
option.nameForSorting = folderNameForSorting + "\t/\t" + names.displayName; 
} else {
option.text = names.displayName ? names.displayName : WebInspector.UIString("(program)");

if (uiSourceCode.isContentScript && names.folderName)
option.text = names.folderName + "/" + option.text;
option.nameForSorting = contentScriptPrefix + option.text;
}
option.title = uiSourceCode.url;

if (uiSourceCode.isContentScript)
option.addStyleClass("extension-script");

function insertOrdered(option)
{
function optionCompare(a, b)
{
return a.nameForSorting.localeCompare(b.nameForSorting);
}
var insertionIndex = insertionIndexForObjectInListSortedByFunction(option, select.childNodes, optionCompare);
select.insertBefore(option, insertionIndex < 0 ? null : select.childNodes.item(insertionIndex));
}

insertOrdered(option);

if (uiSourceCode.isContentScript && !select.contentScriptSection) {
var contentScriptSection = document.createElement("option");
contentScriptSection.text = "\u2014 " + WebInspector.UIString("Content scripts") + " \u2014";
contentScriptSection.disabled = true;
contentScriptSection.nameForSorting = "1/ContentScriptSeparator";
select.contentScriptSection = contentScriptSection;
insertOrdered(contentScriptSection);
}

if (showScriptFolders && !uiSourceCode.isContentScript && names.domain && !select.domainOptions[names.domain]) {
var domainOption = document.createElement("option");
domainOption.text = "\u2014 " + names.domain + " \u2014";
domainOption.nameForSorting = "0:" + names.domain;
domainOption.disabled = true;
select.domainOptions[names.domain] = domainOption;
insertOrdered(domainOption);
}

if (showScriptFolders && names.folderName && !select.folderOptions[folderNameForSorting]) {
var folderOption = document.createElement("option");
folderOption.text = names.folderName;
folderOption.nameForSorting = folderNameForSorting;
folderOption.disabled = true;
select.folderOptions[folderNameForSorting] = folderOption;
insertOrdered(folderOption);
}

option._uiSourceCode = uiSourceCode;
uiSourceCode._option = option;
},

folderAndDisplayNameForScriptURL: function(url)
{
var parsedURL = url.asParsedURL();
if (parsedURL)
url = parsedURL.path;

var folderName = "";
var displayName = url;

var pathLength = displayName.indexOf("?");
if (pathLength === -1)
pathLength = displayName.length;

var fromIndex = displayName.lastIndexOf("/", pathLength - 2);
if (fromIndex !== -1) {
folderName = displayName.substring(0, fromIndex);
displayName = displayName.substring(fromIndex + 1);
}

if (displayName.length > 80)
displayName = "\u2026" + displayName.substring(displayName.length - 80);

if (folderName.length > 80)
folderName = "\u2026" + folderName.substring(folderName.length - 80);

return { domain: (parsedURL ? parsedURL.host : ""), folderName: folderName, displayName: displayName };
},

setScriptSourceIsBeingEdited: function(uiSourceCode, inEditMode)
{
var option = uiSourceCode._option;
if (!option)
return;
if (inEditMode)
option.text = option.text.replace(/[^*]$/, "$&*");
else
option.text = option.text.replace(/[*]$/, "");
},

_consoleMessagesCleared: function()
{
for (var i = 0; i < this._filesSelectElement.length; ++i) {
var option = this._filesSelectElement[i];
if (option._uiSourceCode && option._uiSourceCode._sourceFrame)
option._uiSourceCode._sourceFrame.clearMessages();
}
},

_consoleMessageAdded: function(event)
{
var message = event.data;

var sourceFrame = message.uiSourceCode._sourceFrame;
if (sourceFrame && sourceFrame.loaded)
sourceFrame.addMessageToSource(message.lineNumber, message.originalMessage);
},

_breakpointAdded: function(event)
{
var breakpoint = event.data;

var sourceFrame = breakpoint.uiSourceCode._sourceFrame;
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 = breakpoint.uiSourceCode._sourceFrame;
if (sourceFrame && sourceFrame.loaded)
sourceFrame.removeBreakpoint(breakpoint.lineNumber);

this.sidebarPanes.jsBreakpoints.removeBreakpoint(breakpoint.uiSourceCode, breakpoint.lineNumber);
},

_consoleCommandEvaluatedInSelectedCallFrame: function(event)
{
this.sidebarPanes.scopechain.update(this._presentationModel.selectedCallFrame);
},

_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.inspectorView.setCurrentPanel(this);

this.sidebarPanes.callstack.update(callFrames);
this._updateCallFrame(this._presentationModel.selectedCallFrame);

if (details.reason === WebInspector.DebuggerModel.BreakReason.DOM) {
this.sidebarPanes.domBreakpoints.highlightBreakpoint(details.auxData);
function didCreateBreakpointHitStatusMessage(element)
{
this.sidebarPanes.callstack.setStatus(element);
}
this.sidebarPanes.domBreakpoints.createBreakpointHitStatusMessage(details.auxData, didCreateBreakpointHitStatusMessage.bind(this));
} else if (details.reason === WebInspector.DebuggerModel.BreakReason.EventListener) {
var eventName = details.auxData.eventName;
this.sidebarPanes.eventListenerBreakpoints.highlightBreakpoint(details.auxData.eventName);
var eventNameForUI = WebInspector.EventListenerBreakpointsSidebarPane.eventNameForUI(eventName);
this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a \"%s\" Event Listener.", eventNameForUI));
} else if (details.reason === WebInspector.DebuggerModel.BreakReason.XHR) {
this.sidebarPanes.xhrBreakpoints.highlightBreakpoint(details.auxData["breakpointURL"]);
this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a XMLHttpRequest."));
} else if (details.reason === WebInspector.DebuggerModel.BreakReason.Exception) {
this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on exception: '%s'.", details.auxData.description));
} else {
function didGetUILocation(uiLocation)
{
if (!this._presentationModel.findBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber))
return;
this.sidebarPanes.jsBreakpoints.highlightBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber);
this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint."));
}
callFrames[0].uiLocation(didGetUILocation.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.get());

if (this._debuggerEnabled)
return;

this._debuggerEnabled = true;
this._reset(true);
},

_debuggerWasDisabled: function()
{
if (!this._debuggerEnabled)
return;

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();

this._resetFilesSelect();
delete this._filesSelectElement.initialSelectionProcessed;

this.functionsSelectElement.removeChildren();
this.visibleView = null;

this.sidebarPanes.jsBreakpoints.reset();
this.sidebarPanes.watchExpressions.reset();
if (!preserveItems && this.sidebarPanes.workers)
this.sidebarPanes.workers.reset();
},

_resetFilesSelect: function()
{
this._filesSelectElement.removeChildren();
this._filesSelectElement.domainOptions = {};
this._filesSelectElement.folderOptions = {};
delete this._filesSelectElement.contentScriptSection;
},

get visibleView()
{
return this._visibleView;
},

set visibleView(x)
{
if (this._visibleView === x)
return;

if (this._visibleView)
this._visibleView.detach();

this._visibleView = x;

if (x) {
x.show(this.viewsContainerElement);
this._scriptViewStatusBarItemsContainer.removeChildren();
var statusBarItems = x.statusBarItems || [];
for (var i = 0; i < statusBarItems.length; ++i)
this._scriptViewStatusBarItemsContainer.appendChild(statusBarItems[i]);
}
},

canShowAnchorLocation: function(anchor)
{
return this._debuggerEnabled && anchor.uiSourceCode;
},

showAnchorLocation: function(anchor)
{
this._showSourceLine(anchor.uiSourceCode, anchor.lineNumber);
},

showFunctionDefinition: function(functionLocation)
{
WebInspector.showPanelForAnchorNavigation(this);
var uiLocation = this._presentationModel.rawLocationToUILocation(functionLocation);
this._showSourceLine(uiLocation.uiSourceCode, uiLocation.lineNumber);
},

_showSourceLine: function(uiSourceCode, lineNumber)
{
var sourceFrame = this._showSourceFrameAndAddToHistory(uiSourceCode);
if (typeof lineNumber === "number")
sourceFrame.highlightLine(lineNumber);
},

_showSourceFrameAndAddToHistory: function(uiSourceCode)
{
if (!uiSourceCode._option)
return;

var sourceFrame = this._showSourceFrame(uiSourceCode);

var oldIndex = this._currentBackForwardIndex;
if (oldIndex >= 0)
this._backForwardList.splice(oldIndex + 1, this._backForwardList.length - oldIndex);



var previousEntryIndex = this._backForwardList.indexOf(uiSourceCode);
if (previousEntryIndex !== -1)
this._backForwardList.splice(previousEntryIndex, 1);

this._backForwardList.push(uiSourceCode);
this._currentBackForwardIndex = this._backForwardList.length - 1;

this._updateBackAndForwardButtons();

return sourceFrame;
},

_showSourceFrame: function(uiSourceCode)
{
this._filesSelectElement.selectedIndex = uiSourceCode._option.index;

var sourceFrame = uiSourceCode._sourceFrame || this._createSourceFrame(uiSourceCode);
this.visibleView = sourceFrame;

if (uiSourceCode.url)
WebInspector.settings.lastViewedScriptFile.set(uiSourceCode.url);

return sourceFrame;
},

_createSourceFrame: function(uiSourceCode)
{
var sourceFrame = new WebInspector.JavaScriptSourceFrame(this, this._presentationModel, uiSourceCode);

sourceFrame._uiSourceCode = uiSourceCode;
sourceFrame.addEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this);
uiSourceCode._sourceFrame = sourceFrame;
return sourceFrame;
},

_removeSourceFrame: function(uiSourceCode)
{
var option = uiSourceCode._option;

if (option && this._filesSelectElement === option.parentElement)
this._filesSelectElement.removeChild(option);

var sourceFrame = uiSourceCode._sourceFrame;
if (!sourceFrame)
return;
delete uiSourceCode._sourceFrame;
sourceFrame.detach();
sourceFrame.removeEventListener(WebInspector.SourceFrame.Events.Loaded, this._sourceFrameLoaded, this);
},

_uiSourceCodeReplaced: function(event)
{
var oldUISourceCodeList = event.data.oldUISourceCodeList;
var uiSourceCodeList = event.data.uiSourceCodeList;

var visible = false;
for (var i = 0; i < oldUISourceCodeList.length; ++i) {
var uiSourceCode = oldUISourceCodeList[i];
if (uiSourceCode._sourceFrame === this.visibleView)
visible = true;
this._removeSourceFrame(uiSourceCode);
}

for (var i = 0; i < uiSourceCodeList.length; ++i)
this._uiSourceCodeAdded({ data: uiSourceCodeList[i] });

if (visible)
this._showSourceFrame(uiSourceCodeList[0]);
},

_sourceFrameLoaded: function(event)
{
var sourceFrame = event.target;
var uiSourceCode = sourceFrame._uiSourceCode;

var messages = this._presentationModel.messagesForUISourceCode(uiSourceCode);
for (var i = 0; i < messages.length; ++i) {
var message = messages[i];
sourceFrame.addMessageToSource(message.lineNumber, message.originalMessage);
}

var breakpoints = this._presentationModel.breakpointsForUISourceCode(uiSourceCode);
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;
},

_executionLineChanged: function(event)
{
var uiLocation = event.data;

this._updateExecutionLine(uiLocation);
},

_updateExecutionLine: function(uiLocation)
{
this._clearCurrentExecutionLine();
if (!uiLocation)
return;

if (!uiLocation.uiSourceCode._option) {

this._addOptionToFilesSelect(uiLocation.uiSourceCode);
}
var sourceFrame = this._showSourceFrameAndAddToHistory(uiLocation.uiSourceCode);
sourceFrame.setExecutionLine(uiLocation.lineNumber);
this._executionSourceFrame = sourceFrame;
},

_callFrameSelected: function(event)
{
var callFrame = event.data;

if (!callFrame)
return;

this._updateCallFrame(callFrame);
},

_updateCallFrame: function(callFrame)
{
this.sidebarPanes.scopechain.update(callFrame);
this.sidebarPanes.watchExpressions.refreshExpressions();
this.sidebarPanes.callstack.selectedCallFrame = callFrame;
this._updateExecutionLine(this._presentationModel.executionLineLocation);
},

_filesSelectChanged: function(focusSource)
{
if (this._filesSelectElement.selectedIndex === -1)
return;

var uiSourceCode = this._filesSelectElement[this._filesSelectElement.selectedIndex]._uiSourceCode;
var sourceFrame = this._showSourceFrameAndAddToHistory(uiSourceCode);
if (sourceFrame && focusSource)
sourceFrame.focus();
},

_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.set(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.detach();
} else {
this.enableToggleButton.title = WebInspector.UIString("Debugging disabled. Click to enable.");
this.enableToggleButton.toggled = false;
this._pauseOnExceptionButton.visible = false;
this.panelEnablerView.show(this.element);
}

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 (Capabilities.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();
},

get debuggingEnabled()
{
return this._debuggerEnabled;
},

enableDebugging: function()
{
if (this._debuggerEnabled)
return;
this.toggleDebugging(this.panelEnablerView.alwaysEnabled);
},

disableDebugging: 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.set(false);
WebInspector.debuggerModel.disableDebugger();
} else {
WebInspector.settings.debuggerEnabled.set(!!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()
{
if (!this._paused)
return;

this._paused = false;
this._stepping = true;

this._clearInterface();

DebuggerAgent.stepOver();
},

_stepIntoClicked: function()
{
if (!this._paused)
return;

this._paused = false;
this._stepping = true;

this._clearInterface();

DebuggerAgent.stepInto();
},

_stepOutClicked: function()
{
if (!this._paused)
return;

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.");
WebInspector.inspectorView.element.removeStyleClass("breakpoints-deactivated");
} else {
DebuggerAgent.setBreakpointsActive(false);
this.toggleBreakpointsButton.title = WebInspector.UIString("Activate all breakpoints.");
WebInspector.inspectorView.element.addStyleClass("breakpoints-deactivated");
}
},

_evaluateSelectionInConsole: function()
{
var selection = window.getSelection();
if (selection.type === "Range" && !selection.isCollapsed)
WebInspector.evaluateInConsole(selection.toString());
},

_createEditorToolbar: function()
{
var editorToolbar = document.createElement("div");
editorToolbar.className = "status-bar";
editorToolbar.id = "scripts-editor-toolbar";

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);
editorToolbar.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);
editorToolbar.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, true), false);
this._filesSelectElement.addEventListener("keyup", this._filesSelectChanged.bind(this, false), false);
editorToolbar.appendChild(this._filesSelectElement);

this.functionsSelectElement = document.createElement("select");
this.functionsSelectElement.className = "status-bar-item";
this.functionsSelectElement.id = "scripts-functions";





return editorToolbar;
},

_createDebugToolbar: function()
{
var debugToolbar = document.createElement("div");
debugToolbar.className = "status-bar";
debugToolbar.id = "scripts-debug-toolbar";

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._createButtonAndRegisterShortcuts("scripts-pause", title, handler, shortcuts, WebInspector.UIString("Pause/Continue"));
debugToolbar.appendChild(this.pauseButton);


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._createButtonAndRegisterShortcuts("scripts-step-over", title, handler, shortcuts, WebInspector.UIString("Step over"));
debugToolbar.appendChild(this.stepOverButton);


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._createButtonAndRegisterShortcuts("scripts-step-into", title, handler, shortcuts, WebInspector.UIString("Step into"));
debugToolbar.appendChild(this.stepIntoButton);


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._createButtonAndRegisterShortcuts("scripts-step-out", title, handler, shortcuts, WebInspector.UIString("Step out"));
debugToolbar.appendChild(this.stepOutButton);

this.toggleBreakpointsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Deactivate all breakpoints."), "toggle-breakpoints");
this.toggleBreakpointsButton.toggled = true;
this.toggleBreakpointsButton.addEventListener("click", this._toggleBreakpointsClicked, this);
debugToolbar.appendChild(this.toggleBreakpointsButton.element);

this.debuggerStatusElement = document.createElement("div");
this.debuggerStatusElement.id = "scripts-debugger-status";
debugToolbar.appendChild(this.debuggerStatusElement);

return debugToolbar;
},

_createButtonAndRegisterShortcuts: 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);

var shortcutNames = [];
for (var i = 0; i < shortcuts.length; ++i) {
this.registerShortcut(shortcuts[i].key, handler);
shortcutNames.push(shortcuts[i].name);
}
var section = WebInspector.shortcutsScreen.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();
WebInspector.searchController.updateCurrentMatchIndex(view.currentSearchResultIndex, this);
}

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();
WebInspector.searchController.updateCurrentMatchIndex(this._searchView.currentSearchResultIndex, this);
},

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();
WebInspector.searchController.updateCurrentMatchIndex(this._searchView.currentSearchResultIndex, this);
},

_toggleFormatSource: function()
{
this._toggleFormatSourceButton.toggled = !this._toggleFormatSourceButton.toggled;
this._presentationModel.setFormatSource(this._toggleFormatSourceButton.toggled);
},

addToWatch: function(expression)
{
this.sidebarPanes.watchExpressions.addExpression(expression);
}
}

WebInspector.ScriptsPanel.prototype.__proto__ = WebInspector.Panel.prototype;






WebInspector.ResourcesPanel = function(database)
{
WebInspector.Panel.call(this, "resources");
this.registerRequiredCSS("resourcesPanel.css");

WebInspector.settings.resourcesLastSelectedItem = WebInspector.settings.createSetting("resourcesLastSelectedItem", {});

this.createSplitViewWithSidebarTree();
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 = this.splitView.mainElement;
this.storageViews.addStyleClass("diff-container");

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);

function viewGetter()
{
return this.visibleView;
}
WebInspector.GoToLineDialog.install(this, viewGetter.bind(this));

WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.OnLoad, this._onLoadEventFired, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded, this._cachedResourcesLoaded, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.WillLoadCachedResources, this._resetWithFrames, this);
}

WebInspector.ResourcesPanel.prototype = {
get toolbarItemLabel()
{
return WebInspector.UIString("Resources");
},

get statusBarItems()
{
return [this.storageViewStatusBarItemsContainer];
},

wasShown: function()
{
WebInspector.Panel.prototype.wasShown.call(this);
this._initialize();
},

_initialize: function()
{
if (!this._initialized && this.isShowing() && this._cachedResourcesWereLoaded) {
this._populateResourceTree();
this._populateApplicationCacheTree();
this._initDefaultSelection();
this._initialized = true;
}
},

_onLoadEventFired: function()
{
this._initDefaultSelection();
},

_initDefaultSelection: function()
{
if (!this._initialized)
return;

var itemURL = WebInspector.settings.resourcesLastSelectedItem.get();
if (itemURL) {
for (var treeElement = this.sidebarTree.children[0]; treeElement; treeElement = treeElement.traverseNextTreeElement(false, this.sidebarTree, true)) {
if (treeElement.itemURL === itemURL) {
treeElement.revealAndSelect(true);
return;
}
}
}

var mainResource = WebInspector.inspectedPageURL && this.resourcesListTreeElement && this.resourcesListTreeElement.expanded && WebInspector.resourceTreeModel.resourceForURL(WebInspector.inspectedPageURL);
if (mainResource)
this.showResource(mainResource);
},

_resetWithFrames: function()
{
this.resourcesListTreeElement.removeChildren();
this._treeElementForFrameId = {};
this._reset();
},

_reset: function()
{
this._origins = {};
this._domains = {};
for (var i = 0; i < this._databases.length; ++i) {
var database = this._databases[i];
delete database._tableViews;
if (database._queryView)
database._queryView.removeEventListener(WebInspector.DatabaseQueryView.Events.SchemaUpdated, this._updateDatabaseTables, this);
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.databasesListTreeElement.removeChildren();
this.localStorageListTreeElement.removeChildren();
this.sessionStorageListTreeElement.removeChildren();
this.cookieListTreeElement.removeChildren();

if (this.visibleView)
this.visibleView.detach();

this.storageViewStatusBarItemsContainer.removeChildren();

if (this.sidebarTree.selectedTreeElement)
this.sidebarTree.selectedTreeElement.deselect();
},

_populateResourceTree: function()
{
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);

function populateFrame(frame)
{
this._frameAdded({data:frame});
for (var i = 0; i < frame.childFrames.length; ++i)
populateFrame.call(this, frame.childFrames[i]);

var resources = frame.resources();
for (var i = 0; i < resources.length; ++i)
this._resourceAdded({data:resources[i]});
}
populateFrame.call(this, WebInspector.resourceTreeModel.mainFrame);
},

_frameAdded: function(event)
{
var frame = event.data;
var parentFrame = frame.parentFrame;

var parentTreeElement = parentFrame ? this._treeElementForFrameId[parentFrame.id] : this.resourcesListTreeElement;
if (!parentTreeElement) {
console.warn("No frame to route " + frame.url + " to.")
return;
}

var frameTreeElement = new WebInspector.FrameTreeElement(this, frame);
this._treeElementForFrameId[frame.id] = frameTreeElement;
parentTreeElement.appendChild(frameTreeElement);
},

_frameDetached: function(event)
{
var frame = event.data;
var frameTreeElement = this._treeElementForFrameId[frame.id];
if (!frameTreeElement)
return;

delete this._treeElementForFrameId[frame.id];
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 frame = event.data;

if (!frame.parentFrame)
this._reset();

var frameId = frame.id;
var frameTreeElement = this._treeElementForFrameId[frameId];
if (frameTreeElement)
frameTreeElement.frameNavigated(frame);

var applicationCacheFrameTreeElement = this._applicationCacheFrameElements[frameId];
if (applicationCacheFrameTreeElement)
applicationCacheFrameTreeElement.frameNavigated(frame);
},

_cachedResourcesLoaded: function()
{
this._cachedResourcesWereLoaded = true;
this._initialize();
},

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);
}
},

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);
this.showResource(resource, anchor.lineNumber);
},


showResource: function(resource, line)
{
var resourceTreeElement = this._findTreeElementForResource(resource);
if (resourceTreeElement)
resourceTreeElement.revealAndSelect();

if (typeof line === "number") {
var view = this._resourceViewForResource(resource);
if (view.canHighlightLine())
view.highlightLine(line);
}
return true;
},

_showResourceView: function(resource)
{
var view = this._resourceViewForResource(resource);
if (!view) {
this.visibleView.detach();
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 diffData = TextDiff.compute(baseContent, newContent);
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;
view.addEventListener(WebInspector.DatabaseQueryView.Events.SchemaUpdated, this._updateDatabaseTables, this);
}
}

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(frameId)
{
if (!this._applicationCacheViews[frameId])
this._applicationCacheViews[frameId] = new WebInspector.ApplicationCacheItemsView(this._applicationCacheModel, frameId);

this._innerShowView(this._applicationCacheViews[frameId]);
},

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.detach();

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)
return;
this.visibleView.detach();
delete this.visibleView;
},

_updateDatabaseTables: function(event)
{
var database = event.data;

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);
},

updateDOMStorage: function(storageId)
{
var domStorage = this._domStorageForId(storageId);
if (!domStorage)
return;

var view = domStorage._domStorageView;
if (this.visibleView && view === this.visibleView)
domStorage._domStorageView.update();
},

_populateApplicationCacheTree: function()
{
this._applicationCacheModel = new WebInspector.ApplicationCacheModel();

this._applicationCacheViews = {};
this._applicationCacheFrameElements = {};
this._applicationCacheManifestElements = {};

this._applicationCacheModel.addEventListener(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestAdded, this._applicationCacheFrameManifestAdded, this);
this._applicationCacheModel.addEventListener(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestRemoved, this._applicationCacheFrameManifestRemoved, this);

this._applicationCacheModel.addEventListener(WebInspector.ApplicationCacheModel.EventTypes.FrameManifestStatusUpdated, this._applicationCacheFrameManifestStatusChanged, this);
this._applicationCacheModel.addEventListener(WebInspector.ApplicationCacheModel.EventTypes.NetworkStateChanged, this._applicationCacheNetworkStateChanged, this);
},

_applicationCacheFrameManifestAdded: function(event)
{
var frameId = event.data;
var manifestURL = this._applicationCacheModel.frameManifestURL(frameId);
var status = this._applicationCacheModel.frameManifestStatus(frameId)

var manifestTreeElement = this._applicationCacheManifestElements[manifestURL]
if (!manifestTreeElement) {
manifestTreeElement = new WebInspector.ApplicationCacheManifestTreeElement(this, manifestURL);
this.applicationCacheListTreeElement.appendChild(manifestTreeElement);
this._applicationCacheManifestElements[manifestURL] = manifestTreeElement;
}

var frameTreeElement = new WebInspector.ApplicationCacheFrameTreeElement(this, frameId, manifestURL);
manifestTreeElement.appendChild(frameTreeElement);
manifestTreeElement.expand();
this._applicationCacheFrameElements[frameId] = frameTreeElement;
},

_applicationCacheFrameManifestRemoved: function(event)
{
var frameId = event.data;
var frameTreeElement = this._applicationCacheFrameElements[frameId];
if (!frameTreeElement)
return;

var manifestURL = frameTreeElement.manifestURL;
delete this._applicationCacheFrameElements[frameId];
delete this._applicationCacheViews[frameId];
frameTreeElement.parent.removeChild(frameTreeElement);

var manifestTreeElement = this._applicationCacheManifestElements[manifestURL];
if (manifestTreeElement.children.length !== 0)
return;

delete this._applicationCacheManifestElements[manifestURL];
manifestTreeElement.parent.removeChild(manifestTreeElement);
},

_applicationCacheFrameManifestStatusChanged: function(event)
{
var frameId = event.data;
var status = this._applicationCacheModel.frameManifestStatus(frameId)

if (this._applicationCacheViews[frameId])
this._applicationCacheViews[frameId].updateStatus(status);
},

_applicationCacheNetworkStateChanged: function(event)
{
var isNowOnline = event.data;

for (var manifestURL in this._applicationCacheViews)
this._applicationCacheViews[manifestURL].updateNetworkState(isNowOnline);
},

_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;
},

sidebarResized: function(event)
{
var width = event.data;
this.storageViewStatusBarItemsContainer.style.left = width + "px";
},

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)
continue;

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, totalMatchesCount);

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);
WebInspector.searchController.updateCurrentMatchIndex(searchResult.currentMatchIndex - 1, this);
}


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._titleTextNode = document.createTextNode("");
this.titleElement.appendChild(this._titleTextNode);
this._updateTitle();
this._updateSubtitle();
this.listItemElement.appendChild(this.titleElement);
},

get displayName()
{
return this._displayName;
},

_updateDisplayName: function()
{
this._displayName = this._titleText || "";
if (this._subtitleText)
this._displayName += " (" + this._subtitleText + ")";
},

_updateTitle: function()
{
this._updateDisplayName();

if (!this.titleElement)
return;

this._titleTextNode.textContent = this._titleText || "";
},

_updateSubtitle: function()
{
this._updateDisplayName();

if (!this.titleElement)
return;

if (this._subtitleText) {
if (!this._subtitleElement) {
this._subtitleElement = document.createElement("span");
this._subtitleElement.className = "base-storage-tree-element-subtitle";
this.titleElement.appendChild(this._subtitleElement);
}
this._subtitleElement.textContent = "(" + this._subtitleText + ")";
} else if (this._subtitleElement) {
this.titleElement.removeChild(this._subtitleElement);
delete this._subtitleElement;
}
},

onselect: function()
{
var itemURL = this.itemURL;
if (itemURL)
WebInspector.settings.resourcesLastSelectedItem.set(itemURL);
},

onreveal: function()
{
if (this.listItemElement)
this.listItemElement.scrollIntoViewIfNeeded(false);
},

get titleText()
{
return this._titleText;
},

set titleText(titleText)
{
this._titleText = titleText;
this._updateTitle();
},

get subtitleText()
{
return this._subtitleText;
},

set subtitleText(subtitleText)
{
this._subtitleText = subtitleText;
this._updateSubtitle();
},

get searchMatchesCount()
{
return 0;
}
}

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[this._expandedSettingKey] = WebInspector.settings.createSetting(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].get())
this.expand();
},

onexpand: function()
{
WebInspector.settings[this._expandedSettingKey].set(true);
},

oncollapse: function()
{
WebInspector.settings[this._expandedSettingKey].set(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;

this.titleText = frame.name;
this.subtitleText = WebInspector.Resource.displayName(frame.url);

this._categoryElements = {};
this._treeElementForResource = {};

this._storagePanel.addDocumentURL(frame.url);
},

get itemURL()
{
return "frame://" + encodeURI(this.displayName);
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
this._storagePanel.showCategoryView(this.displayName);

this.listItemElement.removeStyleClass("hovered");
DOMAgent.hideHighlight();
},

set hovered(hovered)
{
if (hovered) {
this.listItemElement.addStyleClass("hovered");
DOMAgent.highlightFrame(this._frameId, WebInspector.Color.PageHighlight.Content.toProtocolRGBA(), WebInspector.Color.PageHighlight.ContentOutline.toProtocolRGBA());
} else {
this.listItemElement.removeStyleClass("hovered");
DOMAgent.hideHighlight();
}
},

appendResource: function(resource)
{
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)
{
var treeElement = this._treeElementForResource[url];
return treeElement ? treeElement.representedObject : null;
},

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(WebInspector.Resource.Events.MessageAdded, this._consoleMessageAdded, this);
this._resource.addEventListener(WebInspector.Resource.Events.MessagesCleared, this._consoleMessagesCleared, 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._appendOpenInNetworkPanelAction(contextMenu, event);
WebInspector.populateResourceContextMenu(contextMenu, this._resource.url, null);
this._appendSaveAsAction(contextMenu, event);
contextMenu.show(event);
},

_appendOpenInNetworkPanelAction: function(contextMenu, event)
{
if (!this._resource.requestId)
return;

contextMenu.appendItem(WebInspector.openInNetworkPanelLabel(), WebInspector.openRequestInNetworkPanel.bind(WebInspector, this._resource));
},

_appendSaveAsAction: function(contextMenu, event)
{
if (!InspectorFrontendHost.canSaveAs())
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");
},

_consoleMessagesCleared: function()
{

if (this._sourceView)
this._sourceView.clearMessages();

this._updateErrorsAndWarningsBubbles();
},

_consoleMessageAdded: 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.isShowing() ? oldView.element.parentNode : null;
newView.inheritScrollPositions(oldView);

this._sourceView.detach();
this._sourceView = newView;

if (oldViewParentNode)
newView.show(oldViewParentNode);

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.ApplicationCacheManifestTreeElement = function(storagePanel, manifestURL)
{
var title = WebInspector.Resource.displayName(manifestURL);
WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, title, ["application-cache-storage-tree-item"]);
this.tooltip = manifestURL;
this._manifestURL = manifestURL;
}

WebInspector.ApplicationCacheManifestTreeElement.prototype = {
get itemURL()
{
return "appcache://" + this._manifestURL;
},

get manifestURL()
{
return this._manifestURL;
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
this._storagePanel.showCategoryView(this._manifestURL);
}
}
WebInspector.ApplicationCacheManifestTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;


WebInspector.ApplicationCacheFrameTreeElement = function(storagePanel, frameId, manifestURL)
{
WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, "", ["frame-storage-tree-item"]);
this._frameId = frameId;
this._manifestURL = manifestURL;
this._refreshTitles();
}

WebInspector.ApplicationCacheFrameTreeElement.prototype = {
get itemURL()
{
return "appcache://" + this._manifestURL + "/" + encodeURI(this.displayName);
},

get frameId()
{
return this._frameId;
},

get manifestURL()
{
return this._manifestURL;
},

_refreshTitles: function()
{
var frame = WebInspector.resourceTreeModel.frameForId(this._frameId);
if (!frame) {
this.subtitleText = WebInspector.UIString("new frame");
return;
}
this.titleText = frame.name;
this.subtitleText = WebInspector.Resource.displayName(frame.url);
},

frameNavigated: function()
{
this._refreshTitles();
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
this._storagePanel.showApplicationCache(this._frameId);
}
}
WebInspector.ApplicationCacheFrameTreeElement.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 (InspectorFrontendHost.canSaveAs()) {
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._emptyView = new WebInspector.EmptyView("");
this._emptyView.show(this.element);
}

WebInspector.StorageCategoryView.prototype = {
setText: function(text)
{
this._emptyView.text = text;
}
}

WebInspector.StorageCategoryView.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.ResourcesSearchController = function(rootElement, matchesCount)
{
this._root = rootElement;
this._matchesCount = matchesCount;
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, 1);

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, this._currentMatchIndex % this._matchesCount + 1);

return this._searchResult(currentTreeElement, this._lastIndex + 1, this._currentMatchIndex + 1);
},


previousSearchResult: function(currentTreeElement)
{
if (!currentTreeElement) {
var treeElement = this._traverser.last();
return this._searchResult(treeElement, treeElement.searchMatchesCount - 1, this._matchesCount);
}

if (currentTreeElement.searchMatchesCount && this._lastTreeElement === currentTreeElement) {
if (this._lastIndex > 0)
return this._searchResult(currentTreeElement, this._lastIndex - 1, this._currentMatchIndex - 1);
else {
var treeElement = this._traverser.previous(currentTreeElement);
var currentMatchIndex = this._currentMatchIndex - 1 ? this._currentMatchIndex - 1 : this._matchesCount;
return this._searchResult(treeElement, treeElement.searchMatchesCount - 1, currentMatchIndex);
}
}

var treeElement = this._traverser.previous(currentTreeElement)
return this._searchResult(treeElement, treeElement.searchMatchesCount - 1);
},


_searchResult: function(treeElement, index, currentMatchIndex)
{
this._lastTreeElement = treeElement;
this._lastIndex = index;
if (!currentMatchIndex)
currentMatchIndex = this._traverser.matchIndex(treeElement, index);
this._currentMatchIndex = currentMatchIndex;
return {treeElement: treeElement, index: index, currentMatchIndex: currentMatchIndex};
}
}


WebInspector.SearchResultsTreeElementsTraverser = function(rootElement)
{
this._root = rootElement;
}

WebInspector.SearchResultsTreeElementsTraverser.prototype = {

first: function()
{
return this.next(this._root);
},


last: function()
{
return this.previous(this._root);
},


next: function(startTreeElement)
{
var treeElement = startTreeElement;
do {
treeElement = this._traverseNext(treeElement) || this._root;
} while (treeElement != startTreeElement && !this._elementSearchMatchesCount(treeElement));
return treeElement;
},


previous: function(startTreeElement)
{
var treeElement = startTreeElement;
do {
treeElement = this._traversePrevious(treeElement) || this._lastTreeElement();
} while (treeElement != startTreeElement && !this._elementSearchMatchesCount(treeElement));
return treeElement;
},


matchIndex: function(startTreeElement, index)
{
var matchIndex = 1;
var treeElement = this._root;
while (treeElement != startTreeElement) {
matchIndex += this._elementSearchMatchesCount(treeElement);
treeElement = this._traverseNext(treeElement) || this._root;
if (treeElement === this._root)
return 0;
}
return matchIndex + index;
},


_elementSearchMatchesCount: function(treeElement)
{
return treeElement.searchMatchesCount;
},


_traverseNext: function(treeElement)
{
return   treeElement.traverseNextTreeElement(false, this._root, true);
},


_traversePrevious: function(treeElement)
{
return   treeElement.traversePreviousTreeElement(false, 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.registerLinkifierPlugin(function(title)
{
var profileStringMatches = WebInspector.ProfileType.URLRegExp.exec(title);
if (profileStringMatches)
title = WebInspector.panels.profiles.displayTitleForProfileLink(profileStringMatches[2], profileStringMatches[1]);
return title;
});

WebInspector.ProfilesPanel = function()
{
WebInspector.Panel.call(this, "profiles");
this.registerRequiredCSS("heapProfiler.css");
this.registerRequiredCSS("profilesPanel.css");

this.createSplitViewWithSidebarTree();

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.enableProfiler, this);

this.profileViews = document.createElement("div");
this.profileViews.id = "profile-views";
this.splitView.mainElement.appendChild(this.profileViews);

this.enableToggleButton = new WebInspector.StatusBarButton("", "enable-toggle-status-bar-item");
this.enableToggleButton.addEventListener("click", this._toggleProfiling.bind(this), false);
if (!Capabilities.profilerCausesRecompilation)
this.enableToggleButton.element.addStyleClass("hidden");

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._profiles = [];
this._profilerEnabled = !Capabilities.profilerCausesRecompilation;
this._reset();

this._registerProfileType(new WebInspector.CPUProfileType());
if (Capabilities.heapProfilerPresent)
this._registerProfileType(new WebInspector.DetailedHeapshotProfileType());

InspectorBackend.registerProfilerDispatcher(new WebInspector.ProfilerDispatcher(this));

if (!Capabilities.profilerCausesRecompilation || WebInspector.settings.profilerEnabled.get())
ProfilerAgent.enable(this._profilerWasEnabled.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;
},

wasShown: function()
{
WebInspector.Panel.prototype.wasShown.call(this);
this._populateProfiles();
},

_profilerWasEnabled: function()
{
if (this._profilerEnabled)
return;

this._profilerEnabled = true;

this._reset();
if (this.isShowing())
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) {
view.detach();
if ("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(this.splitView.mainElement);
},

_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.revealAndSelect();

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.detach();
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._suppressOnSelect = true;
profile._profilesTreeElement.revealAndSelect();
delete profile._profilesTreeElement._suppressOnSelect;

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.DetailedHeapshotProfileType.TypeId)];
if (!profile)
return;

if (!profile.proxy) {
function setProfileWait(event) {
profile.sidebarElement.wait = event.data;
}
var worker = new WebInspector.HeapSnapshotWorker();
worker.addEventListener("wait", setProfileWait, this);
profile.proxy = worker.createObject("WebInspector.HeapSnapshotLoader");
}
var proxy = profile.proxy;
if (proxy.startLoading(callback)) {
profile.sidebarElement.subtitle = WebInspector.UIString("Loading\u2026");
profile.sidebarElement.wait = true;
ProfilerAgent.getProfile(profile.typeId, profile.uid);
}
},

_addHeapSnapshotChunk: function(uid, chunk)
{
var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.DetailedHeapshotProfileType.TypeId)];
if (!profile || !profile.proxy)
return;
profile.proxy.pushJSONChunk(chunk);
},

_finishHeapSnapshot: function(uid)
{
var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.DetailedHeapshotProfileType.TypeId)];
if (!profile || !profile.proxy)
return;
var proxy = profile.proxy;
function parsed(snapshotProxy)
{
profile.proxy = snapshotProxy;
profile.sidebarElement.subtitle = Number.bytesToString(snapshotProxy.totalSize);
profile.sidebarElement.wait = false;
snapshotProxy.worker.startCheckingForLongRunningCalls();
}
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.detach();
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;
},

performSearch: function(query)
{
this.searchCanceled();

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;

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();
},

_searchableViews: function()
{
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()
{
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.Panel.prototype.searchCanceled.call(this);

if (this._currentSearchChunkIntervalIdentifier) {
clearInterval(this._currentSearchChunkIntervalIdentifier);
delete this._currentSearchChunkIntervalIdentifier;
}

this._totalSearchMatches = 0;
this._currentSearchResultIndex = 0;
this._searchResults = [];

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.detach();
} 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.show(this.element);
}
},

get profilerEnabled()
{
return this._profilerEnabled;
},

enableProfiler: function()
{
if (this._profilerEnabled)
return;
this._toggleProfiling(this.panelEnablerView.alwaysEnabled);
},

disableProfiler: function()
{
if (!this._profilerEnabled)
return;
this._toggleProfiling(this.panelEnablerView.alwaysEnabled);
},

_toggleProfiling: function(optionalAlways)
{
if (this._profilerEnabled) {
WebInspector.settings.profilerEnabled.set(false);
ProfilerAgent.disable(this._profilerWasDisabled.bind(this));
} else {
WebInspector.settings.profilerEnabled.set(!!optionalAlways);
ProfilerAgent.enable(this._profilerWasEnabled.bind(this));
}
},

_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;
},

sidebarResized: function(event)
{
var width = event.data;

this.profileViewStatusBarItemsContainer.style.left = Math.max(6 * 31, width) + "px";
},

_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);
WebInspector.userMetrics.ProfilesCPUProfileTaken.record();
} else
this._removeProfileHeader(this._temporaryRecordingProfile);
}
this.updateProfileTypeButtons();
},

takeHeapSnapshot: function()
{
if (!this.hasTemporaryProfile(WebInspector.DetailedHeapshotProfileType.TypeId)) {
if (!this._temporaryTakingSnapshot) {
this._temporaryTakingSnapshot = {
typeId: WebInspector.DetailedHeapshotProfileType.TypeId,
title: WebInspector.UIString("Snapshotting…"),
uid: -1,
isTemporary: true
};
}
this._addProfileHeader(this._temporaryTakingSnapshot);
}
ProfilerAgent.takeHeapSnapshot();
WebInspector.userMetrics.ProfilesHeapProfileTaken.record();
},

_reportHeapSnapshotProgress: function(done, total)
{
if (this.hasTemporaryProfile(WebInspector.DetailedHeapshotProfileType.TypeId)) {
this._temporaryTakingSnapshot.sidebarElement.subtitle = WebInspector.UIString("%.2f%%", (done / total) * 100);
this._temporaryTakingSnapshot.sidebarElement.wait = true;
if (done >= total)
this._removeProfileHeader(this._temporaryTakingSnapshot);
}
}
}

WebInspector.ProfilesPanel.prototype.__proto__ = WebInspector.Panel.prototype;


WebInspector.ProfilerDispatcher = function(profiler)
{
this._profiler = profiler;
}

WebInspector.ProfilerDispatcher.prototype = {
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()
{
if (!this._suppressOnSelect)
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.consoleView.addEventListener(WebInspector.ConsoleView.Events.EntryAdded, this._consoleMessageAdded, this);
WebInspector.consoleView.addEventListener(WebInspector.ConsoleView.Events.ConsoleCleared, this._consoleCleared, this);
this._view = WebInspector.consoleView;
}

WebInspector.ConsolePanel.prototype = {
get toolbarItemLabel()
{
return WebInspector.UIString("Console");
},

get statusBarItems()
{
return this._view.statusBarItems;
},

wasShown: function()
{
WebInspector.Panel.prototype.wasShown.call(this);
if (WebInspector.drawer.visible) {
WebInspector.drawer.hide(WebInspector.Drawer.AnimationType.Immediately);
this._drawerWasVisible = true;
}
this._view.show(this.element);
},

willHide: function()
{
if (this._drawerWasVisible) {
WebInspector.drawer.show(this._view, WebInspector.Drawer.AnimationType.Immediately);
delete this._drawerWasVisible;
}
WebInspector.Panel.prototype.willHide.call(this);
},

searchCanceled: function()
{
this._clearCurrentSearchResultHighlight();
delete this._searchResults;
delete this._searchRegex;
},

performSearch: function(query)
{
WebInspector.searchController.updateSearchMatchesCount(0, this);
this.searchCanceled();
this._searchRegex = createPlainTextSearchRegex(query, "gi");

this._searchResults = [];
var messages = WebInspector.consoleView.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.isShowing())
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.isShowing())
WebInspector.searchController.updateSearchMatchesCount(0, this);
}
}

WebInspector.ConsolePanel.prototype.__proto__ = WebInspector.Panel.prototype;





function defineCommonExtensionSymbols(apiPrivate)
{
if (!apiPrivate.audits)
apiPrivate.audits = {};

apiPrivate.audits.Severity = {
Info: "info",
Warning: "warning",
Severe: "severe"
};

if (!apiPrivate.console)
apiPrivate.console = {};
apiPrivate.console.Severity = {
Tip: "tip",
Debug: "debug",
Log: "log",
Warning: "warning",
Error: "error"
};
apiPrivate.Events = {
AuditStarted: "audit-started-",
ButtonClicked: "button-clicked-",
ConsoleMessageAdded: "console-message-added",
ElementsPanelObjectSelected: "panel-objectSelected-elements",
NetworkRequestFinished: "network-request-finished",
Reset: "reset",
OpenResource: "open-resource",
PanelSearch: "panel-search-",
Reload: "Reload",
ResourceAdded: "resource-added",
ResourceContentCommitted: "resource-content-committed",
TimelineEventRecorded: "timeline-event-recorded",
ViewShown: "view-shown-",
ViewHidden: "view-hidden-"
};
apiPrivate.Commands = {
AddAuditCategory: "addAuditCategory",
AddAuditResult: "addAuditResult",
AddConsoleMessage: "addConsoleMessage",
AddRequestHeaders: "addRequestHeaders",
CreatePanel: "createPanel",
CreateSidebarPane: "createSidebarPane",
CreateStatusBarButton: "createStatusBarButton",
EvaluateOnInspectedPage: "evaluateOnInspectedPage",
GetConsoleMessages: "getConsoleMessages",
GetHAR: "getHAR",
GetPageResources: "getPageResources",
GetRequestContent: "getRequestContent",
GetResourceContent: "getResourceContent",
Subscribe: "subscribe",
SetOpenResourceHandler: "setOpenResourceHandler",
SetResourceContent: "setResourceContent",
SetSidebarContent: "setSidebarContent",
SetSidebarHeight: "setSidebarHeight",
SetSidebarPage: "setSidebarPage",
StopAuditCategoryRun: "stopAuditCategoryRun",
Unsubscribe: "unsubscribe",
UpdateButton: "updateButton",
InspectedURLChanged: "inspectedURLChanged"
};
}

function injectedExtensionAPI(injectedScriptId)
{

var apiPrivate = {};

defineCommonExtensionSymbols(apiPrivate);

var commands = apiPrivate.Commands;
var events = apiPrivate.Events;








function EventSinkImpl(type, customDispatch)
{
this._type = type;
this._listeners = [];
this._customDispatch = customDispatch;
}

EventSinkImpl.prototype = {
addListener: function(callback)
{
if (typeof callback !== "function")
throw "addListener: callback is not a function";
if (this._listeners.length === 0)
extensionServer.sendRequest({ command: commands.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: commands.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.network = new Network();
defineDeprecatedProperty(this, "webInspector", "resources", "network");
this.timeline = new Timeline();
this.console = new Console();

this.onReset = new EventSink(events.Reset);
}


InspectorExtensionAPI.prototype = {
log: function(message)
{
extensionServer.sendRequest({ command: commands.Log, message: message });
}
}


function Console()
{
this.onMessageAdded = new EventSink(events.ConsoleMessageAdded);
}

Console.prototype = {
getMessages: function(callback)
{
extensionServer.sendRequest({ command: commands.GetConsoleMessages }, callback);
},

addMessage: function(severity, text, url, line)
{
extensionServer.sendRequest({ command: commands.AddConsoleMessage, severity: severity, text: text, url: url, line: line });
},

get Severity()
{
return apiPrivate.console.Severity;
}
}


function Network()
{
function dispatchRequestEvent(message)
{
var request = message.arguments[1];
request.__proto__ = new Request(message.arguments[0]);
this._fire(request);
}
this.onRequestFinished = new EventSink(events.NetworkRequestFinished, dispatchRequestEvent);
defineDeprecatedProperty(this, "network", "onFinished", "onRequestFinished");
this.onNavigated = new EventSink(events.InspectedURLChanged);
}

Network.prototype = {
getHAR: function(callback)
{
function callbackWrapper(result)
{
var entries = (result && result.entries) || [];
for (var i = 0; i < entries.length; ++i) {
entries[i].__proto__ = new Request(entries[i]._requestId);
delete entries[i]._requestId;
}
callback(result);
}
return extensionServer.sendRequest({ command: commands.GetHAR }, callback && callbackWrapper);
},

addRequestHeaders: function(headers)
{
return extensionServer.sendRequest({ command: commands.AddRequestHeaders, headers: headers, extensionId: window.location.hostname });
}
}


function RequestImpl(id)
{
this._id = id;
}

RequestImpl.prototype = {
getContent: function(callback)
{
function callbackWrapper(response)
{
callback(response.content, response.encoding);
}
extensionServer.sendRequest({ command: commands.GetRequestContent, 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, icon, page, callback)
{
var id = "extension-panel-" + extensionServer.nextObjectId();
var request = {
command: commands.CreatePanel,
id: id,
title: title,
icon: icon,
page: page
};
extensionServer.sendRequest(request, callback && bind(callback, this, new ExtensionPanel(id)));
},

setOpenResourceHandler: function(callback)
{
var hadHandler = extensionServer.hasHandler(events.OpenResource);

if (!callback)
extensionServer.unregisterHandler(events.OpenResource);
else {
function callbackWrapper(message)
{
callback.call(null, message.resource, message.lineNumber);
}
extensionServer.registerHandler(events.OpenResource, callbackWrapper);
}

if (hadHandler === !callback)
extensionServer.sendRequest({ command: commands.SetOpenResourceHandler, "handlerPresent": !!callback });
}
}


function ExtensionViewImpl(id)
{
this._id = id;

function dispatchShowEvent(message)
{
var frameIndex = message.arguments[0];
this._fire(window.top.frames[frameIndex]);
}
this.onShown = new EventSink(events.ViewShown + id, dispatchShowEvent);
this.onHidden = new EventSink(events.ViewHidden + id);
}


function PanelWithSidebarImpl(id)
{
this._id = id;
}

PanelWithSidebarImpl.prototype = {
createSidebarPane: function(title, callback)
{
var id = "extension-sidebar-" + extensionServer.nextObjectId();
var request = {
command: commands.CreateSidebarPane,
panel: this._id,
id: id,
title: title
};
function callbackWrapper()
{
callback(new ExtensionSidebarPane(id));
}
extensionServer.sendRequest(request, callback && callbackWrapper);
}
}

PanelWithSidebarImpl.prototype.__proto__ = ExtensionViewImpl.prototype;


function ElementsPanel()
{
var id = "elements";
PanelWithSidebar.call(this, id);
this.onSelectionChanged = new EventSink(events.ElementsPanelObjectSelected);
}


function ExtensionPanelImpl(id)
{
ExtensionViewImpl.call(this, id);
this.onSearch = new EventSink(events.PanelSearch + id);
}

ExtensionPanelImpl.prototype = {
createStatusBarButton: function(iconPath, tooltipText, disabled)
{
var id = "button-" + extensionServer.nextObjectId();
var request = {
command: commands.CreateStatusBarButton,
panel: this._id,
id: id,
icon: iconPath,
tooltip: tooltipText,
disabled: !!disabled
};
extensionServer.sendRequest(request);
return new Button(id);
}
};

ExtensionPanelImpl.prototype.__proto__ = ExtensionViewImpl.prototype;


function ExtensionSidebarPaneImpl(id)
{
ExtensionViewImpl.call(this, id);
}

ExtensionSidebarPaneImpl.prototype = {
setHeight: function(height)
{
extensionServer.sendRequest({ command: commands.SetSidebarHeight, id: this._id, height: height });
},

setExpression: function(expression, rootTitle, callback)
{
extensionServer.sendRequest({ command: commands.SetSidebarContent, id: this._id, expression: expression, rootTitle: rootTitle, evaluateOnPage: true }, callback);
},

setObject: function(jsonObject, rootTitle, callback)
{
extensionServer.sendRequest({ command: commands.SetSidebarContent, id: this._id, expression: jsonObject, rootTitle: rootTitle }, callback);
},

setPage: function(page)
{
extensionServer.sendRequest({ command: commands.SetSidebarPage, id: this._id, page: page });
}
}


function ButtonImpl(id)
{
this._id = id;
this.onClicked = new EventSink(events.ButtonClicked + id);
}

ButtonImpl.prototype = {
update: function(iconPath, tooltipText, disabled)
{
var request = {
command: commands.UpdateButton,
id: this._id,
icon: iconPath,
tooltip: tooltipText,
disabled: !!disabled
};
extensionServer.sendRequest(request);
}
};


function Audits()
{
}

Audits.prototype = {
addCategory: function(displayName, resultCount)
{
var id = "extension-audit-category-" + extensionServer.nextObjectId();
extensionServer.sendRequest({ command: commands.AddAuditCategory, id: id, displayName: displayName, resultCount: resultCount });
return new AuditCategory(id);
}
}


function AuditCategoryImpl(id)
{
function dispatchAuditEvent(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(events.AuditStarted + id, dispatchAuditEvent);
}


function AuditResultImpl(id)
{
this._id = id;

this.createURL = bind(this._nodeFactory, null, "url");
this.createSnippet = bind(this._nodeFactory, null, "snippet");
this.createText = bind(this._nodeFactory, null, "text");
}

AuditResultImpl.prototype = {
addResult: function(displayName, description, severity, details)
{

if (details && !(details instanceof AuditResultNode))
details = new AuditResultNode(details instanceof Array ? details : [details]);

var request = {
command: commands.AddAuditResult,
resultId: this._id,
displayName: displayName,
description: description,
severity: severity,
details: details
};
extensionServer.sendRequest(request);
},

createResult: function()
{
return new AuditResultNode(Array.prototype.slice.call(arguments));
},

done: function()
{
extensionServer.sendRequest({ command: commands.StopAuditCategoryRun, resultId: this._id });
},

get Severity()
{
return apiPrivate.audits.Severity;
},

createResourceLink: function(url, lineNumber)
{
return {
type: "resourceLink",
arguments: [url, lineNumber && lineNumber - 1]
};
},

_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 = new AuditResultNode(Array.prototype.slice.call(arguments));
this.children.push(node);
return node;
}
};


function InspectedWindow()
{
function dispatchResourceEvent(message)
{
this._fire(new Resource(message.arguments[0]));
}
function dispatchResourceContentEvent(message)
{
this._fire(new Resource(message.arguments[0]), message.arguments[1]);
}
this.onResourceAdded = new EventSink(events.ResourceAdded, dispatchResourceEvent);
this.onResourceContentCommitted = new EventSink(events.ResourceContentCommitted, dispatchResourceContentEvent);
}

InspectedWindow.prototype = {
reload: function(optionsOrUserAgent)
{
var options = null;
if (typeof optionsOrUserAgent === "object")
options = optionsOrUserAgent;
else if (typeof optionsOrUserAgent === "string") {
options = { userAgent: optionsOrUserAgent };
console.warn("Passing userAgent as string parameter to inspectedWindow.reload() is deprecated. " +
"Use inspectedWindow.reload({ userAgent: value}) instead.");
}
return extensionServer.sendRequest({ command: commands.Reload, options: options });
},

eval: function(expression, callback)
{
function callbackWrapper(result)
{
callback(result.value, result.isException);
}
return extensionServer.sendRequest({ command: commands.EvaluateOnInspectedPage, expression: expression }, callback && callbackWrapper);
},

getResources: function(callback)
{
function wrapResource(resourceData)
{
return new Resource(resourceData);
}
function callbackWrapper(resources)
{
callback(resources.map(wrapResource));
}
return extensionServer.sendRequest({ command: commands.GetPageResources }, callback && callbackWrapper);
}
}


function ResourceImpl(resourceData)
{
this._url = resourceData.url
this._type = resourceData.type;
}

ResourceImpl.prototype = {
get url()
{
return this._url;
},

get type()
{
return this._type;
},

getContent: function(callback)
{
function callbackWrapper(response)
{
callback(response.content, response.encoding);
}

return extensionServer.sendRequest({ command: commands.GetResourceContent, url: this._url }, callback && callbackWrapper);
},

setContent: function(content, commit, callback)
{
return extensionServer.sendRequest({ command: commands.SetResourceContent, url: this._url, content: content, commit: commit }, callback);
}
}


function TimelineImpl()
{
this.onEventRecorded = new EventSink(events.TimelineEventRecorded);
}


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);
},

hasHandler: function(command)
{
return !!this._handlers[command];
},

registerHandler: function(command, handler)
{
this._handlers[command] = handler;
},

unregisterHandler: function(command)
{
delete this._handlers[command];
},

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 bind(func, thisObject, vararg)
{
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 descriptor = null;

for (var owner = implementation; owner && !descriptor; owner = owner.__proto__)
descriptor = Object.getOwnPropertyDescriptor(owner, member);
if (!descriptor)
continue;
if (typeof descriptor.value === "function")
interface[member] = bind(descriptor.value, implementation);
else if (typeof descriptor.get === "function")
interface.__defineGetter__(member, bind(descriptor.get, implementation));
else
Object.defineProperty(interface, member, descriptor);
}
}

function declareInterfaceClass(implConstructor)
{
return function()
{
var impl = { __proto__: implConstructor.prototype };
implConstructor.apply(impl, arguments);
populateInterfaceClass(this, impl);
}
}

function defineDeprecatedProperty(object, className, oldName, newName)
{
var warningGiven = false;
function getter()
{
if (!warningGiven) {
console.warn(className + "." + oldName + " is deprecated. Use " + className + "." + newName + " instead");
warningGiven = true;
}
return object[newName];
}
object.__defineGetter__(oldName, getter);
}

var AuditCategory = declareInterfaceClass(AuditCategoryImpl);
var AuditResult = declareInterfaceClass(AuditResultImpl);
var Button = declareInterfaceClass(ButtonImpl);
var EventSink = declareInterfaceClass(EventSinkImpl);
var ExtensionPanel = declareInterfaceClass(ExtensionPanelImpl);
var ExtensionSidebarPane = declareInterfaceClass(ExtensionSidebarPaneImpl);
var PanelWithSidebar = declareInterfaceClass(PanelWithSidebarImpl);
var Request = declareInterfaceClass(RequestImpl);
var Resource = declareInterfaceClass(ResourceImpl);
var Timeline = declareInterfaceClass(TimelineImpl);

var extensionServer = new ExtensionServerClient();

window.webInspector = new InspectorExtensionAPI();
window.experimental = window.experimental || {};
window.experimental.webInspector = window.webInspector;

}

function buildExtensionAPIInjectedScript(platformAPI)
{
return "(function(injectedScriptHost, inspectedWindow, injectedScriptId){ " +
defineCommonExtensionSymbols.toString() + ";" +
injectedExtensionAPI.toString() + ";" +
"injectedExtensionAPI(injectedScriptId);" +
(platformAPI || "") + ";" +
"return {};" +
"})";
}






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.ExtensionServer = function()
{
this._clientObjects = {};
this._handlers = {};
this._subscribers = {};
this._subscriptionStartHandlers = {};
this._subscriptionStopHandlers = {};
this._extraHeaders = {};
this._requests = {};
this._lastRequestId = 0;
this._registeredExtensions = {};
this._status = new WebInspector.ExtensionStatus();

var commands = WebInspector.extensionAPI.Commands;

this._registerHandler(commands.AddAuditCategory, this._onAddAuditCategory.bind(this));
this._registerHandler(commands.AddAuditResult, this._onAddAuditResult.bind(this));
this._registerHandler(commands.AddConsoleMessage, this._onAddConsoleMessage.bind(this));
this._registerHandler(commands.AddRequestHeaders, this._onAddRequestHeaders.bind(this));
this._registerHandler(commands.CreatePanel, this._onCreatePanel.bind(this));
this._registerHandler(commands.CreateSidebarPane, this._onCreateSidebarPane.bind(this));
this._registerHandler(commands.CreateStatusBarButton, this._onCreateStatusBarButton.bind(this));
this._registerHandler(commands.EvaluateOnInspectedPage, this._onEvaluateOnInspectedPage.bind(this));
this._registerHandler(commands.GetHAR, this._onGetHAR.bind(this));
this._registerHandler(commands.GetConsoleMessages, this._onGetConsoleMessages.bind(this));
this._registerHandler(commands.GetPageResources, this._onGetPageResources.bind(this));
this._registerHandler(commands.GetRequestContent, this._onGetRequestContent.bind(this));
this._registerHandler(commands.GetResourceContent, this._onGetResourceContent.bind(this));
this._registerHandler(commands.Log, this._onLog.bind(this));
this._registerHandler(commands.Reload, this._onReload.bind(this));
this._registerHandler(commands.SetOpenResourceHandler, this._onSetOpenResourceHandler.bind(this));
this._registerHandler(commands.SetResourceContent, this._onSetResourceContent.bind(this));
this._registerHandler(commands.SetSidebarHeight, this._onSetSidebarHeight.bind(this));
this._registerHandler(commands.SetSidebarContent, this._onSetSidebarContent.bind(this));
this._registerHandler(commands.SetSidebarPage, this._onSetSidebarPage.bind(this));
this._registerHandler(commands.StopAuditCategoryRun, this._onStopAuditCategoryRun.bind(this));
this._registerHandler(commands.Subscribe, this._onSubscribe.bind(this));
this._registerHandler(commands.Unsubscribe, this._onUnsubscribe.bind(this));
this._registerHandler(commands.UpdateButton, this._onUpdateButton.bind(this));

window.addEventListener("message", this._onWindowMessage.bind(this), false);
}

WebInspector.ExtensionServer.prototype = {
hasExtensions: function()
{
return !!Object.keys(this._registeredExtensions).length;
},

notifySearchAction: function(panelId, action, searchString)
{
this._postNotification(WebInspector.extensionAPI.Events.PanelSearch + panelId, action, searchString);
},

notifyViewShown: function(identifier, frameIndex)
{
this._postNotification(WebInspector.extensionAPI.Events.ViewShown + identifier, frameIndex);
},

notifyViewHidden: function(identifier)
{
this._postNotification(WebInspector.extensionAPI.Events.ViewHidden + identifier);
},

notifyButtonClicked: function(identifier)
{
this._postNotification(WebInspector.extensionAPI.Events.ButtonClicked + identifier);
},

_inspectedURLChanged: function(event)
{
this._requests = {};
var url = event.data;
this._postNotification(WebInspector.extensionAPI.Events.InspectedURLChanged, url);
},

_mainFrameNavigated: function(event)
{
this._postNotification(WebInspector.extensionAPI.Events.Reset);
},

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];
},


_postNotification: function(type, vararg)
{
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 (var name in message.headers)
extensionHeaders[name] = message.headers[name];
var allHeaders =   {};
for (var extension in this._extraHeaders) {
var headers = this._extraHeaders[extension];
for (name in headers) {
if (typeof headers[name] === "string")
allHeaders[name] = headers[name];
}
}
NetworkAgent.setExtraHTTPHeaders(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 page = this._expandResourcePath(port._extensionOrigin, message.page);
var icon = this._expandResourcePath(port._extensionOrigin, message.icon)
var panel = new WebInspector.ExtensionPanel(id, message.title, page, icon);
this._clientObjects[id] = panel;
WebInspector.panels[id] = panel;
WebInspector.addPanel(panel);
return this._status.OK();
},

_onCreateStatusBarButton: function(message, port)
{
var panel = this._clientObjects[message.panel];
if (!panel || !(panel instanceof WebInspector.ExtensionPanel))
return this._status.E_NOTFOUND(message.panel);
var button = new WebInspector.ExtensionButton(message.id, this._expandResourcePath(port._extensionOrigin, message.icon), message.tooltip, message.disabled);
this._clientObjects[message.id] = button;
panel.addStatusBarItem(button.element);
return this._status.OK();
},

_onUpdateButton: function(message, port)
{
var button = this._clientObjects[message.id];
if (!button || !(button instanceof WebInspector.ExtensionButton))
return this._status.E_NOTFOUND(message.id);
button.update(this._expandResourcePath(port._extensionOrigin, message.icon), message.tooltip, message.disabled);
return this._status.OK();
},

_onCreateSidebarPane: function(message)
{
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();
},

_onSetSidebarHeight: function(message)
{
var sidebar = this._clientObjects[message.id];
if (!sidebar)
return this._status.E_NOTFOUND(message.id);
sidebar.setHeight(message.height);
return this._status.OK();
},

_onSetSidebarContent: function(message, port)
{
var sidebar = this._clientObjects[message.id];
if (!sidebar)
return this._status.E_NOTFOUND(message.id);
function callback(error)
{
var result = error ? this._status.E_FAILED(error) : this._status.OK();
this._dispatchCallback(message.requestId, port, result);
}
if (message.evaluateOnPage)
sidebar.setExpression(message.expression, message.rootTitle, callback.bind(this));
else
sidebar.setObject(message.expression, message.rootTitle, callback.bind(this));
},

_onSetSidebarPage: function(message, port)
{
var sidebar = this._clientObjects[message.id];
if (!sidebar)
return this._status.E_NOTFOUND(message.id);
sidebar.setPage(this._expandResourcePath(port._extensionOrigin, message.page));
},

_onSetOpenResourceHandler: function(message, port)
{
var name = this._registeredExtensions[port._extensionOrigin].name || ("Extension " + port._extensionOrigin);
if (message.handlerPresent)
WebInspector.openAnchorLocationRegistry.registerHandler(name, this._handleOpenURL.bind(this, port));
else
WebInspector.openAnchorLocationRegistry.unregisterHandler(name);
},

_handleOpenURL: function(port, details)
{
var resource = WebInspector.resourceForURL(details.url);
if (!resource)
return false;
var lineNumber = details.lineNumber;
if (typeof lineNumber === "number")
lineNumber += 1;
port.postMessage({
command: "open-resource",
resource: this._makeResource(resource),
lineNumber: lineNumber
});
return true;
},

_onLog: function(message)
{
WebInspector.log(message.message);
},

_onReload: function(message)
{
var options =   (message.options || {});
NetworkAgent.setUserAgentOverride(typeof options.userAgent === "string" ? options.userAgent : "");
var injectedScript;
if (options.injectedScript) {


injectedScript = "((function(){" + options.injectedScript + "})(),function(){return {}})";
}
PageAgent.reload(!!options.ignoreCache, injectedScript);
return this._status.OK();
},

_onEvaluateOnInspectedPage: function(message, port)
{
function callback(error, resultPayload, wasThrown)
{
var result = {};
if (error) {
result.isException = true;
result.value = error.message;
}  else
result.value = resultPayload.value;

if (wasThrown)
result.isException = true;

this._dispatchCallback(message.requestId, port, result);
}
RuntimeAgent.evaluate(message.expression, "", true, undefined, undefined, true, callback.bind(this));
},

_onGetConsoleMessages: function()
{
return WebInspector.console.messages.map(this._makeConsoleMessage);
},

_onAddConsoleMessage: function(message)
{
function convertSeverity(level)
{
switch (level) {
case WebInspector.extensionAPI.console.Severity.Tip:
return WebInspector.ConsoleMessage.MessageLevel.Tip;
case WebInspector.extensionAPI.console.Severity.Log:
return WebInspector.ConsoleMessage.MessageLevel.Log;
case WebInspector.extensionAPI.console.Severity.Warning:
return WebInspector.ConsoleMessage.MessageLevel.Warning;
case WebInspector.extensionAPI.console.Severity.Error:
return WebInspector.ConsoleMessage.MessageLevel.Error;
case WebInspector.extensionAPI.console.Severity.Debug:
return WebInspector.ConsoleMessage.MessageLevel.Debug;
}
}
var level = convertSeverity(message.severity);
if (!level)
return this._status.E_BADARG("message.severity", message.severity);

var consoleMessage = WebInspector.ConsoleMessage.create(
WebInspector.ConsoleMessage.MessageSource.JS,
level,
message.text,
WebInspector.ConsoleMessage.MessageType.Log,
message.url,
message.line);
WebInspector.console.addMessage(consoleMessage);
},

_makeConsoleMessage: function(message)
{
function convertLevel(level)
{
if (!level)
return;
switch (level) {
case WebInspector.ConsoleMessage.MessageLevel.Tip:
return WebInspector.extensionAPI.console.Severity.Tip;
case WebInspector.ConsoleMessage.MessageLevel.Log:
return WebInspector.extensionAPI.console.Severity.Log;
case WebInspector.ConsoleMessage.MessageLevel.Warning:
return WebInspector.extensionAPI.console.Severity.Warning;
case WebInspector.ConsoleMessage.MessageLevel.Error:
return WebInspector.extensionAPI.console.Severity.Error;
case WebInspector.ConsoleMessage.MessageLevel.Debug:
return WebInspector.extensionAPI.console.Severity.Debug;
default:
return WebInspector.extensionAPI.console.Severity.Log;
}
}
var result = {
severity: convertLevel(message.level),
text: message.text,
};
if (message.url)
result.url = message.url;
if (message.line)
result.line = message.line;
return result;
},

_onGetHAR: function()
{
var requests = WebInspector.networkLog.resources;
var harLog = (new WebInspector.HARLog(requests)).build();
for (var i = 0; i < harLog.entries.length; ++i)
harLog.entries[i]._requestId = this._requestId(requests[i]);
return harLog;
},

_makeResource: function(resource)
{
return {
url: resource.url,
type: WebInspector.Resource.Type.toString(resource.type)
};
},

_onGetPageResources: function()
{
var resources = [];
function pushResourceData(resource)
{
resources.push(this._makeResource(resource));
}
WebInspector.resourceTreeModel.forAllResources(pushResourceData.bind(this));
return resources;
},

_getResourceContent: function(resource, message, port)
{
function onContentAvailable(content, encoded)
{
var response = {
encoding: encoded ? "base64" : "",
content: content
};
this._dispatchCallback(message.requestId, port, response);
}
resource.requestContent(onContentAvailable.bind(this));
},

_onGetRequestContent: function(message, port)
{
var request = this._requestById(message.id);
if (!request)
return this._status.E_NOTFOUND(message.id);
this._getResourceContent(request, message, port);
},

_onGetResourceContent: function(message, port)
{
var resource = WebInspector.resourceTreeModel.resourceForURL(message.url);
if (!resource)
return this._status.E_NOTFOUND(message.url);
this._getResourceContent(resource, message, port);
},

_onSetResourceContent: function(message, port)
{
function callbackWrapper(error)
{
var response = error ? this._status.E_FAILED(error) : this._status.OK();
this._dispatchCallback(message.requestId, port, response);
}
var resource = WebInspector.resourceTreeModel.resourceForURL(message.url);
if (!resource)
return this._status.E_NOTFOUND(message.url);
resource.setContent(message.content, message.commit, callbackWrapper.bind(this));
},

_requestId: function(request)
{
if (!request._extensionRequestId) {
request._extensionRequestId = ++this._lastRequestId;
this._requests[request._extensionRequestId] = request;
}
return request._extensionRequestId;
},

_requestById: function(id)
{
return this._requests[id];
},

_onAddAuditCategory: function(message)
{
var category = new WebInspector.ExtensionAuditCategory(message.id, message.displayName, message.resultCount);
if (WebInspector.panels.audits.getCategory(category.id))
return this._status.E_EXISTS(category.id);
this._clientObjects[message.id] = category;
WebInspector.panels.audits.addCategory(category);
},

_onAddAuditResult: function(message)
{
var auditResult = this._clientObjects[message.resultId];
if (!auditResult)
return this._status.E_NOTFOUND(message.resultId);
try {
auditResult.addResult(message.displayName, message.description, message.severity, message.details);
} catch (e) {
return e;
}
return this._status.OK();
},

_onStopAuditCategoryRun: function(message)
{
var auditRun = this._clientObjects[message.resultId];
if (!auditRun)
return this._status.E_NOTFOUND(message.resultId);
auditRun.cancel();
},

_dispatchCallback: function(requestId, port, result)
{
if (requestId)
port.postMessage({ command: "callback", requestId: requestId, result: result });
},

initExtensions: function()
{
this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.ConsoleMessageAdded,
WebInspector.console, WebInspector.ConsoleModel.Events.MessageAdded, this._notifyConsoleMessageAdded);
this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.NetworkRequestFinished,
WebInspector.networkManager, WebInspector.NetworkManager.EventTypes.ResourceFinished, this._notifyRequestFinished);
this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.ResourceAdded,
WebInspector.resourceTreeModel,
WebInspector.ResourceTreeModel.EventTypes.ResourceAdded,
this._notifyResourceAdded);
if (WebInspector.panels.elements) {
this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.ElementsPanelObjectSelected,
WebInspector.panels.elements.treeOutline,
WebInspector.ElementsTreeOutline.Events.SelectedNodeChanged,
this._notifyElementsSelectionChanged);
}
this._registerAutosubscriptionHandler(WebInspector.extensionAPI.Events.ResourceContentCommitted,
WebInspector.resourceTreeModel,
WebInspector.ResourceTreeModel.EventTypes.ResourceContentCommitted,
this._notifyResourceContentCommitted);

function onTimelineSubscriptionStarted()
{
WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded,
this._notifyTimelineEventRecorded, this);
WebInspector.timelineManager.start();
}
function onTimelineSubscriptionStopped()
{
WebInspector.timelineManager.stop();
WebInspector.timelineManager.removeEventListener(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded,
this._notifyTimelineEventRecorded, this);
}
this._registerSubscriptionHandler(WebInspector.extensionAPI.Events.TimelineEventRecorded,
onTimelineSubscriptionStarted.bind(this), onTimelineSubscriptionStopped.bind(this));

WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.InspectedURLChanged,
this._inspectedURLChanged, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._mainFrameNavigated, this);
InspectorExtensionRegistry.getExtensionsAsync();
},

_notifyConsoleMessageAdded: function(event)
{
this._postNotification(WebInspector.extensionAPI.Events.ConsoleMessageAdded, this._makeConsoleMessage(event.data));
},

_notifyResourceAdded: function(event)
{
var resource = event.data;
this._postNotification(WebInspector.extensionAPI.Events.ResourceAdded, this._makeResource(resource));
},

_notifyResourceContentCommitted: function(event)
{
this._postNotification(WebInspector.extensionAPI.Events.ResourceContentCommitted, this._makeResource(event.data.resource), event.data.content);
},

_notifyRequestFinished: function(event)
{
var request = event.data;
this._postNotification(WebInspector.extensionAPI.Events.NetworkRequestFinished, this._requestId(request), (new WebInspector.HAREntry(request)).build());
},

_notifyElementsSelectionChanged: function()
{
this._postNotification(WebInspector.extensionAPI.Events.ElementsPanelObjectSelected);
},

_notifyTimelineEventRecorded: function(event)
{
this._postNotification(WebInspector.extensionAPI.Events.TimelineEventRecorded, event.data);
},


_addExtensions: function(extensions)
{

InspectorFrontendHost.setExtensionAPI(this._buildExtensionAPIScript());
for (var i = 0; i < extensions.length; ++i)
this._addExtension(extensions[i].startPage, extensions[i].name);
},

_addExtension: function(startPage, name)
{
const urlOriginRegExp = new RegExp("([^:]+:\/\/[^/]*)\/"); 

try {
var originMatch = urlOriginRegExp.exec(startPage);
if (!originMatch) {
console.error("Skipping extension with invalid URL: " + startPage);
return false;
}
this._registeredExtensions[originMatch[1]] = { name: name };
var iframe = document.createElement("iframe");
iframe.src = startPage;
iframe.style.display = "none";
document.body.appendChild(iframe);
} catch (e) {
console.error("Failed to initialize extension " + startPage + ":" + e);
return false;
}
return true;
},

_buildExtensionAPIScript: function()
{
var platformAPI = WebInspector.buildPlatformExtensionAPI ? WebInspector.buildPlatformExtensionAPI() : "";
return buildExtensionAPIInjectedScript(platformAPI);
},

_onWindowMessage: function(event)
{
if (event.data === "registerExtension")
this._registerExtension(event.origin, event.ports[0]);
},

_registerExtension: function(origin, port)
{
if (!this._registeredExtensions.hasOwnProperty(origin)) {
if (origin !== window.location.origin) 
console.error("Ignoring unauthorized client request from " + origin);
return;
}
port._extensionOrigin = origin;
port.addEventListener("message", this._onmessage.bind(this), false);
port.start();
},

_onmessage: function(event)
{
var message = event.data;
var result;

if (message.command in this._handlers)
result = this._handlers[message.command](message, event.target);
else
result = this._status.E_NOTSUPPORTED(message.command);

if (result && message.requestId)
this._dispatchCallback(message.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;
},

_registerAutosubscriptionHandler: function(eventTopic, eventTarget, frontendEventType, handler)
{
this._registerSubscriptionHandler(eventTopic,
eventTarget.addEventListener.bind(eventTarget, frontendEventType, handler, this),
eventTarget.removeEventListener.bind(eventTarget, frontendEventType, handler, this));
},

_expandResourcePath: function(extensionPath, resourcePath)
{
if (!resourcePath)
return;
return extensionPath + this._normalizePath(resourcePath);
},

_normalizePath: function(path)
{
var source = path.split("/");
var result = [];

for (var i = 0; i < source.length; ++i) {
if (source[i] === ".")
continue;

if (source[i] === "")
continue;
if (source[i] === "..")
result.pop();
else
result.push(source[i]);
}
return "/" + result.join("/");
}
}


WebInspector.ExtensionStatus = function()
{
function makeStatus(code, description)
{
var details = Array.prototype.slice.call(arguments, 2);
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;
}

this.OK = makeStatus.bind(null, "OK", "OK");
this.E_EXISTS = makeStatus.bind(null, "E_EXISTS", "Object already exists: %s");
this.E_BADARG = makeStatus.bind(null, "E_BADARG", "Invalid argument %s: %s");
this.E_BADARGTYPE = makeStatus.bind(null, "E_BADARGTYPE", "Invalid type for argument %s: got %s, expected %s");
this.E_NOTFOUND = makeStatus.bind(null, "E_NOTFOUND", "Object not found: %s");
this.E_NOTSUPPORTED = makeStatus.bind(null, "E_NOTSUPPORTED", "Object does not support requested operation: %s");
this.E_FAILED = makeStatus.bind(null, "E_FAILED", "Operation failed: %s");
}

WebInspector.addExtensions = function(extensions)
{
WebInspector.extensionServer._addExtensions(extensions);
}

WebInspector.extensionAPI = {};
defineCommonExtensionSymbols(WebInspector.extensionAPI);

WebInspector.extensionServer = new WebInspector.ExtensionServer();

window.addExtension = WebInspector.extensionServer._addExtension.bind(WebInspector.extensionServer);






WebInspector.ExtensionView = function(id, parent, src, className)
{
WebInspector.View.call(this);

this._id = id;
this._iframe = document.createElement("iframe");
this._iframe.addEventListener("load", this._onLoad.bind(this), false);
this._iframe.src = src;
this._iframe.className = className;

this.element.appendChild(this._iframe);
this.show(parent);
}

WebInspector.ExtensionView.prototype = {
wasShown: function()
{
if (typeof this._frameIndex === "number")
WebInspector.extensionServer.notifyViewShown(this._id, this._frameIndex);
},

willHide: function()
{
if (typeof this._frameIndex === "number")
WebInspector.extensionServer.notifyViewHidden(this._id);
},

_onLoad: function()
{
this._frameIndex = Array.prototype.indexOf.call(window.frames, this._iframe.contentWindow);
if (this.isShowing())
WebInspector.extensionServer.notifyViewShown(this._id, this._frameIndex);
}
}

WebInspector.ExtensionView.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.ExtensionNotifierView = function(id)
{
WebInspector.View.call(this);

this._id = id;
}

WebInspector.ExtensionNotifierView.prototype = {
wasShown: function()
{
WebInspector.extensionServer.notifyViewShown(this._id);
},

willHide: function()
{
WebInspector.extensionServer.notifyViewHidden(this._id);
}
}

WebInspector.ExtensionNotifierView.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.ExtensionPanel = function(id, label, pageURL, iconURL)
{
WebInspector.Panel.call(this, id);
this.setHideOnDetach();
this._toolbarItemLabel = label;
this._statusBarItems = [];

if (iconURL) {
this._addStyleRule(".toolbar-item." + id + " .toolbar-icon", "background-image: url(" + iconURL + ");");
this._addStyleRule(".toolbar-small .toolbar-item." + id + " .toolbar-icon", "background-position-x: -32px;");
}
new WebInspector.ExtensionView(id, this.element, pageURL, "extension panel");
}

WebInspector.ExtensionPanel.prototype = {
get toolbarItemLabel()
{
return this._toolbarItemLabel;
},

get defaultFocusedElement()
{
return this.sidebarTreeElement || this.element;
},

get statusBarItems()
{
return this._statusBarItems;
},


addStatusBarItem: function(element)
{
this._statusBarItems.push(element);
},

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.ExtensionButton = function(id, iconURL, tooltip, disabled)
{
this._id = id;
this.element = document.createElement("button");
this.element.className = "status-bar-item extension";
this.element.addEventListener("click", this._onClicked.bind(this), false);
this.update(iconURL, tooltip, disabled);
}

WebInspector.ExtensionButton.prototype = {

update: function(iconURL, tooltip, disabled)
{
if (typeof iconURL === "string")
this.element.style.backgroundImage = "url(" + iconURL + ")";
if (typeof tooltip === "string")
this.element.title = tooltip;
if (typeof disabled === "boolean")
this.element.disabled = disabled;
},

_onClicked: function()
{
WebInspector.extensionServer.notifyButtonClicked(this._id);
}
}


WebInspector.ExtensionSidebarPane = function(title, id)
{
WebInspector.SidebarPane.call(this, title);
this._id = id;
}

WebInspector.ExtensionSidebarPane.prototype = {

setObject: function(object, title, callback)
{
this._createObjectPropertiesView();
this._setObject(WebInspector.RemoteObject.fromLocalObject(object), title, callback);
},


setExpression: function(expression, title, callback)
{
this._createObjectPropertiesView();
RuntimeAgent.evaluate(expression, "extension-watch", true, undefined, undefined, undefined, this._onEvaluate.bind(this, title, callback));
},


setPage: function(url)
{
if (this._objectPropertiesView) {
this._objectPropertiesView.detach();
delete this._objectPropertiesView;
}
if (this._extensionView)
this._extensionView.detach(true);

this._extensionView = new WebInspector.ExtensionView(this._id, this.bodyElement, url, "extension");
},


setHeight: function(height)
{
this.bodyElement.style.height = height;
},


_onEvaluate: function(title, callback, error, result, wasThrown)
{
if (error)
callback(error.toString());
else
this._setObject(WebInspector.RemoteObject.fromPayload(result), title, callback);
},

_createObjectPropertiesView: function()
{
if (this._objectPropertiesView)
return;
if (this._extensionView) {
this._extensionView.detach(true);
delete this._extensionView;
}
this._objectPropertiesView = new WebInspector.ExtensionNotifierView(this._id);
this._objectPropertiesView.show(this.bodyElement);
},


_setObject: function(object, title, callback)
{

if (!this._objectPropertiesView) {
callback("operation cancelled");
return;
}
this._objectPropertiesView.element.removeChildren();
var section = new WebInspector.ObjectPropertiesSection(object, title);
if (!title)
section.headerElement.addStyleClass("hidden");
section.expanded = true;
section.editable = false;
this._objectPropertiesView.element.appendChild(section.element);
callback();
}
}

WebInspector.ExtensionSidebarPane.prototype.__proto__ = WebInspector.SidebarPane.prototype;






WebInspector.AuditsPanel = function()
{
WebInspector.Panel.call(this, "audits");
this.registerRequiredCSS("auditsPanel.css");

this.createSplitViewWithSidebarTree();
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, this);

this.viewsContainerElement = this.splitView.mainElement;

this._constructCategories();

this._launcherView = new WebInspector.AuditLauncherView(this.initiateAudit.bind(this));
for (var 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.networkLog.resources;

var rulesRemaining = 0;
for (var i = 0; i < categories.length; ++i)
rulesRemaining += categories[i].ruleCount;

var results = [];
var mainResourceURL = WebInspector.inspectedPageURL;

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.revealAndSelect();
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));

WebInspector.userMetrics.AuditsStarted.record();
},

_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.detach();

this._visibleView = x;

if (x)
x.show(this.viewsContainerElement);
},

wasShown: function()
{
WebInspector.Panel.prototype.wasShown.call(this);
if (!this._visibleView)
this.auditsItemTreeElement.select();
},

_clearButtonClicked: function()
{
this.auditsItemTreeElement.revealAndSelect();
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;
this._formatters = {
r: WebInspector.AuditRuleResult.linkifyDisplayName
};
var standardFormatters = Object.keys(String.standardFormatters);
for (var i = 0; i < standardFormatters.length; ++i)
this._formatters[standardFormatters[i]] = String.standardFormatters[standardFormatters[i]];
}

WebInspector.AuditRuleResult.linkifyDisplayName = function(url)
{
return WebInspector.linkifyURLAsNode(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");
},


addFormatted: function(format, vararg)
{
var substitutions = Array.prototype.slice.call(arguments, 1);
var fragment = document.createDocumentFragment();

var formattedResult = String.format(format, substitutions, this._formatters, fragment, this._append).formattedResult;
if (formattedResult instanceof Node)
formattedResult.normalize();
return this.addChild(formattedResult);
},

_append: function(a, b)
{
if (!(b instanceof Node))
b = document.createTextNode(b);
a.appendChild(b);
return a;
}
}


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);

this.element.addEventListener("contextmenu", this._contextMenuEventFired.bind(this), true);
}

WebInspector.AuditResultView.prototype = {
_contextMenuEventFired: function(event)
{
var contextMenu = new WebInspector.ContextMenu();
if (WebInspector.populateHrefContextMenu(contextMenu, null, event))
contextMenu.show(event);
}
}

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.title = 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.addFormatted("%r could save ~%s", 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], false);
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, false);
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(domain);
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.addFormatted("%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(resources, result)
{
},

_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 format = "%r";
if (urlToNoDimensionCount[url] > 1)
format += " (%d uses)";
entry.addFormatted(format, url, urlToNoDimensionCount[url]);
result.violationCount++;
}
callback(entry ? result : null);
}

function imageStylesReady(imageId, styles, isLastStyle, computedStyle)
{
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;

if (computedStyle.getPropertyValue("position") === "absolute") {
if (isLastStyle)
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 (isLastStyle)
doneCallback();
}

function getStyles(nodeIds)
{
var targetResult = {};

function inlineCallback(inlineStyle, styleAttributes)
{
targetResult.inlineStyle = inlineStyle;
targetResult.styleAttributes = styleAttributes;
}

function matchedCallback(result)
{
if (result)
targetResult.matchedCSSRules = result.matchedCSSRules;
}

if (!nodeIds || !nodeIds.length)
doneCallback();

for (var i = 0; nodeIds && i < nodeIds.length; ++i) {
WebInspector.cssModel.getMatchedStylesAsync(nodeIds[i], undefined, false, false, matchedCallback);
WebInspector.cssModel.getInlineStylesAsync(nodeIds[i], inlineCallback);
WebInspector.cssModel.getComputedStyleAsync(nodeIds[i], undefined, imageStylesReady.bind(null, nodeIds[i], targetResult, 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.addFormatted("%s style block(s) in the %r body should be moved to the document head.", urlViolations[0], url);
result.violationCount += urlViolations[0];
}
for (var i = 0; i < urlViolations[1].length; ++i)
result.addFormatted("Link node %r should be moved to the document head in %r", urlViolations[1][i], 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 Node)
return value;
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;
},

resourceLink: function(url, line)
{

return WebInspector.linkifyResourceAsNode(url, line, "console-message-url webkit-html-resource-link");
}
};






WebInspector.NetworkItemView = function(resource)
{
WebInspector.TabbedPane.call(this);

this.element.addStyleClass("network-item-view");

var headersView = new WebInspector.ResourceHeadersView(resource);
this.appendTab("headers", WebInspector.UIString("Headers"), headersView);

var responseView = new WebInspector.ResourceResponseView(resource);
var previewView = new WebInspector.ResourcePreviewView(resource, responseView);

this.appendTab("preview", WebInspector.UIString("Preview"), previewView);
this.appendTab("response", WebInspector.UIString("Response"), responseView);

if (resource.requestCookies || resource.responseCookies) {
this._cookiesView = new WebInspector.ResourceCookiesView(resource);
this.appendTab("cookies", WebInspector.UIString("Cookies"), this._cookiesView);
}

if (resource.timing) {
var timingView = new WebInspector.ResourceTimingView(resource);
this.appendTab("timing", WebInspector.UIString("Timing"), timingView);
}

this.addEventListener("tab-selected", this._tabSelected, this);
}

WebInspector.NetworkItemView.prototype = {
wasShown: function()
{
WebInspector.TabbedPane.prototype.wasShown.call();
this._selectTab();
},


_selectTab: function(tabId)
{
if (!tabId)
tabId = WebInspector.settings.resourceViewTab.get();

if (!this.selectTab(tabId)) {
this._isInFallbackSelection = true;
this.selectTab("headers");
delete this._isInFallbackSelection;
}
},

_tabSelected: function(event)
{
if (event.data.isUserGesture)
WebInspector.settings.resourceViewTab.set(event.data.tabId);
}
}

WebInspector.NetworkItemView.prototype.__proto__ = WebInspector.TabbedPane.prototype;


WebInspector.ResourceContentView = function(resource)
{
WebInspector.ResourceView.call(this, resource);
}

WebInspector.ResourceContentView.prototype = {
hasContent: function()
{
return true;
},

get innerView()
{
return this._innerView;
},

set innerView(innerView)
{
this._innerView = innerView;
},

wasShown: function()
{
this._ensureInnerViewShown();
},

_ensureInnerViewShown: function()
{
if (this._innerViewShowRequested)
return;
this._innerViewShowRequested = true;

function callback()
{
this._innerViewShowRequested = false;
this.contentLoaded();
}

this.resource.requestContent(callback.bind(this));
},

contentLoaded: function()
{

},

canHighlightLine: function()
{
return this._innerView && this._innerView.canHighlightLine();
},

highlightLine: function(line)
{
if (this.canHighlightLine())
this._innerView.highlightLine(line);
}
}

WebInspector.ResourceContentView.prototype.__proto__ = WebInspector.ResourceView.prototype;






WebInspector.EmptyView = function(text)
{
WebInspector.View.call(this);
this._text = text;
}

WebInspector.EmptyView.prototype = {
wasShown: function()
{
this.element.className = "storage-empty-view";
this.element.textContent = this._text;
},

set text(text)
{
this._text = text;
if (this.visible)
this.element.textContent = this._text;
},
}

WebInspector.EmptyView.prototype.__proto__ = WebInspector.View.prototype;






WebInspector.ResourceHeadersView = function(resource)
{
WebInspector.View.call(this);
this.registerRequiredCSS("resourceView.css");
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._urlFragmentTreeElement = new TreeElement("", null, true);
this._urlFragmentTreeElement.expanded = true;
this._urlFragmentTreeElement.selectable = false;
this._urlFragmentTreeElement.hidden = true;
this._headersTreeOutline.appendChild(this._urlFragmentTreeElement);

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._refreshUrlFragment();
this._refreshRequestHeaders();
this._refreshResponseHeaders();
this._refreshHTTPInformation();
}

WebInspector.ResourceHeadersView.prototype = {

_formatHeader: function(name, value)
{
var fragment = document.createDocumentFragment();
fragment.createChild("div", "header-name").textContent = name + ":";
fragment.createChild("div", "header-value source-code").textContent = value;

return fragment;
},


_formatParameter: function(value, className, decodeParameters)
{
var errorDecoding = false;

if (decodeParameters) {
value = value.replace(/\+/g, " ");
if (value.indexOf("%") >= 0) {
try {
value = decodeURIComponent(value);
} catch(e) {
errorDecoding = true;
}
}
}
var div = document.createElement("div");
div.className = className;
if (errorDecoding)
div.createChild("span", "error-message").textContent = WebInspector.UIString("(unable to decode value)");
else
div.textContent = value;
return div;
},

_refreshURL: function()
{
this._urlTreeElement.title = this._formatHeader(WebInspector.UIString("Request URL"), this._resource.url);
},

_refreshQueryString: function()
{
var queryParameters = this._resource.queryParameters;
this._queryStringTreeElement.hidden = !queryParameters;
if (queryParameters)
this._refreshParms(WebInspector.UIString("Query String Parameters"), queryParameters, this._queryStringTreeElement);
},

_refreshUrlFragment: function()
{
var urlFragment = this._resource.urlFragment;
this._urlFragmentTreeElement.hidden = !urlFragment;

if (!urlFragment)
return;

var sectionTitle = WebInspector.UIString("URL fragment");

this._urlFragmentTreeElement.removeChildren();
this._urlFragmentTreeElement.listItemElement.removeChildren();
this._urlFragmentTreeElement.listItemElement.appendChild(document.createTextNode(sectionTitle));

var fragmentTreeElement = new TreeElement(null, null, false);
fragmentTreeElement.title = this._formatHeader("#", urlFragment);
fragmentTreeElement.selectable = false;
this._urlFragmentTreeElement.appendChild(fragmentTreeElement);
},

_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 = document.createElement("div");
title.className = "raw-form-data header-value source-code";
title.textContent = formData;

var parmTreeElement = new TreeElement(title, null, false);
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 paramNameValue = document.createDocumentFragment();
var name = this._formatParameter(parms[i].name + ":", "header-name", this._decodeRequestParameters);
var value = this._formatParameter(parms[i].value, "header-value source-code", this._decodeRequestParameters);
paramNameValue.appendChild(name);
paramNameValue.appendChild(value);

var parmTreeElement = new TreeElement(paramNameValue, null, false);
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.sortedRequestHeaders, 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.sortedResponseHeaders, 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;

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";

requestMethodElement.title = this._formatHeader(WebInspector.UIString("Request Method"), this._resource.requestMethod);

var statusCodeFragment = document.createDocumentFragment();
statusCodeFragment.createChild("div", "header-name").textContent = WebInspector.UIString("Status Code") + ":";

var statusCodeImage = statusCodeFragment.createChild("img", "resource-status-image");
statusCodeImage.src = statusImageSource;
statusCodeImage.title = this._resource.statusCode + " " + this._resource.statusText;
var value = statusCodeFragment.createChild("div", "header-value source-code");
value.textContent = this._resource.statusCode + " " + this._resource.statusText;
if (this._resource.cached)
value.createChild("span", "status-from-cache").textContent = " " + WebInspector.UIString("(from cache)");

statusCodeElement.title = statusCodeFragment;
}
},

_refreshHeadersTitle: function(title, headersTreeElement, headersLength)
{
headersTreeElement.listItemElement.removeChildren();
headersTreeElement.listItemElement.appendChild(document.createTextNode(title));

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, length);
headersTreeElement.hidden = !length;
for (var i = 0; i < length; ++i) {
var headerTreeElement = new TreeElement(null, null, false);
headerTreeElement.title = this._formatHeader(headers[i].header, headers[i].value);
headerTreeElement.selectable = false;
headersTreeElement.appendChild(headerTreeElement);
}

if (additionalRow) {
var headerTreeElement = new TreeElement(null, null, false);
headerTreeElement.title = this._formatHeader(additionalRow.header, additionalRow.value);
headerTreeElement.selectable = false;
headersTreeElement.appendChild(headerTreeElement);
}
},

_refreshHeadersText: function(title, headers, headersText, headersTreeElement)
{
headersTreeElement.removeChildren();

this._refreshHeadersTitle(title, headersTreeElement, headers.length);
var headerTreeElement = new TreeElement(null, null, false);
headerTreeElement.selectable = false;
headersTreeElement.appendChild(headerTreeElement);

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 = {
wasShown: function()
{
if (!this._gotCookies) {
if (!this._emptyView) {
this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("This request has no cookies."));
this._emptyView.show(this.element);
}
return;
}

if (!this._cookiesTable)
this._buildCookiesTable();
},

get _gotCookies()
{
return !!(this._resource.requestCookies || this._resource.responseCookies);
},

_buildCookiesTable: function()
{
this.detachChildViews();

this._cookiesTable = new WebInspector.CookiesTable(null, true);
this._cookiesTable.addCookiesFolder(WebInspector.UIString("Request Cookies"), this._resource.requestCookies);
this._cookiesTable.addCookiesFolder(WebInspector.UIString("Response Cookies"), this._resource.responseCookies);
this._cookiesTable.show(this.element);
},

_refreshCookies: function()
{
delete this._cookiesTable;
if (!this._gotCookies || !this.isShowing())
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 = {
wasShown: function()
{
if (!this._resource.timing) {
if (!this._emptyView) {
this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("This request has no detailed timing info."));
this._emptyView.show(this.element);
this.innerView = this._emptyView;
}
return;
}

if (this._emptyView) {
this._emptyView.detach();
delete this._emptyView;
}

this._refresh();
},

_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)
{
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.secondsToString((rows[i].end - rows[i].start) / 1000);
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 prefix = "";


var start = /[{[]/.exec(text);
if (start && start.index) {
prefix = text.substring(0, start.index);
text = text.substring(start.index);
}

try {
return new WebInspector.ParsedJSON(JSON.parse(text), prefix, "");
} catch (e) {
return;
}
}

WebInspector.ResourceJSONView.parseJSONP = function(text)
{

var start = text.indexOf("(");
var end = text.lastIndexOf(")");
if (start == -1 || end == -1 || end < start)
return;

var prefix = text.substring(0, start + 1);
var suffix = text.substring(end);
text = text.substring(start + 1, end);

try {
return new WebInspector.ParsedJSON(JSON.parse(text), prefix, suffix);
} catch (e) {
return;
}
}

WebInspector.ResourceJSONView.prototype = {
hasContent: function()
{
return true;
},

wasShown: function()
{
this._initialize();
},

_initialize: function()
{
if (this._initialized)
return;
this._initialized = true;

var obj = WebInspector.RemoteObject.fromLocalObject(this._parsedJSON.data);
var title = this._parsedJSON.prefix + obj.description + this._parsedJSON.suffix;
var section = new WebInspector.ObjectPropertiesSection(obj, title);
section.expand();
section.editable = false;
this.element.appendChild(section.element);
}
}

WebInspector.ResourceJSONView.prototype.__proto__ = WebInspector.ResourceView.prototype;


WebInspector.ParsedJSON = function(data, prefix, suffix)
{
this.data = data;
this.prefix = prefix;
this.suffix = suffix;
}






WebInspector.ResourceHTMLView = function(resource)
{
WebInspector.ResourceView.call(this, resource);
this.element.addStyleClass("html");
}

WebInspector.ResourceHTMLView.prototype = {
hasContent: function()
{
return true;
},

wasShown: function()
{
this._createIFrame();
},

willHide: function(parentElement)
{
this.element.removeChildren();
},

_createIFrame: function()
{


this.element.removeChildren();
var iframe = document.createElement("iframe");
this.element.appendChild(iframe);
iframe.setAttribute("sandbox", ""); 

iframe.contentDocument.body.innerHTML = this.resource.content;
}
}

WebInspector.ResourceHTMLView.prototype.__proto__ = WebInspector.ResourceView.prototype;






WebInspector.ResourceResponseView = function(resource)
{
WebInspector.ResourceContentView.call(this, resource);
}

WebInspector.ResourceResponseView.prototype = {
get sourceView()
{
if (!this._sourceView && WebInspector.ResourceView.hasTextContent(this.resource))
this._sourceView = new WebInspector.ResourceSourceFrame(this.resource);
return this._sourceView;
},

contentLoaded: function()
{
if (!this.resource.content || !this.sourceView) {
if (!this._emptyView) {
this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("This request has no response data available."));
this._emptyView.show(this.element);
this.innerView = this._emptyView;
}
} else {
if (this._emptyView) {
this._emptyView.detach();
delete this._emptyView;
}

this.sourceView.show(this.element);
this.innerView = this.sourceView;
}
}
}

WebInspector.ResourceResponseView.prototype.__proto__ = WebInspector.ResourceContentView.prototype;






WebInspector.ResourcePreviewView = function(resource, responseView)
{
WebInspector.ResourceContentView.call(this, resource);
this._responseView = responseView;
}

WebInspector.ResourcePreviewView.prototype = {
contentLoaded: function()
{
if (!this.resource.content) {
if (!this._emptyView) {
this._emptyView = this._createEmptyView();
this._emptyView.show(this.element);
this.innerView = this._emptyView;
}
} else {
if (this._emptyView) {
this._emptyView.detach();
delete this._emptyView;
}

if (!this._previewView)
this._previewView = this._createPreviewView();
this._previewView.show(this.element);
this.innerView = this._previewView;
}
},

_createEmptyView: function()
{
return new WebInspector.EmptyView(WebInspector.UIString("This request has no preview available."));
},

_createPreviewView: function()
{
if (this.resource.hasErrorStatusCode() && this.resource.content)
return new WebInspector.ResourceHTMLView(this.resource);

if (this.resource.category === WebInspector.resourceCategories.xhr && this.resource.content) {
var parsedJSON = WebInspector.ResourceJSONView.parseJSON(this.resource.content);
if (parsedJSON)
return new WebInspector.ResourceJSONView(this.resource, parsedJSON);
}

if (this.resource.content && this.resource.category === WebInspector.resourceCategories.scripts && this.resource.mimeType === "application/json") {
var parsedJSONP = WebInspector.ResourceJSONView.parseJSONP(this.resource.content);
if (parsedJSONP)
return new WebInspector.ResourceJSONView(this.resource, parsedJSONP);
}

if (this._responseView.sourceView)
return this._responseView.sourceView;

if (this.resource.category === WebInspector.resourceCategories.other)
return this._createEmptyView();

return WebInspector.ResourceView.nonSourceViewForResource(this.resource);
}
}

WebInspector.ResourcePreviewView.prototype.__proto__ = WebInspector.ResourceContentView.prototype;






WebInspector.ScriptFormatter = function()
{
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, indentString: "    "  };
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 mapping = event.data["mapping"];
var sourceMapping = new WebInspector.FormattedSourceMapping(originalContent.lineEndings(), formattedContent.lineEndings(), mapping);
task.callback(formattedContent, sourceMapping);
},

get _worker()
{
if (!this._cachedWorker) {
this._cachedWorker = new Worker("ScriptFormatterWorker.js");
this._cachedWorker.onmessage = this._didFormatContent.bind(this);
}
return this._cachedWorker;
}
}


WebInspector.FormatterMappingPayload = function()
{
this.original = [];
this.formatted = [];
}


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;
},

collapseToEnd: function()
{
return new WebInspector.TextRange(this.endLine, this.endColumn, this.endLine, this.endColumn);
},

normalize: function()
{
if (this.startLine > this.endLine || (this.startLine === this.endLine && this.startColumn > this.endColumn))
return new WebInspector.TextRange(this.endLine, this.endColumn, this.startLine, this.startColumn);
else
return this;
},

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.Indent = {
TwoSpaces: "  ",
FourSpaces: "    ",
EightSpaces: "        ",
TabCharacter: "\t"
}

WebInspector.TextEditorModel.endsWithBracketRegex = /[{(\[]\s*$/;

WebInspector.TextEditorModel.prototype = {
set changeListener(changeListener)
{
this._changeListener = changeListener;
},

get linesCount()
{
return this._lines.length;
},

get text()
{
return this._lines.join(this._lineBreak);
},

get lineBreak()
{
return 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;
},

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

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);
},

_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.settings.textEditorIndent = WebInspector.settings.createSetting("textEditorIndent", WebInspector.TextEditorModel.Indent.FourSpaces);






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._MaxLineCount = 10000;

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, forceRun)
{
if (this._textModel.linesCount > WebInspector.TextEditorHighlighter._MaxLineCount)
return;


var state = this._textModel.getAttribute(endLine - 1, "highlight");
if (state && state.postConditionStringified) {

return;
}

this._requestedEndLine = endLine;

if (this._highlightTimer && !forceRun) {

return;
}


var startLine = endLine;
while (startLine > 0) {
state = this._textModel.getAttribute(startLine - 1, "highlight");
if (state && state.postConditionStringified)
break;
startLine--;
}


this._highlightInChunks(startLine, endLine);
},

updateHighlight: function(startLine, endLine)
{
if (this._textModel.linesCount > WebInspector.TextEditorHighlighter._MaxLineCount)
return;


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) {
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) {
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";
},

createInitialCondition: function()
{
},

nextToken: function(cursor)
{
}
}


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.CSSCompletions.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-pictograph",
"-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;
var YYMARKER;
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;
var YYMARKER;
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;
var YYMARKER;
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._fontPreviewLines = [ "ABCDEFGHIJKLM", "NOPQRSTUVWXYZ", "abcdefghijklm", "nopqrstuvwxyz", "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);

var fontPreview = document.createElement("div");
for (var i = 0; i < WebInspector.FontView._fontPreviewLines.length; ++i) {
if (i > 0)
fontPreview.appendChild(document.createElement("br"));
fontPreview.appendChild(document.createTextNode(WebInspector.FontView._fontPreviewLines[i]));
}
this.fontPreviewElement = fontPreview.cloneNode(true);
this.fontPreviewElement.style.setProperty("font-family", uniqueFontName);
this.fontPreviewElement.style.setProperty("visibility", "hidden");

this._dummyElement = fontPreview;
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);
this._dummyElement.style.setProperty("font-size", WebInspector.FontView._measureFontSize + "px");

this.element.appendChild(this.fontPreviewElement);
},

wasShown: function()
{
this._createContentIfNeeded();

this.updateFontPreviewSize();
},

onResize: 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.isShowing())
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;
},

wasShown: function()
{
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);
imagePreviewElement.addEventListener("contextmenu", this._contextMenu.bind(this), true);

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, undefined, undefined, 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;
},

_contextMenu: function(event)
{
var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy image URL" : "Copy Image URL"), this._copyImageURL.bind(this));
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Open image in new tab" : "Open Image in New Tab"), this._openInNewTab.bind(this));
contextMenu.show(event);
},

_copyImageURL: function(event)
{
InspectorFrontendHost.copyText(this.resource.url);
},

_openInNewTab: function(event)
{
PageAgent.open(this.resource.url, true);
}
}

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, this);
}

WebInspector.DatabaseTableView.prototype = {
wasShown: function()
{
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.detachChildViews();
this.element.removeChildren();

var dataGrid = WebInspector.DataGrid.createSortableDataGrid(columnNames, values);
if (!dataGrid) {
this._emptyView = new WebInspector.EmptyView(WebInspector.UIString("The “%s”\ntable is empty.", this.tableName));
this._emptyView.show(this.element);
return;
}
dataGrid.show(this.element);
dataGrid.autoSizeColumns(5);
},

_queryError: function(error)
{
this.detachChildViews();
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.TextPromptWithHistory(this.completions.bind(this), " ");
this.prompt.attach(this._promptElement);
}

WebInspector.DatabaseQueryView.Events = {
SchemaUpdated: "SchemaUpdated"
}

WebInspector.DatabaseQueryView.prototype = {
wasShown: function()
{
function moveBackIfOutside()
{
if (!this.prompt.isCaretInsidePrompt() && window.getSelection().isCollapsed)
this.prompt.moveCaretToEndOfPrompt();
}

setTimeout(moveBackIfOutside.bind(this), 0);
},

afterShow: function()
{
WebInspector.setCurrentFocusElement(this._promptElement);
},

completions: function(wordRange, force, completionsReadyCallback)
{
var prefix = wordRange.toString().toLowerCase();
if (!prefix.length && !force)
return;

var results = [];

function accumulateMatches(textArray)
{
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]);
}
}

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);
},

_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);
},

_promptKeyDown: function(event)
{
if (isEnterKey(event)) {
this._enterKeyPressed(event);
return;
}
},

_enterKeyPressed: function(event)
{
event.preventDefault();
event.stopPropagation();

this.prompt.clearAutoComplete(true);

var query = this.prompt.text;
if (!query.length)
return;

this.prompt.pushHistoryItem(query);
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.DataGrid.createSortableDataGrid(columnNames, values);
var trimmedQuery = query.trim();

if (dataGrid) {
dataGrid.element.addStyleClass("inline");
this._appendViewQueryResult(trimmedQuery, dataGrid);
dataGrid.autoSizeColumns(5);
}

if (trimmedQuery.match(/^create /i) || trimmedQuery.match(/^drop table /i))
this.dispatchEventToListeners(WebInspector.DatabaseQueryView.Events.SchemaUpdated, 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._appendErrorQueryResult(query, message);
},


_appendViewQueryResult: function(query, view)
{
var resultElement = this._appendQueryResult(query);
view.show(resultElement);

this._promptElement.scrollIntoView(false);
},


_appendErrorQueryResult: function(query, errorText)
{
var resultElement = this._appendQueryResult(query);
resultElement.addStyleClass("error")
resultElement.textContent = errorText;

this._promptElement.scrollIntoView(false);
},

_appendQueryResult: function(query)
{
var element = document.createElement("div");
element.className = "database-user-query";
this.element.insertBefore(element, this.prompt.proxyElement);

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";
element.appendChild(resultElement);
return resultElement;
}
}

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, !Capabilities.samplingCPUProfiler);
}

var data = {};

data["function"] = this.functionName;
data["calls"] = this.numberOfCalls;

if (this.profileView.showSelfTimeAsPercent.get())
data["self"] = WebInspector.UIString("%.2f%%", this.selfPercent);
else
data["self"] = formatMilliseconds(this.selfTime);

if (this.profileView.showTotalTimeAsPercent.get())
data["total"] = WebInspector.UIString("%.2f%%", this.totalPercent);
else
data["total"] = formatMilliseconds(this.totalTime);

if (this.profileView.showAverageTimeAsPercent.get())
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 = this.profileNode.lineNumber ? this.profileNode.lineNumber - 1 : 0;
var urlElement = this.profileView._linkifier.linkifyLocation(this.profileNode.url, lineNumber, 0, "profile-node-file");
urlElement.style.maxWidth = "75%";
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 = WebInspector.settings.createSetting("cpuProfilerShowSelfTimeAsPercent", true);
this.showTotalTimeAsPercent = WebInspector.settings.createSetting("cpuProfilerShowTotalTimeAsPercent", true);
this.showAverageTimeAsPercent = WebInspector.settings.createSetting("cpuProfilerShowAverageTimeAsPercent", true);
this._viewType = WebInspector.settings.createSetting("cpuProfilerView", WebInspector.CPUProfileView._TypeHeavy);

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 (Capabilities.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.dataGrid.show(this.element);

this.viewSelectElement = document.createElement("select");
this.viewSelectElement.className = "status-bar-item";
this.viewSelectElement.addEventListener("change", this._changeView.bind(this), false);

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.viewSelectElement.selectedIndex = this._viewType.get() === WebInspector.CPUProfileView._TypeHeavy ? 0 : 1;

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;

function profileCallback(error, profile)
{
if (error)
return;
this.profile.head = profile.head;
this._assignParentsInProfile();
this._changeView();
this._updatePercentButton();
}

this._linkifier = WebInspector.debuggerPresentationModel.createLinkifier(new WebInspector.DebuggerPresentationModel.DefaultLinkifierFormatter(30));

ProfilerAgent.getProfile(this.profile.typeId, this.profile.uid, profileCallback.bind(this));
}

WebInspector.CPUProfileView._TypeTree = "Tree";
WebInspector.CPUProfileView._TypeHeavy = "Heavy";

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;
},

willHide: function()
{
this._currentSearchResultIndex = -1;
},

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.revealAndSelect();
},

_changeView: function()
{
if (!this.profile)
return;

if (this.viewSelectElement.selectedIndex == 1) {
this.profileDataGridTree = this.topDownProfileDataGridTree;
this._sortProfile();
this._viewType.set(WebInspector.CPUProfileView._TypeTree);
} else if (this.viewSelectElement.selectedIndex == 0) {
this.profileDataGridTree = this.bottomUpProfileDataGridTree;
this._sortProfile();
this._viewType.set(WebInspector.CPUProfileView._TypeHeavy);
}

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.get() && this.showTotalTimeAsPercent.get() && this.showAverageTimeAsPercent.get();
this.showSelfTimeAsPercent.set(!currentState);
this.showTotalTimeAsPercent.set(!currentState);
this.showAverageTimeAsPercent.set(!currentState);
this.refreshShowAsPercents();
},

_updatePercentButton: function()
{
if (this.showSelfTimeAsPercent.get() && this.showTotalTimeAsPercent.get() && this.showAverageTimeAsPercent.get()) {
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._linkifier.reset();
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.set(!this.showTotalTimeAsPercent.get());
else if (cell.hasStyleClass("self-column"))
this.showSelfTimeAsPercent.set(!this.showSelfTimeAsPercent.get());
else if (cell.hasStyleClass("average-column"))
this.showAverageTimeAsPercent.set(!this.showAverageTimeAsPercent.get());

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.instance = this;
}

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.");
},

isRecordingProfile: function()
{
return this._recording;
},

startRecordingProfile: function()
{
this._recording = true;
ProfilerAgent.start();
},

stopRecordingProfile: function()
{
this._recording = false;
ProfilerAgent.stop();
},

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;





Object.defineProperty(Array.prototype, "sortRange", { value: 

function(comparator, leftBound, rightBound, k)
{
function swap(array, i1, i2)
{
var temp = array[i1];
array[i1] = array[i2];
array[i2] = temp;
}

function partition(array, comparator, left, right, pivotIndex)
{
var pivotValue = array[pivotIndex];
swap(array, right, pivotIndex);
var storeIndex = left;
for (var i = left; i < right; ++i) {
if (comparator(array[i], pivotValue) < 0) {
swap(array, storeIndex, i);
++storeIndex;
}
}
swap(array, right, storeIndex);
return storeIndex;
}

function quickSortFirstK(array, comparator, left, right, k)
{
if (right <= left)
return;
var pivotIndex = Math.floor(Math.random() * (right - left)) + left;
var pivotNewIndex = partition(array, comparator, left, right, pivotIndex);
quickSortFirstK(array, comparator, left, pivotNewIndex - 1, k);
if (pivotNewIndex < left + k - 1)
quickSortFirstK(array, comparator, pivotNewIndex + 1, right, k);
}

if (leftBound === 0 && rightBound === (this.length - 1) && k === this.length)
this.sort(comparator);
else
quickSortFirstK(this, comparator, leftBound, rightBound, k);
return this;
}});





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];
},

slice: function(start, end)
{
if (typeof end === "undefined")
end = start + this._start + this.length;
return this._snapshot[this._arrayName].slice(this._start + start, end);
}
}

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 canBeQueried()
{
var flags = this._snapshot._flagsOfNode(this);
return !!(flags & this._snapshot._nodeFlags.canBeQueried);
},

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 flags()
{
return this._snapshot._flagsOfNode(this);
},

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 isDOMWindow()
{
return this.name.substr(0, 9) === "DOMWindow";
},

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._nodeFlags = { canBeQueried: 1 };

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;
delete this._aggregatesSortedFlags;
}
delete this._baseNodeIds;
delete this._dominatedNodes;
delete this._dominatedIndex;
delete this._flags;
},

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 maxNodeId()
{
if (typeof this._maxNodeId === "number")
return this._maxNodeId;
this._maxNodeId = 0;
for (var iter = this._allNodes; iter.hasNext(); iter.next()) {
var id = iter.node.id;
if ((id % 2) && id > this._maxNodeId)
this._maxNodeId = id;
}
return this._maxNodeId;
},

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);
},

_dominatedNodesOfNode: function(node)
{
if (!this._dominatedNodes)
this._buildDominatedNodes();

var dominatedIndexFrom = this._getDominatedIndex(node.nodeIndex);
var dominatedIndexTo = this._getDominatedIndex(node._nextNodeIndex);
return new WebInspector.HeapSnapshotArraySlice(this, "_dominatedNodes", dominatedIndexFrom, dominatedIndexTo);
},

_flagsOfNode: function(node)
{
if (!this._flags)
this._calculateFlags();
return this._flags[node.nodeIndex];
},

aggregates: function(sortedIndexes, key, filterString)
{
if (!this._aggregates) {
this._aggregates = {};
this._aggregatesSortedFlags = {};
}

var aggregates = this._aggregates[key];
if (aggregates) {
if (sortedIndexes && !this._aggregatesSortedFlags[key]) {
this._sortAggregateIndexes(aggregates);
this._aggregatesSortedFlags[key] = sortedIndexes;
}
return aggregates;
}

var filter;
if (filterString)
filter = this._parseFilter(filterString);

aggregates = this._buildAggregates(filter);

if (sortedIndexes)
this._sortAggregateIndexes(aggregates);

this._aggregatesSortedFlags[key] = sortedIndexes;
this._aggregates[key] = aggregates;

return aggregates;
},

_buildReverseIndex: function(indexArrayName, backRefsArrayName, indexCallback, dataCallback)
{
if (!this._nodeIndex)
this._buildNodeIndex();






var indexArray = this[indexArrayName] = new Array(this._nodeIndex.length);
for (var i = 0, l = indexArray.length; i < l; ++i)
indexArray[i] = 0;
for (var nodesIter = this._allNodes; nodesIter.hasNext(); nodesIter.next()) {
indexCallback(nodesIter.node, function (position) { ++indexArray[position]; });
}
var backRefsCount = 0;
for (i = 0, l = indexArray.length; i < l; ++i)
backRefsCount += indexArray[i];
var backRefsArray = this[backRefsArrayName] = new Array(backRefsCount + 1);


var backRefsPosition = 0;
for (i = 0, l = indexArray.length; i < l; ++i) {
backRefsCount = backRefsArray[backRefsPosition] = indexArray[i];
indexArray[i] = backRefsPosition;
backRefsPosition += backRefsCount;
}
for (nodesIter = this._allNodes; nodesIter.hasNext(); nodesIter.next()) {
dataCallback(nodesIter.node,
function (backRefIndex) { return backRefIndex + (--backRefsArray[backRefIndex]); },
function (backRefIndex, destIndex) { backRefsArray[backRefIndex] = destIndex; });
}
},

_buildRetainers: function()
{
this._buildReverseIndex(
"_retainerIndex",
"_retainers",
(function (node, callback)
{
for (var edgesIter = node.edges; edgesIter.hasNext(); edgesIter.next())
callback(this._findNodePositionInIndex(edgesIter.edge.nodeIndex));
}).bind(this),
(function (node, indexCallback, dataCallback)
{
for (var edgesIter = node.edges; edgesIter.hasNext(); edgesIter.next()) {
var edge = edgesIter.edge;
var retIndex = this._getRetainerIndex(edge.nodeIndex);
dataCallback(indexCallback(retIndex), node.nodeIndex + this._firstEdgeOffset + edge.edgeIndex);
}
}).bind(this));
},

_buildAggregates: function(filter)
{
var aggregates = {};
for (var iter = this._allNodes; iter.hasNext(); iter.next()) {
var node = iter.node;
if (filter && !filter(node))
continue;
if (node.type !== "native" && node.selfSize === 0)
continue;
var nameMatters = node.type === "object" || node.type === "native";
var className = node.className;
if (!aggregates.hasOwnProperty(className))
aggregates[className] = { count: 0, self: 0, maxRet: 0, type: node.type, name: nameMatters ? node.name : null, idxs: [] };
var clss = 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 aggregates)
aggregates[className].idxs = aggregates[className].idxs.slice(0);
return aggregates;
},

_sortAggregateIndexes: function(aggregates)
{
var nodeA = new WebInspector.HeapSnapshotNode(this);
var nodeB = new WebInspector.HeapSnapshotNode(this);
for (var clss in aggregates)
aggregates[clss].idxs.sort(
function(idxA, idxB) {
nodeA.nodeIndex = idxA;
nodeB.nodeIndex = idxB;
return nodeA.id < nodeB.id ? -1 : 1;
});
},

_buildNodeIndex: function()
{
var count = this.nodeCount;
this._nodeIndex = new Array(count + 1);
count = 0;
for (var 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];
},

_buildDominatedNodes: function()
{
this._buildReverseIndex(
"_dominatedIndex",
"_dominatedNodes",
(function (node, callback)
{
var dominatorIndex = node.dominatorIndex;
if (dominatorIndex !== node.nodeIndex)
callback(this._findNodePositionInIndex(dominatorIndex));
}).bind(this),
(function (node, indexCallback, dataCallback)
{
var dominatorIndex = node.dominatorIndex;
if (dominatorIndex !== node.nodeIndex) {
var dominatedIndex = this._getDominatedIndex(dominatorIndex);
dataCallback(indexCallback(dominatedIndex), node.nodeIndex);
}
}).bind(this));
},

_getDominatedIndex: function(nodeIndex)
{
var nodePosition = this._findNodePositionInIndex(nodeIndex);
return this._dominatedIndex[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);
},

_calculateFlags: function()
{
var flag = this._nodeFlags.canBeQueried;
this._flags = new Array(this.nodeCount);



var list = [];
for (var iter = this.rootNode.edges; iter.hasNext(); iter.next()) {
if (iter.edge.node.isDOMWindow)
list.push(iter.edge.node);
}
while (list.length) {
var node = list.shift();
if (node.canBeQueried) continue;
this._flags[node.nodeIndex] = flag;
for (var iter = node.edges; iter.hasNext(); iter.next()) {
var edge = iter.edge;
if (!edge.isHidden && !edge.isInvisible &&
edge.name && (!edge.isInternal || edge.name === "native") &&
!edge.node.canBeQueried)
list.push(edge.node);
}
}
},

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, aggregatesKey)
{
return new WebInspector.HeapSnapshotNodesProvider(this, null, this.aggregates(false, aggregatesKey)[className].idxs);
},

createNodesProviderForDominator: function(nodeIndex, filter)
{
var node = new WebInspector.HeapSnapshotNode(this, nodeIndex);
return new WebInspector.HeapSnapshotNodesProvider(this, this._parseFilter(filter), this._dominatedNodesOfNode(node));
},

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, nodeFlags: this._nodeFlags, maxNodeId: this.maxNodeId};
}
};

WebInspector.HeapSnapshotFilteredOrderedIterator = function(iterator, filter, unfilteredIterationOrder)
{
this._filter = filter;
this._iterator = iterator;
this._unfilteredIterationOrder = unfilteredIterationOrder;
this._iterationOrder = null;
this._position = 0;
this._currentComparator = null;
this._lastComparator = null;
}

WebInspector.HeapSnapshotFilteredOrderedIterator.prototype = {
_createIterationOrder: function()
{
if (this._iterationOrder)
return;
if (this._unfilteredIterationOrder && !this._filter) {
this._iterationOrder = this._unfilteredIterationOrder.slice(0);
this._unfilteredIterationOrder = null;
return;
}
this._iterationOrder = [];
var iterator = this._iterator;
if (!this._unfilteredIterationOrder && !this._filter) {
for (iterator.first(); iterator.hasNext(); iterator.next())
this._iterationOrder.push(iterator.index);
} else if (!this._unfilteredIterationOrder) {
for (iterator.first(); iterator.hasNext(); iterator.next()) {
if (this._filter(iterator.item))
this._iterationOrder.push(iterator.index);
}
} 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))
this._iterationOrder.push(iterator.index);
}
this._unfilteredIterationOrder = null;
}
},

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()
{
this._createIterationOrder();
return this._iterationOrder.length;
},

next: function()
{
++this._position;
},

serializeNextItems: function(count)
{
this._createIterationOrder();
var result = new Array(count);
if (this._lastComparator !== this._currentComparator)
this.sort(this._currentComparator, this._position, this._iterationOrder.length - 1, 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._iterationOrder.length;
return result;
},

sortAndRewind: function(comparator)
{
this._lastComparator = this._currentComparator;
this._currentComparator = comparator;
var result = this._lastComparator !== this._currentComparator;
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, leftBound, rightBound, count)
{
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;
}

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.sortRange(sortByEdgeAndNode, leftBound, rightBound, count);
else if (fieldName2 === "!edgeName")
this._iterationOrder.sortRange(sortByNodeAndEdge, leftBound, rightBound, count);
else
this._iterationOrder.sortRange(sortByNodeAndNode, leftBound, rightBound, count);
}
};

WebInspector.HeapSnapshotEdgesProvider.prototype.__proto__ = WebInspector.HeapSnapshotFilteredOrderedIterator.prototype;

WebInspector.HeapSnapshotNodesProvider = function(snapshot, filter, nodeIndexes)
{
this.snapshot = snapshot;
WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, snapshot._allNodes, filter, nodeIndexes);
}

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, flags: node.flags};
},

sort: function(comparator, leftBound, rightBound, count)
{
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;
}

function sortByComparator(indexA, indexB) {
var result = sortByNodeField(fieldName1, ascending1, indexA, indexB);
if (result === 0)
result = sortByNodeField(fieldName2, ascending2, indexA, indexB);
return result;
}

this._iterationOrder.sortRange(sortByComparator, leftBound, rightBound, count);
}
};

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._previousCallbacks = [];

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();
if (this._interval)
clearInterval(this._interval);
},

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});
},

startCheckingForLongRunningCalls: function()
{
this._checkLongRunningCalls();
this._interval = setInterval(this._checkLongRunningCalls.bind(this), 300);
},

_checkLongRunningCalls: function()
{
for (var callId in this._previousCallbacks)
if (!(callId in this._callbacks))
delete this._previousCallbacks[callId];
var hasLongRunningCalls = false;
for (callId in this._previousCallbacks) {
hasLongRunningCalls = true;
break;
}
this.dispatchEventToListeners("wait", hasLongRunningCalls);
for (callId in this._callbacks)
this._previousCallbacks[callId] = true;
},

_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.HeapSnapshotWorker.prototype.__proto__ = WebInspector.Object.prototype;

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));
},

get worker() {
return this._worker;
}
};

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, key, filter, callback)
{
this.callMethod(callback, "aggregates", sortedIndexes, key, filter);
},

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, aggregatesKey)
{
return this.callFactoryMethod(null, "createNodesProviderForClass", "WebInspector.HeapSnapshotProviderProxy", className, aggregatesKey);
},

createNodesProviderForDominator: function(nodeIndex, filter)
{
return this.callFactoryMethod(null, "createNodesProviderForDominator", "WebInspector.HeapSnapshotProviderProxy", nodeIndex, filter);
},

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 maxNodeId()
{
return this._staticData.maxNodeId;
},

get nodeCount()
{
return this._staticData.nodeCount;
},

nodeFieldValuesByIndex: function(fieldName, indexes, callback)
{
this.callMethod(callback, "nodeFieldValuesByIndex", fieldName, indexes);
},

get nodeFlags()
{
return this._staticData.nodeFlags;
},

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.bind(null, this), 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.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,

queryObjectContent: function(callback)
{
},

_populate: function(event)
{
this.removeEventListener("populate", this._populate, this);
function sorted(ignored)
{
this.populateChildren();
}
this._provider.sortAndRewind(this.comparator(), sorted.bind(this));
},

populateChildren: function(provider, howMany, atIndex, afterPopulate, suppressNotifyAboutCompletion)
{
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;
}
}

var part = 0;
function callSerialize()
{
if (part >= howMany)
return;
part += this._defaultPopulateCount;
provider.serializeNextItems(this._defaultPopulateCount, childrenRetrieved.bind(this));
}
function childrenRetrieved(items)
{
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 (part < howMany) {
setTimeout(callSerialize.bind(this), 0);
return;
}

if (items.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);
}
}
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()
{
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)) {
this._name = this.shortenWindowURL(this._name, false);
this.hasHoverMessage = true;
} else if (node.flags & tree.snapshot.nodeFlags.canBeQueried)
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":
if (!value)
value = "[]";
else
value += " []";
break;
};
if (this.hasHoverMessage)
valueStyle += " highlight";
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;
},

queryObjectContent: function(callback)
{
if (this._type === "string")
callback(WebInspector.RemoteObject.fromPrimitiveValue(this._name));
else {
function formatResult(error, object)
{
if (!error && object.type)
callback(WebInspector.RemoteObject.fromPayload(object), !!error);
else
callback(WebInspector.RemoteObject.fromPrimitiveValue(WebInspector.UIString("Not available")));
}
ProfilerAgent.getObjectByHeapObjectId(this.snapshotNodeId, formatResult);
}
},

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)
{
var startPos = fullName.indexOf("/");
var endPos = hasObjectId ? fullName.indexOf("@") : fullName.length;
if (startPos !== -1 && endPos !== -1) {
var fullURL = fullName.substring(startPos + 1, endPos).trimLeft();
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, aggregatesKey)
{
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, aggregatesKey);
}

WebInspector.HeapSnapshotConstructorNode.prototype = {
_createChildNode: function(item)
{
return new WebInspector.HeapSnapshotInstanceNode(this.dataGrid, null, this.dataGrid.snapshot, item);
},

_createNodesProvider: function(snapshot, className, aggregatesKey)
{
return snapshot.createNodesProviderForClass(className, aggregatesKey);
},

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.createNodesProviderForDominator(nodeIndex,
"function (node) {" +
"     return " + 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;
}
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);
this._filterProfileIndex = -1;
}

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;
if (this._filterProfileIndex === -1)
this.populateChildren();
},

populateChildren: function()
{
function aggregatesReceived(key, aggregates)
{
for (var constructor in aggregates)
this.appendChild(new WebInspector.HeapSnapshotConstructorNode(this, constructor, aggregates[constructor], key));
this.sortingChanged();
}

if (this._filterProfileIndex === -1) {
this.snapshot.aggregates(false, "allObjects", null, aggregatesReceived.bind(this, "allObjects"));
return;
}

this.dispose();
this.removeChildren();
this.resetSortingCache();

var key = this._minNodeId + ".." + this._maxNodeId;
var filter = "function(node) { var id = node.id; return id > " + this._minNodeId + " && id <= " + this._maxNodeId + "; }";
this.snapshot.aggregates(false, key, filter, aggregatesReceived.bind(this, key));
},

_filterSelectIndexChanged: function(loader, profileIndex)
{
this._filterProfileIndex = profileIndex;

delete this._maxNodeId;
delete this._minNodeId;

if (this._filterProfileIndex === -1) {
this.populateChildren();
return;
}

function firstSnapshotLoaded(snapshot)
{
this._maxNodeId = snapshot.maxNodeId;
if (profileIndex > 0)
loader(profileIndex - 1, secondSnapshotLoaded.bind(this));
else {
this._minNodeId = 0;
this.populateChildren();
}
}

function secondSnapshotLoaded(snapshot)
{
this._minNodeId = snapshot.maxNodeId;
this.populateChildren();
}

loader(profileIndex, firstSnapshotLoaded.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;
},

_baseProfileIndexChanged: function(loader, profileIndex)
{
loader(profileIndex, this.setBaseDataSource.bind(this));
},

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, "allObjects", null, aggregatesReceived.bind(this));
}
this.baseSnapshot.aggregates(true, "allObjects", null, 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.HeapSnapshotPathFinderState = function(snapshot, nodeIndex, rootFilter)
{
this._pathFinder = snapshot.createPathFinder(nodeIndex, !WebInspector.DetailedHeapshotView.prototype.showHiddenData);
this._pathFinder.updateRoots(rootFilter);
this._foundCount = 0;
this._foundCountMax = null;
this._totalFoundCount = 0;
this._cancelled = false;
}

WebInspector.HeapSnapshotPathFinderState.prototype = {
batchDone: function(status)
{
},

pathFound: function(path)
{
},

cancel: function()
{
this._cancelled = true;
this._pathFinder.dispose();
},

startBatch: function(count)
{
if (this._cancelled)
return;
this._foundCount = 0;
this._foundCountMax = count;
this._pathFinder.findNext(this._pathFound.bind(this));
},

_pathFound: function(result)
{
if (this._cancelled)
return;
if (result === null) {
if (!this._totalFoundCount)
this.batchDone("no-paths-at-all");
} else if (result !== false) {
this.pathFound(result);
++this._foundCount;
++this._totalFoundCount;
if (this._foundCount < this._foundCountMax)
this._pathFinder.findNext(this._pathFound.bind(this));
else
this.batchDone("have-more-paths");
} else {
this.batchDone("no-more-paths");
}
}
};

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;
this._nodeIndex = null;
this._state = null;
this._prefix = null;
}

WebInspector.HeapSnapshotRetainingPathsList.prototype = {
dispose: function()
{
if (this._state)
this._state.cancel();
},

_sortFields: function(sortColumn, sortAscending)
{
return {
path: ["path", sortAscending, "len", true],
len: ["len", sortAscending, "path", true]
}[sortColumn];
},

_resetPaths: function()
{
var rootFilter = this.snapshotView.isTracingToWindowObjects ?
"function (node) { return node.name.substr(0, 9) === \"DOMWindow\"; }" : null;
if (this._state)
this._state.cancel();
this._state = new WebInspector.HeapSnapshotPathFinderState(this._snapshot, this._nodeIndex, rootFilter);
this._state.batchDone = this._batchDone.bind(this);
this._state.pathFound = this._pathFound.bind(this);
this.removeChildren();
this.resetSortingCache();
this.showNext(this._defaultPopulateCount);
},

setDataSource: function(snapshotView, snapshot, nodeIndex, prefix)
{
if (this._nodeIndex === nodeIndex)
return;
this.snapshotView = snapshotView;
this._snapshot = snapshot;
this._nodeIndex = nodeIndex;
this._prefix = prefix;
this._resetPaths();
},

refresh: function()
{
if (this.snapshotView)
this._resetPaths();
},

reset: function()
{
if (this._state)
this._state.cancel();
this.removeChildren();
this.resetSortingCache();
this.appendChild(new WebInspector.DataGridNode({path:WebInspector.UIString("Click on an object to show retaining paths"), len:""}, false));
},

_batchDone: function(state)
{
switch (state) {
case "no-paths-at-all":
this.appendChild(new WebInspector.DataGridNode({path:WebInspector.UIString("Can't find any paths."), len:""}, false));
break;
case "have-more-paths":
this.appendChild(new WebInspector.ShowMoreDataGridNode(this.showNext.bind(this), this._defaultPopulateCount));
this.resetSortingCache();
this.sortingChanged();
break;
case "no-more-paths":

break;
}
},

_pathFound: function(result)
{
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);
},

showNext: function(pathsCount)
{
this._state.startBatch(pathsCount);
},

_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.parent.addEventListener("profile added", this._updateFilterOptions, 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._mouseClickInContentsGrid.bind(this), true);
this.containmentDataGrid.element.addEventListener("mousedown", this._mouseDownInContentsGrid.bind(this), true);
this.containmentDataGrid.show(this.containmentView.element);

this.constructorsView = new WebInspector.View();
this.constructorsView.element.addStyleClass("view");
this.constructorsDataGrid = new WebInspector.HeapSnapshotConstructorsDataGrid();
this.constructorsDataGrid.element.addEventListener("click", this._mouseClickInContentsGrid.bind(this), true);
this.constructorsDataGrid.element.addEventListener("mousedown", this._mouseDownInContentsGrid.bind(this), true);
this.constructorsDataGrid.show(this.constructorsView.element);

this.diffView = new WebInspector.View();
this.diffView.element.addStyleClass("view");
this.diffDataGrid = new WebInspector.HeapSnapshotDiffDataGrid();
this.diffDataGrid.element.addEventListener("click", this._mouseClickInContentsGrid.bind(this), true);
this.diffDataGrid.show(this.diffView.element);

this.dominatorView = new WebInspector.View();
this.dominatorView.element.addStyleClass("view");
this.dominatorDataGrid = new WebInspector.HeapSnapshotDominatorsDataGrid();
this.dominatorDataGrid.element.addEventListener("click", this._mouseClickInContentsGrid.bind(this), true);
this.dominatorDataGrid.element.addEventListener("mousedown", this._mouseDownInContentsGrid.bind(this), true);
this.dominatorDataGrid.show(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.retainmentDataGrid.show(this.retainmentView.element);
this.retainmentView.show(this.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.filterSelectElement = document.createElement("select");
this.filterSelectElement.className = "status-bar-item";
this.filterSelectElement.addEventListener("change", this._changeFilter.bind(this), false);
this._updateFilterOptions();

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.ObjectPopoverHelper(this.element, this._getHoverAnchor.bind(this), this._showObjectPopover.bind(this), null, true);

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;
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.filterSelectElement, this.percentButton.element, this.helpButton.element];
},

get profile()
{
return this.parent.getProfile(WebInspector.DetailedHeapshotProfileType.TypeId, this._profileUid);
},

get profileWrapper()
{
return this.profile.proxy;
},

get baseProfile()
{
return this.parent.getProfile(WebInspector.DetailedHeapshotProfileType.TypeId, this._baseProfileUid);
},

get baseProfileWrapper()
{
return this.baseProfile.proxy;
},

wasShown: function()
{
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.viewsContainer);
}
},

willHide: function()
{
this._currentSearchResultIndex = -1;
},

onResize: function()
{
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.revealAndSelect();
},

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.dataGrid._baseProfileIndexChanged(this._loadProfileByIndex.bind(this), this.baseSelectElement.selectedIndex);

if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults)
return;




this._searchFinishedCallback(this, -this._searchResults.length);
this.performSearch(this.currentQuery, this._searchFinishedCallback);
},

_changeFilter: function()
{
var profileIndex = this.filterSelectElement.selectedIndex - 1;
this.dataGrid._filterSelectIndexChanged(this._loadProfileByIndex.bind(this), profileIndex);

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.DetailedHeapshotProfileType.TypeId);
},

_loadProfile: function(profileUid, callback)
{
WebInspector.panels.profiles.loadHeapSnapshot(profileUid, callback);
},

_loadProfileByIndex: function(profileIndex, callback)
{
var profileUid = this._profiles()[profileIndex].uid;
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);
},

_mouseClickInContentsGrid: function(event)
{
var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
if (!cell || (!cell.hasStyleClass("object-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();
},

_mouseDownInContentsGrid: function(event)
{
if (event.detail < 2)
return;

var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
if (!cell || (!cell.hasStyleClass("count-column") && !cell.hasStyleClass("shallowSize-column") && !cell.hasStyleClass("retainedSize-column")))
return;

if (cell.hasStyleClass("count-column"))
this.showCountAsPercent = !this.showCountAsPercent;
else if (cell.hasStyleClass("shallowSize-column"))
this.showShallowSizeAsPercent = !this.showShallowSizeAsPercent;
else if (cell.hasStyleClass("retainedSize-column"))
this.showRetainedSizeAsPercent = !this.showRetainedSizeAsPercent;
this.refreshShowAsPercents();

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

_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.detach();
var view = this.views[this.views.current];
this.currentView = view.view;
this.dataGrid = view.grid;
this.currentView.show(this.viewsContainer);
this.refreshVisibleData();
this.dataGrid.updateWidths();

if (this.currentView === this.diffView) {
this.baseSelectElement.removeStyleClass("hidden");
if (!this.dataGrid.snapshotView) {
this._changeBase();
this.dataGrid.setDataSource(this, this.profileWrapper);
}
} else {
this.baseSelectElement.addStyleClass("hidden");
if (!this.dataGrid.snapshotView)
this.dataGrid.setDataSource(this, this.profileWrapper);
}

if (this.currentView === this.constructorsView)
this.filterSelectElement.removeStyleClass("hidden");
else
this.filterSelectElement.addStyleClass("hidden");

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();
},

_showObjectPopover: function(element, showCallback)
{
element.node.queryObjectContent(showCallback);
},

_helpClicked: function(event)
{
if (!this._helpPopoverContentElement) {
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._helpPopoverContentElement = contentElement;
this.helpPopover = new WebInspector.Popover();

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._helpPopoverContentElement, this.helpButton.element);
},

_startRetainersHeaderDragging: function(event)
{
if (!this.isShowing() || 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);
}
},

_updateFilterOptions: function()
{
var list = this._profiles();

if (this.filterSelectElement.length - 1 === list.length)
return;

if (!this.filterSelectElement.length) {
var filterOption = document.createElement("option");
filterOption.label = WebInspector.UIString("All objects");
this.filterSelectElement.appendChild(filterOption);
}

for (var i = this.filterSelectElement.length - 1, n = list.length; i < n; ++i) {
var filterOption = document.createElement("option");
var title = list[i].title;
if (!title.indexOf(UserInitiatedProfileName)) {
if (!i)
title = WebInspector.UIString("Objects allocated before Snapshot %d", title.substring(UserInitiatedProfileName.length + 1));
else
title = WebInspector.UIString("Objects allocated between Snapshots %d and %d", title.substring(UserInitiatedProfileName.length + 1) - 1, title.substring(UserInitiatedProfileName.length + 1));
}
filterOption.label = title;
this.filterSelectElement.appendChild(filterOption);
}
},

_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.DetailedHeapshotProfileType.TypeId, WebInspector.UIString("HEAP SNAPSHOTS"));
}

WebInspector.DetailedHeapshotProfileType.TypeId = "HEAP";

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();
},

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 = null;

this._scripts = {};

this._canSetScriptSource = false;

InspectorBackend.registerDebuggerDispatcher(new WebInspector.DebuggerDispatcher(this));
}


WebInspector.DebuggerPausedDetails = function(callFrames, reason, auxData)
{
this.callFrames = callFrames;
this.reason = reason;
this.auxData = auxData;
}


WebInspector.DebuggerModel.Location = function()
{
this.scriptId = null;
}

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",
GlobalObjectCleared: "global-object-cleared"
}

WebInspector.DebuggerModel.BreakReason = {
DOM: "DOM",
EventListener: "EventListener",
XHR: "XHR",
Exception: "exception"
}

WebInspector.DebuggerModel.prototype = {
enableDebugger: function()
{
function callback(error, result)
{
this._canSetScriptSource = result;
}
DebuggerAgent.canSetScriptSource(callback.bind(this));
DebuggerAgent.enable(this._debuggerWasEnabled.bind(this));
},

disableDebugger: function()
{
DebuggerAgent.disable(this._debuggerWasDisabled.bind(this));
},


canSetScriptSource: function()
{
return this._canSetScriptSource;
},

_debuggerWasEnabled: function()
{
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerWasEnabled);
},

_debuggerWasDisabled: function()
{
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerWasDisabled);
},


continueToLocation: function(location)
{
DebuggerAgent.continueToLocation(location);
},


setBreakpointByScriptLocation: function(location, condition, callback)
{
var script = this.scriptForSourceID(location.scriptId);
if (script.sourceURL)
this.setBreakpoint(script.sourceURL, location.lineNumber, location.columnNumber, condition, callback);
else
this.setBreakpointBySourceId(location, condition, callback);
},


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(lineNumber, url, undefined, columnNumber, condition, didSetBreakpoint.bind(this));
WebInspector.userMetrics.ScriptsBreakpointSet.record();
},


setBreakpointBySourceId: function(location, condition, callback)
{

function didSetBreakpoint(error, breakpointId, actualLocation)
{
if (callback)
callback(error ? null : breakpointId, [actualLocation]);
}
DebuggerAgent.setBreakpoint(location, condition, didSetBreakpoint.bind(this));
WebInspector.userMetrics.ScriptsBreakpointSet.record();
},


removeBreakpoint: function(breakpointId, callback)
{
DebuggerAgent.removeBreakpoint(breakpointId, callback);
},


_breakpointResolved: function(breakpointId, location)
{
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointResolved, {breakpointId: breakpointId, location: location});
},

_globalObjectCleared: function()
{
this._debuggerPausedDetails = null;
this._scripts = {};
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.GlobalObjectCleared);
},


get scripts()
{
return this._scripts;
},


scriptForSourceID: function(scriptId)
{
return this._scripts[scriptId];
},


scriptsForURL: function(url)
{
return this.queryScripts(function(s) { return s.sourceURL === url; });
},


queryScripts: function(filter)
{
var scripts = [];
for (var scriptId in this._scripts) {
var script = this._scripts[scriptId];
if (filter(script))
scripts.push(script);
}
return scripts;
},


setScriptSource: function(scriptId, newSource, callback)
{
this._scripts[scriptId].editSource(newSource, this._didEditScriptSource.bind(this, scriptId, newSource, callback));
},


_didEditScriptSource: function(scriptId, newSource, callback, error, callFrames)
{
if (!error && callFrames && callFrames.length)
this._debuggerPausedDetails.callFrames = callFrames;
callback(error);
},


get callFrames()
{
return this._debuggerPausedDetails ? this._debuggerPausedDetails.callFrames : null;
},


get debuggerPausedDetails()
{
return this._debuggerPausedDetails;
},


_pausedScript: function(callFrames, reason, auxData)
{
this._debuggerPausedDetails = new WebInspector.DebuggerPausedDetails(callFrames, reason, auxData);
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPausedDetails);
},

_resumedScript: function()
{
this._debuggerPausedDetails = null;
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerResumed);
},


_parsedScriptSource: function(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript)
{
var script = new WebInspector.Script(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript);
this._scripts[scriptId] = 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, false);
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(callFrames, reason, auxData)
{
this._debuggerModel._pausedScript(callFrames, reason, auxData);
},

resumed: function()
{
this._debuggerModel._resumedScript();
},

globalObjectCleared: function()
{
this._debuggerModel._globalObjectCleared();
},


scriptParsed: function(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript)
{
this._debuggerModel._parsedScriptSource(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, !!isContentScript);
},


scriptFailedToParse: function(sourceURL, source, startingLine, errorLine, errorMessage)
{
this._debuggerModel._failedToParseScriptSource(sourceURL, source, startingLine, errorLine, errorMessage);
},


breakpointResolved: function(breakpointId, location)
{
this._debuggerModel._breakpointResolved(breakpointId, location);
}
}


WebInspector.debuggerModel = null;






WebInspector.DebuggerPresentationModel = function()
{

this._formatter = new WebInspector.ScriptFormatter();
this._rawSourceCodes = [];
this._rawSourceCodeForScriptId = {};
this._rawSourceCodeForURL = {};
this._rawSourceCodeForDocumentURL = {};
this._presentationCallFrames = [];

this._breakpointManager = new WebInspector.BreakpointManager(WebInspector.settings.breakpoints, this._breakpointAdded.bind(this), this._breakpointRemoved.bind(this), WebInspector.debuggerModel);

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.DebuggerPaused, this._debuggerPaused, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerResumed, this._debuggerResumed, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);

WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, this._consoleMessageAdded, this);
WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.ConsoleCleared, this._consoleCleared, this);

new WebInspector.DebuggerPresentationModelResourceBinding(this);
}

WebInspector.DebuggerPresentationModel.Events = {
UISourceCodeAdded: "source-file-added",
UISourceCodeReplaced: "source-file-replaced",
UISourceCodeRemoved: "source-file-removed",
ConsoleMessageAdded: "console-message-added",
ConsoleMessagesCleared: "console-messages-cleared",
BreakpointAdded: "breakpoint-added",
BreakpointRemoved: "breakpoint-removed",
DebuggerPaused: "debugger-paused",
DebuggerResumed: "debugger-resumed",
DebuggerReset: "debugger-reset",
CallFrameSelected: "call-frame-selected",
ConsoleCommandEvaluatedInSelectedCallFrame: "console-command-evaluated-in-selected-call-frame",
ExecutionLineChanged: "execution-line-changed"
}

WebInspector.DebuggerPresentationModel.prototype = {

createLinkifier: function(formatter)
{
return new WebInspector.DebuggerPresentationModel.Linkifier(this, formatter);
},


createPlacard: function(callFrame)
{
return new WebInspector.DebuggerPresentationModel.CallFramePlacard(callFrame);
},


rawLocationToUILocation: function(rawLocation)
{
var rawSourceCode = this._rawSourceCodeForScriptId[rawLocation.scriptId];
if (!rawSourceCode.sourceMapping)
return null;
return rawSourceCode.sourceMapping.rawLocationToUILocation(rawLocation);
},


_parsedScriptSource: function(event)
{
var script =   event.data;
this._addScript(script);
},


_failedToParseScriptSource: function(event)
{
var script =   event.data;
this._addScript(script);
},


_addScript: function(script)
{
var resource;
var isInlineScript = false;
if (script.isInlineScript()) {
resource = WebInspector.networkManager.inflightResourceForURL(script.sourceURL) || WebInspector.resourceForURL(script.sourceURL);
if (resource && resource.type === WebInspector.Resource.Type.Document) {
isInlineScript = true;
var rawSourceCode = this._rawSourceCodeForDocumentURL[script.sourceURL];
if (rawSourceCode) {
rawSourceCode.addScript(script);
this._bindScriptToRawSourceCode(script, rawSourceCode);
return;
}
}
}

rawSourceCode = new WebInspector.RawSourceCode(script.scriptId, script, resource, this._formatter, this._formatSource);
this._rawSourceCodes.push(rawSourceCode);
this._bindScriptToRawSourceCode(script, rawSourceCode);

if (isInlineScript)
this._rawSourceCodeForDocumentURL[script.sourceURL] = rawSourceCode;

if (rawSourceCode.sourceMapping)
this._updateSourceMapping(rawSourceCode, null);
rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._sourceMappingUpdated, this);
},


_bindScriptToRawSourceCode: function(script, rawSourceCode)
{
this._rawSourceCodeForScriptId[script.scriptId] = rawSourceCode;
this._rawSourceCodeForURL[script.sourceURL] = rawSourceCode;
},


_sourceMappingUpdated: function(event)
{
var rawSourceCode =   event.target;
var oldSourceMapping =   event.data["oldSourceMapping"];
this._updateSourceMapping(rawSourceCode, oldSourceMapping);
},


uiSourceCodes: function()
{
var result = [];
for (var i = 0; i < this._rawSourceCodes.length; ++i) {
var uiSourceCodeList = this._rawSourceCodes[i].sourceMapping.uiSourceCodeList();
for (var j = 0; j < uiSourceCodeList.length; ++j)
result.push(uiSourceCodeList[j]);
}
return result;
},


_updateSourceMapping: function(rawSourceCode, oldSourceMapping)
{
if (oldSourceMapping) {
var oldUISourceCodeList = oldSourceMapping.uiSourceCodeList();
for (var i = 0; i < oldUISourceCodeList.length; ++i) {
var breakpoints = this._breakpointManager.breakpointsForUISourceCode(oldUISourceCodeList[i]);
for (var lineNumber in breakpoints) {
var breakpoint = breakpoints[lineNumber];
this._breakpointRemoved(breakpoint);
delete breakpoint.uiSourceCode;
}
}
}

this._restoreBreakpoints(rawSourceCode);
this._restoreConsoleMessages(rawSourceCode);

if (!oldSourceMapping) {
var uiSourceCodeList = rawSourceCode.sourceMapping.uiSourceCodeList();
for (var i = 0; i < uiSourceCodeList.length; ++i)
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.UISourceCodeAdded, uiSourceCodeList[i]);
} else {
var eventData = { uiSourceCodeList: rawSourceCode.sourceMapping.uiSourceCodeList(), oldUISourceCodeList: oldSourceMapping.uiSourceCodeList() };
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.UISourceCodeReplaced, eventData);
}
},


_restoreBreakpoints: function(rawSourceCode)
{
var uiSourceCodeList = rawSourceCode.sourceMapping.uiSourceCodeList();
for (var i = 0; i < uiSourceCodeList.length; ++i) {
var uiSourceCode = uiSourceCodeList[i];
this._breakpointManager.uiSourceCodeAdded(uiSourceCode);
var breakpoints = this._breakpointManager.breakpointsForUISourceCode(uiSourceCode);
for (var lineNumber in breakpoints)
this._breakpointAdded(breakpoints[lineNumber]);
}

},


_restoreConsoleMessages: function(rawSourceCode)
{
var messages = rawSourceCode.messages;
for (var i = 0; i < messages.length; ++i)
messages[i]._presentationMessage = this._createPresentationMessage(messages[i], rawSourceCode.sourceMapping);
},


canEditScriptSource: function(uiSourceCode)
{
if (!WebInspector.debuggerModel.canSetScriptSource() || this._formatSource)
return false;
var rawSourceCode = uiSourceCode.rawSourceCode;
var script = this._scriptForRawSourceCode(rawSourceCode);
return script && !script.lineOffset && !script.columnOffset;
},


setScriptSource: function(uiSourceCode, newSource, callback)
{
var rawSourceCode = uiSourceCode.rawSourceCode;
var script = this._scriptForRawSourceCode(rawSourceCode);


function didEditScriptSource(error)
{
callback(error);
if (error)
return;

var resource = WebInspector.resourceForURL(rawSourceCode.url);
if (resource)
resource.addRevision(newSource);

uiSourceCode.contentChanged(newSource);

if (WebInspector.debuggerModel.callFrames)
this._debuggerPaused();
}
WebInspector.debuggerModel.setScriptSource(script.scriptId, newSource, didEditScriptSource.bind(this));
},


_updateBreakpointsAfterLiveEdit: function(uiSourceCode, oldSource, newSource)
{
var breakpoints = this._breakpointManager.breakpointsForUISourceCode(uiSourceCode);


var diff = Array.diff(oldSource.split("\n"), newSource.split("\n"));
for (var lineNumber in breakpoints) {
var breakpoint = breakpoints[lineNumber];

this.removeBreakpoint(uiSourceCode, parseInt(lineNumber, 10));

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(uiSourceCode, newLineNumber, breakpoint.condition, breakpoint.enabled);
}
},


setFormatSource: function(formatSource)
{
if (this._formatSource === formatSource)
return;

this._formatSource = formatSource;
this._breakpointManager.reset();
for (var i = 0; i < this._rawSourceCodes.length; ++i)
this._rawSourceCodes[i].setFormatted(this._formatSource);
},


setCompilerSourceMapping: function(uiSourceCode, sourceMappingURL)
{
var sourceMapping = new WebInspector.ClosureCompilerSourceMapping(sourceMappingURL);
uiSourceCode.rawSourceCode.setCompilerSourceMapping(sourceMapping);
},


_consoleMessageAdded: function(event)
{
var message =   event.data;
if (!message.url || !message.isErrorOrWarning() || !message.message)
return;

var rawSourceCode = this._rawSourceCodeForScriptWithURL(message.url);
if (!rawSourceCode)
return;

rawSourceCode.messages.push(message);
if (rawSourceCode.sourceMapping) {
message._presentationMessage = this._createPresentationMessage(message, rawSourceCode.sourceMapping);
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.ConsoleMessageAdded, message._presentationMessage);
}
},


_createPresentationMessage: function(message, sourceMapping)
{

var lineNumber = message.stackTrace ? message.stackTrace[0].lineNumber - 1 : message.line - 1;
var columnNumber = message.stackTrace ? message.stackTrace[0].columnNumber - 1 : 0;
var uiLocation = sourceMapping.rawLocationToUILocation(  { lineNumber: lineNumber, columnNumber: columnNumber });
var presentationMessage = new WebInspector.PresentationConsoleMessage(uiLocation.uiSourceCode, uiLocation.lineNumber, message);
return presentationMessage;
},

_consoleCleared: function()
{
for (var i = 0; i < this._rawSourceCodes.length; ++i)
this._rawSourceCodes[i].messages = [];
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.ConsoleMessagesCleared);
},


continueToLine: function(uiSourceCode, lineNumber)
{

var rawLocation = uiSourceCode.rawSourceCode.sourceMapping.uiLocationToRawLocation(uiSourceCode, lineNumber, 0);
WebInspector.debuggerModel.continueToLocation(rawLocation);
},


breakpointsForUISourceCode: function(uiSourceCode)
{
var breakpointsMap = this._breakpointManager.breakpointsForUISourceCode(uiSourceCode);
var breakpointsList = [];
for (var lineNumber in breakpointsMap)
breakpointsList.push(breakpointsMap[lineNumber]);
return breakpointsList;
},


messagesForUISourceCode: function(uiSourceCode)
{
var rawSourceCode = uiSourceCode.rawSourceCode;
var messages = [];
for (var i = 0; i < rawSourceCode.messages.length; ++i)
messages.push(rawSourceCode.messages[i]._presentationMessage);
return messages;
},


setBreakpoint: function(uiSourceCode, lineNumber, condition, enabled)
{
this._breakpointManager.setBreakpoint(uiSourceCode, lineNumber, condition, enabled);
},


setBreakpointEnabled: function(uiSourceCode, lineNumber, enabled)
{
var breakpoint = this.findBreakpoint(uiSourceCode, lineNumber);
if (!breakpoint)
return;
this._breakpointManager.removeBreakpoint(uiSourceCode, lineNumber);
this._breakpointManager.setBreakpoint(uiSourceCode, lineNumber, breakpoint.condition, enabled);
},


updateBreakpoint: function(uiSourceCode, lineNumber, condition, enabled)
{
this._breakpointManager.removeBreakpoint(uiSourceCode, lineNumber);
this._breakpointManager.setBreakpoint(uiSourceCode, lineNumber, condition, enabled);
},


removeBreakpoint: function(uiSourceCode, lineNumber)
{
this._breakpointManager.removeBreakpoint(uiSourceCode, lineNumber);
},


findBreakpoint: function(uiSourceCode, lineNumber)
{
return this._breakpointManager.breakpointsForUISourceCode(uiSourceCode)[lineNumber];
},


_breakpointAdded: function(breakpoint)
{
if (breakpoint.uiSourceCode)
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointAdded, breakpoint);
},


_breakpointRemoved: function(breakpoint)
{
if (breakpoint.uiSourceCode)
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.BreakpointRemoved, breakpoint);
},

_debuggerPaused: function()
{
var callFrames = WebInspector.debuggerModel.callFrames;
this._presentationCallFrames = [];
for (var i = 0; i < callFrames.length; ++i) {
var callFrame = callFrames[i];
var script = WebInspector.debuggerModel.scriptForSourceID(callFrame.location.scriptId);
if (!script)
continue;
var rawSourceCode = this._rawSourceCodeForScript(script);
this._presentationCallFrames.push(new WebInspector.PresentationCallFrame(callFrame, i, this, rawSourceCode));
}
var details = WebInspector.debuggerModel.debuggerPausedDetails;
this.selectedCallFrame = this._presentationCallFrames[0];
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.DebuggerPaused, { callFrames: this._presentationCallFrames, details: details });
},

_debuggerResumed: function()
{
this._presentationCallFrames = [];
this.selectedCallFrame = null;
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.DebuggerResumed);
},

get paused()
{
return !!WebInspector.debuggerModel.debuggerPausedDetails;
},

set selectedCallFrame(callFrame)
{
if (this._selectedCallFrame)
this._selectedCallFrame.rawSourceCode.removeEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._dispatchExecutionLineChanged, this);
this._selectedCallFrame = callFrame;
if (!this._selectedCallFrame)
return;

this._selectedCallFrame.rawSourceCode.forceUpdateSourceMapping();
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.CallFrameSelected, callFrame);

this._selectedCallFrame.rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._dispatchExecutionLineChanged, this);
},

get selectedCallFrame()
{
return this._selectedCallFrame;
},


evaluateInSelectedCallFrame: function(code, objectGroup, includeCommandLineAPI, returnByValue, callback)
{

function didEvaluate(result, wasThrown)
{
if (returnByValue)
callback(null, wasThrown, wasThrown ? null : result);
else
callback(WebInspector.RemoteObject.fromPayload(result), wasThrown);

if (objectGroup === "console")
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame);
}

this.selectedCallFrame.evaluate(code, objectGroup, includeCommandLineAPI, returnByValue, didEvaluate.bind(this));
},


getSelectedCallFrameVariables: function(callback)
{
var result = { this: true };

var selectedCallFrame = this.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);
}
},


_dispatchExecutionLineChanged: function(event)
{
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.ExecutionLineChanged, this.executionLineLocation);
},


get executionLineLocation()
{
if (!this._selectedCallFrame.rawSourceCode.sourceMapping)
return;

var rawLocation = this._selectedCallFrame._callFrame.location;
var uiLocation = this._selectedCallFrame.rawSourceCode.sourceMapping.rawLocationToUILocation(rawLocation);
return uiLocation;
},


_rawSourceCodeForScriptWithURL: function(sourceURL)
{
return this._rawSourceCodeForURL[sourceURL];
},


_rawSourceCodeForScript: function(script)
{
return this._rawSourceCodeForScriptId[script.scriptId];
},


_scriptForRawSourceCode: function(rawSourceCode)
{

function filter(script)
{
return script.scriptId === rawSourceCode.id;
}
return WebInspector.debuggerModel.queryScripts(filter.bind(this))[0];
},

_debuggerReset: function()
{
for (var i = 0; i < this._rawSourceCodes.length; ++i) {
var rawSourceCode = this._rawSourceCodes[i];
if (rawSourceCode.sourceMapping) {
var uiSourceCodeList = rawSourceCode.sourceMapping.uiSourceCodeList();
for (var j = 0; j < uiSourceCodeList.length; ++j)
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.UISourceCodeRemoved, uiSourceCodeList[j]);
}
rawSourceCode.removeAllListeners();
}
this._rawSourceCodes = [];
this._rawSourceCodeForScriptId = {};
this._rawSourceCodeForURL = {};
this._rawSourceCodeForDocumentURL = {};
this._presentationCallFrames = [];
this._selectedCallFrame = null;
this._breakpointManager.debuggerReset();
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.DebuggerReset);
}
}

WebInspector.DebuggerPresentationModel.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.PresentationConsoleMessage = function(uiSourceCode, lineNumber, originalMessage)
{
this.uiSourceCode = uiSourceCode;
this.lineNumber = lineNumber;
this.originalMessage = originalMessage;
}


WebInspector.PresentationCallFrame = function(callFrame, index, model, rawSourceCode)
{
this._callFrame = callFrame;
this._index = index;
this._model = model;
this._rawSourceCode = rawSourceCode;
}

WebInspector.PresentationCallFrame.prototype = {

get type()
{
return this._callFrame.type;
},


get scopeChain()
{
return this._callFrame.scopeChain;
},


get this()
{
return this._callFrame.this;
},


get index()
{
return this._index;
},


get rawSourceCode()
{
return this._rawSourceCode;
},


evaluate: function(code, objectGroup, includeCommandLineAPI, returnByValue, callback)
{

function didEvaluateOnCallFrame(error, result, wasThrown)
{
if (error) {
console.error(error);
callback(null, false);
return;
}
callback(result, wasThrown);
}
DebuggerAgent.evaluateOnCallFrame(this._callFrame.callFrameId, code, objectGroup, includeCommandLineAPI, returnByValue, didEvaluateOnCallFrame.bind(this));
},


uiLocation: function(callback)
{
function sourceMappingReady()
{
this._rawSourceCode.removeEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, sourceMappingReady, this);
callback(this._rawSourceCode.sourceMapping.rawLocationToUILocation(this._callFrame.location));
}
if (this._rawSourceCode.sourceMapping)
sourceMappingReady.call(this);
else
this._rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, sourceMappingReady, this);
}
}


WebInspector.DebuggerPresentationModel.CallFramePlacard = function(callFrame)
{
WebInspector.Placard.call(this, callFrame._callFrame.functionName || WebInspector.UIString("(anonymous function)"), "");
this._callFrame = callFrame;
var rawSourceCode = callFrame._rawSourceCode;
if (rawSourceCode.sourceMapping)
this._update();
rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._update, this);
}

WebInspector.DebuggerPresentationModel.CallFramePlacard.prototype = {
discard: function()
{
this._callFrame._rawSourceCode.removeEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._update, this);
},

_update: function()
{
var rawSourceCode = this._callFrame._rawSourceCode;
var uiLocation = rawSourceCode.sourceMapping.rawLocationToUILocation(this._callFrame._callFrame.location);
this.subtitle = WebInspector.displayNameForURL(uiLocation.uiSourceCode.url) + ":" + (uiLocation.lineNumber + 1);
}
}

WebInspector.DebuggerPresentationModel.CallFramePlacard.prototype.__proto__ = WebInspector.Placard.prototype;


WebInspector.DebuggerPresentationModelResourceBinding = function(model)
{
this._presentationModel = model;
WebInspector.Resource.registerDomainModelBinding(WebInspector.Resource.Type.Script, this);
}

WebInspector.DebuggerPresentationModelResourceBinding.prototype = {

canSetContent: function(resource)
{
var rawSourceCode = this._presentationModel._rawSourceCodeForScriptWithURL(resource.url)
if (!rawSourceCode)
return false;
return this._presentationModel.canEditScriptSource(rawSourceCode.sourceMapping.uiSourceCodeList()[0]);
},


setContent: function(resource, content, majorChange, userCallback)
{
if (!majorChange)
return;

var rawSourceCode = this._presentationModel._rawSourceCodeForScriptWithURL(resource.url);
if (!rawSourceCode) {
userCallback("Resource is not editable");
return;
}

resource.requestContent(this._setContentWithInitialContent.bind(this, rawSourceCode.sourceMapping.uiSourceCodeList()[0], content, userCallback));
},


_setContentWithInitialContent: function(uiSourceCode, content, userCallback, oldContent)
{

function callback(error)
{
if (userCallback)
userCallback(error);
if (!error)
this._presentationModel._updateBreakpointsAfterLiveEdit(uiSourceCode, oldContent, content);
}
this._presentationModel.setScriptSource(uiSourceCode, content, callback.bind(this));
}
}


WebInspector.DebuggerPresentationModel.LinkifierFormatter = function()
{
}

WebInspector.DebuggerPresentationModel.LinkifierFormatter.prototype = {

formatRawSourceCodeAnchor: function(rawSourceCode, anchor) { },
}


WebInspector.DebuggerPresentationModel.DefaultLinkifierFormatter = function(maxLength)
{
this._maxLength = maxLength;
}

WebInspector.DebuggerPresentationModel.DefaultLinkifierFormatter.prototype = {

formatRawSourceCodeAnchor: function(rawSourceCode, anchor)
{
var uiLocation = rawSourceCode.sourceMapping.rawLocationToUILocation(anchor.rawLocation);

anchor.textContent = WebInspector.formatLinkText(uiLocation.uiSourceCode.url, uiLocation.lineNumber);

var text = WebInspector.formatLinkText(uiLocation.uiSourceCode.url, uiLocation.lineNumber);
if (this._maxLength)
text = text.trimMiddle(this._maxLength);
anchor.textContent = text;
}
}

WebInspector.DebuggerPresentationModel.DefaultLinkifierFormatter.prototype.__proto__ = WebInspector.DebuggerPresentationModel.LinkifierFormatter.prototype;


WebInspector.DebuggerPresentationModel.Linkifier = function(model, formatter)
{
this._model = model;
this._formatter = formatter || new WebInspector.DebuggerPresentationModel.DefaultLinkifierFormatter();
this._anchorsForRawSourceCode = {};
}

WebInspector.DebuggerPresentationModel.Linkifier.prototype = {

linkifyLocation: function(sourceURL, lineNumber, columnNumber, classes)
{
var rawSourceCode = this._model._rawSourceCodeForScriptWithURL(sourceURL);
if (!rawSourceCode)
return WebInspector.linkifyResourceAsNode(sourceURL, lineNumber, classes);

return this.linkifyRawSourceCode(rawSourceCode, lineNumber, columnNumber, classes);
},


linkifyRawSourceCode: function(rawSourceCode, lineNumber, columnNumber, classes)
{
var anchor = WebInspector.linkifyURLAsNode(rawSourceCode.url, "", classes, false);
anchor.rawLocation = { lineNumber: lineNumber, columnNumber: columnNumber };

var anchors = this._anchorsForRawSourceCode[rawSourceCode.id];
if (!anchors) {
anchors = [];
this._anchorsForRawSourceCode[rawSourceCode.id] = anchors;
rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._updateSourceAnchors, this);
}

if (rawSourceCode.sourceMapping)
this._updateAnchor(rawSourceCode, anchor);
anchors.push(anchor);
return anchor;
},

reset: function()
{
for (var id in this._anchorsForRawSourceCode) {
if (this._model._rawSourceCodeForScriptId[id]) 
this._model._rawSourceCodeForScriptId[id].removeEventListener(WebInspector.RawSourceCode.Events.SourceMappingUpdated, this._updateSourceAnchors, this);
}
this._anchorsForRawSourceCode = {};
},


_updateSourceAnchors: function(event)
{
var rawSourceCode =   event.target;
var anchors = this._anchorsForRawSourceCode[rawSourceCode.id];
for (var i = 0; i < anchors.length; ++i)
this._updateAnchor(rawSourceCode, anchors[i]);
},


_updateAnchor: function(rawSourceCode, anchor)
{
var uiLocation = rawSourceCode.sourceMapping.rawLocationToUILocation(anchor.rawLocation);
anchor.preferredPanel = "scripts";
anchor.uiSourceCode = uiLocation.uiSourceCode;
anchor.lineNumber = uiLocation.lineNumber;

this._formatter.formatRawSourceCodeAnchor(rawSourceCode, anchor);
}
}

WebInspector.DebuggerPresentationModelResourceBinding.prototype.__proto__ = WebInspector.ResourceDomainModelBinding.prototype;


WebInspector.debuggerPresentationModel = null;






WebInspector.BreakpointManager = function(breakpointStorage, breakpointAddedDelegate, breakpointRemovedDelegate, debuggerModel)
{
this._breakpointStorage = breakpointStorage;
this._breakpointAddedDelegate = breakpointAddedDelegate;
this._breakpointRemovedDelegate = breakpointRemovedDelegate;

this._breakpointsByUILocation = {};

this._debuggerModel = debuggerModel;


this._breakpointsByDebuggerId = {};
this._debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this);

var breakpoints = this._breakpointStorage.get();
for (var i = 0; i < breakpoints.length; ++i) {
var breakpoint = WebInspector.Breakpoint.deserialize(breakpoints[i]);
if (!this._breakpoint(breakpoint.uiSourceCodeId, breakpoint.lineNumber))
this._addBreakpointToUI(breakpoint);
}
}

WebInspector.BreakpointManager.prototype = {

uiSourceCodeAdded: function(uiSourceCode)
{
var breakpoints = this._breakpoints(uiSourceCode.id);
for (var lineNumber in breakpoints) {
var breakpoint = breakpoints[lineNumber];
breakpoint.uiSourceCode = uiSourceCode;
this._materializeBreakpoint(breakpoint, uiSourceCode.rawSourceCode.sourceMapping, uiSourceCode);
if (breakpoint._debuggerLocation)
this._breakpointDebuggerLocationChanged(breakpoint);
}
},


breakpointsForUISourceCode: function(uiSourceCode)
{
return this._breakpoints(uiSourceCode.id);
},


setBreakpoint: function(uiSourceCode, lineNumber, condition, enabled)
{
if (this._breakpoint(uiSourceCode.id, lineNumber))
return;

var persistent = !!uiSourceCode.url;
var breakpoint = new WebInspector.Breakpoint(uiSourceCode.id, lineNumber, condition, enabled, persistent);
breakpoint.uiSourceCode = uiSourceCode;
this._addBreakpointToUI(breakpoint);
this._materializeBreakpoint(breakpoint, uiSourceCode.rawSourceCode.sourceMapping, uiSourceCode);
},


removeBreakpoint: function(uiSourceCode, lineNumber)
{
var breakpoint = this._breakpoint(uiSourceCode.id, lineNumber);
if (!breakpoint)
return;
this._deleteBreakpointFromUI(breakpoint);
this._removeBreakpointFromDebugger(breakpoint);
},


_materializeBreakpoint: function(breakpoint, sourceMapping, uiSourceCode)
{
if (!breakpoint.enabled || breakpoint._materialized)
return;

breakpoint._materialized = true;
var rawLocation = sourceMapping.uiLocationToRawLocation(uiSourceCode, breakpoint.lineNumber, 0);
this._setBreakpointInDebugger(breakpoint, rawLocation);
},


_breakpointDebuggerLocationChanged: function(breakpoint)
{
if (!breakpoint.uiSourceCode)
return;
var uiLocation = breakpoint.uiSourceCode.rawSourceCode.sourceMapping.rawLocationToUILocation(breakpoint._debuggerLocation);
if (uiLocation.lineNumber === breakpoint.lineNumber)
return;

if (!this._moveBreakpointInUI(breakpoint, uiLocation.lineNumber))
this._removeBreakpointFromDebugger(breakpoint);
},


_addBreakpointToUI: function(breakpoint)
{
console.assert(!this._breakpoint(breakpoint.uiSourceCodeId, breakpoint.lineNumber));
this._breakpoints(breakpoint.uiSourceCodeId)[breakpoint.lineNumber] = breakpoint;
this._saveBreakpoints();
this._breakpointAddedDelegate(breakpoint);
},


_deleteBreakpointFromUI: function(breakpoint)
{
console.assert(this._breakpoint(breakpoint.uiSourceCodeId, breakpoint.lineNumber) === breakpoint);
delete this._breakpoints(breakpoint.uiSourceCodeId)[breakpoint.lineNumber];
this._saveBreakpoints();
this._breakpointRemovedDelegate(breakpoint);
},


_moveBreakpointInUI: function(breakpoint, lineNumber)
{
this._deleteBreakpointFromUI(breakpoint);
if (this._breakpoint(breakpoint.uiSourceCodeId, lineNumber))
return false;
breakpoint.lineNumber = lineNumber;
this._addBreakpointToUI(breakpoint);
return true;
},


_breakpoints: function(uiSourceCodeId)
{
if (!this._breakpointsByUILocation[uiSourceCodeId])
this._breakpointsByUILocation[uiSourceCodeId] = {};
return this._breakpointsByUILocation[uiSourceCodeId];
},


_breakpoint: function(uiSourceCodeId, lineNumber)
{
return this._breakpoints(uiSourceCodeId)[lineNumber];
},


_forEachBreakpoint: function(handler)
{
for (var uiSourceCodeId in this._breakpointsByUILocation) {
var breakpoints = this._breakpointsByUILocation[uiSourceCodeId];
for (var lineNumber in breakpoints)
handler(breakpoints[lineNumber]);
}
},


_setBreakpointInDebugger: function(breakpoint, rawLocation)
{

function didSetBreakpoint(breakpointId, locations)
{
if (breakpoint === this._breakpoint(breakpoint.uiSourceCodeId, breakpoint.lineNumber)) {
if (!breakpointId) {
this._deleteBreakpointFromUI(breakpoint);
return;
}
} else {
if (breakpointId)
this._debuggerModel.removeBreakpoint(breakpointId);
return;
}

this._breakpointsByDebuggerId[breakpointId] = breakpoint;
breakpoint._debuggerId = breakpointId;
breakpoint._debuggerLocation = locations[0];
if (breakpoint._debuggerLocation)
this._breakpointDebuggerLocationChanged(breakpoint);
}
this._debuggerModel.setBreakpointByScriptLocation(rawLocation, breakpoint.condition, didSetBreakpoint.bind(this));
},


_removeBreakpointFromDebugger: function(breakpoint)
{
if (!("_debuggerId" in breakpoint))
return;
this._debuggerModel.removeBreakpoint(breakpoint._debuggerId);
delete this._breakpointsByDebuggerId[breakpoint._debuggerId];
delete breakpoint._debuggerId;
delete breakpoint._debuggerLocation;
},


_breakpointResolved: function(event)
{
var breakpoint = this._breakpointsByDebuggerId[event.data["breakpointId"]];
breakpoint._debuggerLocation = event.data["location"];
this._breakpointDebuggerLocationChanged(breakpoint);
},

_saveBreakpoints: function()
{
var serializedBreakpoints = [];

function serializePersistent(breakpoint)
{
if (breakpoint.persistent)
serializedBreakpoints.push(breakpoint.serialize());
}
this._forEachBreakpoint(serializePersistent.bind(this));
this._breakpointStorage.set(serializedBreakpoints);
},

reset: function()
{

function resetBreakpoint(breakpoint)
{
this._removeBreakpointFromDebugger(breakpoint);
delete breakpoint._materialized;
}
this._forEachBreakpoint(resetBreakpoint.bind(this));
},

debuggerReset: function()
{

function resetOrDeleteBreakpoint(breakpoint)
{
if (breakpoint.persistent) {
delete breakpoint.uiSourceCode;
delete breakpoint._debuggerLocation;
} else {
this._deleteBreakpointFromUI(breakpoint);
delete this._breakpointsByDebuggerId[breakpoint._debuggerId];
}
}
this._forEachBreakpoint(resetOrDeleteBreakpoint.bind(this));

for (var id in this._breakpointsByUILocation) {
var empty = true;
for (var lineNumber in this._breakpointsByUILocation[id]) {
empty = false;
break;
}
if (empty)
delete this._breakpointsByUILocation[id];
}
}
}


WebInspector.Breakpoint = function(uiSourceCodeId, lineNumber, condition, enabled, persistent)
{
this.uiSourceCodeId = uiSourceCodeId;
this.lineNumber = lineNumber;
this.condition = condition;
this.enabled = enabled;
this.persistent = persistent;
}

WebInspector.Breakpoint.prototype = {

serialize: function()
{
var serializedBreakpoint = {};
serializedBreakpoint.sourceFileId = this.uiSourceCodeId;
serializedBreakpoint.lineNumber = this.lineNumber;
serializedBreakpoint.condition = this.condition;
serializedBreakpoint.enabled = this.enabled;
return serializedBreakpoint;
}
}


WebInspector.Breakpoint.deserialize = function(serializedBreakpoint)
{
return new WebInspector.Breakpoint(
serializedBreakpoint.sourceFileId,
serializedBreakpoint.lineNumber,
serializedBreakpoint.condition,
serializedBreakpoint.enabled,
true);
}






WebInspector.UISourceCode = function(id, url, isContentScript, rawSourceCode, contentProvider)
{
this._id = id;
this._url = url;
this._isContentScript = isContentScript;
this._rawSourceCode = rawSourceCode;
this._contentProvider = contentProvider;

this._requestContentCallbacks = [];
}

WebInspector.UISourceCode.Events = {
ContentChanged: "content-changed"
}

WebInspector.UISourceCode.prototype = {

get id()
{
return this._id;
},


get url()
{
return this._url;
},


get isContentScript()
{
return this._isContentScript;
},


get rawSourceCode()
{
return this._rawSourceCode;
},


requestContent: function(callback)
{
if (this._contentLoaded) {
callback(this._mimeType, this._content);
return;
}

this._requestContentCallbacks.push(callback);
if (this._requestContentCallbacks.length === 1)
this._contentProvider.requestContent(this._didRequestContent.bind(this));
},


contentChanged: function(newContent)
{
console.assert(this._contentLoaded);
this._content = newContent;
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.ContentChanged);
},


searchInContent: function(query, caseSensitive, isRegex, callback)
{
this._contentProvider.searchInContent(query, caseSensitive, isRegex, callback);
},


_didRequestContent: function(mimeType, content)
{
this._contentLoaded = true;
this._mimeType = mimeType;
this._content = content;

for (var i = 0; i < this._requestContentCallbacks.length; ++i)
this._requestContentCallbacks[i](mimeType, content);
this._requestContentCallbacks = [];
}
}

WebInspector.UISourceCode.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.ContentProvider = function() { }
WebInspector.ContentProvider.prototype = {

requestContent: function(callback) { },


searchInContent: function(query, caseSensitive, isRegex, callback) { }
}


WebInspector.ContentProvider.SearchMatch = function(lineNumber, lineContent) {
this.lineNumber = lineNumber;
this.lineContent = lineContent;
}






WebInspector.ScriptContentProvider = function(script)
{
this._mimeType = "text/javascript";
this._script = script;
};

WebInspector.ScriptContentProvider.prototype = {

requestContent: function(callback)
{
function didRequestSource(source)
{
callback(this._mimeType, source);
}
this._script.requestSource(didRequestSource.bind(this));
},


searchInContent: function(query, caseSensitive, isRegex, callback)
{
this._script.searchInContent(query, caseSensitive, isRegex, callback);
}
}

WebInspector.ScriptContentProvider.prototype.__proto__ = WebInspector.ContentProvider.prototype;


WebInspector.ConcatenatedScriptsContentProvider = function(scripts)
{
this._mimeType = "text/html";
this._scripts = scripts;
};

WebInspector.ConcatenatedScriptsContentProvider.scriptOpenTag = "<script>";
WebInspector.ConcatenatedScriptsContentProvider.scriptCloseTag = "</script>";

WebInspector.ConcatenatedScriptsContentProvider.prototype = {

_sortedScripts: function()
{
if (this._sortedScriptsArray)
return this._sortedScriptsArray;

this._sortedScriptsArray = [];

var scripts = this._scripts.slice();
scripts.sort(function(x, y) { return x.lineOffset - y.lineOffset || x.columnOffset - y.columnOffset; });

var scriptOpenTagLength = WebInspector.ConcatenatedScriptsContentProvider.scriptOpenTag.length;
var scriptCloseTagLength = WebInspector.ConcatenatedScriptsContentProvider.scriptCloseTag.length;

this._sortedScriptsArray.push(scripts[0]);
for (var i = 1; i < scripts.length; ++i) {
var previousScript = this._sortedScriptsArray[this._sortedScriptsArray.length - 1];

var lineNumber = previousScript.endLine;
var columnNumber = previousScript.endColumn + scriptCloseTagLength + scriptOpenTagLength;

if (lineNumber < scripts[i].lineOffset || (lineNumber === scripts[i].lineOffset && columnNumber <= scripts[i].columnOffset))
this._sortedScriptsArray.push(scripts[i]);
}
return this._sortedScriptsArray;
},


requestContent: function(callback)
{
var scripts = this._sortedScripts();
var sources = [];
function didRequestSource(source)
{
sources.push(source);
if (sources.length == scripts.length)
callback(this._mimeType, this._concatenateScriptsContent(scripts, sources));
}
for (var i = 0; i < scripts.length; ++i)
scripts[i].requestSource(didRequestSource.bind(this));
},


searchInContent: function(query, caseSensitive, isRegex, callback)
{
var results = {};
var scripts = this._sortedScripts();
var scriptsLeft = scripts.length;

function maybeCallback()
{
if (scriptsLeft)
return;

var result = [];
for (var i = 0; i < scripts.length; ++i)
result = result.concat(results[scripts[i].scriptId]);
callback(result);
}


function searchCallback(script, searchMatches)
{
results[script.scriptId] = [];
for (var i = 0; i < searchMatches.length; ++i) {
var searchMatch = new WebInspector.ContentProvider.SearchMatch(searchMatches[i].lineNumber + script.lineOffset, searchMatches[i].lineContent);
results[script.scriptId].push(searchMatch);
}
scriptsLeft--;
maybeCallback.call(this);
}

maybeCallback();
for (var i = 0; i < scripts.length; ++i)
scripts[i].searchInContent(query, caseSensitive, isRegex, searchCallback.bind(this, scripts[i]));
},


_concatenateScriptsContent: function(scripts, sources)
{
var content = "";
var lineNumber = 0;
var columnNumber = 0;

var scriptOpenTag = WebInspector.ConcatenatedScriptsContentProvider.scriptOpenTag;
var scriptCloseTag = WebInspector.ConcatenatedScriptsContentProvider.scriptCloseTag;
for (var i = 0; i < scripts.length; ++i) {

for (var newLinesCount = scripts[i].lineOffset - lineNumber; newLinesCount > 0; --newLinesCount) {
columnNumber = 0;
content += "\n";
}
for (var spacesCount = scripts[i].columnOffset - columnNumber - scriptOpenTag.length; spacesCount > 0; --spacesCount)
content += " ";


content += scriptOpenTag;
content += sources[i];
content += scriptCloseTag;
lineNumber = scripts[i].endLine;
columnNumber = scripts[i].endColumn + scriptCloseTag.length;
}

return content;
}
}

WebInspector.ConcatenatedScriptsContentProvider.prototype.__proto__ = WebInspector.ContentProvider.prototype;


WebInspector.ResourceContentProvider = function(resource)
{
this._mimeType = resource.type === WebInspector.Resource.Type.Script ? "text/javascript" : "text/html";
this._resource = resource;
};

WebInspector.ResourceContentProvider.prototype = {

requestContent: function(callback)
{
function didRequestContent(content)
{
callback(this._mimeType, content);
}
this._resource.requestContent(didRequestContent.bind(this));
},


searchInContent: function(query, caseSensitive, isRegex, callback)
{
this._resource.searchInContent(query, caseSensitive, isRegex, callback);
}
}

WebInspector.ResourceContentProvider.prototype.__proto__ = WebInspector.ContentProvider.prototype;


WebInspector.CompilerSourceMappingContentProvider = function(sourceURL, compilerSourceMapping)
{
this._mimeType = "text/javascript";
this._sourceURL = sourceURL;
this._compilerSourceMapping = compilerSourceMapping;
};

WebInspector.CompilerSourceMappingContentProvider.prototype = {

requestContent: function(callback)
{
var sourceCode = this._compilerSourceMapping.loadSourceCode(this._sourceURL);
callback(this._mimeType, sourceCode);
},


searchInContent: function(query, caseSensitive, isRegex, callback)
{
callback([]);
}
}

WebInspector.CompilerSourceMappingContentProvider.prototype.__proto__ = WebInspector.ContentProvider.prototype;


WebInspector.StaticContentProvider = function(mimeType, content)
{
this._mimeType = mimeType;
this._content = content;
};

WebInspector.StaticContentProvider.prototype = {

requestContent: function(callback)
{
callback(this._mimeType, this._content);
},


searchInContent: function(query, caseSensitive, isRegex, callback)
{
function performSearch()
{
var regex = createSearchRegex(query, caseSensitive, isRegex);

var result = [];
var lineEndings = this._content.lineEndings();
for (var i = 0; i < lineEndings.length; ++i) {
var lineStart = i > 0 ? lineEndings[i - 1] + 1 : 0;
var lineEnd = lineEndings[i];
var lineContent = this._content.substring(lineStart, lineEnd);
if (lineContent.length > 0 && lineContent.charAt(lineContent.length - 1) === "\r")
lineContent = lineContent.substring(0, lineContent.length - 1)

if (regex.exec(lineContent))
result.push(new WebInspector.ContentProvider.SearchMatch(i, lineContent));
}
callback(result);
}


window.setTimeout(performSearch.bind(this), 0);
}
}

WebInspector.StaticContentProvider.prototype.__proto__ = WebInspector.ContentProvider.prototype;









WebInspector.RawSourceCode = function(id, script, resource, formatter, formatted)
{
this.id = id;
this.url = script.sourceURL;
this.isContentScript = script.isContentScript;
this._scripts = [script];
this._formatter = formatter;
this._formatted = formatted;
this._resource = resource;
this.messages = [];

this._useTemporaryContent = this._resource && !this._resource.finished;
this._hasNewScripts = true;
if (!this._useTemporaryContent)
this._updateSourceMapping();
else if (this._resource)
this._resource.addEventListener("finished", this._resourceFinished.bind(this));
}

WebInspector.RawSourceCode.Events = {
SourceMappingUpdated: "source-mapping-updated"
}

WebInspector.RawSourceCode.prototype = {

addScript: function(script)
{
this._scripts.push(script);
this._hasNewScripts = true;
},


get sourceMapping()
{
return this._sourceMapping;
},


setFormatted: function(formatted)
{
if (this._formatted === formatted)
return;
this._formatted = formatted;
this._updateSourceMapping();
},


setCompilerSourceMapping: function(compilerSourceMapping)
{
if (compilerSourceMapping)
this._useTemporaryContent = false;
this._compilerSourceMapping = compilerSourceMapping;
this._updateSourceMapping();
},

_resourceFinished: function()
{
if (this._compilerSourceMapping)
return;
this._useTemporaryContent = false;
this._updateSourceMapping();
},


_scriptForRawLocation: function(lineNumber, columnNumber)
{
var closestScript = this._scripts[0];
for (var i = 1; i < this._scripts.length; ++i) {
var script = this._scripts[i];
if (script.lineOffset > lineNumber || (script.lineOffset === lineNumber && script.columnOffset > columnNumber))
continue;
if (script.lineOffset > closestScript.lineOffset ||
(script.lineOffset === closestScript.lineOffset && script.columnOffset > closestScript.columnOffset))
closestScript = script;
}
return closestScript;
},


forceUpdateSourceMapping: function(script)
{
if (!this._useTemporaryContent || !this._hasNewScripts)
return;
this._hasNewScripts = false;
this._updateSourceMapping();
},

_updateSourceMapping: function()
{
if (this._updatingSourceMapping) {
this._updateNeeded = true;
return;
}
this._updatingSourceMapping = true;
this._updateNeeded = false;

this._createSourceMapping(didCreateSourceMapping.bind(this));


function didCreateSourceMapping(sourceMapping)
{
this._updatingSourceMapping = false;
if (!sourceMapping)
return;
if (!this._updateNeeded)
this._saveSourceMapping(sourceMapping);
else
this._updateSourceMapping();
}
},

_createContentProvider: function()
{
if (this._resource && this._resource.finished)
return new WebInspector.ResourceContentProvider(this._resource);
if (this._scripts.length === 1 && !this._scripts[0].lineOffset && !this._scripts[0].columnOffset)
return new WebInspector.ScriptContentProvider(this._scripts[0]);
return new WebInspector.ConcatenatedScriptsContentProvider(this._scripts);
},


_createSourceMapping: function(callback)
{
if (this._compilerSourceMapping) {
var success = this._compilerSourceMapping.load();
if (!success) {
delete this._compilerSourceMapping;
callback(null);
return;
}
var uiSourceCodeList = [];
var sourceURLs = this._compilerSourceMapping.sources();
for (var i = 0; i < sourceURLs.length; ++i) {
var sourceURL = sourceURLs[i];
var contentProvider = new WebInspector.CompilerSourceMappingContentProvider(sourceURL, this._compilerSourceMapping);
var uiSourceCode = new WebInspector.UISourceCode(sourceURL, sourceURL, this.isContentScript, this, contentProvider);
uiSourceCodeList.push(uiSourceCode);
}
var sourceMapping = new WebInspector.RawSourceCode.CompilerSourceMapping(this, uiSourceCodeList, this._compilerSourceMapping);
callback(sourceMapping);
return;
}

var originalContentProvider = this._createContentProvider();
if (!this._formatted) {
var uiSourceCode = new WebInspector.UISourceCode(this.url, this.url, this.isContentScript, this, originalContentProvider);
var sourceMapping = new WebInspector.RawSourceCode.PlainSourceMapping(this, uiSourceCode);
callback(sourceMapping);
return;
}


function didRequestContent(mimeType, content)
{

function didFormatContent(formattedContent, mapping)
{
var contentProvider = new WebInspector.StaticContentProvider(mimeType, formattedContent)
var uiSourceCode = new WebInspector.UISourceCode("deobfuscated:" + this.url, this.url, this.isContentScript, this, contentProvider);
var sourceMapping = new WebInspector.RawSourceCode.FormattedSourceMapping(this, uiSourceCode, mapping);
callback(sourceMapping);
}
this._formatter.formatContent(mimeType, content, didFormatContent.bind(this));
}
originalContentProvider.requestContent(didRequestContent.bind(this));
},


_saveSourceMapping: function(sourceMapping)
{
var oldSourceMapping;
if (this._sourceMapping)
oldSourceMapping = this._sourceMapping;
this._sourceMapping = sourceMapping;
this.dispatchEventToListeners(WebInspector.RawSourceCode.Events.SourceMappingUpdated, { oldSourceMapping: oldSourceMapping });
}
}

WebInspector.RawSourceCode.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.RawSourceCode.SourceMapping = function()
{
}

WebInspector.RawSourceCode.SourceMapping.prototype = {

rawLocationToUILocation: function(rawLocation) { },


uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) { }
}


WebInspector.RawSourceCode.PlainSourceMapping = function(rawSourceCode, uiSourceCode)
{
this._rawSourceCode = rawSourceCode;
this._uiSourceCodeList = [uiSourceCode];
}

WebInspector.RawSourceCode.PlainSourceMapping.prototype = {

rawLocationToUILocation: function(rawLocation)
{
return new WebInspector.UILocation(this._uiSourceCodeList[0], rawLocation.lineNumber, rawLocation.columnNumber || 0);
},


uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
{
console.assert(uiSourceCode === this._uiSourceCodeList[0]);
var rawLocation = { lineNumber: lineNumber, columnNumber: columnNumber };
rawLocation.scriptId = this._rawSourceCode._scriptForRawLocation(rawLocation.lineNumber, rawLocation.columnNumber).scriptId;
return   rawLocation;
},


uiSourceCodeList: function()
{
return this._uiSourceCodeList;
}
}


WebInspector.RawSourceCode.FormattedSourceMapping = function(rawSourceCode, uiSourceCode, mapping)
{
this._rawSourceCode = rawSourceCode;
this._uiSourceCodeList = [uiSourceCode];
this._mapping = mapping;
}

WebInspector.RawSourceCode.FormattedSourceMapping.prototype = {

rawLocationToUILocation: function(rawLocation)
{
var location = this._mapping.originalToFormatted(rawLocation);
return new WebInspector.UILocation(this._uiSourceCodeList[0], location.lineNumber, location.columnNumber || 0);
},


uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
{
console.assert(uiSourceCode === this._uiSourceCodeList[0]);
var rawLocation = this._mapping.formattedToOriginal({ lineNumber: lineNumber, columnNumber: columnNumber });
rawLocation.scriptId = this._rawSourceCode._scriptForRawLocation(rawLocation.lineNumber, rawLocation.columnNumber).scriptId;
return rawLocation;
},


uiSourceCodeList: function()
{
return this._uiSourceCodeList;
}
}


WebInspector.RawSourceCode.CompilerSourceMapping = function(rawSourceCode, uiSourceCodeList, mapping)
{
this._rawSourceCode = rawSourceCode;
this._uiSourceCodeList = uiSourceCodeList;
this._mapping = mapping;
this._uiSourceCodeByURL = {};
for (var i = 0; i < uiSourceCodeList.length; ++i)
this._uiSourceCodeByURL[uiSourceCodeList[i].url] = uiSourceCodeList[i];
}

WebInspector.RawSourceCode.CompilerSourceMapping.prototype = {

rawLocationToUILocation: function(rawLocation)
{
var location = this._mapping.compiledLocationToSourceLocation(rawLocation.lineNumber, rawLocation.columnNumber || 0);
var uiSourceCode = this._uiSourceCodeByURL[location.sourceURL];
return new WebInspector.UILocation(uiSourceCode, location.lineNumber, location.columnNumber);
},


uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
{
var rawLocation = this._mapping.sourceLocationToCompiledLocation(uiSourceCode.url, lineNumber);
rawLocation.scriptId = this._rawSourceCode._scriptForRawLocation(rawLocation.lineNumber, rawLocation.columnNumber).scriptId;
return   rawLocation;
},


uiSourceCodeList: function()
{
return this._uiSourceCodeList;
}
}


WebInspector.UILocation = function(uiSourceCode, lineNumber, columnNumber)
{
this.uiSourceCode = uiSourceCode;
this.lineNumber = lineNumber;
this.columnNumber = columnNumber;
}






WebInspector.CompilerSourceMapping = function()
{
}

WebInspector.CompilerSourceMapping.prototype = {

compiledLocationToSourceLocation: function(lineNumber, columnNumber) { },


sourceLocationToCompiledLocation: function(sourceURL, lineNumber) { },


sources: function() { }
}


WebInspector.ClosureCompilerSourceMappingPayload = function()
{
this.mappings = "";
this.sources = [];
}


WebInspector.ClosureCompilerSourceMapping = function(sourceMappingURL)
{
if (!WebInspector.ClosureCompilerSourceMapping.prototype._base64Map) {
const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
WebInspector.ClosureCompilerSourceMapping.prototype._base64Map = {};
for (var i = 0; i < base64Digits.length; ++i)
WebInspector.ClosureCompilerSourceMapping.prototype._base64Map[base64Digits.charAt(i)] = i;
}

this._sourceMappingURL = sourceMappingURL;
this._sources = [];
this._mappings = [];
this._reverseMappingsBySourceURL = {};
}

WebInspector.ClosureCompilerSourceMapping.prototype = {

load: function()
{
try {

var response = InspectorFrontendHost.loadResourceSynchronously(this._sourceMappingURL);
this._parseMappingPayload(JSON.parse(response));
return true
} catch(e) {
console.error(e.message);
return false;
}
},


compiledLocationToSourceLocation: function(lineNumber, columnNumber)
{
var mapping = this._findMapping(lineNumber, columnNumber);
return { sourceURL: mapping[2], lineNumber: mapping[3], columnNumber: mapping[4] };
},

sourceLocationToCompiledLocation: function(sourceURL, lineNumber)
{
var mappings = this._reverseMappingsBySourceURL[sourceURL];
for ( ; lineNumber < mappings.length; ++lineNumber) {
var mapping = mappings[lineNumber];
if (mapping)
return { lineNumber: mapping[0], columnNumber: mapping[1] };
}
},


sources: function()
{
return this._sources;
},


loadSourceCode: function(sourceURL)
{
try {

return InspectorFrontendHost.loadResourceSynchronously(sourceURL);
} catch(e) {
console.error(e.message);
return "";
}
},

_findMapping: function(lineNumber, columnNumber)
{
var first = 0;
var count = this._mappings.length;
while (count > 1) {
var step = count >> 1;
var middle = first + step;
var mapping = this._mappings[middle];
if (lineNumber < mapping[0] || (lineNumber == mapping[0] && columnNumber < mapping[1]))
count = step;
else {
first = middle;
count -= step;
}
}
return this._mappings[first];
},

_parseMappingPayload: function(mappingPayload)
{
if (mappingPayload.sections)
this._parseSections(mappingPayload.sections);
else
this._parseMap(mappingPayload, 0, 0);
},

_parseSections: function(sections)
{
for (var i = 0; i < sections.length; ++i) {
var section = sections[i];
this._parseMap(section.map, section.offset.line - 1, section.offset.column)
}
},

_parseMap: function(map, lineNumber, columnNumber)
{
var sourceIndex = this._sources.length;
var sourceLineNumber = 0;
var sourceColumnNumber = 0;
var nameIndex = 0;

for (var i = 0; i < map.sources.length; ++i) {
var url = this._canonicalizeURL(map.sourceRoot, map.sources[i]);
this._sources.push(url);
this._reverseMappingsBySourceURL[url] = [];
}

var stringCharIterator = new WebInspector.ClosureCompilerSourceMapping.StringCharIterator(map.mappings);
var sourceURL = this._sources[sourceIndex];
var reverseMappings = this._reverseMappingsBySourceURL[sourceURL];

while (true) {
if (stringCharIterator.peek() === ",")
stringCharIterator.next();
else {
while (stringCharIterator.peek() === ";") {
lineNumber += 1;
columnNumber = 0;
stringCharIterator.next();
}
if (!stringCharIterator.hasNext())
break;
}

columnNumber += this._decodeVLQ(stringCharIterator);
if (!this._isSeparator(stringCharIterator.peek())) {
var sourceIndexDelta = this._decodeVLQ(stringCharIterator);
if (sourceIndexDelta) {
sourceIndex += sourceIndexDelta;
sourceURL = this._sources[sourceIndex];
reverseMappings = this._reverseMappingsBySourceURL[sourceURL];
}
sourceLineNumber += this._decodeVLQ(stringCharIterator);
sourceColumnNumber += this._decodeVLQ(stringCharIterator);
if (!this._isSeparator(stringCharIterator.peek()))
nameIndex += this._decodeVLQ(stringCharIterator);

this._mappings.push([lineNumber, columnNumber, sourceURL, sourceLineNumber, sourceColumnNumber]);
if (!reverseMappings[sourceLineNumber])
reverseMappings[sourceLineNumber] = [lineNumber, columnNumber];
}
}
},

_isSeparator: function(char)
{
return char === "," || char === ";";
},

_decodeVLQ: function(stringCharIterator)
{

var result = 0;
var shift = 0;
do {
var digit = this._base64Map[stringCharIterator.next()];
result += (digit & this._VLQ_BASE_MASK) << shift;
shift += this._VLQ_BASE_SHIFT;
} while (digit & this._VLQ_CONTINUATION_MASK);


var negative = result & 1;
result >>= 1;
return negative ? -result : result;
},

_canonicalizeURL: function(sourceRoot, sourceURL)
{
return sourceRoot ? sourceRoot + "/" + sourceURL : sourceURL;
},

_VLQ_BASE_SHIFT: 5,
_VLQ_BASE_MASK: (1 << 5) - 1,
_VLQ_CONTINUATION_MASK: 1 << 5
}


WebInspector.ClosureCompilerSourceMapping.StringCharIterator = function(string)
{
this._string = string;
this._position = 0;
}

WebInspector.ClosureCompilerSourceMapping.StringCharIterator.prototype = {
next: function()
{
return this._string.charAt(this._position++);
},

peek: function()
{
return this._string.charAt(this._position);
},

hasNext: function()
{
return this._position < this._string.length;
}
}






WebInspector.ScriptsSearchScope = function()
{

WebInspector.SearchScope.call(this)
this._searchId = 0;
}

WebInspector.ScriptsSearchScope.prototype = {

performSearch: function(searchConfig, searchResultCallback, searchFinishedCallback)
{
this.stopSearch();

var uiSourceCodes = this._sortedUISourceCodes();
var uiSourceCodeIndex = 0;

function filterOutContentScripts(uiSourceCode)
{
return !uiSourceCode.isContentScript;
}

if (!WebInspector.settings.searchInContentScripts.get())
uiSourceCodes = uiSourceCodes.filter(filterOutContentScripts);

function continueSearch()
{


if (uiSourceCodeIndex < uiSourceCodes.length) {
var uiSourceCode = uiSourceCodes[uiSourceCodeIndex++];
uiSourceCode.searchInContent(searchConfig.query, !searchConfig.ignoreCase, searchConfig.isRegex, searchCallbackWrapper.bind(this, this._searchId, uiSourceCode));
} else 
searchFinishedCallback(true);
}

function searchCallbackWrapper(searchId, uiSourceCode, searchMatches)
{
if (searchId !== this._searchId) {
searchFinishedCallback(false);
return;
}

var searchResult = new WebInspector.FileBasedSearchResultsPane.SearchResult(uiSourceCode, searchMatches);
searchResultCallback(searchResult);
continueSearch.call(this);
}

continueSearch.call(this);
return uiSourceCodes.length;
},

stopSearch: function()
{
++this._searchId;
},


createSearchResultsPane: function(searchConfig)
{
return new WebInspector.ScriptsSearchResultsPane(searchConfig);
},


_sortedUISourceCodes: function()
{
function filterOutAnonymous(uiSourceCode)
{
return !!uiSourceCode.url;
}

function comparator(a, b)
{
return a.url.localeCompare(b.url);   
}

var uiSourceCodes = WebInspector.debuggerPresentationModel.uiSourceCodes();

uiSourceCodes = uiSourceCodes.filter(filterOutAnonymous);
uiSourceCodes.sort(comparator);

return uiSourceCodes;
}
}

WebInspector.ScriptsSearchScope.prototype.__proto__ = WebInspector.SearchScope.prototype;


WebInspector.ScriptsSearchResultsPane = function(searchConfig)
{
WebInspector.FileBasedSearchResultsPane.call(this, searchConfig)

this._linkifier = WebInspector.debuggerPresentationModel.createLinkifier(new WebInspector.ScriptsSearchResultsPane.LinkifierFormatter());
}

WebInspector.ScriptsSearchResultsPane.prototype = {

createAnchor: function(file, lineNumber, columnNumber)
{

var uiSourceCode = file;
var rawSourceCode = uiSourceCode.rawSourceCode;
var rawLocation = rawSourceCode.sourceMapping.uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber);
var anchor = this._linkifier.linkifyRawSourceCode(uiSourceCode.rawSourceCode, rawLocation.lineNumber, rawLocation.columnNumber);
anchor.removeChildren();
return anchor;
},


fileName: function(file)
{
var uiSourceCode = file;
return uiSourceCode.url;
},
}

WebInspector.ScriptsSearchResultsPane.prototype.__proto__ = WebInspector.FileBasedSearchResultsPane.prototype;


WebInspector.ScriptsSearchResultsPane.LinkifierFormatter = function()
{
}

WebInspector.ScriptsSearchResultsPane.LinkifierFormatter.prototype = {

formatRawSourceCodeAnchor: function(rawSourceCode, anchor)
{

}
}

WebInspector.ScriptsSearchResultsPane.LinkifierFormatter.prototype.__proto__ = WebInspector.DebuggerPresentationModel.LinkifierFormatter.prototype;

WebInspector.settings.searchInContentScripts = WebInspector.settings.createSetting("searchInContentScripts", false);






WebInspector.DOMNode = function(doc, payload) {
this.ownerDocument = doc;

this.id = payload.nodeId;
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;
},


nodeNameInCorrectCase: function()
{
return this.isXMLNode() ? this.nodeName() : this.nodeName().toLowerCase();
},


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, text, callback)
{
DOMAgent.setAttributesAsText(this.id, text, name, callback);
},


setAttributeValue: function(name, value, callback)
{
DOMAgent.setAttributeValue(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.requestChildNodes(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() || this.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;
},


isAncestor: function(node)
{
if (!node)
return false;

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


isDescendant: function(descendant)
{
return descendant !== null && descendant.isAncestor(this);
},


_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);
},


_setAttribute: function(name, value)
{
var attr = this._attributesMap[name];
if (attr)
attr.value = value;
else
this._addAttribute(name, value);
},


_removeAttribute: function(name)
{
var attr = this._attributesMap[name];
if (attr) {
this._attributes.remove(attr);
delete this._attributesMap[name];
}
},


ownerDocumentElement: function()
{


var node = this;
while (node.parentNode && !node.parentNode.documentURL)
node = node.parentNode;
return node;
},


moveTo: function(targetNode, anchorNode, callback)
{
DOMAgent.moveTo(this.id, targetNode.id, anchorNode ? anchorNode.id : undefined, callback);
},


isXMLNode: function()
{
return !!this.ownerDocument && !!this.ownerDocument.xmlVersion;
}
}


WebInspector.DOMDocument = function(domAgent, payload)
{
WebInspector.DOMNode.call(this, this, payload);


this.documentURL;
this._listeners = {};
this._domAgent = domAgent;
}

WebInspector.DOMDocument.prototype.__proto__ = WebInspector.DOMNode.prototype;


WebInspector.DOMAgent = function() {

this._idToDOMNode = {};
this._document = null;
this._attributeLoadNodeIds = {};
InspectorBackend.registerDOMDispatcher(new WebInspector.DOMDispatcher(this));
}

WebInspector.DOMAgent.Events = {
AttrModified: "AttrModified",
AttrRemoved: "AttrRemoved",
CharacterDataModified: "CharacterDataModified",
NodeInserted: "NodeInserted",
NodeRemoved: "NodeRemoved",
DocumentUpdated: "DocumentUpdated",
ChildNodeCountUpdated: "ChildNodeCountUpdated",
InspectElementRequested: "InspectElementRequested",
StyleInvalidated: "StyleInvalidated"
}

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.requestNode.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(func, arg, callback)
{
var callbackWrapper = this._wrapClientCallback(callback);

function onDocumentAvailable()
{
if (this._document)
func.call(null, arg, callbackWrapper);
else {
if (callbackWrapper)
callbackWrapper("No document");
}
}
this.requestDocument(onDocumentAvailable.bind(this));
},


_attributeModified: function(nodeId, name, value)
{
var node = this._idToDOMNode[nodeId];
if (!node)
return;
node._setAttribute(name, value);
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.AttrModified, { node: node, name: name });
},


_attributeRemoved: function(nodeId, name)
{
var node = this._idToDOMNode[nodeId];
if (!node)
return;
node._removeAttribute(name);
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.AttrRemoved, { node: node, name: name });
},


_inlineStyleInvalidated: function(nodeIds)
{
for (var i = 0; i < nodeIds.length; ++i)
this._attributeLoadNodeIds[nodeIds[i]] = true;
if ("_loadNodeAttributesTimeout" in this)
return;
this._loadNodeAttributesTimeout = setTimeout(this._loadNodeAttributes.bind(this), 0);
},

_loadNodeAttributes: function()
{

function callback(nodeId, attributes)
{
if (!attributes)
return;
var node = this._idToDOMNode[nodeId];
if (node) {
node._setAttributesPayload(attributes);
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.AttrModified, { node: node, name: "style" });
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.StyleInvalidated, node);                
}
}

delete this._loadNodeAttributesTimeout;

for (var nodeId in this._attributeLoadNodeIds)
DOMAgent.getAttributes(parseInt(nodeId, 10), this._wrapClientCallback(callback.bind(this, nodeId)));
this._attributeLoadNodeIds = {};
},


_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);
},


_setDocument: function(payload)
{
this._idToDOMNode = {};
if (payload && "nodeId" in payload) {
this._document = new WebInspector.DOMDocument(this, payload);
this._idToDOMNode[payload.nodeId] = 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.nodeId] = 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];
},


inspectElement: function(nodeId)
{
var node = this._idToDOMNode[nodeId];
if (node)
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.InspectElementRequested, node);
},


performSearch: function(query, searchCallback)
{
this.cancelSearch();


function callback(error, searchId, resultsCount)
{
this._searchId = searchId;
searchCallback(resultsCount);
}
DOMAgent.performSearch(query, callback.bind(this));
},


searchResult: function(index, callback)
{
if (this._searchId) {

function mycallback(error, nodeIds)
{
if (error) {
console.error(error);
callback(null);
return;
}
if (nodeIds.length != 1)
return;

callback(this._idToDOMNode[nodeIds[0]]);
}
DOMAgent.getSearchResults(this._searchId, index, index + 1, mycallback.bind(this));
} else
callback(null);
},

cancelSearch: function()
{
if (this._searchId) {
DOMAgent.discardSearchResults(this._searchId);
delete this._searchId;
}
},


querySelector: function(nodeId, selectors, callback)
{
DOMAgent.querySelector(nodeId, selectors, this._wrapClientCallback(callback));
},


querySelectorAll: function(nodeId, selectors, callback)
{
DOMAgent.querySelectorAll(nodeId, selectors, this._wrapClientCallback(callback));
},


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

this._highlightedDOMNodeId = nodeId;
if (nodeId)
DOMAgent.highlightNode(nodeId, this._buildHighlightConfig(mode));
else
DOMAgent.hideHighlight();
},

hideDOMNodeHighlight: function()
{
this.highlightDOMNode(0);
},


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


setInspectModeEnabled: function(enabled, callback)
{
DOMAgent.setInspectModeEnabled(enabled, this._buildHighlightConfig(), callback);
},


_buildHighlightConfig: function(mode)
{
mode = mode || "all";
var highlightConfig = { showInfo: mode === "all" };
if (mode === "all" || mode === "content")
highlightConfig.contentColor = WebInspector.Color.PageHighlight.Content.toProtocolRGBA();

if (mode === "all" || mode === "padding")
highlightConfig.paddingColor = WebInspector.Color.PageHighlight.Padding.toProtocolRGBA();

if (mode === "all" || mode === "border")
highlightConfig.borderColor = WebInspector.Color.PageHighlight.Border.toProtocolRGBA();

if (mode === "all" || mode === "margin")
highlightConfig.marginColor = WebInspector.Color.PageHighlight.Margin.toProtocolRGBA();

return highlightConfig;
}
}

WebInspector.DOMAgent.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.DOMDispatcher = function(domAgent)
{
this._domAgent = domAgent;
}

WebInspector.DOMDispatcher.prototype = {
documentUpdated: function()
{
this._domAgent._documentUpdated();
},


attributeModified: function(nodeId, name, value)
{
this._domAgent._attributeModified(nodeId, name, value);
},


attributeRemoved: function(nodeId, name)
{
this._domAgent._attributeRemoved(nodeId, name);
},


inlineStyleInvalidated: function(nodeIds)
{
this._domAgent._inlineStyleInvalidated(nodeIds);
},


characterDataModified: function(nodeId, characterData)
{
this._domAgent._characterDataModified(nodeId, characterData);
},


setChildNodes: function(parentId, payloads)
{
this._domAgent._setChildNodes(parentId, payloads);
},


childNodeCountUpdated: function(nodeId, childNodeCount)
{
this._domAgent._childNodeCountUpdated(nodeId, childNodeCount);
},


childNodeInserted: function(parentNodeId, previousNodeId, payload)
{
this._domAgent._childNodeInserted(parentNodeId, previousNodeId, payload);
},


childNodeRemoved: function(parentNodeId, nodeId)
{
this._domAgent._childNodeRemoved(parentNodeId, nodeId);
}
}


WebInspector.domAgent = null;






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",

TimeStamp: "TimeStamp",

MarkLoad: "MarkLoad",
MarkDOMContent: "MarkDOMContent",

ScheduleResourceRequest: "ScheduleResourceRequest",
ResourceSendRequest: "ResourceSendRequest",
ResourceReceiveResponse: "ResourceReceiveResponse",
ResourceReceivedData: "ResourceReceivedData",
ResourceFinish: "ResourceFinish",

FunctionCall: "FunctionCall",
GCEvent: "GCEvent",

RegisterAnimationFrameCallback: "RegisterAnimationFrameCallback",
CancelAnimationFrameCallback: "CancelAnimationFrameCallback",
FireAnimationFrameEvent: "FireAnimationFrameEvent"
}






WebInspector.TimelinePanel = function()
{
WebInspector.Panel.call(this, "timeline");
this.registerRequiredCSS("timelinePanel.css");

this.element.appendChild(this._createTopPane());
this.element.addEventListener("contextmenu", this._contextMenu.bind(this), true);
this.element.tabIndex = 0;

this._sidebarBackgroundElement = document.createElement("div");
this._sidebarBackgroundElement.className = "sidebar split-view-sidebar-left timeline-sidebar-background";
this.element.appendChild(this._sidebarBackgroundElement);

this.createSplitViewWithSidebarTree();
this._containerElement = this.splitView.element;
this._containerElement.id = "timeline-container";
this._containerElement.addEventListener("scroll", this._onScroll.bind(this), false);

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 = this.splitView.mainElement;
this._containerContentElement.id = "resources-container-content";

this._timelineGrid = new WebInspector.TimelineGrid();
this._itemsGraphsElement = this._timelineGrid.itemsGraphsElement;
this._itemsGraphsElement.id = "timeline-graphs";
this._itemsGraphsElement.addEventListener("mousewheel", this._overviewPane.scrollWindow.bind(this._overviewPane), true);
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._registeredAnimationCallbackRecords = {};

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));
this._containerElement.addEventListener("mousemove", this._mouseMove.bind(this), false);
this._containerElement.addEventListener("mouseout", this._mouseOut.bind(this), false);


this.toggleFilterButton.toggled = true;
this._calculator._showShortEvents = this.toggleFilterButton.toggled;
this._timeStampRecords = [];
this._expandOffset = 15;

this._createFileSelector();
this._model = new WebInspector.TimelineModel(this);

this._registerShortcuts();
WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded, this._onTimelineEventRecorded, this);
this._linkifier = WebInspector.debuggerPresentationModel.createLinkifier();
}


WebInspector.TimelinePanel.rowHeight = 18;
WebInspector.TimelinePanel.shortRecordThreshold = 0.015;

WebInspector.TimelinePanel.prototype = {
_linkifyLocation: function(url, lineNumber, columnNumber)
{

lineNumber = lineNumber ? lineNumber - 1 : lineNumber;
columnNumber = columnNumber ? columnNumber - 1 : 0;
return this._linkifier.linkifyLocation(url, lineNumber, columnNumber, "timeline-details");
},

_linkifyCallFrame: function(callFrame)
{
return this._linkifyLocation(callFrame.url, callFrame.lineNumber, callFrame.columnNumber);
},

_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.revealAndSelect(false);
timelinesOverviewItem.onselect = this._timelinesOverviewItemSelected.bind(this);

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.TimeStamp] = { title: WebInspector.UIString("Stamp"), 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 };
recordStyles[recordTypes.RegisterAnimationFrameCallback] = { title: WebInspector.UIString("Register Animation Callback"), category: this.categories.scripting };
recordStyles[recordTypes.CancelAnimationFrameCallback] = { title: WebInspector.UIString("Cancel Animation Callback"), category: this.categories.scripting };
recordStyles[recordTypes.FireAnimationFrameEvent] = { title: WebInspector.UIString("Animation Frame Event"), category: this.categories.scripting };
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, this);

this.clearButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear"), "clear-status-bar-item");
this.clearButton.addEventListener("click", this._clearPanel, this);

this.toggleFilterButton = new WebInspector.StatusBarButton(this._hideShortRecordsTitleText, "timeline-filter-status-bar-item");
this.toggleFilterButton.addEventListener("click", this._toggleFilterButtonClicked, this);

this.garbageCollectButton = new WebInspector.StatusBarButton(WebInspector.UIString("Collect Garbage"), "garbage-collect-status-bar-item");
this.garbageCollectButton.addEventListener("click", this._garbageCollectButtonClicked, this);

this.recordsCounter = document.createElement("span");
this.recordsCounter.className = "timeline-records-counter";
},

_registerShortcuts: function()
{
var shortcut = WebInspector.KeyboardShortcut;
var modifiers = shortcut.Modifiers;
var section = WebInspector.shortcutsScreen.section(WebInspector.UIString("Timeline Panel"));

this._shortcuts[shortcut.makeKey("e", modifiers.CtrlOrMeta)] = this._toggleTimelineButtonClicked.bind(this);
section.addKey(shortcut.shortcutToString("e", modifiers.CtrlOrMeta), WebInspector.UIString("Start/stop recording"));

this._shortcuts[shortcut.makeKey("s", modifiers.CtrlOrMeta)] = this._saveToFile.bind(this);
section.addKey(shortcut.shortcutToString("s", modifiers.CtrlOrMeta), WebInspector.UIString("Save Timeline data\u2026"));

this._shortcuts[shortcut.makeKey("o", modifiers.CtrlOrMeta)] = this._fileSelectorElement.click.bind(this._fileSelectorElement);
section.addKey(shortcut.shortcutToString("o", modifiers.CtrlOrMeta), WebInspector.UIString("Load Timeline data\u2026"));
},

_createFileSelector: function()
{
if (this._fileSelectorElement)
this.element.removeChild(this._fileSelectorElement);

var fileSelectorElement = document.createElement("input");
fileSelectorElement.type = "file";
fileSelectorElement.style.zIndex = -1;
fileSelectorElement.style.position = "absolute";
fileSelectorElement.onchange = this._loadFromFile.bind(this);
this.element.appendChild(fileSelectorElement);
this._fileSelectorElement = fileSelectorElement;
},

_contextMenu: function(event)
{
var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendItem(WebInspector.UIString("&Save Timeline data\u2026"), this._saveToFile.bind(this));
contextMenu.appendItem(WebInspector.UIString("L&oad Timeline data\u2026"), this._fileSelectorElement.click.bind(this._fileSelectorElement));
contextMenu.show(event);
},

_saveToFile: function()
{
this._model._saveToFile();
},

_loadFromFile: function()
{
if (this.toggleTimelineButton.toggled)
WebInspector.timelineManager.stop();

this._clearPanel();

this._model._loadFromFile(this._fileSelectorElement.files[0]);
this._createFileSelector();
},

_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._timeStampRecords.length; ++i) {
var record = this._timeStampRecords[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._timeStampRecords, 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.TimeStamp) {
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(30);
WebInspector.userMetrics.TimelineStarted.record();
}
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)
{
this._model._addRecord(record);
this._innerAddRecordToTimeline(record, this._rootRecord);
this._scheduleRefresh(false);
},

_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["requestId"]];
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.RegisterAnimationFrameCallback) {
this._registeredAnimationCallbackRecords[record.data["id"]] = record;
return;
}

if (record.type === recordTypes.MarkDOMContent || record.type === recordTypes.MarkLoad)
parentRecord = null; 
else if (parentRecord === this._rootRecord ||
record.type === recordTypes.ResourceReceiveResponse ||
record.type === recordTypes.ResourceFinish ||
record.type === recordTypes.ResourceReceivedData) {
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 || record.type === recordTypes.FireAnimationFrameEvent) && 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._timeStampRecords.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) {
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.TimeStamp)
this._timeStampRecords.push(formattedRecord);
},

sidebarResized: function(event)
{
var width = event.data;
this._sidebarBackgroundElement.style.width = width + "px";
this._topPaneSidebarElement.style.width = width + "px";
this._scheduleRefresh(false);
this._overviewPane.sidebarResized(width);
},

onResize: function()
{
this._closeRecordDetails();
this._scheduleRefresh(false);
},

_createRootRecord: function()
{
var rootRecord = {};
rootRecord.children = [];
rootRecord._visibleRecordsCount = 0;
rootRecord._allRecordsCount = 0;
rootRecord._aggregatedStats = {};
return rootRecord;
},

_clearPanel: function()
{
this._timeStampRecords = [];
this._sendRequestRecords = {};
this._scheduledResourceRequests = {};
this._timerRecords = {};
this._registeredAnimationCallbackRecords = {};
this._rootRecord = this._createRootRecord();
this._boundariesAreValid = false;
this._overviewPane.reset();
this._adjustScrollPosition(0);
this._refresh();
this._closeRecordDetails();
this._model._reset();
this._linkifier.reset();
},

elementsToRestoreScrollPositionsFor: function()
{
return [this._containerElement];
},

wasShown: function()
{
WebInspector.Panel.prototype.wasShown.call(this);
this._refresh();
WebInspector.drawer.currentPanelCounters = this.recordsCounter;
},

willHide: function()
{
this._closeRecordDetails();
WebInspector.drawer.currentPanelCounters = null;
WebInspector.Panel.prototype.willHide.call(this);
},

_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(false);
},

_scheduleRefresh: function(preserveBoundaries)
{
this._closeRecordDetails();
this._boundariesAreValid &= preserveBoundaries;

if (!this.isShowing())
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.splitView.sidebarResizerElement.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).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.splitView.sidebarResizerElement.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");
},

_mouseOut: function(e)
{
this._hideRectHighlight();
},

_mouseMove: function(e)
{
var anchor = this._getPopoverAnchor(e.target);

if (anchor && anchor.row._record.type === "Paint")
this._highlightRect(anchor.row._record);
else
this._hideRectHighlight();
},

_highlightRect: function(record)
{
if (this._highlightedRect === record.data)
return;
this._highlightedRect = record.data;
DOMAgent.highlightRect(this._highlightedRect.x, this._highlightedRect.y, this._highlightedRect.width, this._highlightedRect.height, WebInspector.Color.PageHighlight.Content.toProtocolRGBA(), WebInspector.Color.PageHighlight.ContentOutline.toProtocolRGBA());
},

_hideRectHighlight: function()
{
if (this._highlightedRect) {
delete this._highlightedRect;
DOMAgent.hideHighlight();
}
},

_showPopover: function(anchor, popover)
{
var record = anchor.row._record;
popover.show(record._generatePopupContent(this._calculator, this.categories), anchor);
},

_closeRecordDetails: function()
{
this._popoverHelper.hidePopover();
}
}

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(false);
},

dispose: function()
{
this.element.parentElement.removeChild(this.element);
this._expandElement._dispose();
}
}


WebInspector.TimelinePanel.FormattedRecord = function(record, parentRecord, panel, scriptDetails)
{
this._panel = panel;
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["requestId"]] = 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["requestId"]];
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["requestId"]];
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;
}
} else if (record.type === recordTypes.FireAnimationFrameEvent) {
var registerCallbackRecord = panel._registeredAnimationCallbackRecords[record.data["id"]];
if (registerCallbackRecord)
this.callSiteStackTrace = registerCallbackRecord.stackTrace;
}
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, this._panel);

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.FireAnimationFrameEvent:
contentHelper._appendTextRow(WebInspector.UIString("Callback ID"), this.data["id"]);
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 ? this._panel._linkifyLocation(this.scriptName, this.scriptLine, 0) : this.data["timerId"];
case WebInspector.TimelineAgent.RecordType.FunctionCall:
return this.scriptName ? this._panel._linkifyLocation(this.scriptName, this.scriptLine, 0) : null;
case WebInspector.TimelineAgent.RecordType.FireAnimationFrameEvent:
return this.scriptName ? this._panel._linkifyLocation(this.scriptName, this.scriptLine, 0) : this.data["id"];
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 ? this._panel._linkifyCallFrame(this.stackTrace[0]) : this.data["timerId"];
case WebInspector.TimelineAgent.RecordType.RegisterAnimationFrameCallback:
case WebInspector.TimelineAgent.RecordType.CancelAnimationFrameCallback:
return this.stackTrace ? this._panel._linkifyCallFrame(this.stackTrace[0]) : this.data["id"];
case WebInspector.TimelineAgent.RecordType.ParseHTML:
case WebInspector.TimelineAgent.RecordType.RecalculateStyles:
return this.stackTrace ? this._panel._linkifyCallFrame(this.stackTrace[0]) : null;
case WebInspector.TimelineAgent.RecordType.EvaluateScript:
return this.url ? this._panel._linkifyLocation(this.url, this.data["lineNumber"], 0) : 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.TimeStamp:
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, panel)
{
this._panel = panel;
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 = this._panel._linkifyLocation(scriptName, scriptLine, 0, "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");
var urlElement = this._panel._linkifyCallFrame(stackFrame);
linkCell.appendChild(urlElement);
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.TimelineModel = function(timelinePanel)
{
this._panel = timelinePanel;
this._records = [];
}

WebInspector.TimelineModel.prototype = {
_addRecord: function(record)
{
this._records.push(record);
},

_loadNextChunk: function(data, index)
{
for (var i = 0; i < 20 && index < data.length; ++i, ++index)
this._panel._addRecordToTimeline(data[index]);

if (index !== data.length)
setTimeout(this._loadNextChunk.bind(this, data, index), 0);
},

_loadFromFile: function(file)
{
function onLoad(e)
{
var data = JSON.parse(e.target.result);
var version = data[0];
this._loadNextChunk(data, 1);
}

function onError(e)
{
switch(e.target.error.code) {
case e.target.error.NOT_FOUND_ERR:
WebInspector.log(WebInspector.UIString('Timeline.loadFromFile: File "%s" not found.', file.name));
break;
case e.target.error.NOT_READABLE_ERR:
WebInspector.log(WebInspector.UIString('Timeline.loadFromFile: File "%s" is not readable', file.name));
break;
case e.target.error.ABORT_ERR:
break;
default:
WebInspector.log(WebInspector.UIString('Timeline.loadFromFile: An error occurred while reading the file "%s"', file.name));
}
}

var reader = new FileReader();
reader.onload = onLoad.bind(this);
reader.onerror = onError;
reader.readAsText(file);
},

_saveToFile: function()
{
var records = ['[' + JSON.stringify(window.navigator.appVersion)];
for (var i = 0; i < this._records.length; ++i)
records.push(JSON.stringify(this._records[i]));
records[records.length - 1] = records[records.length - 1] + "]";

var now= new Date();
var suggestedFileName = "TimelineRawData-" + now.toISO8601Compact() + ".json";
InspectorFrontendHost.saveAs(suggestedFileName, records.join(",\n"));
},

_reset: function()
{
this._records = [];
}
}






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._overviewGrid.element.addEventListener("mousewheel", this.scrollWindow.bind(this), true);
this._overviewGrid.element.addEventListener("dblclick", this._resizeWindowMaximum.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.WindowScrollSpeedFactor = .3;

WebInspector.TimelineOverviewPane.ResizerOffset = 3.5; 

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 markPercentagesForRecord(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, markPercentagesForRecord.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);
},

sidebarResized: function(width)
{
this._overviewGrid.element.style.left = width + "px";

this.statusBarFilters.style.left = Math.max(7 * 31, 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, "ew-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 + WebInspector.TimelineOverviewPane.ResizerOffset, this._rightResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.ResizerOffset), 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, "ew-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);
},

_resizeWindowMaximum: function()
{
this._setWindowPosition(0, this._overviewGrid.element.clientWidth);
},

_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);
},

scrollWindow: function(event)
{
if (typeof event.wheelDeltaX === "number" && event.wheelDeltaX !== 0)
this._windowDragging(event.pageX + Math.round(event.wheelDeltaX * WebInspector.TimelineOverviewPane.WindowScrollSpeedFactor), this._leftResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.ResizerOffset, this._rightResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.ResizerOffset, 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, false);
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 = 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);
this._element.tabIndex = 0;
this._element.addEventListener("focus", this._onBlur.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");
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,
];
}

WebInspector.HelpScreen.visibleScreen_ = null;

WebInspector.HelpScreen.prototype = {
show: function(onHide)
{
if (this._isShown)
return;

if (WebInspector.HelpScreen.visibleScreen_)
WebInspector.HelpScreen.visibleScreen_.hide();
WebInspector.HelpScreen.visibleScreen_ = this;

document.body.appendChild(this._element);
this._isShown = true;
this._onHide = onHide;
this._previousFocusElement = WebInspector.currentFocusElement();
WebInspector.setCurrentFocusElement(this._element);
},

hide: function()
{
if (!this._isShown)
return;

this._isShown = false;
document.body.removeChild(this._element);
WebInspector.setCurrentFocusElement(this._previousFocusElement);
WebInspector.HelpScreen.visibleScreen_ = null;
if (this._onHide) {
this._onHide();
delete this._onHide;
}
},

_onKeyDown: function(event)
{
if (this._isShown && this._closeKeys.indexOf(event.keyCode) >= 0) {
this.hide();
event.stopPropagation();
}
},

_onBlur: function(event)
{

if (this._isShown && event.target !== this._element && !this._element.isAncestor(event.target))
WebInspector.setCurrentFocusElement(this._element);
}
}






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.setCurrentFocusElement(this._input);
this._input.select();
}

WebInspector.GoToLineDialog.install = function(panel, viewGetter)
{
function showGoToLineDialog()
{
var view = viewGetter();
if (view)
WebInspector.GoToLineDialog._show(view);
}

var goToLineShortcut = WebInspector.GoToLineDialog.createShortcut();
panel.registerShortcut(goToLineShortcut.key, showGoToLineDialog);
}

WebInspector.GoToLineDialog._show = function(sourceView)
{
if (!sourceView || !sourceView.canHighlightLine())
return;
if (WebInspector.GoToLineDialog._instance)
return;
WebInspector.GoToLineDialog._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.setCurrentFocusElement(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.SettingsScreen = function()
{
WebInspector.HelpScreen.call(this, WebInspector.UIString("Settings"));

this._leftColumnElement = document.createElement("td");
this._rightColumnElement = document.createElement("td");

var p = this._appendSection(WebInspector.UIString("Elements"));
p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Word wrap"), WebInspector.settings.domWordWrap));

p = this._appendSection(WebInspector.UIString("Styles"));
p.appendChild(this._createRadioSetting(WebInspector.UIString("Color format"), [
[ WebInspector.StylesSidebarPane.ColorFormat.Original, WebInspector.UIString("As authored") ],
[ WebInspector.StylesSidebarPane.ColorFormat.HEX, "HEX: #DAC0DE" ],
[ WebInspector.StylesSidebarPane.ColorFormat.RGB, "RGB: rgb(128, 255, 255)" ],
[ WebInspector.StylesSidebarPane.ColorFormat.HSL, "HSL: hsl(300, 80%, 90%)" ] ], WebInspector.settings.colorFormat));
p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show user agent styles"), WebInspector.settings.showUserAgentStyles));

p = this._appendSection(WebInspector.UIString("Text editor"));
p.appendChild(this._createSelectSetting(WebInspector.UIString("Indent"), [
[ WebInspector.UIString("2 spaces"), WebInspector.TextEditorModel.Indent.TwoSpaces ],
[ WebInspector.UIString("4 spaces"), WebInspector.TextEditorModel.Indent.FourSpaces ],
[ WebInspector.UIString("8 spaces"), WebInspector.TextEditorModel.Indent.EightSpaces ],
[ WebInspector.UIString("Tab character"), WebInspector.TextEditorModel.Indent.TabCharacter ]
], WebInspector.settings.textEditorIndent));

p = this._appendSection(WebInspector.UIString("Network"), true);
if (Preferences.exposeDisableCache)
p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Disable cache"), WebInspector.settings.cacheDisabled));
p.appendChild(this._createUserActionControl());

p = this._appendSection(WebInspector.UIString("Scripts"), true);
p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show script folders"), WebInspector.settings.showScriptFolders));
p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Search in content scripts"), WebInspector.settings.searchInContentScripts));

p = this._appendSection(WebInspector.UIString("Console"), true);
p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Log XMLHttpRequests"), WebInspector.settings.monitoringXHREnabled));
p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Preserve log upon navigation"), WebInspector.settings.preserveConsoleLog));

if (WebInspector.extensionServer.hasExtensions()) {
var handlerSelector = new WebInspector.HandlerSelector(WebInspector.openAnchorLocationRegistry);
p = this._appendSection(WebInspector.UIString("Extensions"), true);
p.appendChild(this._createCustomSetting(WebInspector.UIString("Open links in"), handlerSelector.element));
}
var table = document.createElement("table");
table.className = "help-table";
var tr = document.createElement("tr");
tr.appendChild(this._leftColumnElement);
tr.appendChild(this._rightColumnElement);
table.appendChild(tr);
this.contentElement.appendChild(table);
}

WebInspector.SettingsScreen.prototype = {

_appendSection: function(name, right)
{
var p = document.createElement("p");
p.className = "help-section";
var title = document.createElement("div");
title.className = "help-section-title";
title.textContent = name;
p.appendChild(title);
this._columnElement(right).appendChild(p);
return p;
},

_columnElement: function(right)
{
return right ? this._rightColumnElement : this._leftColumnElement;
},

_createCheckboxSetting: function(name, setting)
{
var input = document.createElement("input");
input.type = "checkbox";
input.name = name;
input.checked = setting.get();
function listener()
{
setting.set(input.checked);
}
input.addEventListener("click", listener, false);

var p = document.createElement("p");
var label = document.createElement("label");
label.appendChild(input);
label.appendChild(document.createTextNode(name));
p.appendChild(label);
return p;
},

_createSelectSetting: function(name, options, setting)
{
var fieldsetElement = document.createElement("fieldset");
fieldsetElement.createChild("label").textContent = name;

var select = document.createElement("select");
var settingValue = setting.get();

for (var i = 0; i < options.length; ++i) {
var option = options[i];
select.add(new Option(option[0], option[1]));
if (settingValue === option[1])
select.selectedIndex = i;
}

function changeListener(e)
{
setting.set(e.target.value);
}

select.addEventListener("change", changeListener, false);
fieldsetElement.appendChild(select);

var p = document.createElement("p");
p.appendChild(fieldsetElement);
return p;
},

_createRadioSetting: function(name, options, setting)
{
var pp = document.createElement("p");
var fieldsetElement = document.createElement("fieldset");
var legendElement = document.createElement("legend");
legendElement.textContent = name;
fieldsetElement.appendChild(legendElement);

function clickListener(e)
{
setting.set(e.target.value);
}

var settingValue = setting.get();
for (var i = 0; i < options.length; ++i) {
var p = document.createElement("p");
var label = document.createElement("label");
p.appendChild(label);

var input = document.createElement("input");
input.type = "radio";
input.name = setting.name;
input.value = options[i][0];
input.addEventListener("click", clickListener, false);
if (settingValue == input.value)
input.checked = true;

label.appendChild(input);
label.appendChild(document.createTextNode(options[i][1]));

fieldsetElement.appendChild(p);
}

pp.appendChild(fieldsetElement);
return pp;
},

_createCustomSetting: function(name, element)
{
var p = document.createElement("p");
var fieldsetElement = document.createElement("fieldset");
fieldsetElement.createChild("label").textContent = name;
fieldsetElement.appendChild(element);
p.appendChild(fieldsetElement);
return p;
},

_createUserActionControl: function()
{
var userAgent = WebInspector.settings.userAgent.get();

var p = document.createElement("p");
var labelElement = p.createChild("label");
var checkboxElement = labelElement.createChild("input");
checkboxElement.type = "checkbox";
checkboxElement.checked = !!userAgent;
checkboxElement.addEventListener("click", checkboxClicked.bind(this), false);
labelElement.appendChild(document.createTextNode("Override User Agent"));

var selectSectionElement;
function checkboxClicked()
{
if (checkboxElement.checked) {
selectSectionElement = this._createUserAgentSelectRowElement();
p.appendChild(selectSectionElement);
} else {
if (selectSectionElement) {
p.removeChild(selectSectionElement);
selectSectionElement = null;
}
WebInspector.settings.userAgent.set("");
}
}

checkboxClicked.call(this);
return p;
},

_createUserAgentSelectRowElement: function()
{
var userAgent = WebInspector.settings.userAgent.get();
const userAgents = [
["Internet Explorer 9", "Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0)"],
["Internet Explorer 8", "Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.0; Trident/4.0)"],
["Internet Explorer 7", "Mozilla/4.0 (compatible; MSIE 7.0; Windows NT 6.0)"],

["Firefox 7 \u2014 Windows", "Mozilla/5.0 (Windows NT 6.1; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1"],
["Firefox 7 \u2014 Mac", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:7.0.1) Gecko/20100101 Firefox/7.0.1"],
["Firefox 4 \u2014 Windows", "Mozilla/5.0 (Windows NT 6.1; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"],
["Firefox 4 \u2014 Mac", "Mozilla/5.0 (Macintosh; Intel Mac OS X 10.6; rv:2.0.1) Gecko/20100101 Firefox/4.0.1"],

["iPhone \u2014 iOS 5", "Mozilla/5.0 (iPhone; CPU iPhone OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3"],
["iPhone \u2014 iOS 4", "Mozilla/5.0 (iPhone; U; CPU iPhone OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5"],
["iPad \u2014 iOS 5", "Mozilla/5.0 (iPad; CPU OS 5_0 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A334 Safari/7534.48.3"],
["iPad \u2014 iOS 4", "Mozilla/5.0 (iPad; CPU OS 4_3_2 like Mac OS X; en-us) AppleWebKit/533.17.9 (KHTML, like Gecko) Version/5.0.2 Mobile/8H7 Safari/6533.18.5"],

["Android 2.3 \u2014 Nexus S", "Mozilla/5.0 (Linux; U; Android 2.3.6; en-us; Nexus S Build/GRK39F) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1"],
[WebInspector.UIString("Other..."), "Other"]
];

var fieldsetElement = document.createElement("fieldset");
var selectElement = fieldsetElement.createChild("select");
var otherUserAgentElement = fieldsetElement.createChild("input");
otherUserAgentElement.value = userAgent;
otherUserAgentElement.title = userAgent;

var selectionRestored = false;
for (var i = 0; i < userAgents.length; ++i) {
var agent = userAgents[i];
selectElement.add(new Option(agent[0], agent[1]));
if (userAgent === agent[1]) {
selectElement.selectedIndex = i;
selectionRestored = true;
}
}

if (!selectionRestored) {
if (!userAgent)
selectElement.selectedIndex = 0;
else
selectElement.selectedIndex = userAgents.length - 1;
}

selectElement.addEventListener("change", selectionChanged.bind(this), false);

function selectionChanged()
{
var value = selectElement.options[selectElement.selectedIndex].value;
if (value !== "Other") {
WebInspector.settings.userAgent.set(value);
otherUserAgentElement.value = value;
otherUserAgentElement.title = value;
otherUserAgentElement.disabled = true;
} else {
otherUserAgentElement.disabled = false;
otherUserAgentElement.focus();
}
}

fieldsetElement.addEventListener("dblclick", textDoubleClicked.bind(this), false);
otherUserAgentElement.addEventListener("blur", textChanged.bind(this), false);

function textDoubleClicked()
{
selectElement.selectedIndex = userAgents.length - 1;
selectionChanged.call(this);
}

function textChanged()
{
WebInspector.settings.userAgent.set(otherUserAgentElement.value);
}

selectionChanged.call(this);
return fieldsetElement;
}
}

WebInspector.SettingsScreen.prototype.__proto__ = WebInspector.HelpScreen.prototype;






WebInspector.ShortcutsScreen = function()
{
WebInspector.HelpScreen.call(this, WebInspector.UIString("Keyboard Shortcuts"));
this._sections = {};
this._tableReady = false;
}

WebInspector.ShortcutsScreen.prototype = {
section: function(name)
{
var section = this._sections[name];
if (!section)
this._sections[name] = section = new WebInspector.ShortcutsSection(name);
return section;
},

show: function(onHide)
{
this._buildTable(this.contentElement, 2);
WebInspector.HelpScreen.prototype.show.call(this, onHide);
},

_buildTable: function(parent, nColumns)
{
if (this._tableReady)
return;
this._tableReady = true;

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.ShortcutsScreen.prototype.__proto__ = WebInspector.HelpScreen.prototype;


WebInspector.shortcutsScreen = null;


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(keyElement, description)
{
this._lines.push({ key: keyElement, text: description })
},

renderSection: function(parent)
{
this._renderHeader(parent);

for (var line = 0; line < this._lines.length; ++line) {
var tr = parent.createChild("tr");
var td = tr.createChild("td", "help-key-cell");
td.appendChild(this._lines[line].key);
td.appendChild(document.createTextNode(" : "));
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 delimiterSpan = this._createSpan("help-key-delimiter", delimiter);
return this._joinNodes(sequence.map(this._renderKey.bind(this)), delimiterSpan);
},

_renderKey: function(key)
{
var plus = this._createSpan("help-combine-keys", "+");
return this._joinNodes(key.split(" + ").map(this._createSpan.bind(this, "help-key monospace")), plus);
},

get _height()
{
return this._lines.length + 2; 
},

_createSpan: function(className, textContent)
{
var node = document.createElement("span");
node.className = className;
node.textContent = textContent;
return node;
},

_joinNodes: function(nodes, delimiter)
{
var result = document.createDocumentFragment();
for (var i = 0; i < nodes.length; ++i) {
if (i > 0)
result.appendChild(delimiter.cloneNode(true));
result.appendChild(nodes[i]);
}
return result;
}
}












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._buildRequestURL(this._resource.url),
httpVersion: this._resource.requestHttpVersion,
headers: this._buildHeaders(this._resource.requestHeaders),
queryString: this._buildParameters(this._resource.queryParameters || []),
cookies: this._buildCookies(this._resource.requestCookies || []),
headersSize: this._resource.requestHeadersSize,
bodySize: this.requestBodySize
};
if (this._resource.requestFormData)
res.postData = this._buildPostData();

return res;
},

_buildResponse: function()
{
return {
status: this._resource.statusCode,
statusText: this._resource.statusText,
httpVersion: this._resource.responseHttpVersion,
headers: this._buildHeaders(this._resource.responseHeaders),
cookies: this._buildCookies(this._resource.responseCookies || []),
content: this._buildContent(),
redirectURL: this._resource.responseHeaderValue("Location") || "",
headersSize: this._resource.responseHeadersSize,
bodySize: this.responseBodySize
};
},

_buildContent: function()
{
return {
size: this._resource.resourceSize,
compression: this.responseCompression,
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();
},

_buildRequestURL: function(url)
{
return url.split("#", 2)[0];
},

_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);
},

get requestBodySize()
{
return !this._resource.requestFormData ? 0 : this._resource.requestFormData.length;
},

get responseBodySize()
{
return this._resource.transferSize - this._resource.responseHeadersSize
},

get responseCompression()
{
return this._resource.resourceSize - (this._resource.transferSize - this._resource.responseHeadersSize);
}
}

WebInspector.HAREntry._toMilliseconds = function(time)
{
return time === -1 ? -1 : Math.round(time * 1000);
}


WebInspector.HARLog = function(resources)
{
this._resources = resources;
}

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: this._resources.map(this._convertResource.bind(this))
}
},

_buildPages: function()
{
return [
{
startedDateTime: new Date(WebInspector.mainResourceStartTime * 1000),
id: WebInspector.inspectedPageURL,
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.mainResourceStartTime;
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.inspectorView.setCurrentPanel(panel);
}
toolbarItem.addEventListener("click", onToolbarItemClicked, false);

var iconElement = toolbarItem.createChild("div", "toolbar-icon");

if ("toolbarItemLabel" in panel)
toolbarItem.createChild("div", "toolbar-label").textContent = panel.toolbarItemLabel;

if (panel === WebInspector.inspectorView.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);
},

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.toolbar = null;






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.inspectorView.currentPanel();

panel.currentSearchMatches = matches;

if (panel === WebInspector.inspectorView.currentPanel())
this._updateSearchMatchesCountAndCurrentMatchIndex(WebInspector.inspectorView.currentPanel().currentQuery && matches);
},

updateCurrentMatchIndex: function(currentMatchIndex, panel)
{
if (panel === WebInspector.inspectorView.currentPanel())
this._updateSearchMatchesCountAndCurrentMatchIndex(panel.currentSearchMatches, currentMatchIndex);
},

updateSearchLabel: function()
{
var panelName = WebInspector.inspectorView.currentPanel() && WebInspector.inspectorView.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("");
},

disableSearchUntilExplicitAction: function(event)
{
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.inspectorView.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;

var panel = WebInspector.inspectorView.currentPanel();
if (panel.performSearch) {
function performPanelSearch()
{
this._updateSearchMatchesCountAndCurrentMatchIndex();

panel.currentQuery = this._currentQuery;
panel.performSearch(this._currentQuery);
}


setTimeout(performPanelSearch.bind(this), 0);
} else {

this._updateSearchMatchesCountAndCurrentMatchIndex();
}
},


_updateSearchMatchesCountAndCurrentMatchIndex: function(matches, currentMatchIndex)
{
if (matches == null) {
this._matchesElement.addStyleClass("hidden");
return;
}

if (matches) {
if (matches === 1) {
if (currentMatchIndex === 0)
var matchesString = WebInspector.UIString("1 of 1 match");
else
var matchesString = WebInspector.UIString("1 match");
} else {
if (typeof currentMatchIndex === "number")
var matchesString = WebInspector.UIString("%d of %d matches", currentMatchIndex + 1, matches);
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.setCurrentFocusElement(event.target);
},

_onKeyDown: function(event)
{

if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Esc.code) {



if (event.target.value === "" && WebInspector.currentFocusElement() === WebInspector.previousFocusElement())
return;
event.preventDefault();
event.stopPropagation();

this.cancelSearch();
WebInspector.setCurrentFocusElement(WebInspector.previousFocusElement());
if (WebInspector.currentFocusElement() === event.target)
WebInspector.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._updateSearchMatchesCountAndCurrentMatchIndex();

return;
}

var currentPanel = WebInspector.inspectorView.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._updateSearchMatchesCountAndCurrentMatchIndex();

if (!currentPanel.performSearch)
return;

currentPanel.currentQuery = query;
currentPanel.performSearch(query);
}
}


WebInspector.searchController = null;






WebInspector.WorkerManager = function()
{
this._workerIdToWindow = {};
InspectorBackend.registerWorkerDispatcher(new WebInspector.WorkerDispatcher(this));
}

WebInspector.WorkerManager.isWorkerFrontend = function()
{
return !!WebInspector.queryParamsObject["dedicatedWorkerId"] ||
!!WebInspector.queryParamsObject["isSharedWorker"];
}

WebInspector.WorkerManager.loaded = function()
{
var workerId = WebInspector.queryParamsObject["dedicatedWorkerId"];
if (workerId)
WebInspector.WorkerManager._initializeDedicatedWorkerFrontend(workerId);
else
WebInspector.workerManager = new WebInspector.WorkerManager();
}

WebInspector.WorkerManager.loadCompleted = function()
{


if (WebInspector.queryParamsObject["workerPaused"]) {
DebuggerAgent.pause();
RuntimeAgent.run(calculateTitle);
} else if (WebInspector.WorkerManager.isWorkerFrontend())
calculateTitle();

function calculateTitle()
{
WebInspector.WorkerManager._calculateWorkerInspectorTitle();
}

if (WebInspector.workerManager)
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, WebInspector.workerManager._mainFrameNavigated, WebInspector.workerManager);
}

WebInspector.WorkerManager._initializeDedicatedWorkerFrontend = function(workerId)
{
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.WorkerManager._calculateWorkerInspectorTitle = function()
{
var expression = "location.href";
if (WebInspector.queryParamsObject["isSharedWorker"])
expression += " + (this.name ? ' (' + this.name + ')' : '')";
RuntimeAgent.evaluate.invoke({expression:expression, doNotPauseOnExceptions:true, returnByValue: true}, evalCallback.bind(this));
function evalCallback(error, result, wasThrown)
{
if (error || wasThrown) {
console.error(error);
return;
}
InspectorFrontendHost.inspectedURLChanged(result.value);
}
}

WebInspector.WorkerManager.Events = {
WorkerAdded: "worker-added",
WorkerRemoved: "worker-removed",
WorkersCleared: "workers-cleared",
}

WebInspector.WorkerManager.prototype = {
_workerCreated: function(workerId, url, inspectorConnected)
{
if (inspectorConnected)
this._openInspectorWindow(workerId, true);
this.dispatchEventToListeners(WebInspector.WorkerManager.Events.WorkerAdded, {workerId: workerId, url: url, inspectorConnected: inspectorConnected});
},

_workerTerminated: function(workerId)
{
this.closeWorkerInspector(workerId);
this.dispatchEventToListeners(WebInspector.WorkerManager.Events.WorkerRemoved, workerId);
},

_sendMessageToWorkerInspector: function(workerId, message)
{
var workerInspectorWindow = this._workerIdToWindow[workerId];
if (workerInspectorWindow)
workerInspectorWindow.postMessage(message, "*");
},

openWorkerInspector: function(workerId)
{
var existingInspector = this._workerIdToWindow[workerId];
if (existingInspector) {
existingInspector.focus();
return;
}

this._openInspectorWindow(workerId, false);
WorkerAgent.connectToWorker(workerId);
},

_openInspectorWindow: function(workerId, workerIsPaused)
{
var url = window.location.href + "&dedicatedWorkerId=" + workerId;
if (workerIsPaused)
url += "&workerPaused=true";
url = url.replace("docked=true&", "");

var workerInspectorWindow = window.open(url, undefined, "location=0");
this._workerIdToWindow[workerId] = workerInspectorWindow;
workerInspectorWindow.addEventListener("beforeunload", this._workerInspectorClosing.bind(this, workerId), true);


window.addEventListener("beforeunload", this._pageInspectorClosing.bind(this), true);
WebInspector.notifications.addEventListener(WebInspector.Events.InspectorClosing, this._pageInspectorClosing, this);
},

closeWorkerInspector: function(workerId)
{
var workerInspectorWindow = this._workerIdToWindow[workerId];
if (workerInspectorWindow)
workerInspectorWindow.close();
},

_mainFrameNavigated: function(event)
{
for (var workerId in this._workerIdToWindow)
this.closeWorkerInspector(workerId);
this.dispatchEventToListeners(WebInspector.WorkerManager.Events.WorkersCleared);
},

_pageInspectorClosing: function()
{
this._ignoreWorkerInspectorClosing = true;
for (var workerId in this._workerIdToWindow) {
this._workerIdToWindow[workerId].close();
WorkerAgent.disconnectFromWorker(parseInt(workerId, 10));
}
},

_workerInspectorClosing: function(workerId, event)
{
if (this._ignoreWorkerInspectorClosing)
return;
delete this._workerIdToWindow[workerId];
WorkerAgent.disconnectFromWorker(workerId);
},

_disconnectedFromWorker: function()
{
function onHide()
{
WebInspector.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, screen.hide, screen);
}
var screen = new WebInspector.WorkerTerminatedScreen();
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, screen.hide, screen);
screen.show(onHide.bind(this));
}
}

WebInspector.WorkerManager.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.WorkerDispatcher = function(workerManager)
{
this._workerManager = workerManager;
window.addEventListener("message", this._receiveMessage.bind(this), true);
}

WebInspector.WorkerDispatcher.prototype = {
_receiveMessage: function(event)
{
var workerId = event.data["workerId"];
workerId = parseInt(workerId, 10);
var command = event.data.command;
var message = event.data.message;

if (command == "sendMessageToBackend")
WorkerAgent.sendMessageToWorker(workerId, message);
},

workerCreated: function(workerId, url, inspectorConnected)
{
this._workerManager._workerCreated(workerId, url, inspectorConnected);
},

workerTerminated: function(workerId)
{
this._workerManager._workerTerminated(workerId);
},

dispatchMessageFromWorker: function(workerId, message)
{
this._workerManager._sendMessageToWorkerInspector(workerId, message);
},

disconnectedFromWorker: function()
{
this._workerManager._disconnectedFromWorker();
}
}


WebInspector.WorkerTerminatedScreen = function()
{
WebInspector.HelpScreen.call(this, WebInspector.UIString("Inspected worker terminated"));
var p = this.contentElement.createChild("p");
p.addStyleClass("help-section");
p.textContent = WebInspector.UIString("Inspected worker has terminated. Once it restarts we will attach to it automatically.");
}

WebInspector.WorkerTerminatedScreen.prototype.__proto__ = WebInspector.HelpScreen.prototype;






WebInspector.UserMetrics = function()
{
for (var actionName in WebInspector.UserMetrics._ActionCodes) {
var actionCode = WebInspector.UserMetrics._ActionCodes[actionName];
this[actionName] = new WebInspector.UserMetrics._Recorder(actionCode);
}

function settingChanged(trueCode, falseCode, event)
{
if (event.data)
InspectorFrontendHost.recordSettingChanged(trueCode);
else
InspectorFrontendHost.recordSettingChanged(falseCode);
}

WebInspector.settings.domWordWrap.addChangeListener(settingChanged.bind(this, WebInspector.UserMetrics._SettingCodes.ElementsDOMWrapOn, WebInspector.UserMetrics._SettingCodes.ElementsDOMWrapOff));
WebInspector.settings.monitoringXHREnabled.addChangeListener(settingChanged.bind(this, WebInspector.UserMetrics._SettingCodes.ConsoleMonitorXHROn, WebInspector.UserMetrics._SettingCodes.ConsoleMonitorXHROff));
WebInspector.settings.preserveConsoleLog.addChangeListener(settingChanged.bind(this, WebInspector.UserMetrics._SettingCodes.ConsolePreserveLogOn, WebInspector.UserMetrics._SettingCodes.ConsolePreserveLogOff));
WebInspector.settings.resourcesLargeRows.addChangeListener(settingChanged.bind(this, WebInspector.UserMetrics._SettingCodes.NetworkShowLargeRowsOn, WebInspector.UserMetrics._SettingCodes.NetworkShowLargeRowsOff));
}





WebInspector.UserMetrics._ActionCodes = {
WindowDocked: 1,
WindowUndocked: 2,
ScriptsBreakpointSet: 3,
TimelineStarted: 4,
ProfilesCPUProfileTaken: 5,
ProfilesHeapProfileTaken: 6,
AuditsStarted: 7,
ConsoleEvaluated: 8
}

WebInspector.UserMetrics._SettingCodes = {
ElementsDOMWrapOn: 1,
ElementsDOMWrapOff: 2,
ConsoleMonitorXHROn: 3,
ConsoleMonitorXHROff: 4,
ConsolePreserveLogOn: 5,
ConsolePreserveLogOff: 6,
NetworkShowLargeRowsOn: 7,
NetworkShowLargeRowsOff: 8
}

WebInspector.UserMetrics._PanelCodes = {
elements: 1,
resources: 2,
network: 3,
scripts: 4,
timeline: 5,
profiles: 6,
audits: 7,
console: 8
}

WebInspector.UserMetrics.prototype = {
panelShown: function(panelName)
{
InspectorFrontendHost.recordPanelShown(WebInspector.UserMetrics._PanelCodes[panelName] || 0);
}
}


WebInspector.UserMetrics._Recorder = function(actionCode)
{
this._actionCode = actionCode;
}

WebInspector.UserMetrics._Recorder.prototype = {
record: function()
{
InspectorFrontendHost.recordActionTaken(this._actionCode);
}
}

WebInspector.userMetrics = new WebInspector.UserMetrics();






WebInspector.JavaScriptContextManager = function(resourceTreeModel, consoleView)
{
resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, this._frameAdded, this);
resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this);
resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this._frameDetached, this);
this._consoleView = consoleView;
this._frameIdToContext = {};
}

WebInspector.JavaScriptContextManager.prototype = {
_frameAdded: function(event)
{
var frame = event.data;
var context = new WebInspector.FrameEvaluationContext(frame);
this._frameIdToContext[frame.id] = context;
this._consoleView.addContext(context);
},

_frameNavigated: function(event)
{
var frame = event.data;
var context = this._frameIdToContext[frame.id];
if (context)
context._frameNavigated(frame);
},

_frameDetached: function(event)
{
var frame = event.data;
var context = this._frameIdToContext[frame.id];
if (!context)
return;
this._consoleView.removeContext(context);
delete this._frameIdToContext[frame.id];
},
}

WebInspector.JavaScriptContextManager.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.FrameEvaluationContext = function(frame)
{
this._frame = frame;
}

WebInspector.FrameEvaluationContext.EventTypes = {
Updated: "updated"
}

WebInspector.FrameEvaluationContext.prototype =
{
_frameNavigated: function(frame)
{
this._frame = frame;
this.dispatchEventToListeners(WebInspector.FrameEvaluationContext.EventTypes.Updated, this);
},

get frameId()
{
return this._frame.id;
},

get url()
{
return this._frame.url;
},

get displayName()
{
if (!this._frame.parentFrame)
return "<top frame>";
var name = this._frame.name || "";
var subtitle = WebInspector.Resource.displayName(this._frame.url);
if (subtitle) {
if (!name)
return subtitle;
return name + "( " + subtitle + " )";
}
return "<iframe>";
}
}

WebInspector.FrameEvaluationContext.prototype.__proto__ = WebInspector.Object.prototype;






WebInspector.HandlerRegistry = function(setting)
{
WebInspector.Object.call(this);
this._handlers = {};
this._setting = setting;
this._activeHandler = this._setting.get();
}

WebInspector.HandlerRegistry.prototype = {
get handlerNames()
{
return Object.getOwnPropertyNames(this._handlers);
},

get activeHandler()
{
return this._activeHandler;
},

set activeHandler(value)
{
this._activeHandler = value;
this._setting.set(value);
},


dispatch: function(data)
{
return this.dispatchToHandler(this._activeHandler, data);
},


dispatchToHandler: function(name, data)
{
var handler = this._handlers[name];
var result = handler && handler(data);
return !!result;
},

registerHandler: function(name, handler)
{
this._handlers[name] = handler;
this.dispatchEventToListeners(WebInspector.HandlerRegistry.EventTypes.HandlersUpdated);
},

unregisterHandler: function(name)
{
delete this._handlers[name];
this.dispatchEventToListeners(WebInspector.HandlerRegistry.EventTypes.HandlersUpdated);
}
}

WebInspector.HandlerRegistry.EventTypes = {
HandlersUpdated: "HandlersUpdated"
}

WebInspector.HandlerRegistry.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.HandlerSelector = function(handlerRegistry)
{
this._handlerRegistry = handlerRegistry;
this.element = document.createElement("select");
this.element.addEventListener("change", this._onChange.bind(this), false);
this._update();
this._handlerRegistry.addEventListener(WebInspector.HandlerRegistry.EventTypes.HandlersUpdated, this._update.bind(this));
}

WebInspector.HandlerSelector.prototype =
{
_update: function()
{
this.element.removeChildren();
var names = this._handlerRegistry.handlerNames;
var activeHandler = this._handlerRegistry.activeHandler;

for (var i = 0; i < names.length; ++i) {
var option = document.createElement("option");
option.textContent = names[i];
option.selected = activeHandler === names[i];
this.element.appendChild(option);
}
this.element.disabled = names.length <= 1;
},

_onChange: function(event)
{
var value = event.target.value;
this._handlerRegistry.activeHandler = value;
}
}







{(function () {
Preferences.useLowerCaseMenuTitlesOnWindows = true;
Preferences.sharedWorkersDebugNote = "Shared workers can be inspected in the Task Manager";
Preferences.localizeUI = false;
Preferences.applicationTitle = "Developer Tools - %s";
Preferences.exposeDisableCache = true;
Preferences.exposeWorkersInspection = true;
})();}

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 || {};

var properties = Object.getOwnPropertyNames(webInspector);
for (var i = 0; i < properties.length; ++i) {
var descriptor = Object.getOwnPropertyDescriptor(webInspector, properties[i]);
Object.defineProperty(chrome.experimental.devtools, properties[i], descriptor);
}
}

WebInspector.buildPlatformExtensionAPI = function()
{
return "(" + WebInspector.platformExtensionAPI + ")(" + WebInspector._inspectedTabId + ");";
}

WebInspector.setInspectedTabId = function(tabId)
{
WebInspector._inspectedTabId = tabId;
}








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.inspectorView.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.inspectorView.currentPanel(), "Elements panel should be current one.");

WebInspector.debuggerPresentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.DebuggerReset, waitUntilScriptIsParsed);


test.evaluateInConsole_("window.location.reload(true);", function(resultText) {});

function waitUntilScriptIsParsed()
{
WebInspector.debuggerPresentationModel.removeEventListener(WebInspector.DebuggerPresentationModel.Events.DebuggerReset, 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");


if (WebInspector.debuggerModel.debuggerPausedDetails)
return;

this._waitForScriptPause(this.releaseControl.bind(this));
this.takeControl();
};




TestSuite.prototype.testPauseWhenScriptIsRunning = function()
{
this.showPanel("scripts");

this.evaluateInConsole_(
'setTimeout("handleClick()" , 0)',
didEvaluateInConsole.bind(this));

function didEvaluateInConsole(resultText) {
this.assertTrue(!isNaN(resultText), "Failed to get timer id: " + resultText);


setTimeout(testScriptPause.bind(this), 300);
}

function testScriptPause() {


WebInspector.panels.scripts.pauseButton.click();

this._waitForScriptPause(this.releaseControl.bind(this));
}

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.testConsoleOnNavigateBack = function()
{
if (WebInspector.console.messages.length === 1)
firstConsoleMessageReceived.call(this);
else
WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, firstConsoleMessageReceived, this);

function firstConsoleMessageReceived() {
this.evaluateInConsole_("clickLink();", didClickLink.bind(this));
}

function didClickLink() {

this.assertEquals(1, WebInspector.console.messages.length);
this.assertEquals(1, WebInspector.console.messages[0].totalRepeatCount);
this.evaluateInConsole_("history.back();", didNavigateBack.bind(this));
}

function didNavigateBack()
{

this.evaluateInConsole_("void 0;", didCompleteNavigation.bind(this));
}

function didCompleteNavigation() {
this.assertEquals(1, WebInspector.console.messages.length);
this.assertEquals(1, WebInspector.console.messages[0].totalRepeatCount);
this.releaseControl();
}

this.takeControl();
};


TestSuite.prototype.testReattachAfterCrash = function()
{
this.evaluateInConsole_("1+1;", this.releaseControl.bind(this));
this.takeControl();
};


TestSuite.prototype.testSharedWorker = function()
{
function didEvaluateInConsole(resultText) {
this.assertEquals("2011", resultText);
this.releaseControl();
}
this.evaluateInConsole_("globalVar", didEvaluateInConsole.bind(this));
this.takeControl();
};


TestSuite.prototype.testPauseInSharedWorkerInitialization = function()
{
if (WebInspector.debuggerModel.debuggerPausedDetails)
return;
this._waitForScriptPause(this.releaseControl.bind(this));
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.inspectorView.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.consoleView.prompt.text = code;
WebInspector.consoleView.promptElement.dispatchEvent(TestSuite.createKeyEvent("Enter"));

this.addSniffer(WebInspector.ConsoleView.prototype, "_appendConsoleMessage",
function(commandResult) {
callback(commandResult.toMessageElement().textContent);
});
};



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(callback)
{
function pauseListener(event) {
WebInspector.debuggerModel.removeEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, pauseListener, this);
callback();
}
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerPaused, pauseListener, this);
};



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 oldLoadCompleted = InspectorFrontendAPI.loadCompleted;
InspectorFrontendAPI.loadCompleted = function()
{
oldLoadCompleted.call(InspectorFrontendAPI);
runTests();
}

})();

}

