




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.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.trimEnd = function(maxLength)
{
if (this.length <= maxLength)
return this;
return this.substr(0, maxLength - 1) + "\u2026";
}

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

String.prototype.startsWith = function(substring)
{
return !this.lastIndexOf(substring, 0);
}

String.prototype.endsWith = function(substring)
{
return this.indexOf(substring, this.length - substring.length) !== -1;
}

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

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

(function() {
var partition = {

value: function(comparator, left, right, pivotIndex)
{
function swap(array, i1, i2)
{
var temp = array[i1];
array[i1] = array[i2];
array[i2] = temp;
}

var pivotValue = this[pivotIndex];
swap(this, right, pivotIndex);
var storeIndex = left;
for (var i = left; i < right; ++i) {
if (comparator(this[i], pivotValue) < 0) {
swap(this, storeIndex, i);
++storeIndex;
}
}
swap(this, right, storeIndex);
return storeIndex;
}
};
Object.defineProperty(Array.prototype, "partition", partition);
Object.defineProperty(Uint32Array.prototype, "partition", partition);

var sortRange = {

value: function(comparator, leftBound, rightBound, k)
{
function quickSortFirstK(array, comparator, left, right, k)
{
if (right <= left)
return;
var pivotIndex = Math.floor(Math.random() * (right - left)) + left;
var pivotNewIndex = array.partition(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;
}
}
Object.defineProperty(Array.prototype, "sortRange", sortRange);
Object.defineProperty(Uint32Array.prototype, "sortRange", sortRange);
})();

Object.defineProperty(Array.prototype, "qselect",
{

value: function(k, comparator)
{
if (k < 0 || k >= this.length)
return;
if (!comparator)
comparator = function(a, b) { return a - b; }

var low = 0;
var high = this.length - 1;
for (;;) {
var pivotPosition = this.partition(comparator, low, high, Math.floor((high + low) / 2));
if (pivotPosition === k)
return this[k];
else if (pivotPosition > k)
high = pivotPosition - 1;
else
low = pivotPosition + 1;
}
}
});


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

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

function isDigit(c)
{
return !!/[0-9]/.exec(c);
}

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

if (isDigit(format[index])) {

var number = parseInt(format.substring(index), 10);
while (isDigit(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 (isDigit(format[index]))
++index;
}

if (!(format[index] in formatters)) {
addStringToken(format.substring(precentIndex, index + 1));
++index;
continue;
}

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


var Map = function()
{
this._map = {};
}

Map._lastObjectIdentifier = 0;

Map.prototype = {

put: function(key, value)
{
var objectIdentifier = key.__identifier;
if (!objectIdentifier) {
objectIdentifier = ++Map._lastObjectIdentifier;
key.__identifier = objectIdentifier;
}
this._map[objectIdentifier] = value;
},


remove: function(key)
{
var result = this._map[key.__identifier];
delete this._map[key.__identifier];
return result;
},

values: function()
{
var result = [];
for (var objectIdentifier in this._map)
result.push(this._map[objectIdentifier]);
return result;
},


get: function(key)
{
return this._map[key.__identifier];
},

clear: function()
{
this._map = {};
}
}






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.isSelfOrDescendant(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()
{
return this.totalOffset().left;
}


Element.prototype.totalOffsetTop = function()
{
return this.totalOffset().top;

}

Element.prototype.totalOffset = function()
{
var totalLeft = 0;
var totalTop = 0;

for (var element = this; element; element = element.offsetParent) {
totalLeft += element.offsetLeft;
totalTop += element.offsetTop;
if (this !== element) {
totalLeft += element.clientLeft - element.scrollLeft;
totalTop += element.clientTop - element.scrollTop;
}
}

return { left: totalLeft, top: totalTop };
}

Element.prototype.scrollOffset = function()
{
var curLeft = 0;
var curTop = 0;
for (var element = this; element; element = element.scrollParent) {
curLeft += element.scrollLeft;
curTop += element.scrollTop;
}
return { left: curLeft, top: curTop };
}


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 = Math.min(this.offsetWidth, window.innerWidth - anchorBox.x);
anchorBox.height = Math.min(this.offsetHeight, window.innerHeight - anchorBox.y);

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


Event.prototype.consume = function(preventDefault)
{
this.stopImmediatePropagation();
if (preventDefault)
this.preventDefault();
this.handled = true;
}

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

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.isSelfOrAncestor = function(node)
{
return !!node && (node === this || this.isAncestor(node));
}

Node.prototype.isSelfOrDescendant = function(node)
{
return !!node && (node === this || this.isDescendant(node));
}

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

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

function isEnterKey(event) {

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

function consumeEvent(e)
{
e.consume();
}






function TreeOutline(listNode, nonFocusable)
{

this.children = [];
this.selectedTreeElement = null;
this._childrenListNode = listNode;
this.childrenListElement = this._childrenListNode;
this._childrenListNode.removeChildren();
this.expandTreeElementsWhenArrowing = false;
this.root = true;
this.hasChildren = false;
this.expanded = true;
this.selected = false;
this.treeOutline = this;
this.comparator = null;
this.searchable = false;
this.searchInputElement = null;

this.setFocusable(!nonFocusable);
this._childrenListNode.addEventListener("keydown", this._treeKeyDown.bind(this), true);
this._childrenListNode.addEventListener("keypress", this._treeKeyPress.bind(this), true);

this._treeElementsMap = new Map();
this._expandedStateMap = new Map();
}

TreeOutline.prototype.setFocusable = function(focusable)
{
if (focusable)
this._childrenListNode.setAttribute("tabIndex", 0);
else
this._childrenListNode.removeAttribute("tabIndex");
}

TreeOutline.prototype.appendChild = function(child)
{
var insertionIndex;
if (this.treeOutline.comparator)
insertionIndex = insertionIndexForObjectInListSortedByFunction(child, this.children, this.treeOutline.comparator);
else
insertionIndex = this.children.length;
this.insertChild(child, insertionIndex);
}

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 && typeof(child.treeOutline._expandedStateMap.get(child.representedObject)) !== "undefined")
child.expanded = child.treeOutline._expandedStateMap.get(child.representedObject);

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._rememberTreeElement = function(element)
{
if (!this._treeElementsMap.get(element.representedObject))
this._treeElementsMap.put(element.representedObject, []);


var elements = this._treeElementsMap.get(element.representedObject);
if (elements.indexOf(element) !== -1)
return;


elements.push(element);
}

TreeOutline.prototype._forgetTreeElement = function(element)
{
if (this._treeElementsMap.get(element.representedObject))
this._treeElementsMap.get(element.representedObject).remove(element, true);
}

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

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

var elements = this._treeElementsMap.get(representedObject);
if (elements && elements.length)
return elements[0];
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._treeKeyPress = function(event)
{
if (!this.searchable || WebInspector.isBeingEdited(this._childrenListNode))
return;

var searchText = String.fromCharCode(event.charCode);

if (searchText.trim() !== searchText)
return;

this._startSearch(searchText);
event.consume(true);
}

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();
} else if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Space.code) {
if (this.selectedTreeElement.onspace)
handled = this.selectedTreeElement.onspace();
}

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

if (handled)
event.consume(true);
}

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

}


TreeOutline.prototype._startSearch = function(searchText)
{
if (!this.searchInputElement || !this.searchable)
return;

this._searching = true;

if (this.searchStarted)
this.searchStarted();

this.searchInputElement.value = searchText;

function focusSearchInput()
{
this.searchInputElement.focus();
}
window.setTimeout(focusSearchInput.bind(this), 0);
this._searchTextChanged();
this._boundSearchTextChanged = this._searchTextChanged.bind(this);
this.searchInputElement.addEventListener("paste", this._boundSearchTextChanged);
this.searchInputElement.addEventListener("cut", this._boundSearchTextChanged);
this.searchInputElement.addEventListener("keypress", this._boundSearchTextChanged);
this._boundSearchInputKeyDown = this._searchInputKeyDown.bind(this);
this.searchInputElement.addEventListener("keydown", this._boundSearchInputKeyDown);
this._boundSearchInputBlur = this._searchInputBlur.bind(this);
this.searchInputElement.addEventListener("blur", this._boundSearchInputBlur);
}

TreeOutline.prototype._searchTextChanged = function()
{
function updateSearch()
{
var nextSelectedElement = this._nextSearchMatch(this.searchInputElement.value, this.selectedTreeElement, false);
if (!nextSelectedElement)
nextSelectedElement = this._nextSearchMatch(this.searchInputElement.value, this.children[0], false);
this._showSearchMatchElement(nextSelectedElement);
}

window.setTimeout(updateSearch.bind(this), 0);
}

TreeOutline.prototype._showSearchMatchElement = function(treeElement)
{
this._currentSearchMatchElement = treeElement;
if (treeElement) {
this._childrenListNode.classList.add("search-match-found");
this._childrenListNode.classList.remove("search-match-not-found");
treeElement.revealAndSelect(true);
} else {
this._childrenListNode.classList.remove("search-match-found");
this._childrenListNode.classList.add("search-match-not-found");
}
}

TreeOutline.prototype._searchInputKeyDown = function(event)
{
if (event.shiftKey || event.metaKey || event.ctrlKey || event.altKey)
return;

var handled = false;
var nextSelectedElement;
if (event.keyIdentifier === "Down") {
nextSelectedElement = this._nextSearchMatch(this.searchInputElement.value, this.selectedTreeElement, true);
handled = true;
} else if (event.keyIdentifier === "Up") {
nextSelectedElement = this._previousSearchMatch(this.searchInputElement.value, this.selectedTreeElement);
handled = true;
} else if (event.keyCode === 27  ) {
this._searchFinished();
handled = true;
} else if (isEnterKey(event)) {
var lastSearchMatchElement = this._currentSearchMatchElement;
this._searchFinished();
if (lastSearchMatchElement && lastSearchMatchElement.onenter)
lastSearchMatchElement.onenter();
handled = true;
}

if (nextSelectedElement)
this._showSearchMatchElement(nextSelectedElement);

if (handled)
event.consume(true);
else
window.setTimeout(this._boundSearchTextChanged, 0); 
}


TreeOutline.prototype._nextSearchMatch = function(searchText, startTreeElement, skipStartTreeElement)
{
var currentTreeElement = startTreeElement;
var skipCurrentTreeElement = skipStartTreeElement;
while (currentTreeElement && (skipCurrentTreeElement || !currentTreeElement.matchesSearchText || !currentTreeElement.matchesSearchText(searchText))) {
currentTreeElement = currentTreeElement.traverseNextTreeElement(true, null, true);
skipCurrentTreeElement = false;
}

return currentTreeElement;
}


TreeOutline.prototype._previousSearchMatch = function(searchText, startTreeElement)
{
var currentTreeElement = startTreeElement;
var skipCurrentTreeElement = true;
while (currentTreeElement && (skipCurrentTreeElement || !currentTreeElement.matchesSearchText || !currentTreeElement.matchesSearchText(searchText))) {
currentTreeElement = currentTreeElement.traversePreviousTreeElement(true, true);
skipCurrentTreeElement = false;
}

return currentTreeElement;
}

TreeOutline.prototype._searchInputBlur = function(event)
{
this._searchFinished();
}

TreeOutline.prototype._searchFinished = function()
{
if (!this._searching)
return;

delete this._searching;
this._childrenListNode.classList.remove("search-match-found");
this._childrenListNode.classList.remove("search-match-not-found");
delete this._currentSearchMatchElement;

this.searchInputElement.value = "";
this.searchInputElement.removeEventListener("paste", this._boundSearchTextChanged);
this.searchInputElement.removeEventListener("cut", this._boundSearchTextChanged);
delete this._boundSearchTextChanged;

this.searchInputElement.removeEventListener("keydown", this._boundSearchInputKeyDown);
delete this._boundSearchInputKeyDown;

this.searchInputElement.removeEventListener("blur", this._boundSearchInputBlur);
delete this._boundSearchInputBlur;

if (this.searchFinished)
this.searchFinished();

this.treeOutline._childrenListNode.focus();
}

TreeOutline.prototype.stopSearch = function()
{
this._searchFinished();
}


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

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._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.consume();
}

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

if (element.treeElement.ondblclick) {
var handled = element.treeElement.ondblclick.call(element.treeElement, event);
if (handled)
return;
} 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._expandedStateMap.put(this.representedObject, 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._expandedStateMap.put(this.representedObject, 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)
{
if (this.select(false, true))
event.consume(true);
}


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

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

this.selected = true;

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


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

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


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.timeline = new WebInspector.TimelinePanel();
this.panels.profiles = new WebInspector.ProfilesPanel();
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("styles") === -1 && WebInspector.experimentsSettings.showStylesPanel.isEnabled())
this.panels.styles = new WebInspector.StylesPanel();
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;
WebInspector.updateDockToggleButton();

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

closeDrawerView: function()
{

if (!this._consoleWasShown)
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;

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

if (x)
document.body.removeStyleClass("detached");
else
document.body.addStyleClass("detached");

this._setCompactMode(x && !WebInspector.settings.dockToRight.get());
},

isCompactMode: function()
{
return this.attached && !WebInspector.settings.dockToRight.get();
},

_setCompactMode: function(x)
{
var body = document.body;
if (x)
body.addStyleClass("compact");
else
body.removeStyleClass("compact");



if (WebInspector.toolbar)
WebInspector.toolbar.compact = 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;
},


networkRequestById: function(requestId)
{
return this.panels.network.requestById(requestId);
},

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

_zoomIn: function()
{
++this._zoomLevel;
this._requestZoom();
},

_zoomOut: function()
{
--this._zoomLevel;
this._requestZoom();
},

_resetZoom: function()
{
this._zoomLevel = 0;
this._requestZoom();
},

_requestZoom: function()
{
WebInspector.settings.zoomLevel.set(this._zoomLevel);
InspectorFrontendHost.setZoomFactor(Math.pow(1.2, this._zoomLevel));
}
}

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

var ws;
if ("ws" in WebInspector.queryParamsObject)
ws = "ws://" + WebInspector.queryParamsObject.ws;
else if ("page" in WebInspector.queryParamsObject) {
var page = WebInspector.queryParamsObject.page;
var host = "host" in WebInspector.queryParamsObject ? WebInspector.queryParamsObject.host : window.location.host;
ws = "ws://" + host + "/devtools/page/" + page;
}

if (ws) {
WebInspector.socket = new WebSocket(ws);
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", null));
PageAgent.canOverrideDeviceMetrics(WebInspector._initializeCapability.bind(WebInspector, "canOverrideDeviceMetrics", 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.snippetsModel = new WebInspector.SnippetsModel();
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();
this.userAgentSupport = new WebInspector.UserAgentSupport();
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._zoomLevel = WebInspector.settings.zoomLevel.get();
if (this._zoomLevel)
this._requestZoom();

WebInspector.CSSCompletions.requestCSSNameCompletions();
this._createPanels();
this._createGlobalStatusBarItems();

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

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

if (WebInspector.settings.showPaintRects.get())
PageAgent.setShowPaintRects(true);

if (WebInspector.settings.javaScriptDisabled.get())
PageAgent.setScriptExecutionDisabled(true);

this.domAgent._emulateTouchEventsChanged();

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

WebInspector._installDockToRight = function()
{

WebInspector.settings.dockToRight.set(WebInspector.queryParamsObject.dockSide === "right");

if (WebInspector.settings.dockToRight.get())
document.body.addStyleClass("dock-to-right");

if (WebInspector.attached)
WebInspector._setCompactMode(!WebInspector.settings.dockToRight.get());

WebInspector.settings.dockToRight.addChangeListener(listener.bind(this));

function listener(event)
{
var value = WebInspector.settings.dockToRight.get();
if (value) {
InspectorFrontendHost.requestSetDockSide("right");
document.body.addStyleClass("dock-to-right");
} else {
InspectorFrontendHost.requestSetDockSide("bottom");
document.body.removeStyleClass("dock-to-right");
}
if (WebInspector.attached)
WebInspector._setCompactMode(!value);
}
}

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.updateDockToggleButton();
}

WebInspector.setDockingUnavailable = function(unavailable)
{
this._isDockingUnavailable = unavailable;
WebInspector.updateDockToggleButton();
}

WebInspector.updateDockToggleButton = function()
{
if (!this._dockToggleButton)
return;
this._dockToggleButton.disabled = this.attached ? false : this._isDockingUnavailable;
}

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.consume(true);

function followLink()
{
if (WebInspector.isBeingEdited(event.target) || 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.showPanel("resources");
WebInspector.panels.resources.showResource(resource);
} else
InspectorFrontendHost.openInNewTab(resourceURL);
}

WebInspector.openRequestInNetworkPanel = function(request)
{
WebInspector.showPanel("network");
WebInspector.panels.network.revealAndHighlightRequest(request);
}

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("Go to the panel to the left/right"));

var keys = [
shortcut.shortcutToString("[", shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Alt),
shortcut.shortcutToString("]", shortcut.Modifiers.CtrlOrMeta | shortcut.Modifiers.Alt)
];
section.addRelatedKeys(keys, WebInspector.UIString("Go back/forward in panel history"));

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)
{
const helpKey = WebInspector.isMac() ? "U+003F" : "U+00BF"; 

if (event.keyIdentifier === "F1" ||
(event.keyIdentifier === helpKey && event.shiftKey && (!WebInspector.isBeingEdited(event.target) || event.metaKey))) {
WebInspector.shortcutsScreen.show();
event.consume(true);
return;
}

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

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

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

var isMac = WebInspector.isMac();
switch (event.keyIdentifier) {
case "U+0052": 
if ((event.metaKey && isMac) || (event.ctrlKey && !isMac)) {
PageAgent.reload(event.shiftKey);
event.consume(true);
}
break;
case "F5":
if (!isMac) {
PageAgent.reload(event.ctrlKey || event.shiftKey);
event.consume(true);
}
break;
}

var isValidZoomShortcut = WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) &&
!event.shiftKey &&
!event.altKey &&
!InspectorFrontendHost.isStub;
switch (event.keyCode) {
case 107: 
case 187: 
if (isValidZoomShortcut) {
WebInspector._zoomIn();
event.consume(true);
}
break;
case 109: 
case 189: 
if (isValidZoomShortcut) {
WebInspector._zoomOut();
event.consume(true);
}
break;
case 48: 
if (isValidZoomShortcut) {
WebInspector._resetZoom();
event.consume(true);
}
break;
}
}

WebInspector.postDocumentKeyDown = function(event)
{
if (event.handled)
return;

if (event.keyIdentifier === "U+001B") { 

if (!this._toggleConsoleButton.toggled && WebInspector.drawer.visible)
this.closeDrawerView();
else
this._toggleConsoleButtonClicked();
}
}

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 || !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, showResultOnly)
{
this.showConsole();
this.consoleView.evaluateUsingTextPrompt(expression, showResultOnly);
}

WebInspector.addMainEventListeners = function(doc)
{
doc.addEventListener("keydown", this.documentKeyDown.bind(this), true);
doc.addEventListener("keydown", this.postDocumentKeyDown.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.save = function(url, content, forceSaveAs)
{

var savedURLs = WebInspector.settings.savedURLs.get();
delete savedURLs[url];
WebInspector.settings.savedURLs.set(savedURLs);

InspectorFrontendHost.save(url, content, forceSaveAs);
}

WebInspector.savedURL = function(url)
{
var savedURLs = WebInspector.settings.savedURLs.get();
savedURLs[url] = true;
WebInspector.settings.savedURLs.set(savedURLs);
}

WebInspector.isURLSaved = function(url)
{
var savedURLs = WebInspector.settings.savedURLs.get();
return savedURLs[url];
}





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)
{
if (element.hasStyleClass("text-prompt") || element.nodeName === "INPUT")
return true;

if (!WebInspector.__editingCount)
return false;

while (element) {
if (element.__editing)
return true;
element = element.parentElement;
}
return false;
}

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

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.getAttribute("tabIndex");
if (typeof oldTabIndex !== "number" || oldTabIndex < 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");

if (typeof oldTabIndex !== "number")
element.removeAttribute("tabIndex");
else
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);

WebInspector.restoreFocusFromElement(element);
}


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.consume(true);
} else if (result === "cancel") {
editingCancelled.call(element);
event.consume(true);
} else if (result && result.startsWith("move-")) {
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);
}

Number.withThousandsSeparator = function(num)
{
var str = num + "";
var re = /(\d+)(\d{3})/;
while (str.match(re))
str = str.replace(re, "$1\u2009$2"); 
return str;
}

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._textInputTypes = ["text", "search", "tel", "url", "email", "password"].keySet(); 
WebInspector._isTextEditingElement = function(element)
{
if (element instanceof HTMLInputElement)
return element.type in WebInspector._textInputTypes;

if (element instanceof HTMLTextAreaElement)
return true;

return false;
}

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 (!WebInspector._isTextEditingElement(WebInspector._currentFocusElement) && 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.restoreFocusFromElement = function(element)
{
if (element && element.isSelfOrAncestor(WebInspector.currentFocusElement()))
WebInspector.setCurrentFocusElement(WebInspector.previousFocusElement());
}

WebInspector.setToolbarColors = function(backgroundColor, color)
{
if (!WebInspector._themeStyleElement) {
WebInspector._themeStyleElement = document.createElement("style");
document.head.appendChild(WebInspector._themeStyleElement);
}
WebInspector._themeStyleElement.textContent =
"#toolbar {\
             background-image: none !important;\
             background-color: " + backgroundColor + " !important;\
         }\
         \
         .toolbar-label {\
             color: " + color + " !important;\
             text-shadow: none;\
         }";
}

WebInspector.resetToolbarColors = function()
{
if (WebInspector._themeStyleElement)
WebInspector._themeStyleElement.textContent = "";
}


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


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


WebInspector.highlightRangesWithStyleClass = function(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;
}

WebInspector.applyDomChanges = function(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;
}
}
}

WebInspector.revertDomChanges = function(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;
}
}
}


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;


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

;(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) {
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 ? messageObject.error.message : null);
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.registerInspectorDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Inspector");
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.registerCommand("Inspector.enable", [], []);
InspectorBackend.registerCommand("Inspector.disable", [], []);


InspectorBackend.registerMemoryDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Memory");
InspectorBackend.registerCommand("Memory.getDOMNodeCount", [], ["domGroups", "strings"]);


InspectorBackend.registerPageDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Page");
InspectorBackend.registerEvent("Page.domContentEventFired", ["timestamp"]);
InspectorBackend.registerEvent("Page.loadEventFired", ["timestamp"]);
InspectorBackend.registerEvent("Page.frameNavigated", ["frame"]);
InspectorBackend.registerEvent("Page.frameDetached", ["frameId"]);
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.navigate", [{"name": "url", "type": "string", "optional": false}], []);
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("Page.setDocumentContent", [{"name": "frameId", "type": "string", "optional": false}, {"name": "html", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("Page.canOverrideDeviceMetrics", [], ["result"]);
InspectorBackend.registerCommand("Page.setDeviceMetricsOverride", [{"name": "width", "type": "number", "optional": false}, {"name": "height", "type": "number", "optional": false}, {"name": "fontScaleFactor", "type": "number", "optional": false}, {"name": "fitWindow", "type": "boolean", "optional": false}], []);
InspectorBackend.registerCommand("Page.setShowPaintRects", [{"name": "result", "type": "boolean", "optional": false}], []);
InspectorBackend.registerCommand("Page.getScriptExecutionStatus", [], ["result"]);
InspectorBackend.registerCommand("Page.setScriptExecutionDisabled", [{"name": "value", "type": "boolean", "optional": false}], []);


InspectorBackend.registerCommand("Runtime.evaluate", [{"name": "expression", "type": "string", "optional": false}, {"name": "objectGroup", "type": "string", "optional": true}, {"name": "includeCommandLineAPI", "type": "boolean", "optional": true}, {"name": "doNotPauseOnExceptionsAndMuteConsole", "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": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "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.registerConsoleDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Console");
InspectorBackend.registerEvent("Console.messageAdded", ["message"]);
InspectorBackend.registerEvent("Console.messageRepeatCountUpdated", ["count"]);
InspectorBackend.registerEvent("Console.messagesCleared", []);
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("Console.addInspectedHeapObject", [{"name": "heapObjectId", "type": "number", "optional": false}], []);


InspectorBackend.registerNetworkDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Network");
InspectorBackend.registerEvent("Network.requestWillBeSent", ["requestId", "frameId", "loaderId", "documentURL", "request", "timestamp", "initiator", "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("Network.webSocketFrameReceived", ["requestId", "timestamp", "response"]);
InspectorBackend.registerEvent("Network.webSocketFrameError", ["requestId", "timestamp", "errorMessage"]);
InspectorBackend.registerEvent("Network.webSocketFrameSent", ["requestId", "timestamp", "response"]);
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.registerDatabaseDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Database");
InspectorBackend.registerEvent("Database.addDatabase", ["database"]);
InspectorBackend.registerEvent("Database.sqlTransactionSucceeded", ["transactionId", "columnNames", "values"]);
InspectorBackend.registerEvent("Database.sqlTransactionFailed", ["transactionId", "sqlError"]);
InspectorBackend.registerCommand("Database.enable", [], []);
InspectorBackend.registerCommand("Database.disable", [], []);
InspectorBackend.registerCommand("Database.getDatabaseTableNames", [{"name": "databaseId", "type": "string", "optional": false}], ["tableNames"]);
InspectorBackend.registerCommand("Database.executeSQL", [{"name": "databaseId", "type": "string", "optional": false}, {"name": "query", "type": "string", "optional": false}], ["success", "transactionId"]);


InspectorBackend.registerIndexedDBDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "IndexedDB");
InspectorBackend.registerEvent("IndexedDB.databaseNamesLoaded", ["requestId", "securityOriginWithDatabaseNames"]);
InspectorBackend.registerEvent("IndexedDB.databaseLoaded", ["requestId", "databaseWithObjectStores"]);
InspectorBackend.registerEvent("IndexedDB.objectStoreDataLoaded", ["requestId", "objectStoreDataEntries", "hasMore"]);
InspectorBackend.registerEvent("IndexedDB.indexDataLoaded", ["requestId", "indexDataEntries", "hasMore"]);
InspectorBackend.registerCommand("IndexedDB.enable", [], []);
InspectorBackend.registerCommand("IndexedDB.disable", [], []);
InspectorBackend.registerCommand("IndexedDB.requestDatabaseNamesForFrame", [{"name": "requestId", "type": "number", "optional": false}, {"name": "frameId", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("IndexedDB.requestDatabase", [{"name": "requestId", "type": "number", "optional": false}, {"name": "frameId", "type": "string", "optional": false}, {"name": "databaseName", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("IndexedDB.requestData", [{"name": "requestId", "type": "number", "optional": false}, {"name": "frameId", "type": "string", "optional": false}, {"name": "databaseName", "type": "string", "optional": false}, {"name": "objectStoreName", "type": "string", "optional": false}, {"name": "indexName", "type": "string", "optional": false}, {"name": "skipCount", "type": "number", "optional": false}, {"name": "pageSize", "type": "number", "optional": false}, {"name": "keyRange", "type": "object", "optional": true}], []);


InspectorBackend.registerDOMStorageDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "DOMStorage");
InspectorBackend.registerEvent("DOMStorage.addDOMStorage", ["storage"]);
InspectorBackend.registerEvent("DOMStorage.updateDOMStorage", ["storageId"]);
InspectorBackend.registerCommand("DOMStorage.enable", [], []);
InspectorBackend.registerCommand("DOMStorage.disable", [], []);
InspectorBackend.registerCommand("DOMStorage.getDOMStorageEntries", [{"name": "storageId", "type": "string", "optional": false}], ["entries"]);
InspectorBackend.registerCommand("DOMStorage.setDOMStorageItem", [{"name": "storageId", "type": "string", "optional": false}, {"name": "key", "type": "string", "optional": false}, {"name": "value", "type": "string", "optional": false}], ["success"]);
InspectorBackend.registerCommand("DOMStorage.removeDOMStorageItem", [{"name": "storageId", "type": "string", "optional": false}, {"name": "key", "type": "string", "optional": false}], ["success"]);


InspectorBackend.registerApplicationCacheDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "ApplicationCache");
InspectorBackend.registerEvent("ApplicationCache.applicationCacheStatusUpdated", ["frameId", "manifestURL", "status"]);
InspectorBackend.registerEvent("ApplicationCache.networkStateUpdated", ["isNowOnline"]);
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.registerFileSystemDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "FileSystem");
InspectorBackend.registerCommand("FileSystem.enable", [], []);
InspectorBackend.registerCommand("FileSystem.disable", [], []);


InspectorBackend.registerDOMDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "DOM");
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("DOM.shadowRootPushed", ["hostId", "root"]);
InspectorBackend.registerEvent("DOM.shadowRootPopped", ["hostId", "rootId"]);
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.getOuterHTML", [{"name": "nodeId", "type": "number", "optional": false}], ["outerHTML"]);
InspectorBackend.registerCommand("DOM.setOuterHTML", [{"name": "nodeId", "type": "number", "optional": false}, {"name": "outerHTML", "type": "string", "optional": false}], []);
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("DOM.setTouchEmulationEnabled", [{"name": "enabled", "type": "boolean", "optional": false}], []);
InspectorBackend.registerCommand("DOM.undo", [], []);
InspectorBackend.registerCommand("DOM.redo", [], []);
InspectorBackend.registerCommand("DOM.markUndoableState", [], []);


InspectorBackend.registerCSSDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "CSS");
InspectorBackend.registerEvent("CSS.mediaQueryResultChanged", []);
InspectorBackend.registerEvent("CSS.styleSheetChanged", ["styleSheetId"]);
InspectorBackend.registerCommand("CSS.enable", [], []);
InspectorBackend.registerCommand("CSS.disable", [], []);
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", "attributesStyle"]);
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("CSS.startSelectorProfiler", [], []);
InspectorBackend.registerCommand("CSS.stopSelectorProfiler", [], ["profile"]);


InspectorBackend.registerTimelineDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Timeline");
InspectorBackend.registerEvent("Timeline.eventRecorded", ["record"]);
InspectorBackend.registerCommand("Timeline.start", [{"name": "maxCallStackDepth", "type": "number", "optional": true}], []);
InspectorBackend.registerCommand("Timeline.stop", [], []);
InspectorBackend.registerCommand("Timeline.setIncludeMemoryDetails", [{"name": "enabled", "type": "boolean", "optional": false}], []);


InspectorBackend.registerDebuggerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Debugger");
InspectorBackend.registerEvent("Debugger.globalObjectCleared", []);
InspectorBackend.registerEvent("Debugger.scriptParsed", ["scriptId", "url", "startLine", "startColumn", "endLine", "endColumn", "isContentScript", "sourceMapURL"]);
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.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.getFunctionDetails", [{"name": "functionId", "type": "string", "optional": false}], ["details"]);
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": "doNotPauseOnExceptionsAndMuteConsole", "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.setInstrumentationBreakpoint", [{"name": "eventName", "type": "string", "optional": false}], []);
InspectorBackend.registerCommand("DOMDebugger.removeInstrumentationBreakpoint", [{"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.registerProfilerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Profiler");
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.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}, {"name": "objectGroup", "type": "string", "optional": true}], ["result"]);


InspectorBackend.registerWorkerDispatcher = InspectorBackend.registerDomainDispatcher.bind(InspectorBackend, "Worker");
InspectorBackend.registerEvent("Worker.workerCreated", ["workerId", "url", "inspectorConnected"]);
InspectorBackend.registerEvent("Worker.workerTerminated", ["workerId"]);
InspectorBackend.registerEvent("Worker.dispatchMessageFromWorker", ["workerId", "message"]);
InspectorBackend.registerEvent("Worker.disconnectedFromWorker", []);
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}], []);







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

showMainResourceForFrame: function(frameId)
{

},

showResources: function()
{
WebInspector.inspectorView.setCurrentPanel(WebInspector.panels.resources);
},

setDockingUnavailable: function(unavailable)
{
WebInspector.setDockingUnavailable(unavailable);
},

enterInspectElementMode: function()
{
WebInspector.toggleSearchingForNode();
},

savedURL: function(url)
{
WebInspector.savedURL(url);
},

setToolbarColors: function(backgroundColor, color)
{
WebInspector.setToolbarColors(backgroundColor, color);
},

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


consume: function(preventDefault)
{
this.stopPropagation();
if (preventDefault)
this.preventDefault();
}
}

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",
showHeapSnapshotObjectsHiddenProperties: false,
showDockToRight: false
}

var Capabilities = {
samplingCPUProfiler: false,
debuggerCausesRecompilation: true,
profilerCausesRecompilation: true,
nativeInstrumentationEnabled: false,
heapProfilerPresent: false,
canOverrideDeviceMetrics: 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.sourceMapsEnabled = this.createSetting("sourceMapsEnabled", false);
this.cacheDisabled = this.createSetting("cacheDisabled", false);
this.overrideUserAgent = this.createSetting("overrideUserAgent", "");
this.userAgent = this.createSetting("userAgent", "");
this.deviceMetrics = this.createSetting("deviceMetrics", "");
this.deviceFitWindow = this.createSetting("deviceFitWindow", false);
this.showScriptFolders = this.createSetting("showScriptFolders", true);
this.dockToRight = this.createSetting("dockToRight", false);
this.emulateTouchEvents = this.createSetting("emulateTouchEvents", false);
this.showPaintRects = this.createSetting("showPaintRects", false);
this.zoomLevel = this.createSetting("zoomLevel", 0);
this.savedURLs = this.createSetting("savedURLs", {});
this.javaScriptDisabled = this.createSetting("javaScriptDisabled", false);



if (this.breakpoints.get().length > 500000)
this.breakpoints.set([]);
}

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()
{
if (typeof this._value !== "undefined")
return this._value;

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

set: function(value)
{
this._value = 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.ExperimentsSettings = function()
{
this._setting = WebInspector.settings.createSetting("experiments", {});
this._experiments = [];
this._enabledForTest = {};


this.timelineVerticalOverview = this._createExperiment("timelineStartAtZero", "Enable vertical overview mode in the Timeline panel");
this.showShadowDOM = this._createExperiment("showShadowDOM", "Show shadow DOM");
this.snippetsSupport = this._createExperiment("snippetsSupport", "Snippets support");
this.showStylesPanel = this._createExperiment("stylesPanel", "Show styles panel");

this._cleanUpSetting();
}

WebInspector.ExperimentsSettings.prototype = {

get experiments()
{
return this._experiments.slice();
},


get experimentsEnabled()
{
return "experiments" in WebInspector.queryParamsObject;
},


_createExperiment: function(experimentName, experimentTitle)
{
var experiment = new WebInspector.Experiment(this, experimentName, experimentTitle);
this._experiments.push(experiment);
return experiment;
},


isEnabled: function(experimentName)
{
if (this._enabledForTest[experimentName])
return true;

if (!this.experimentsEnabled)
return false;

var experimentsSetting = this._setting.get();
return experimentsSetting[experimentName];
},


setEnabled: function(experimentName, enabled)
{
var experimentsSetting = this._setting.get();
experimentsSetting[experimentName] = enabled;
this._setting.set(experimentsSetting);
},


_enableForTest: function(experimentName)
{
this._enabledForTest[experimentName] = true;
},

_cleanUpSetting: function()
{
var experimentsSetting = this._setting.get();
var cleanedUpExperimentSetting = {};
for (var i = 0; i < this._experiments.length; ++i) {
var experimentName = this._experiments[i].name;
if (experimentsSetting[experimentName])
cleanedUpExperimentSetting[experimentName] = true;
}
this._setting.set(cleanedUpExperimentSetting);
}
}


WebInspector.Experiment = function(experimentsSettings, name, title)
{
this._name = name;
this._title = title;
this._experimentsSettings = experimentsSettings;
}

WebInspector.Experiment.prototype = {

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


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


isEnabled: function()
{
return this._experimentsSettings.isEnabled(this._name);
},


setEnabled: function(enabled)
{
return this._experimentsSettings.setEnabled(this._name, enabled);
},

enableForTest: function()
{
this._experimentsSettings._enableForTest(this._name);
}
}

WebInspector.settings = new WebInspector.Settings();
WebInspector.experimentsSettings = new WebInspector.ExperimentsSettings();





if (!window.InspectorFrontendHost) {


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

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

requestAttachWindow: function()
{
},

requestDetachWindow: function()
{
},

requestSetDockSide: function()
{
},

setAttachedWindowHeight: function(height)
{
},

moveWindowBy: function(x, y)
{
},

setInjectedScriptForOrigin: function(origin, script)
{
},

loaded: function()
{
},

localizedStringsURL: function()
{
return undefined;
},

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

inspectedURLChanged: function(url)
{
document.title = WebInspector.UIString(Preferences.applicationTitle, url);
},

copyText: function()
{
},

openInNewTab: function(url)
{
window.open(url, "_blank");
},

canSave: function()
{
return true;
},

save: function(url, content, forceSaveAs)
{
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);
},

sendMessageToBackend: function(message)
{
},

recordActionTaken: function(actionCode)
{
},

recordPanelShown: function(panelCode)
{
},

recordSettingChanged: function(settingCode)
{
},

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

setZoomFactor: function(zoom)
{
}
}

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


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.consume(true);
},

_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.consume(true);
},

_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.consume(true);
},

_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.consume(true);
}
}
}

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: "<Left>" },           
Up: { code: 38, name: "<Up>" },             
Right: { code: 39, name: "<Right>" },          
Down: { code: 40, name: "<Down>" },           
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._boundSelectStart, 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);
this._element.removeStyleClass("text-prompt");
this._element.removeEventListener("keydown", this._boundOnKeyDown, false);
this._element.removeEventListener("selectstart", this._boundSelectStart, false);
delete this._proxyElement;
WebInspector.restoreFocusFromElement(this._element);
},

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

_removeSuggestionAids: function()
{
this.clearAutoComplete();
this.hideSuggestBox();
},

_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.consume(true);

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;
}
delete this._waitingForCompletions;

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) {
this.hideSuggestBox();
return;
}

var wordPrefixRange = selectionRange.startContainer.rangeOfWord(selectionRange.startOffset, this._completionStopCharacters, this._element, "backward");
this._waitingForCompletions = true;
this._loadCompletions(this, 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;
},


_buildCommonPrefix: function(completions, wordPrefixLength)
{
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;
}
}
}
return commonPrefix;
},


_completionsReady: function(selection, auto, originalWordPrefixRange, reverse, completions)
{
if (!this._waitingForCompletions || !completions || !completions.length) {
this.hideSuggestBox();
return;
}
delete this._waitingForCompletions;

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];
var commonPrefix = this._buildCommonPrefix(completions, wordPrefixLength);

this._commonPrefix = commonPrefix;
} else {
if (completions.length === 1) {
var completionText = completions[0];
wordPrefixLength = completionText.length;
} else {
var commonPrefix = this._buildCommonPrefix(completions, wordPrefixLength);
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);
},

_completeCommonPrefix: function()
{
if (!this.autoCompleteElement || !this._commonPrefix || !this._userEnteredText || !this._commonPrefix.startsWith(this._userEnteredText))
return;

if (!this.isSuggestBoxVisible()) {
this.acceptAutoComplete();
return;
}

this.autoCompleteElement.textContent = this._commonPrefix.substring(this._userEnteredText.length);
this.acceptSuggestion(true)
},


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(prefixAccepted)
{
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 (!prefixAccepted) {
this.hideSuggestBox();
this.dispatchEventToListeners(WebInspector.TextPrompt.Events.ItemAccepted);
} else
this.autoCompleteSoon(true);

return true;
},

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

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.isSelfOrDescendant(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)
{
this._completeCommonPrefix();


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.consume(true);
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);

this._bodyElement = inputElement.ownerDocument.body;
this._element = inputElement.ownerDocument.createElement("div");
this._element.className = "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.parentElement;
},

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.parentElement.removeChild(this._element);
delete this._selectedElement;
},

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


_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.consume(true);
},

_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);
if (!this.visible)
this._bodyElement.appendChild(this._element);
this._rememberRowCountPerViewport();
} else
this.hide();
},

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

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

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

setCanShrink: function(canShrink)
{
this._hasFixedHeight = !canShrink;
this._contentDiv.addStyleClass("fixed-height");
},

_positionElement: function(anchorElement, preferredWidth, preferredHeight)
{
const borderWidth = 25;
const scrollerWidth = this._hasFixedHeight ? 0 : 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;
newElementPosition.height = anchorBox.y - borderRadius * 2 - arrowHeight;
if (this._hasFixedHeight && newElementPosition.height < preferredHeight) {
newElementPosition.y = borderRadius;
newElementPosition.height = preferredHeight;
}
}
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;
if (this._hasFixedHeight && newElementPosition.height < preferredHeight) {
newElementPosition.y = totalHeight - preferredHeight - borderRadius;
newElementPosition.height = preferredHeight;
}
}

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;
arrowRightPosition = Math.min(arrowRightPosition, newElementPosition.width - borderRadius - arrowOffset);
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);
panelElement.addEventListener("mouseout", this._mouseOut.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 (event.target.isSelfOrDescendant(this._hoverElement))
return;

this._startHidePopoverTimer();
this._handleMouseAction(event, false);
},

_mouseOut: function(event)
{
if (event.target === this._hoverElement)
this._startHidePopoverTimer();
},

_startHidePopoverTimer: function()
{

if (!this._popover || this._hidePopoverTimer)
return;

function doHide()
{
this._hidePopover();
delete this._hidePopoverTimer;
}
this._hidePopoverTimer = setTimeout(doHide.bind(this), this._timeout / 2);
},

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

isPopoverVisible: function()
{
return !!this._popover;
},

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

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

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

this._popover.dispose();
delete this._popover;
this._hoverElement = null;
},

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

if (window.debugCSS) {  
styleElement = document.createElement("link");
styleElement.rel = "stylesheet";
styleElement.type = "text/css";
styleElement.href = cssFile;
} else {
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 + "}");
},


defaultFocusedElement: function()
{
return this._defaultFocusedElement || this.element;
},


setDefaultFocusedElement: function(element)
{
this._defaultFocusedElement = element;
},

focus: function()
{
var element = this.defaultFocusedElement();
if (!element || element.isAncestor(document.activeElement))
return;

WebInspector.setCurrentFocusElement(element);
}
}

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.registerRequiredCSS("tabbedPane.css");
this.element.addStyleClass("tabbed-pane");
this._headerElement = this.element.createChild("div", "tabbed-pane-header");
this._headerContentsElement = this._headerElement.createChild("div", "tabbed-pane-header-contents");
this._tabsElement = this._headerContentsElement.createChild("div", "tabbed-pane-header-tabs");
this._contentElement = this.element.createChild("div", "tabbed-pane-content");
this._tabs = [];
this._tabsHistory = [];
this._tabsById = {};
this.element.addEventListener("click", this.focus.bind(this), false);

this._dropDownButton = this._createDropDownButton();
}

WebInspector.TabbedPane.EventTypes = {
TabSelected: "TabSelected",
TabClosed: "TabClosed"
}

WebInspector.TabbedPane.prototype = {

get visibleView()
{
return this._currentTab ? this._currentTab.view : null;
},


get selectedTabId()
{
return this._currentTab ? this._currentTab.id : null;
},


set shrinkableTabs(shrinkableTabs)
{
this._shrinkableTabs = shrinkableTabs;
},


set closeableTabs(closeableTabs)
{
this._closeableTabs = closeableTabs;
},

defaultFocusedElement: function()
{
return this.visibleView ? this.visibleView.defaultFocusedElement() : null;
},


appendTab: function(id, tabTitle, view, tabTooltip, userGesture)
{
var tab = new WebInspector.TabbedPaneTab(this, this._tabsElement, id, tabTitle, this._closeableTabs, view, tabTooltip);
this._tabsById[id] = tab;

this._tabs.push(tab);
this._tabsHistory.push(tab);

if (this._tabsHistory[0] === tab)
this.selectTab(tab.id, userGesture);

this._updateTabElements();
},


closeTab: function(id, userGesture)
{
this._innerCloseTab(id, userGesture);
this._updateTabElements();
if (this._tabsHistory.length)
this.selectTab(this._tabsHistory[0].id, userGesture);
},


_innerCloseTab: function(id, userGesture)
{
if (this._currentTab && this._currentTab.id === id)
this._hideCurrentTab();

var tab = this._tabsById[id];
delete this._tabsById[id];

this._tabsHistory.splice(this._tabsHistory.indexOf(tab), 1);
this._tabs.splice(this._tabs.indexOf(tab), 1);
if (tab.shown)
this._hideTabElement(tab);

var eventData = { tabId: id, view: tab.view, isUserGesture: userGesture };
this.dispatchEventToListeners(WebInspector.TabbedPane.EventTypes.TabClosed, eventData);
return true;
},


closeAllTabs: function(userGesture)
{
var tabs = this._tabs.slice();
for (var i = 0; i < tabs.length; ++i)
this._innerCloseTab(tabs[i].id, userGesture);
this._updateTabElements();
},


selectTab: function(id, userGesture)
{
var tab = this._tabsById[id];
if (!tab)
return;
if (this._currentTab && this._currentTab.id === id)
return;

this._hideCurrentTab();
this._showTab(tab);
this._currentTab = tab;

this._tabsHistory.splice(this._tabsHistory.indexOf(tab), 1);
this._tabsHistory.splice(0, 0, tab);

this._updateTabElements();

var eventData = { tabId: id, view: tab.view, isUserGesture: userGesture };
this.dispatchEventToListeners(WebInspector.TabbedPane.EventTypes.TabSelected, eventData);
return true;
},


lastOpenedTabIds: function(tabsCount)
{
function tabToTabId(tab) {
return tab.id;
}

return this._tabsHistory.slice(0, tabsCount).map(tabToTabId);
},


changeTabTitle: function(id, tabTitle)
{
var tab = this._tabsById[id];
tab.title = tabTitle;
this._updateTabElements();
},


changeTabView: function(id, view)
{
var tab = this._tabsById[id];
if (this._currentTab && this._currentTab.id === tab.id) {
this._hideTab(tab);
tab.view = view;
this._showTab(tab);
} else
tab.view = view;
},


changeTabTooltip: function(id, tabTooltip)
{
var tab = this._tabsById[id];
tab.tooltip = tabTooltip;
},

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

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

if (!this._tabs.length)
this._contentElement.addStyleClass("has-no-tabs");
else
this._contentElement.removeStyleClass("has-no-tabs");

if (!this._measuredDropDownButtonWidth)
this._measureDropDownButton();

if (this._shrinkableTabs)
this._updateWidths();

this._updateTabsDropDown();
},


_showTabElement: function(index, tab)
{
if (index >= this._tabsElement.children.length)
this._tabsElement.appendChild(tab.tabElement);
else
this._tabsElement.insertBefore(tab.tabElement, this._tabsElement.children[index]);
tab.shown = true;
},


_hideTabElement: function(tab)
{
this._tabsElement.removeChild(tab.tabElement);
tab.shown = false;
},

_createDropDownButton: function()
{
var dropDownContainer = document.createElement("div");
dropDownContainer.addStyleClass("tabbed-pane-header-tabs-drop-down-container");
var dropDownButton = dropDownContainer.createChild("div", "tabbed-pane-header-tabs-drop-down");
dropDownButton.appendChild(document.createTextNode("\u00bb"));
this._tabsSelect = dropDownButton.createChild("select", "tabbed-pane-header-tabs-drop-down-select");
this._tabsSelect.addEventListener("change", this._tabsSelectChanged.bind(this), false);
return dropDownContainer;
},

_updateTabsDropDown: function()
{
var tabsToShowIndexes = this._tabsToShowIndexes(this._tabs, this._tabsHistory, this._headerContentsElement.offsetWidth, this._measuredDropDownButtonWidth);

for (var i = 0; i < this._tabs.length; ++i) {
if (this._tabs[i].shown && tabsToShowIndexes.indexOf(i) === -1)
this._hideTabElement(this._tabs[i]);
}
for (var i = 0; i < tabsToShowIndexes.length; ++i) {
var tab = this._tabs[tabsToShowIndexes[i]];
if (!tab.shown)
this._showTabElement(i, tab);
}

this._populateDropDownFromIndex();
},

_populateDropDownFromIndex: function()
{
if (this._dropDownButton.parentElement)
this._headerContentsElement.removeChild(this._dropDownButton);

this._tabsSelect.removeChildren();
var tabsToShow = [];
for (var i = 0; i < this._tabs.length; ++i) {
if (!this._tabs[i].shown)
tabsToShow.push(this._tabs[i]);
continue;
}

function compareFunction(tab1, tab2)
{
return tab1.title.localeCompare(tab2.title);
}
tabsToShow.sort(compareFunction);

for (var i = 0; i < tabsToShow.length; ++i) {
var option = new Option(tabsToShow[i].title);
option.tab = tabsToShow[i];
this._tabsSelect.appendChild(option);
}
if (this._tabsSelect.options.length) {
this._headerContentsElement.appendChild(this._dropDownButton);
this._tabsSelect.selectedIndex = -1;
}
},

_tabsSelectChanged: function()
{
var options = this._tabsSelect.options;
var selectedOption = options[this._tabsSelect.selectedIndex];
this.selectTab(selectedOption.tab.id, true);
},

_measureDropDownButton: function()
{
this._dropDownButton.addStyleClass("measuring");
this._headerContentsElement.appendChild(this._dropDownButton);
this._measuredDropDownButtonWidth = this._dropDownButton.offsetWidth;
this._headerContentsElement.removeChild(this._dropDownButton);
this._dropDownButton.removeStyleClass("measuring");
},

_updateWidths: function()
{
var measuredWidths = [];
for (var tabId in this._tabs)
measuredWidths.push(this._tabs[tabId].measuredWidth);

var maxWidth = this._calculateMaxWidth(measuredWidths, this._headerContentsElement.offsetWidth);

for (var tabId in this._tabs) {
var tab = this._tabs[tabId];
tab.width = Math.min(tab.measuredWidth, maxWidth);
}
},


_calculateMaxWidth: function(measuredWidths, totalWidth)
{
if (!measuredWidths.length)
return 0;

measuredWidths.sort(function(x, y) { return x - y });

var totalMeasuredWidth = 0;
for (var i = 0; i < measuredWidths.length; ++i)
totalMeasuredWidth += measuredWidths[i];

if (totalWidth >= totalMeasuredWidth)
return measuredWidths[measuredWidths.length - 1];

var totalExtraWidth = 0;
for (var i = measuredWidths.length - 1; i > 0; --i) {
var extraWidth = measuredWidths[i] - measuredWidths[i - 1];
totalExtraWidth += (measuredWidths.length - i) * extraWidth;

if (totalWidth + totalExtraWidth >= totalMeasuredWidth)
return measuredWidths[i - 1] + (totalWidth + totalExtraWidth - totalMeasuredWidth) / (measuredWidths.length - i); 
}

return totalWidth / measuredWidths.length;
},


_tabsToShowIndexes: function(tabsOrdered, tabsHistory, totalWidth, measuredDropDownButtonWidth)
{
var tabsToShowIndexes = [];

var totalTabsWidth = 0;
for (var i = 0; i < tabsHistory.length; ++i) {
totalTabsWidth += tabsHistory[i].width;
var minimalRequiredWidth = totalTabsWidth;
if (i !== tabsHistory.length - 1)
minimalRequiredWidth += measuredDropDownButtonWidth;
if (minimalRequiredWidth > totalWidth)
break;
tabsToShowIndexes.push(tabsOrdered.indexOf(tabsHistory[i]));
}

tabsToShowIndexes.sort(function(x, y) { return x - y });

return tabsToShowIndexes;
},

_hideCurrentTab: function()
{
if (!this._currentTab)
return;

this._hideTab(this._currentTab);
delete this._currentTab;
},


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


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

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



WebInspector.TabbedPaneTab = function(tabbedPane, measureElement, id, title, closeable, view, tooltip)
{
this._closeable = closeable;
this._tabbedPane = tabbedPane;
this._measureElement = measureElement;
this._id = id;
this._title = title;
this._tooltip = tooltip;
this._view = view;
this.shown = false;
this._measuredWidth;
this._tabElement;
}

WebInspector.TabbedPaneTab.prototype = {

get id()
{
return this._id;
},


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

set title(title)
{
this._title = title;
if (this._titleElement)
this._titleElement.textContent = title;
delete this._measuredWidth;
},


get view()
{
return this._view;
},

set view(view)
{
this._view = view;
},


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

set tooltip(tooltip)
{
this._tooltip = tooltip;
if (this._titleElement)
this._titleElement.title = tooltip || "";
},


get tabElement()
{
if (typeof(this._tabElement) !== "undefined")
return this._tabElement;

this._createTabElement(false);
return this._tabElement;
},


get measuredWidth()
{
if (typeof(this._measuredWidth) !== "undefined")
return this._measuredWidth;

this._measure();
return this._measuredWidth;
},


get width()
{
return this._width || this.measuredWidth;
},

set width(width)
{
this.tabElement.style.width = width + "px";
this._width = width;
},


_createTabElement: function(measuring)
{
var tabElement = document.createElement("div");
tabElement.addStyleClass("tabbed-pane-header-tab");
tabElement.tabIndex = -1;

var titleElement = tabElement.createChild("span", "tabbed-pane-header-tab-title");
titleElement.textContent = this.title;
titleElement.title = this.tooltip || "";
if (!measuring)
this._titleElement = titleElement;

if (this._closeable) {
var closeButtonSpan = tabElement.createChild("span", "tabbed-pane-header-tab-close-button");
closeButtonSpan.textContent = "\u00D7"; 
}

if (measuring)
tabElement.addStyleClass("measuring");
else {
this._tabElement = tabElement;
tabElement.addEventListener("click", this._tabClicked.bind(this), false);
}

return tabElement;
},

_measure: function()
{
var measuringTabElement = this._createTabElement(true);
this._measureElement.appendChild(measuringTabElement);
this._measuredWidth = measuringTabElement.offsetWidth;
this._measureElement.removeChild(measuringTabElement);
},


_tabClicked: function(event)
{
if (this._closeable && (event.button === 1 || event.target.hasStyleClass("tabbed-pane-header-tab-close-button")))
this._tabbedPane.closeTab(this.id, true);
else
this._tabbedPane.selectTab(this.id, true);
this._tabbedPane.focus();
}
}






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().doResize();
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;

WebInspector.restoreFocusFromElement(this.element);

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

_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.consume(true);
},

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

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

event.consume();
}
}


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 = msg.clone();
msgCopy.totalRepeatCount = count;
msgCopy.repeatCount = (count - prevRepeatCount) || 1;
msgCopy.repeatDelta = msgCopy.repeatCount;
this.addMessage(msgCopy);
}
}
}

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


WebInspector.ConsoleMessage = function(source, level, url, line, repeatCount)
{
this.source = source;
this.level = level;
this.url = url || null;
this.line = line || 0;

repeatCount = repeatCount || 1;
this.repeatCount = repeatCount;
this.repeatDelta = repeatCount;
this.totalRepeatCount = repeatCount;
}

WebInspector.ConsoleMessage.prototype = {

isErrorOrWarning: function()
{
return (this.level === WebInspector.ConsoleMessage.MessageLevel.Warning || this.level === WebInspector.ConsoleMessage.MessageLevel.Error);
},

updateRepeatCount: function()
{

},


clone: 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.networkRequestById(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, source, level, url, line, repeatCount);

this._linkifier = linkifier;
this.type = type || WebInspector.ConsoleMessage.MessageType.Log;
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";

if (this.source === WebInspector.ConsoleMessage.MessageSource.ConsoleAPI) {
switch (this.type) {
case WebInspector.ConsoleMessage.MessageType.Trace:
this._messageElement = document.createTextNode("console.trace()");
break;
case WebInspector.ConsoleMessage.MessageType.Assert:
var args = [WebInspector.UIString("Assertion failed:")];
if (this._parameters)
args = args.concat(this._parameters);
this._messageElement = this._format(args);
break;
case WebInspector.ConsoleMessage.MessageType.Dir:
var obj = this._parameters ? this._parameters[0] : undefined;
var args = ["%O", obj];
this._messageElement = this._format(args);
break;
default:
var args = this._parameters || [this._messageText];
this._messageElement = this._format(args);
}
} else if (this.source === WebInspector.ConsoleMessage.MessageSource.Network) {
if (this._request) {
this._stackTrace = this._request.initiator.stackTrace;
if (this._request.initiator && this._request.initiator.url) {
this.url = this._request.initiator.url;
this.line = this._request.initiator.lineNumber;
}
this._messageElement = document.createElement("span");
if (this.level === WebInspector.ConsoleMessage.MessageLevel.Error) {
this._messageElement.appendChild(document.createTextNode(this._request.requestMethod + " "));
this._messageElement.appendChild(WebInspector.linkifyRequestAsNode(this._request));
if (this._request.failed)
this._messageElement.appendChild(document.createTextNode(" " + this._request.localizedFailDescription));
else
this._messageElement.appendChild(document.createTextNode(" " + this._request.statusCode + " (" + this._request.statusText + ")"));
} else {
var fragment = WebInspector.linkifyStringAsFragmentWithCustomLinkifier(this._messageText, WebInspector.linkifyRequestAsNode.bind(null, this._request, ""));
this._messageElement.appendChild(fragment);
}
} else {
if (this.url) {
var isExternal = !WebInspector.resourceForURL(this.url);
this._anchorElement = WebInspector.linkifyURLAsNode(this.url, this.url, "console-message-url", isExternal);
}
this._messageElement = this._format([this._messageText]);
}
} else {
var args = this._parameters || [this._messageText];
this._messageElement = this._format(args);
}

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

this._formattedMessage.appendChild(this._messageElement);
if (this._anchorElement) {
this._formattedMessage.appendChild(document.createTextNode(" "));
this._formattedMessage.appendChild(this._anchorElement);
}

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 = this._messageElement.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);
treeOutline.element.treeElementForTest = treeOutline.children[0];
}
object.pushNodeToFrontend(printNode.bind(this));
},

_formatParameterAsArray: function(array, elem)
{
const maxFlatArrayLength = 100;
if (array.arrayLength() > maxFlatArrayLength)
this._formatParameterAsObject(array, elem);
else
array.getOwnProperties(this._printArray.bind(this, array, 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(array, elem, properties)
{
if (!properties)
return;

var elements = [];
for (var i = 0; i < properties.length; ++i) {
var property = properties[i];
var name = property.name;
if (!isNaN(name))
elements[name] = this._formatAsArrayEntry(property.value);
}

elem.appendChild(document.createTextNode("["));
var lastNonEmptyIndex = -1;

function appendUndefined(elem, index)
{
if (index - lastNonEmptyIndex <= 1)
return;
var span = elem.createChild(span, "console-formatted-undefined");
span.textContent = WebInspector.UIString("undefined × %d", index - lastNonEmptyIndex - 1);
}

var length = array.arrayLength();
for (var i = 0; i < length; ++i) {
var element = elements[i];
if (!element)
continue;

if (i - lastNonEmptyIndex > 1) {
appendUndefined(elem, i);
elem.appendChild(document.createTextNode(", "));
}

elem.appendChild(element);
lastNonEmptyIndex = i;
if (i < length - 1)
elem.appendChild(document.createTextNode(", "));
}       
appendUndefined(elem, length);

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;
delete this._anchorElement;
delete this._messageElement;
this._formatMessage();
this._element.replaceChild(this._formattedMessage, highlightedMessage);
},

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

this._highlightSearchResultsInElement(regexObject, this._messageElement);
if (this._anchorElement)
this._highlightSearchResultsInElement(regexObject, this._anchorElement);

this._element.scrollIntoViewIfNeeded();
},

_highlightSearchResultsInElement: function(regexObject, element)
{
regexObject.lastIndex = 0;
var text = element.textContent;
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);
}
WebInspector.highlightSearchResults(element, matchRanges);
},

matchesRegex: function(regexObject)
{
return regexObject.test(this._message) || (this._anchorElement && regexObject.test(this._anchorElement.textContent));
},

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) {
content.appendChild(document.createTextNode(" "));
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;
},

location: function()
{

var lineNumber = this.stackTrace ? this.stackTrace[0].lineNumber - 1 : this.line - 1;
var columnNumber = this.stackTrace ? this.stackTrace[0].columnNumber - 1 : 0;
return WebInspector.debuggerModel.createRawLocationByURL(this.url, lineNumber, columnNumber);
},

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


clone: function()
{
return WebInspector.ConsoleMessage.create(this.source, this.level, this._messageText, this.type, this.url, this.line, this.repeatCount, this._parameters, this._stackTrace, this._request);
}
}

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 = new WebInspector.Linkifier();

this.prompt = new WebInspector.TextPromptWithHistory(this.completionsForTextPrompt.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);
}
},

willHide: function()
{
this.prompt.hideSuggestBox();
this.prompt.clearAutoComplete(true);
},

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()
{
delete this._scrollIntoViewTimer;
this.promptElement.scrollIntoView(true);
}
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();
},

completionsForTextPrompt: function(textPrompt, wordRange, force, completionsReadyCallback)
{

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

completionsForExpression: 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.debuggerModel.selectedCallFrame())
WebInspector.debuggerModel.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, undefined, 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.startsWith(prefix))
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 shortcutM = shortcut.makeDescriptor("m", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta | WebInspector.KeyboardShortcut.Modifiers.Shift);
this._shortcuts[shortcutM.key] = this._dumpMemory.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, doNotPauseOnExceptionsAndMuteConsole, returnByValue, callback)
{
if (WebInspector.debuggerModel.selectedCallFrame()) {
WebInspector.debuggerModel.evaluateOnSelectedCallFrame(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, 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, doNotPauseOnExceptionsAndMuteConsole, this._currentEvaluationContextId(), returnByValue, evalCallback);
},

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

_enterKeyPressed: function(event)
{
if (event.altKey || event.ctrlKey || event.shiftKey)
return;

event.consume(true);

this.prompt.clearAutoComplete(true);

var str = this.prompt.text;
if (!str.length)
return;
this._appendCommand(str, "", true, false);
},

_appendCommand: function(text, newPromptText, useCommandLineAPI, showResultOnly)
{
if (!showResultOnly) {
var commandMessage = new WebInspector.ConsoleCommand(text);
WebInspector.console.interruptRepeatCount();
this._appendConsoleMessage(commandMessage);
}
this.prompt.text = newPromptText;

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

if (!showResultOnly) {
this.prompt.pushHistoryItem(text);
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];
},

_dumpMemory: function()
{
function comparator(a, b)
{
if (a.size < b.size)
return 1;
if (a.size > b.size)
return -1;
return a.title.localeCompare(b.title);
}

function callback(error, groups)
{
var titles = [];
groups.sort(comparator);
for (var i = 0; i < groups.length; ++i) {
var suffix = groups[i].size > 0 ? " [" + groups[i].size + "]" : "";
titles.push(groups[i].title + suffix + (groups[i].documentURI ? " (" + groups[i].documentURI + ")" : ""));
}

var counter = 1;
var previousTitle = null;
for (var i = 0; i < titles.length; ++i) {
var title = titles[i];
if (title === previousTitle) {
counter++;
continue;
}
if (previousTitle)
WebInspector.log(counter > 1 ? counter + " x " + previousTitle : previousTitle);
previousTitle = title;
counter = 1;
}
WebInspector.log(counter > 1 ? counter + " x " + previousTitle : previousTitle);
}
MemoryAgent.getDOMNodeCount(callback);
}
}

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);
}
WebInspector.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.consume(true);
}
}


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

this.focus();
},

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

defaultFocusedElement: function()
{
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)
{
},

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

unregisterShortcut: function(key)
{
delete this._shortcuts[key];
}
}

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)
{
switch (event.keyIdentifier) {

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.consume();
return;
}

var isGoBack = WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && event.altKey;
if (isGoBack && this._canGoBackInHistory()) {
this._goBackInHistory();
event.consume();
}
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.consume();
return;
}

var isGoForward = WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && event.altKey;
if (isGoForward && this._canGoForwardInHistory()) {
this._goForwardInHistory();
event.consume();
}
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);
},

close: function()
{
this.stopSearch();
WebInspector.closeDrawerView();
},


_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._searchDoneButton = this._searchPanelElement.createChild("button");
this._searchDoneButton.textContent = WebInspector.UIString("Close");
this._searchDoneButton.addStyleClass("search-close-button");
this._searchDoneButton.addEventListener("click", this._closeButtonPressed.bind(this));

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()
{
return new WebInspector.SearchConfig(this._search.value, this._ignoreCaseCheckbox.checked, this._regexCheckbox.checked);
},


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)
{
switch (event.keyCode) {
case WebInspector.KeyboardShortcut.Keys.Enter.code:
this._onAction();
break;
case WebInspector.KeyboardShortcut.Keys.Esc.code:
this._controller.close();
event.consume(true);
break;
}        
},

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

_closeButtonPressed: function()
{
this._controller.close();
},

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

get dividersElement()
{
return this._dividersElement;
},

removeDividers: function()
{
this._dividersElement.removeChildren();
this._dividersLabelBarElement.removeChildren();
},

updateDividers: function(calculator)
{
var dividersElementClientWidth = this._dividersElement.clientWidth;
var dividerCount = Math.round(dividersElementClientWidth / 64);
var slice = calculator.boundarySpan / dividerCount;

this._currentDividerSlice = slice;


var divider = this._dividersElement.firstChild;
var dividerLabelBar = this._dividersLabelBarElement.firstChild;

var paddingLeft = calculator.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);
}

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;
if (!slice) {
left = dividersElementClientWidth / dividerCount * i + paddingLeft;
dividerLabelBar._labelElement.textContent = "";
} else {
left = calculator.computePosition(calculator.minimumBoundary + slice * i);
dividerLabelBar._labelElement.textContent = calculator.formatTime(slice * i);
}
var percentLeft = 100 * left / dividersElementClientWidth;
this._setDividerAndBarLeft(divider, dividerLabelBar, percentLeft);

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.ContentProvider = function() { }

WebInspector.ContentProvider.prototype = {

contentURL: function() { },


requestContent: function(callback) { },


searchInContent: function(query, caseSensitive, isRegex, callback) { }
}


WebInspector.ContentProvider.SearchMatch = function(lineNumber, lineContent) {
this.lineNumber = lineNumber;
this.lineContent = lineContent;
}






WebInspector.Resource = function(request, url, documentURL, frameId, loaderId, type, mimeType)
{
this._request = request;
if (this._request)
this._request.setResource(this);
this.url = url;
this._documentURL = documentURL;
this._frameId = frameId;
this._loaderId = loaderId;
this._type = type || WebInspector.resourceTypes.Other;
this._mimeType = mimeType;
this.history = [];

this._content;
this._contentEncoded;
this._pendingContentCallbacks = [];
}

WebInspector.Resource._domainModelBindings = [];


WebInspector.Resource.registerDomainModelBinding = function(type, binding)
{
WebInspector.Resource._domainModelBindings[type.name()] = 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 request()
{
return this._request;
},


get url()
{
return this._url;
},

set url(x)
{
this._url = x;
this._parsedURL = new WebInspector.ParsedURL(x);
},

get parsedURL()
{
return this._parsedURL;
},


get documentURL()
{
return this._documentURL;
},


get frameId()
{
return this._frameId;
},


get loaderId()
{
return this._loaderId;
},


get displayName()
{
return this._parsedURL.displayName;
},


get type()
{
return this._request ? this._request.type : this._type;
},


get mimeType()
{
return this._request ? this._request.mimeType : this._mimeType;
},


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.name()];
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.name()];
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);
},


contentURL: function()
{
return this._url;
},


requestContent: function(callback)
{
if (typeof this._content !== "undefined") {
callback(this._content, !!this._contentEncoded, this.canonicalMimeType());
return;
}

this._pendingContentCallbacks.push(callback);
this._innerRequestContent();
},

canonicalMimeType: function()
{
if (this.type === WebInspector.resourceTypes.Document)
return "text/html";
if (this.type === WebInspector.resourceTypes.Script)
return "text/javascript";
if (this.type === WebInspector.resourceTypes.Stylesheet)
return "text/css";
return this.mimeType;
},


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


_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 callback(error, content, contentEncoded)
{
this._content = error ? null : content;
this._contentEncoded = contentEncoded;
this._originalContent = content;
var callbacks = this._pendingContentCallbacks.slice();
for (var i = 0; i < callbacks.length; ++i)
callbacks[i](this._content, this._contentEncoded, this.canonicalMimeType());
this._pendingContentCallbacks.length = 0;
delete this._contentRequested;
}
PageAgent.getResourceContent(this.frameId, this.url, callback.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 || null;
},

revertToThis: function()
{
function revert(content)
{
this._resource.setContent(content, true);
}
this.requestContent(revert.bind(this));
},


contentURL: function()
{
return this._resource.url;
},


requestContent: function(callback)
{
if (typeof this._content === "string") {
callback(this._content, false, this.resource.mimeType);
return;
}


if (typeof this.resource._originalContent === "string") {
this._content = this._resource._originalContent;
callback(this._content, false, this.resource.mimeType);
return;
}


function callbackWrapper(error, content, contentEncoded)
{
callback(error ? null : content, contentEncoded, this.resource.mimeType);
}

PageAgent.getResourceContent(this._resource.frameId, this._resource.url, callbackWrapper.bind(this));
},


searchInContent: function(query, caseSensitive, isRegex, callback)
{
callback([]);
}
}


WebInspector.ResourceDomainModelBinding = function() { }

WebInspector.ResourceDomainModelBinding.prototype = {

canSetContent: function(resource) { return true; },


setContent: function(resource, content, majorChange, callback) { }
}






WebInspector.NetworkRequest = function(requestId, url, documentURL, frameId, loaderId)
{
this._requestId = requestId;
this.url = url;
this._documentURL = documentURL;
this._frameId = frameId;
this._loaderId = loaderId;
this._startTime = -1;
this._endTime = -1;

this.statusCode = 0;
this.statusText = "";
this.requestMethod = "";
this.requestTime = 0;
this.receiveHeadersEnd = 0;

this._type = WebInspector.resourceTypes.Other;
this._content = undefined;
this._contentEncoded = false;
this._pendingContentCallbacks = [];
this._frames = [];
}

WebInspector.NetworkRequest.Events = {
FinishedLoading: "FinishedLoading",
TimingChanged: "TimingChanged",
RequestHeadersChanged: "RequestHeadersChanged",
ResponseHeadersChanged: "ResponseHeadersChanged",
}

WebInspector.NetworkRequest.prototype = {

get requestId()
{
return this._requestId;
},

set requestId(requestId)
{
this._requestId = requestId;
},


get url()
{
return this._url;
},

set url(x)
{
if (this._url === x)
return;

this._url = x;
this._parsedURL = new WebInspector.ParsedURL(x);
delete this._parsedQueryParameters;
},


get documentURL()
{
return this._documentURL;
},

get parsedURL()
{
return this._parsedURL;
},


get frameId()
{
return this._frameId;
},


get loaderId()
{
return this._loaderId;
},


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(WebInspector.NetworkRequest.Events.FinishedLoading, this);
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 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(WebInspector.NetworkRequest.Events.TimingChanged, this);
}
},


get mimeType()
{
return this._mimeType;
},

set mimeType(x)
{
this._mimeType = x;
},


get displayName()
{
return this._parsedURL.displayName;
},


get folder()
{
var path = this._parsedURL.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 type()
{
return this._type;
},

set type(x)
{
this._type = x;
},


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(WebInspector.NetworkRequest.Events.RequestHeadersChanged);
},


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(WebInspector.NetworkRequest.Events.RequestHeadersChanged);
},


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(WebInspector.NetworkRequest.Events.ResponseHeadersChanged);
},


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(WebInspector.NetworkRequest.Events.ResponseHeadersChanged);
},


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 null;
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 null;
var requestContentType = this.requestContentType();
if (!requestContentType || !requestContentType.match(/^application\/x-www-form-urlencoded\s*(;.*)?$/i))
return null;
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 content()
{
return this._content;
},


get contentEncoded()
{
return this._contentEncoded;
},


contentURL: function()
{
return this._url;
},


requestContent: function(callback)
{



if (this.type === WebInspector.resourceTypes.WebSocket) {
callback(null, false, this._mimeType);
return;
}
if (typeof this._content !== "undefined") {
callback(this.content || null, this._contentEncoded, this._mimeType);
return;
}
this._pendingContentCallbacks.push(callback);
if (this.finished)
this._innerRequestContent();
},


searchInContent: function(query, caseSensitive, isRegex, callback)
{
callback([]);
},


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


populateImageSource: function(image)
{

function onResourceContent(content, contentEncoded, mimeType)
{
const maxDataUrlSize = 1024 * 1024;

if (this._content == null || this._content.length > maxDataUrlSize)
return this.url;
image.src = "data:" + this.mimeType + (this._contentEncoded ? ";base64," : ",") + this._content;
}

this.requestContent(onResourceContent.bind(this));
},

_innerRequestContent: function()
{
if (this._contentRequested)
return;
this._contentRequested = true;


function onResourceContent(error, content, contentEncoded)
{
this._content = error ? null : content;
this._contentEncoded = contentEncoded;
var callbacks = this._pendingContentCallbacks.slice();
for (var i = 0; i < callbacks.length; ++i)
callbacks[i](this._content, this._contentEncoded, this._mimeType);
this._pendingContentCallbacks.length = 0;
delete this._contentRequested;
}
NetworkAgent.getResponseBody(this._requestId, onResourceContent.bind(this));
},


setResource: function(resource)
{
this._resource = resource;
},


resource: function()
{
return this._resource;
},


frames: function()
{
return this._frames;
},


frame: function(position)
{
return this._frames[position];
},


addFrameError: function(errorMessage, time)
{
var errorObject = {};
errorObject.errorMessage = errorMessage;
errorObject.time = time;
this._pushFrame(errorObject);
},


addFrame: function(response, time, sent)
{
response.time = time;
if (sent)
response.sent = true;
this._pushFrame(response);
},

_pushFrame: function(object)
{
if (this._frames.length >= 100) {
this._frames.splice(0, 10);
}
this._frames.push(object);
}
}

WebInspector.NetworkRequest.prototype.__proto__ = WebInspector.Object.prototype;






WebInspector.CSSStyleModel = function()
{
this._pendingCommandsMajorState = [];
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.UndoRedoRequested, this._undoRedoRequested, this);
WebInspector.domAgent.addEventListener(WebInspector.DOMAgent.Events.UndoRedoCompleted, this._undoRedoCompleted, this);
new WebInspector.CSSStyleModelResourceBinding(this);
InspectorBackend.registerCSSDispatcher(new WebInspector.CSSDispatcher(this));
CSSAgent.enable();
}

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",
MediaQueryResultChanged: "MediaQueryResultChanged"
}

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, attributesStylePayload)
{
if (error || !inlinePayload)
userCallback(null, null);
else
userCallback(WebInspector.CSSStyleDeclaration.parsePayload(inlinePayload), attributesStylePayload ? WebInspector.CSSStyleDeclaration.parsePayload(attributesStylePayload) : 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);
}


function callback(nodeId, successCallback, failureCallback, newSelector, error, rulePayload)
{
this._pendingCommandsMajorState.pop();
if (error)
failureCallback();
else {
WebInspector.domAgent.markUndoableState();
var ownerDocumentId = this._ownerDocumentId(nodeId);
if (ownerDocumentId)
WebInspector.domAgent.querySelectorAll(ownerDocumentId, newSelector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
else
failureCallback();
}
}

this._pendingCommandsMajorState.push(true);
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);
}


function callback(successCallback, failureCallback, selector, error, rulePayload)
{
this._pendingCommandsMajorState.pop();
if (error) {

failureCallback();
} else {
WebInspector.domAgent.markUndoableState();
var ownerDocumentId = this._ownerDocumentId(nodeId);
if (ownerDocumentId)
WebInspector.domAgent.querySelectorAll(ownerDocumentId, selector, checkAffectsCallback.bind(this, nodeId, successCallback, rulePayload));
else
failureCallback();
}
}

this._pendingCommandsMajorState.push(true);
CSSAgent.addRule(nodeId, selector, callback.bind(this, successCallback, failureCallback, selector));
},

mediaQueryResultChanged: function()
{
this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.MediaQueryResultChanged);
},

_ownerDocumentId: function(nodeId)
{
var node = WebInspector.domAgent.nodeForId(nodeId);
if (!node)
return null;
return node.ownerDocument ? node.ownerDocument.id : null;
},

_fireStyleSheetChanged: function(styleSheetId)
{
if (!this._pendingCommandsMajorState.length)
return;

var majorChange = this._pendingCommandsMajorState[this._pendingCommandsMajorState.length - 1];

if (!majorChange || !styleSheetId || !this.hasEventListeners(WebInspector.CSSStyleModel.Events.StyleSheetChanged))
return;

this.dispatchEventToListeners(WebInspector.CSSStyleModel.Events.StyleSheetChanged, { styleSheetId: styleSheetId, majorChange: majorChange });
},

setStyleSheetText: function(styleSheetId, newText, majorChange, userCallback)
{
function callback(error)
{
this._pendingCommandsMajorState.pop();
if (!error && majorChange)
WebInspector.domAgent.markUndoableState();

if (!error && userCallback)
userCallback(error);
}
this._pendingCommandsMajorState.push(majorChange);
CSSAgent.setStyleSheetText(styleSheetId, newText, callback.bind(this));
},

_undoRedoRequested: function()
{
this._pendingCommandsMajorState.push(true);
},

_undoRedoCompleted: function()
{
this._pendingCommandsMajorState.pop();
}
}

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(index)
{
index = (typeof index === "undefined") ? this.pastLastSourcePropertyIndex() : index;
return new WebInspector.CSSProperty(this, index, "", "", "", "active", true, false, false, "");
},

insertPropertyAt: function(index, name, value, userCallback)
{
function callback(userCallback, error, payload)
{
WebInspector.cssModel._pendingCommandsMajorState.pop();
if (!userCallback)
return;

if (error) {
console.error(error);
userCallback(null);
} else {
userCallback(WebInspector.CSSStyleDeclaration.parsePayload(payload));
}
}

WebInspector.cssModel._pendingCommandsMajorState.push(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 === "regular";
}
}


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, overwrite, userCallback)
{
function enabledCallback(style)
{
if (userCallback)
userCallback(style);
}

function callback(error, stylePayload)
{
WebInspector.cssModel._pendingCommandsMajorState.pop();
if (!error) {
if (majorChange)
WebInspector.domAgent.markUndoableState();
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;
}

if (userCallback)
userCallback(style);
} else {
if (userCallback)
userCallback(null);
}
}

if (!this.ownerStyle)
throw "No ownerStyle for property";


WebInspector.cssModel._pendingCommandsMajorState.push(majorChange);
CSSAgent.setPropertyText(this.ownerStyle.id, this.index, propertyText, overwrite, callback.bind(this));
},


setValue: function(newValue, majorChange, overwrite, userCallback)
{
var text = this.name + ": " + newValue + (this.priority ? " !" + this.priority : "") + ";"
this.setText(text, majorChange, overwrite, userCallback);
},

setDisabled: function(disabled, userCallback)
{
if (!this.ownerStyle && userCallback)
userCallback(null);
if (disabled === this.disabled && userCallback)
userCallback(this.ownerStyle);

function callback(error, stylePayload)
{
WebInspector.cssModel._pendingCommandsMajorState.pop();
if (error) {
if (userCallback)
userCallback(null);
return;
}
WebInspector.domAgent.markUndoableState();
if (userCallback) {
var style = WebInspector.CSSStyleDeclaration.parsePayload(stylePayload);
userCallback(style);
}
}

WebInspector.cssModel._pendingCommandsMajorState.push(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 (!error)
WebInspector.domAgent.markUndoableState();

WebInspector.cssModel._pendingCommandsMajorState.pop();
if (userCallback)
userCallback(error);
}

WebInspector.cssModel._pendingCommandsMajorState.push(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.resourceTypes.Stylesheet, this);
}

WebInspector.CSSStyleModelResourceBinding.prototype = {
setContent: function(resource, content, majorChange, userCallback)
{
if (majorChange && resource.type === WebInspector.resourceTypes.Stylesheet)
resource.addRevision(content);

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._isSettingContent = true;
function callbackWrapper(error)
{
if (userCallback)
userCallback(error);
delete this._isSettingContent;
}
this._cssModel.setStyleSheetText(styleSheetId, content, majorChange, callbackWrapper.bind(this));
},

_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)
{
if (this._isSettingContent)
return;

if (!event.data.majorChange)
return;

function callback(error, content)
{
if (!error)
this._innerStyleSheetChanged(event.data.styleSheetId, content);
}
CSSAgent.getStyleSheetText(event.data.styleSheetId, callback.bind(this));
},

_innerStyleSheetChanged: function(styleSheetId, content)
{
function setContent()
{
var url = this._styleSheetIdToURL[styleSheetId];
if (!url)
return;

var resource = WebInspector.resourceForURL(url);
if (resource && resource.type === WebInspector.resourceTypes.Stylesheet)
resource.addRevision(content);
}

if (!this._styleSheetIdToURL[styleSheetId]) {
this._loadStyleSheetHeaders(setContent.bind(this));
return;
}
setContent.call(this);
}
}

WebInspector.CSSStyleModelResourceBinding.prototype.__proto__ = WebInspector.ResourceDomainModelBinding.prototype;


WebInspector.CSSDispatcher = function(cssModel)
{
this._cssModel = cssModel;
}

WebInspector.CSSDispatcher.prototype = {
mediaQueryResultChanged: function()
{
this._cssModel.mediaQueryResultChanged();
},

styleSheetChanged: function(styleSheetId)
{
this._cssModel._fireStyleSheetChanged(styleSheetId);
}
}


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 = {
ResourceTrackingEnabled: "ResourceTrackingEnabled",
ResourceTrackingDisabled: "ResourceTrackingDisabled",
RequestStarted: "RequestStarted",
RequestUpdated: "RequestUpdated",
RequestFinished: "RequestFinished",
RequestUpdateDropped: "RequestUpdateDropped"
}

WebInspector.NetworkManager._MIMETypes = {
"text/html":                   {"document": true},
"text/xml":                    {"document": true},
"text/plain":                  {"document": true},
"application/xhtml+xml":       {"document": true},
"text/css":                    {"stylesheet": true},
"text/xsl":                    {"stylesheet": true},
"image/jpeg":                  {"image": true},
"image/png":                   {"image": true},
"image/gif":                   {"image": true},
"image/bmp":                   {"image": true},
"image/svg+xml":               {"image": true},
"image/vnd.microsoft.icon":    {"image": true},
"image/webp":                  {"image": true},
"image/x-icon":                {"image": true},
"image/x-xbitmap":             {"image": true},
"font/ttf":                    {"font": true},
"font/opentype":               {"font": true},
"font/woff":                   {"font": true},
"application/x-font-type1":    {"font": true},
"application/x-font-ttf":      {"font": true},
"application/x-font-woff":     {"font": true},
"application/x-truetype-font": {"font": true},
"text/javascript":             {"script": true},
"text/ecmascript":             {"script": true},
"application/javascript":      {"script": true},
"application/ecmascript":      {"script": true},
"application/x-javascript":    {"script": true},
"application/json":            {"script": true},
"text/javascript1.1":          {"script": true},
"text/javascript1.2":          {"script": true},
"text/javascript1.3":          {"script": true},
"text/jscript":                {"script": true},
"text/livescript":             {"script": true},
}

WebInspector.NetworkManager.prototype = {
enableResourceTracking: function()
{
function callback(error)
{
this.dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceTrackingEnabled);
}
NetworkAgent.enable(callback.bind(this));
},

disableResourceTracking: function()
{
function callback(error)
{
this.dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.ResourceTrackingDisabled);
}
NetworkAgent.disable(callback.bind(this));
},


inflightRequestForURL: function(url)
{
return this._dispatcher._inflightRequestsByURL[url];
},


_cacheDisabledSettingChanged: function(event)
{
var enabled =   event.data;
NetworkAgent.setCacheDisabled(enabled);
},

_userAgentSettingChanged: function()
{
NetworkAgent.setUserAgentOverride(WebInspector.settings.userAgent.get());
}
}

WebInspector.NetworkManager.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.NetworkDispatcher = function(manager)
{
this._manager = manager;
this._inflightRequestsById = {};
this._inflightRequestsByURL = {};
InspectorBackend.registerNetworkDispatcher(this);
}

WebInspector.NetworkDispatcher.prototype = {

_updateNetworkRequestWithRequest: function(networkRequest, request)
{
networkRequest.requestMethod = request.method;
networkRequest.requestHeaders = request.headers;
networkRequest.requestFormData = request.postData;
},


_updateNetworkRequestWithResponse: function(networkRequest, response)
{
if (!response)
return;

if (response.url && networkRequest.url !== response.url)
networkRequest.url = response.url;
networkRequest.mimeType = response.mimeType;
networkRequest.statusCode = response.status;
networkRequest.statusText = response.statusText;
networkRequest.responseHeaders = response.headers;
if (response.headersText)
networkRequest.responseHeadersText = response.headersText;
if (response.requestHeaders)
networkRequest.requestHeaders = response.requestHeaders;
if (response.requestHeadersText)
networkRequest.requestHeadersText = response.requestHeadersText;

networkRequest.connectionReused = response.connectionReused;
networkRequest.connectionId = response.connectionId;

if (response.fromDiskCache)
networkRequest.cached = true;
else
networkRequest.timing = response.timing;

if (!this._mimeTypeIsConsistentWithType(networkRequest)) {
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\".", networkRequest.type.title(), networkRequest.mimeType, networkRequest.url),
WebInspector.ConsoleMessage.MessageType.Log,
"",
0,
1,
[],
null,
networkRequest));
}
},


_mimeTypeIsConsistentWithType: function(networkRequest)
{






if (networkRequest.hasErrorStatusCode() || networkRequest.statusCode === 304)
return true;

if (typeof networkRequest.type === "undefined"
|| networkRequest.type === WebInspector.resourceTypes.Other
|| networkRequest.type === WebInspector.resourceTypes.XHR
|| networkRequest.type === WebInspector.resourceTypes.WebSocket)
return true;

if (!networkRequest.mimeType)
return true; 

if (networkRequest.mimeType in WebInspector.NetworkManager._MIMETypes)
return networkRequest.type.name() in WebInspector.NetworkManager._MIMETypes[networkRequest.mimeType];

return false;
},


_updateNetworkRequestWithCachedResource: function(networkRequest, cachedResource)
{
networkRequest.type = WebInspector.resourceTypes[cachedResource.type];
networkRequest.resourceSize = cachedResource.bodySize;
this._updateNetworkRequestWithResponse(networkRequest, cachedResource.response);
},


_isNull: function(response)
{
if (!response)
return true;
return !response.status && !response.mimeType && (!response.headers || !Object.keys(response.headers).length);
},


requestWillBeSent: function(requestId, frameId, loaderId, documentURL, request, time, initiator, redirectResponse)
{
var networkRequest = this._inflightRequestsById[requestId];
if (networkRequest) {

if (!redirectResponse)
return;
this.responseReceived(requestId, frameId, loaderId, time, "Other", redirectResponse);
networkRequest = this._appendRedirect(requestId, time, request.url);
} else
networkRequest = this._createNetworkRequest(requestId, frameId, loaderId, request.url, documentURL, initiator);
networkRequest.hasNetworkData = true;
this._updateNetworkRequestWithRequest(networkRequest, request);
networkRequest.startTime = time;

this._startNetworkRequest(networkRequest);
},


requestServedFromCache: function(requestId)
{
var networkRequest = this._inflightRequestsById[requestId];
if (!networkRequest)
return;

networkRequest.cached = true;
},


responseReceived: function(requestId, frameId, loaderId, time, resourceType, response)
{

if (this._isNull(response))
return;

var networkRequest = this._inflightRequestsById[requestId];
if (!networkRequest) {

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.RequestUpdateDropped, eventData);
return;
}

networkRequest.responseReceivedTime = time;
networkRequest.type = WebInspector.resourceTypes[resourceType];

this._updateNetworkRequestWithResponse(networkRequest, response);

this._updateNetworkRequest(networkRequest);
},


dataReceived: function(requestId, time, dataLength, encodedDataLength)
{
var networkRequest = this._inflightRequestsById[requestId];
if (!networkRequest)
return;

networkRequest.resourceSize += dataLength;
if (encodedDataLength != -1)
networkRequest.increaseTransferSize(encodedDataLength);
networkRequest.endTime = time;

this._updateNetworkRequest(networkRequest);
},


loadingFinished: function(requestId, finishTime)
{
var networkRequest = this._inflightRequestsById[requestId];
if (!networkRequest)
return;
this._finishNetworkRequest(networkRequest, finishTime);
},


loadingFailed: function(requestId, time, localizedDescription, canceled)
{
var networkRequest = this._inflightRequestsById[requestId];
if (!networkRequest)
return;

networkRequest.failed = true;
networkRequest.canceled = canceled;
networkRequest.localizedFailDescription = localizedDescription;
this._finishNetworkRequest(networkRequest, time);
},


requestServedFromMemoryCache: function(requestId, frameId, loaderId, documentURL, time, initiator, cachedResource)
{
var networkRequest = this._createNetworkRequest(requestId, frameId, loaderId, cachedResource.url, documentURL, initiator);
this._updateNetworkRequestWithCachedResource(networkRequest, cachedResource);
networkRequest.cached = true;
networkRequest.requestMethod = "GET";
this._startNetworkRequest(networkRequest);
networkRequest.startTime = networkRequest.responseReceivedTime = time;
this._finishNetworkRequest(networkRequest, time);
},


webSocketCreated: function(requestId, requestURL)
{
var networkRequest = new WebInspector.NetworkRequest(requestId, requestURL, "", "", "");
networkRequest.type = WebInspector.resourceTypes.WebSocket;
this._startNetworkRequest(networkRequest);
},


webSocketWillSendHandshakeRequest: function(requestId, time, request)
{
var networkRequest = this._inflightRequestsById[requestId];
if (!networkRequest)
return;

networkRequest.requestMethod = "GET";
networkRequest.requestHeaders = request.headers;
networkRequest.webSocketRequestKey3 = request.requestKey3;
networkRequest.startTime = time;

this._updateNetworkRequest(networkRequest);
},


webSocketHandshakeResponseReceived: function(requestId, time, response)
{
var networkRequest = this._inflightRequestsById[requestId];
if (!networkRequest)
return;

networkRequest.statusCode = response.status;
networkRequest.statusText = response.statusText;
networkRequest.responseHeaders = response.headers;
networkRequest.webSocketChallengeResponse = response.challengeResponse;
networkRequest.responseReceivedTime = time;

this._updateNetworkRequest(networkRequest);
},


webSocketFrameReceived: function(requestId, time, response)
{
var networkRequest = this._inflightRequestsById[requestId];
if (!networkRequest)
return;

networkRequest.addFrame(response, time);
networkRequest.responseReceivedTime = time;

this._updateNetworkRequest(networkRequest);
},


webSocketFrameSent: function(requestId, time, response)
{
var networkRequest = this._inflightRequestsById[requestId];
if (!networkRequest)
return;

networkRequest.addFrame(response, time, true);
networkRequest.responseReceivedTime = time;

this._updateNetworkRequest(networkRequest);
},


webSocketFrameError: function(requestId, time, errorMessage)
{
var networkRequest = this._inflightRequestsById[requestId];
if (!networkRequest)
return;

networkRequest.addFrameError(errorMessage, time);
networkRequest.responseReceivedTime = time;

this._updateNetworkRequest(networkRequest);
},


webSocketClosed: function(requestId, time)
{
var networkRequest = this._inflightRequestsById[requestId];
if (!networkRequest)
return;
this._finishNetworkRequest(networkRequest, time);
},


_appendRedirect: function(requestId, time, redirectURL)
{
var originalNetworkRequest = this._inflightRequestsById[requestId];
var previousRedirects = originalNetworkRequest.redirects || [];
originalNetworkRequest.requestId = "redirected:" + requestId + "." + previousRedirects.length;
delete originalNetworkRequest.redirects;
if (previousRedirects.length > 0)
originalNetworkRequest.redirectSource = previousRedirects[previousRedirects.length - 1];
this._finishNetworkRequest(originalNetworkRequest, time);
var newNetworkRequest = this._createNetworkRequest(requestId, originalNetworkRequest.frameId, originalNetworkRequest.loaderId,
redirectURL, originalNetworkRequest.documentURL, originalNetworkRequest.initiator);
newNetworkRequest.redirects = previousRedirects.concat(originalNetworkRequest);
return newNetworkRequest;
},


_startNetworkRequest: function(networkRequest)
{
this._inflightRequestsById[networkRequest.requestId] = networkRequest;
this._inflightRequestsByURL[networkRequest.url] = networkRequest;
this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.RequestStarted, networkRequest);
},


_updateNetworkRequest: function(networkRequest)
{
this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.RequestUpdated, networkRequest);
},


_finishNetworkRequest: function(networkRequest, finishTime)
{
networkRequest.endTime = finishTime;
networkRequest.finished = true;
this._dispatchEventToListeners(WebInspector.NetworkManager.EventTypes.RequestFinished, networkRequest);
delete this._inflightRequestsById[networkRequest.requestId];
delete this._inflightRequestsByURL[networkRequest.url];
},


_dispatchEventToListeners: function(eventType, networkRequest)
{
this._manager.dispatchEventToListeners(eventType, networkRequest);
},


_createNetworkRequest: function(requestId, frameId, loaderId, url, documentURL, initiator)
{
var networkRequest = new WebInspector.NetworkRequest(requestId, url, documentURL, frameId, loaderId);
networkRequest.initiator = initiator;
return networkRequest;
}
}


WebInspector.networkManager = null;






WebInspector.NavigatorOverlayController = function(panel, parentSplitView, navigatorView, editorView)
{
this._panel = panel;
this._parentSplitView = parentSplitView;
this._navigatorView = navigatorView;
this._editorView = editorView;

this._navigatorSidebarResizeWidgetElement = document.createElement("div");
this._navigatorSidebarResizeWidgetElement.addStyleClass("scripts-navigator-resizer-widget");
this._parentSplitView.installResizer(this._navigatorSidebarResizeWidgetElement);
this._navigatorView.element.appendChild(this._navigatorSidebarResizeWidgetElement);

this._navigatorShowHideButton = this._createNavigatorControlButton(WebInspector.UIString("Show navigator"), "scripts-navigator-show-hide-button", this._toggleNavigator.bind(this));
this._navigatorShowHideButton.addStyleClass("toggled-on");
this._navigatorShowHideButton.title = WebInspector.UIString("Hide navigator");
this._parentSplitView.element.appendChild(this._navigatorShowHideButton);

this._navigatorPinButton = this._createNavigatorControlButton(WebInspector.UIString("Pin navigator"), "scripts-navigator-pin-button", this._pinNavigator.bind(this));
this._navigatorPinButton.addStyleClass("hidden");
this._navigatorView.element.appendChild(this._navigatorPinButton);

WebInspector.settings.navigatorHidden = WebInspector.settings.createSetting("navigatorHidden", true);
if (WebInspector.settings.navigatorHidden.get())
this._toggleNavigator();
}

WebInspector.NavigatorOverlayController.prototype = {
wasShown: function()
{
window.setTimeout(this._maybeShowNavigatorOverlay.bind(this), 0);
},

_createNavigatorControlButton: function(title, id, listener)
{
var button = document.createElement("button");
button.title = title;
button.id = id;
button.addStyleClass("scripts-navigator-control-button");
button.addEventListener("click", listener, false);
button.createChild("div", "glyph");
return button;
},

_escDownWhileNavigatorOverlayOpen: function(event)
{
this.hideNavigatorOverlay();
},

_maybeShowNavigatorOverlay: function()
{
if (WebInspector.settings.navigatorHidden.get() && !WebInspector.settings.navigatorWasOnceHidden.get())
this.showNavigatorOverlay();
},

_toggleNavigator: function()
{
if (this._navigatorOverlayShown)
this.hideNavigatorOverlay();
else if (this._navigatorHidden)
this.showNavigatorOverlay();
else
this._hidePinnedNavigator();
},

_hidePinnedNavigator: function()
{
this._navigatorHidden = true;
this._navigatorShowHideButton.removeStyleClass("toggled-on");
this._navigatorShowHideButton.title = WebInspector.UIString("Show scripts navigator");
this._editorView.element.addStyleClass("navigator-hidden");
this._navigatorSidebarResizeWidgetElement.addStyleClass("hidden");

this._navigatorPinButton.removeStyleClass("hidden");

this._parentSplitView.hideSidebarElement();
this._navigatorView.detach();
this._editorView.focus();
WebInspector.settings.navigatorHidden.set(true);
},

_pinNavigator: function()
{
delete this._navigatorHidden;
this.hideNavigatorOverlay();

this._navigatorPinButton.addStyleClass("hidden");
this._navigatorShowHideButton.addStyleClass("toggled-on");
this._navigatorShowHideButton.title = WebInspector.UIString("Hide scripts navigator");

this._editorView.element.removeStyleClass("navigator-hidden");
this._navigatorSidebarResizeWidgetElement.removeStyleClass("hidden");

this._parentSplitView.showSidebarElement();
this._navigatorView.show(this._parentSplitView.sidebarElement);
this._navigatorView.focus();
WebInspector.settings.navigatorHidden.set(false);
},

showNavigatorOverlay: function()
{
if (this._navigatorOverlayShown)
return;

this._navigatorOverlayShown = true;
this._sidebarOverlay = new WebInspector.SidebarOverlay(this._navigatorView, "scriptsPanelNavigatorOverlayWidth", Preferences.minScriptsSidebarWidth);
this._sidebarOverlay.addEventListener(WebInspector.SidebarOverlay.EventTypes.WasShown, this._navigatorOverlayWasShown, this);
this._sidebarOverlay.addEventListener(WebInspector.SidebarOverlay.EventTypes.WillHide, this._navigatorOverlayWillHide, this);

var navigatorOverlayResizeWidgetElement = document.createElement("div");
navigatorOverlayResizeWidgetElement.addStyleClass("scripts-navigator-resizer-widget");
this._sidebarOverlay.resizerWidgetElement = navigatorOverlayResizeWidgetElement;

this._sidebarOverlay.show(this._parentSplitView.element);
},

hideNavigatorOverlay: function()
{
if (!this._navigatorOverlayShown)
return;

this._sidebarOverlay.hide();
this._editorView.focus();
},

_navigatorOverlayWasShown: function(event)
{
this._navigatorView.element.appendChild(this._navigatorShowHideButton);
this._navigatorShowHideButton.addStyleClass("toggled-on");
this._navigatorShowHideButton.title = WebInspector.UIString("Hide navigator");
this._navigatorView.focus();
this._panel.registerShortcut(WebInspector.KeyboardShortcut.Keys.Esc.code, this._escDownWhileNavigatorOverlayOpen.bind(this));
},

_navigatorOverlayWillHide: function(event)
{
delete this._navigatorOverlayShown;
WebInspector.settings.navigatorWasOnceHidden.set(true);
this._parentSplitView.element.appendChild(this._navigatorShowHideButton);
this._navigatorShowHideButton.removeStyleClass("toggled-on");
this._navigatorShowHideButton.title = WebInspector.UIString("Show navigator");
this._panel.unregisterShortcut(WebInspector.KeyboardShortcut.Keys.Esc.code);
}
}






WebInspector.NavigatorView = function()
{
WebInspector.View.call(this);
this.registerRequiredCSS("navigatorView.css");

this._treeSearchBoxElement = document.createElement("div");
this._treeSearchBoxElement.className = "navigator-tree-search-box";
this.element.appendChild(this._treeSearchBoxElement);

var scriptsTreeElement = document.createElement("ol");
this._scriptsTree = new WebInspector.NavigatorTreeOutline(this._treeSearchBoxElement, scriptsTreeElement);

var scriptsOutlineElement = document.createElement("div");
scriptsOutlineElement.addStyleClass("outline-disclosure");
scriptsOutlineElement.addStyleClass("navigator");
scriptsOutlineElement.appendChild(scriptsTreeElement);

this.element.addStyleClass("fill");
this.element.addStyleClass("navigator-container");
this.element.appendChild(scriptsOutlineElement);
this.setDefaultFocusedElement(this._scriptsTree.element);

this._folderTreeElements = {};
this._scriptTreeElementsByUISourceCode = new Map();

WebInspector.settings.showScriptFolders.addChangeListener(this._showScriptFoldersSettingChanged.bind(this));
}


WebInspector.NavigatorView.Events = {
ItemSelected: "ItemSelected"
}

WebInspector.NavigatorView.prototype = {

addUISourceCode: function(uiSourceCode)
{
if (this._scriptTreeElementsByUISourceCode.get(uiSourceCode))
return;

var scriptTreeElement = new WebInspector.NavigatorScriptTreeElement(this, uiSourceCode, "");
this._scriptTreeElementsByUISourceCode.put(uiSourceCode, scriptTreeElement);
this._updateScriptTitle(uiSourceCode);

var folderTreeElement = this.getOrCreateFolderTreeElement(uiSourceCode);
folderTreeElement.appendChild(scriptTreeElement);
},


_updateScriptTitle: function(uiSourceCode)
{
var scriptTreeElement = this._scriptTreeElementsByUISourceCode.get(uiSourceCode);
if (!scriptTreeElement)
return;

var titleText;
if (uiSourceCode.parsedURL.isValid) {
titleText = uiSourceCode.parsedURL.lastPathComponent;
if (uiSourceCode.parsedURL.queryParams)
titleText += "?" + uiSourceCode.parsedURL.queryParams;
} else if (uiSourceCode.parsedURL)
titleText = uiSourceCode.parsedURL.url;
if (!titleText)
titleText = WebInspector.UIString("(program)");
scriptTreeElement.titleText = titleText;
},


isScriptSourceAdded: function(uiSourceCode)
{
var scriptTreeElement = this._scriptTreeElementsByUISourceCode.get(uiSourceCode);
return !!scriptTreeElement;
},


revealUISourceCode: function(uiSourceCode)
{
if (this._scriptsTree.selectedTreeElement)
this._scriptsTree.selectedTreeElement.deselect();

this._lastSelectedUISourceCode = uiSourceCode;

var scriptTreeElement = this._scriptTreeElementsByUISourceCode.get(uiSourceCode);
scriptTreeElement.revealAndSelect(true);
},


replaceUISourceCodes: function(oldUISourceCodeList, uiSourceCodeList)
{
var added = false;
var selected = false;
for (var i = 0; i < oldUISourceCodeList.length; ++i) {
var uiSourceCode = oldUISourceCodeList[i];
if (!this._scriptTreeElementsByUISourceCode.get(uiSourceCode))
continue;
added = true;

if (this._lastSelectedUISourceCode === uiSourceCode)
selected = true;
this._removeUISourceCode(uiSourceCode);
}

if (!added)
return;

for (var i = 0; i < uiSourceCodeList.length; ++i)
this.addUISourceCode(uiSourceCodeList[i]);

if (selected)
this.revealUISourceCode(uiSourceCodeList[0]);
},


_scriptSelected: function(uiSourceCode, focusSource)
{
this._lastSelectedUISourceCode = uiSourceCode;
var data = { uiSourceCode: uiSourceCode, focusSource: focusSource};
this.dispatchEventToListeners(WebInspector.NavigatorView.Events.ItemSelected, data);
},


_removeUISourceCode: function(uiSourceCode)
{
var treeElement = this._scriptTreeElementsByUISourceCode.get(uiSourceCode);
while (treeElement) {
var parent = treeElement.parent;
if (parent) {
if (treeElement instanceof WebInspector.NavigatorFolderTreeElement)
delete this._folderTreeElements[treeElement.folderIdentifier];
parent.removeChild(treeElement);
if (parent.children.length)
break;
}
treeElement = parent;
}
this._scriptTreeElementsByUISourceCode.remove(uiSourceCode);
},

_showScriptFoldersSettingChanged: function()
{
var uiSourceCodes = this._scriptsTree.scriptTreeElements();
this.reset();

for (var i = 0; i < uiSourceCodes.length; ++i)
this.addUISourceCode(uiSourceCodes[i]);

if (this._lastSelectedUISourceCode)
this.revealUISourceCode(this._lastSelectedUISourceCode);
},

_fileRenamed: function(uiSourceCode, newTitle)
{

},


rename: function(uiSourceCode, callback)
{
var scriptTreeElement = this._scriptTreeElementsByUISourceCode.get(uiSourceCode);
if (!scriptTreeElement)
return;


WebInspector.markBeingEdited(scriptTreeElement.treeOutline.element, true);

function commitHandler(element, newTitle, oldTitle)
{
if (newTitle && newTitle !== oldTitle)
this._fileRenamed(uiSourceCode, newTitle);
else
this._updateScriptTitle(uiSourceCode);
afterEditing();
}

function cancelHandler()
{
afterEditing();
}

function afterEditing()
{
WebInspector.markBeingEdited(scriptTreeElement.treeOutline.element, false);
if (callback)
callback();
}

var editingConfig = new WebInspector.EditingConfig(commitHandler.bind(this), cancelHandler.bind(this));
WebInspector.startEditing(scriptTreeElement.titleElement, editingConfig);
window.getSelection().setBaseAndExtent(scriptTreeElement.titleElement, 0, scriptTreeElement.titleElement, 1);
},

reset: function()
{
this._scriptsTree.stopSearch();
this._scriptsTree.removeChildren();
this._folderTreeElements = {};
this._scriptTreeElementsByUISourceCode.clear();
},


createFolderTreeElement: function(parentFolderElement, folderIdentifier, domain, folderName)
{
var folderTreeElement = new WebInspector.NavigatorFolderTreeElement(folderIdentifier, domain, folderName);
parentFolderElement.appendChild(folderTreeElement);
this._folderTreeElements[folderIdentifier] = folderTreeElement;
return folderTreeElement;
},


getOrCreateFolderTreeElement: function(uiSourceCode)
{
return this._getOrCreateFolderTreeElement(uiSourceCode.parsedURL.host, uiSourceCode.parsedURL.folderPathComponents);
},


_getOrCreateFolderTreeElement: function(domain, folderName)
{
var folderIdentifier = domain + "/" + folderName;

if (this._folderTreeElements[folderIdentifier])
return this._folderTreeElements[folderIdentifier];

var showScriptFolders = WebInspector.settings.showScriptFolders.get();

if ((!domain && !folderName) || !showScriptFolders)
return this._scriptsTree;

var parentFolderElement;
if (!folderName)
parentFolderElement = this._scriptsTree;
else
parentFolderElement = this._getOrCreateFolderTreeElement(domain, "");

return this.createFolderTreeElement(parentFolderElement, folderIdentifier, domain, folderName);
},

handleContextMenu: function(event, uiSourceCode)
{

}
}

WebInspector.NavigatorView.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.NavigatorTreeOutline = function(treeSearchBoxElement, element)
{
TreeOutline.call(this, element);
this.element = element;

this._treeSearchBoxElement = treeSearchBoxElement;

this.comparator = WebInspector.NavigatorTreeOutline._treeElementsCompare;

this.searchable = true;
this.searchInputElement = document.createElement("input");
}

WebInspector.NavigatorTreeOutline._treeElementsCompare = function compare(treeElement1, treeElement2)
{

function typeWeight(treeElement)
{
if (treeElement instanceof WebInspector.NavigatorFolderTreeElement) {
if (treeElement.isDomain)
return 1;
return 2;
}
return 3;
}

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.titleText;
var title2 = treeElement2.titleText;
result = title1.localeCompare(title2);
}
return result;
}

WebInspector.NavigatorTreeOutline.prototype = {

scriptTreeElements: function()
{
var result = [];
if (this.children.length) {
for (var treeElement = this.children[0]; treeElement; treeElement = treeElement.traverseNextTreeElement(false, this, true)) {
if (treeElement instanceof WebInspector.NavigatorScriptTreeElement)
result.push(treeElement.uiSourceCode);
}
}
return result;
},

searchStarted: function()
{
this._treeSearchBoxElement.appendChild(this.searchInputElement);
this._treeSearchBoxElement.addStyleClass("visible");
},

searchFinished: function()
{
this._treeSearchBoxElement.removeChild(this.searchInputElement);
this._treeSearchBoxElement.removeStyleClass("visible");
}
}

WebInspector.NavigatorTreeOutline.prototype.__proto__ = TreeOutline.prototype;


WebInspector.BaseNavigatorTreeElement = function(title, iconClasses, hasChildren, noIcon)
{
TreeElement.call(this, "", null, hasChildren);
this._titleText = title;
this._iconClasses = iconClasses;
this._noIcon = noIcon;
}

WebInspector.BaseNavigatorTreeElement.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-navigator-tree-element-title";
this._titleTextNode = document.createTextNode("");
this._titleTextNode.textContent = this._titleText;
this.titleElement.appendChild(this._titleTextNode);
this.listItemElement.appendChild(this.titleElement);

this.expand();
},

onreveal: function()
{
if (this.listItemElement)
this.listItemElement.scrollIntoViewIfNeeded(true);
},


get titleText()
{
return this._titleText;
},

set titleText(titleText)
{
this._titleText = titleText || "";
if (this.titleElement)
this.titleElement.textContent = this._titleText;
},


matchesSearchText: function(searchText)
{
return this.titleText.match(new RegExp("^" + searchText.escapeForRegExp(), "i"));
}
}

WebInspector.BaseNavigatorTreeElement.prototype.__proto__ = TreeElement.prototype;


WebInspector.NavigatorFolderTreeElement = function(folderIdentifier, domain, folderName)
{
this._folderIdentifier = folderIdentifier;
this._folderName = folderName;

var iconClass = this.isDomain ? "navigator-domain-tree-item" : "navigator-folder-tree-item";
var title = this.isDomain ? domain : folderName.substring(1);

WebInspector.BaseNavigatorTreeElement.call(this, title, [iconClass], true);
this.tooltip = folderName;
}

WebInspector.NavigatorFolderTreeElement.prototype = {

get folderIdentifier()
{
return this._folderIdentifier;
},


get isDomain()
{
return this._folderName === "";
},

onattach: function()
{
WebInspector.BaseNavigatorTreeElement.prototype.onattach.call(this);
if (this._isDomain)
this.collapse();
else
this.expand();
}
}

WebInspector.NavigatorFolderTreeElement.prototype.__proto__ = WebInspector.BaseNavigatorTreeElement.prototype;


WebInspector.NavigatorScriptTreeElement = function(navigatorView, uiSourceCode, title)
{
WebInspector.BaseNavigatorTreeElement.call(this, title, ["navigator-script-tree-item"], false);
this._navigatorView = navigatorView;
this._uiSourceCode = uiSourceCode;
this.tooltip = uiSourceCode.url;
}

WebInspector.NavigatorScriptTreeElement.prototype = {

get uiSourceCode()
{
return this._uiSourceCode;
},

onattach: function()
{
WebInspector.BaseNavigatorTreeElement.prototype.onattach.call(this);
this.listItemElement.addEventListener("click", this._onclick.bind(this), false);
},

onspace: function()
{
this._navigatorView._scriptSelected(this.uiSourceCode, true);
return true;
},


_onclick: function(event)
{
this._navigatorView._scriptSelected(this.uiSourceCode, false);
},

ondblclick: function()
{
this._navigatorView._scriptSelected(this.uiSourceCode, true);
},

onenter: function()
{
this._navigatorView._scriptSelected(this.uiSourceCode, true);
return true;
},


_handleContextMenuEvent: function(event)
{
this._navigatorView.handleContextMenu(event, this._uiSourceCode);
}
}

WebInspector.NavigatorScriptTreeElement.prototype.__proto__ = WebInspector.BaseNavigatorTreeElement.prototype;






WebInspector.NetworkLog = function()
{
this._requests = [];
WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestStarted, this._onRequestStarted, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._onMainFrameNavigated, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.OnLoad, this._onLoad, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.DOMContentLoaded, this._onDOMContentLoaded, this);
}

WebInspector.NetworkLog.prototype = {

get requests()
{
return this._requests;
},


pageLoadForRequest: function(request)
{
return request.__page;
},


_onMainFrameNavigated: function(event)
{
var mainFrame =   event.data;

this._currentPageLoad = null;
var oldRequests = this._requests.splice(0, this._requests.length);
for (var i = 0; i < oldRequests.length; ++i) {
var request = oldRequests[i];
if (request.loaderId === mainFrame.loaderId) {
if (!this._currentPageLoad)
this._currentPageLoad = new WebInspector.PageLoad(request);
this._requests.push(request);
request.__page = this._currentPageLoad;
}
}
},


_onRequestStarted: function(event)
{
var request =   event.data;
this._requests.push(request);
request.__page = this._currentPageLoad;
},


_onDOMContentLoaded: function(event)
{
if (this._currentPageLoad)
this._currentPageLoad.contentLoadTime = event.data;
},


_onLoad: function(event)
{
if (this._currentPageLoad)
this._currentPageLoad.loadTime = event.data;
}
}


WebInspector.networkLog = null;


WebInspector.PageLoad = function(mainRequest)
{
this.id = ++WebInspector.PageLoad._lastIdentifier;
this.url = mainRequest.url;
this.startTime = mainRequest.startTime;
}

WebInspector.PageLoad._lastIdentifier = 0;






WebInspector.ResourceTreeModel = function(networkManager)
{
networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.ResourceTrackingEnabled, this._onResourceTrackingEnabled, this);
networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestUpdated, this._onRequestUpdated, this);
networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestFinished, this._onRequestUpdated, this);
networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestUpdateDropped, this._onRequestUpdateDropped, 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();

NetworkAgent.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 = {
_onResourceTrackingEnabled: function()
{
this._fetchResourceTree();
},

_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.requests.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._remove();
},


_onRequestUpdated: function(event)
{
if (!this._cachedResourcesProcessed)
return;

var request =   event.data;
if (request.failed || request.type === WebInspector.resourceTypes.XHR)
return;

var frame = this._frames[request.frameId];
if (frame) {
var resource = frame._addRequest(request);
this._addPendingConsoleMessagesToResource(resource);
}
},


_onRequestUpdateDropped: 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 = new WebInspector.Resource(null, url, frame.url, frameId, event.data.loaderId, WebInspector.resourceTypes[event.data.resourceType], event.data.mimeType);
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 = msg.url ? this.resourceForURL(msg.url) : null;
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, WebInspector.resourceTypes.Document, framePayload.mimeType);

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, WebInspector.resourceTypes[subresource.type], subresource.mimeType);
frame._addResource(resource);
}
},


_createResourceFromFramePayload: function(frame, url, type, mimeType)
{
return new WebInspector.Resource(null, url, frame.url, frame.id, frame.loaderId, type, mimeType);
}
}

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._securityOrigin = payload.securityOrigin || "";
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 securityOrigin()
{
return this._securityOrigin;
},


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._securityOrigin = framePayload.securityOrigin || "";
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)
{
this._childFrames.remove(frame);
frame._remove();
},

_removeChildFrames: function()
{
var copy = this._childFrames.slice();
for (var i = 0; i < copy.length; ++i)
this._removeChildFrame(copy[i]); 
},

_remove: function()
{
this._removeChildFrames();
delete this._model._frames[this.id];
this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this);
},


_addResource: function(resource)
{
if (this._resourcesMap[resource.url] === resource) {

return;
}
this._resourcesMap[resource.url] = resource;
this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resource);
},


_addRequest: function(request)
{
var resource = this._resourcesMap[request.url];
if (resource && resource.request === request) {

return resource;
}
resource = new WebInspector.Resource(request, request.url, request.documentURL, request.frameId, request.loaderId, request.type, request.mimeType);
this._resourcesMap[resource.url] = resource;
this._model.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, resource);
return 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);
},

loadEventFired: function(time)
{
this._resourceTreeModel.dispatchEventToListeners(WebInspector.ResourceTreeModel.EventTypes.OnLoad, time);
},

frameNavigated: function(frame)
{
this._resourceTreeModel._frameNavigated(frame);
},

frameDetached: function(frameId)
{
this._resourceTreeModel._frameDetached(frameId);
}
}


WebInspector.resourceTreeModel = null;






WebInspector.ParsedURL = function(url)
{
this.isValid = false;
this.url = url;
this.scheme = "";
this.host = "";
this.port = "";
this.path = "";
this.queryParams = "";
this.fragment = "";
this.folderPathComponents = "";
this.lastPathComponent = "";







var match = url.match(/^([^:]+):\/\/([^\/:]*)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i);
if (match) {
this.isValid = true;
this.scheme = match[1].toLowerCase();
this.host = match[2];
this.port = match[3];
this.path = match[4] || "/";
this.fragment = match[5];
} else {
if (this.url.startsWith("data:")) {
this.scheme = "data";
return;
}
if (this.url === "about:blank") {
this.scheme = "about";
return;
}
this.path = this.url;
}

if (this.path) {

var path = this.path;
var indexOfQuery = path.indexOf("?");
if (indexOfQuery !== -1) {
this.queryParams = path.substring(indexOfQuery + 1)
path = path.substring(0, indexOfQuery);
}


var lastSlashIndex = path.lastIndexOf("/");
if (lastSlashIndex !== -1) {
this.folderPathComponents = path.substring(0, lastSlashIndex);
this.lastPathComponent = path.substring(lastSlashIndex + 1);
} else
this.lastPathComponent = path;
}
}

WebInspector.ParsedURL.prototype = {
get displayName()
{
if (this._displayName)
return this._displayName;

if (this.scheme === "data") {
this._displayName = this.url.trimEnd(20);
return this._displayName;
}

if (this.url === "about:blank")
return this.url;

this._displayName = this.lastPathComponent;
if (!this._displayName)
this._displayName = WebInspector.displayDomain(this.host);
if (!this._displayName && this.url)
this._displayName = this.url.trimURL(WebInspector.inspectedPageDomain ? WebInspector.inspectedPageDomain : "");
if (this._displayName === "/")
this._displayName = this.url;
return this._displayName;
}
}

String.prototype.asParsedURL = function()
{
var parsedURL = new WebInspector.ParsedURL(this.toString());
if (parsedURL.isValid)
return parsedURL;
return null;
}


WebInspector.resourceForURL = function(url)
{
return WebInspector.resourceTreeModel.resourceForURL(url);
}


WebInspector.forAllResources = function(callback)
{
WebInspector.resourceTreeModel.forAllResources(callback);
}


WebInspector.displayDomain = function(host)
{
if (host && (!WebInspector.inspectedPageDomain || (WebInspector.inspectedPageDomain && host !== WebInspector.inspectedPageDomain)))
return host;
return "";
}


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.startsWith(baseURL))
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.startsWith("www.") ? "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)
{
    /**
     * @param {string} title
     * @param {string} url
     * @param {string=} lineNumber
     * @return {Node}
     */
    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.NetworkRequest} request
 * @param {string=} classes
 * @return {Element}
 */
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().startsWith("javascript:"))
        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.parsedURL.path === url) {
            resourceURL = resource.url;
            return true;
        }
    }
    WebInspector.forAllResources(callback);
    return resourceURL;
}

/**
 * @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.startsWith("data:") || trimmedHref.startsWith("javascript:"))
            return href;
    }

    var parsedURL = baseURL.asParsedURL();
    if (parsedURL) {
        var path = href;
        if (path.charAt(0) !== "/") {
            var basePath = parsedURL.path;

            // Trim off the query part of the basePath.
            var questionMarkIndex = basePath.indexOf("?");
            if (questionMarkIndex > 0)
                basePath = basePath.substring(0, questionMarkIndex);
            // 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;
}

/* ResourceType.js */

/*
 * Copyright (C) 2012 Google Inc.  All rights reserved.
 * 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
 * @param {string} name
 * @param {string} title
 * @param {string} categoryTitle
 * @param {string} color
 * @param {boolean} isTextType
 */
WebInspector.ResourceType = function(name, title, categoryTitle, color, isTextType)
{
    this._name = name;
    this._title = title;
    this._categoryTitle = categoryTitle;
    this._color = color;
    this._isTextType = isTextType;
}

WebInspector.ResourceType.prototype = {
    /**
     * @return {string}
     */
    name: function()
    {
        return this._name;
    },

    /**
     * @return {string}
     */
    title: function()
    {
        return this._title;
    },

    /**
     * @return {string}
     */
    categoryTitle: function()
    {
        return this._categoryTitle;
    },

    /**
     * @return {string}
     */
    color: function()
    {
        return this._color;
    },

    /**
     * @return {boolean}
     */
    isTextType: function()
    {
        return this._isTextType;
    },

    /**
     * @return {string}
     */
    toString: function()
    {
        return this._name;
    }
}

//Keep these in sync with WebCore::InspectorPageAgent::resourceTypeJson
WebInspector.resourceTypes = {
    Document: new WebInspector.ResourceType("document", "Document", "Documents", "rgb(47,102,236)", true),
    Stylesheet: new WebInspector.ResourceType("stylesheet", "Stylesheet", "Stylesheets", "rgb(157,231,119)", true),
    Image: new WebInspector.ResourceType("image", "Image", "Images", "rgb(164,60,255)", false),
    Script: new WebInspector.ResourceType("script", "Script", "Scripts", "rgb(255,121,0)", true),
    XHR: new WebInspector.ResourceType("xhr", "XHR", "XHR", "rgb(231,231,10)", true),
    Font: new WebInspector.ResourceType("font", "Font", "Fonts", "rgb(255,82,62)", false),
    WebSocket: new WebInspector.ResourceType("websocket", "WebSocket", "WebSockets", "rgb(186,186,186)", false), // FIXME: Decide the color.
    Other: new WebInspector.ResourceType("other", "Other", "Other", "rgb(186,186,186)", false)
}

/* 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;

/* TimelineModel.js */

/*
 * Copyright (C) 2012 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.TimelineModel = function()
{
    this._records = [];
    this._minimumRecordTime = -1;
    this._maximumRecordTime = -1;
    this._collectionEnabled = false;

    WebInspector.timelineManager.addEventListener(WebInspector.TimelineManager.EventTypes.TimelineEventRecorded, this._onRecordAdded, this);
}

WebInspector.TimelineModel.RecordType = {
    Root: "Root",
    EventDispatch: "EventDispatch",

    BeginFrame: "BeginFrame",
    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",

    RequestAnimationFrame: "RequestAnimationFrame",
    CancelAnimationFrame: "CancelAnimationFrame",
    FireAnimationFrame: "FireAnimationFrame"
}

WebInspector.TimelineModel.Events = {
    RecordAdded: "RecordAdded",
    RecordsCleared: "RecordsCleared"
}

WebInspector.TimelineModel.startTimeInSeconds = function(record)
{
    return record.startTime / 1000;
}

WebInspector.TimelineModel.endTimeInSeconds = function(record)
{
    return (typeof record.endTime === "undefined" ? record.startTime : record.endTime) / 1000;
}

WebInspector.TimelineModel.durationInSeconds = function(record)
{
    return WebInspector.TimelineModel.endTimeInSeconds(record) - WebInspector.TimelineModel.startTimeInSeconds(record);
}

/**
 * @param {Object} total
 * @param {Object} rawRecord
 */
WebInspector.TimelineModel.aggregateTimeForRecord = function(total, rawRecord)
{
    var childrenTime = 0;
    var children = rawRecord["children"] || [];
    for (var i = 0; i < children.length; ++i)  {
        WebInspector.TimelineModel.aggregateTimeForRecord(total, children[i]);
        childrenTime += WebInspector.TimelineModel.durationInSeconds(children[i]);
    }
    var categoryName = WebInspector.TimelinePresentationModel.recordStyle(rawRecord).category.name;
    var ownTime = WebInspector.TimelineModel.durationInSeconds(rawRecord) - childrenTime;
    total[categoryName] = (total[categoryName] || 0) + ownTime;
}

WebInspector.TimelineModel.prototype = {
    startRecord: function()
    {
        if (this._collectionEnabled)
            return;
        this.reset();
        WebInspector.timelineManager.start(30);
        this._collectionEnabled = true;
    },

    stopRecord: function()
    {
        if (!this._collectionEnabled)
            return;
        WebInspector.timelineManager.stop();
        this._collectionEnabled = false;
    },

    get records()
    {
        return this._records;
    },

    _onRecordAdded: function(event)
    {
        if (this._collectionEnabled)
            this._addRecord(event.data);
    },

    _addRecord: function(record)
    {
        this._records.push(record);
        this._updateBoundaries(record);
        this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordAdded, record);
    },

    _loadNextChunk: function(data, index)
    {
        for (var i = 0; i < 20 && index < data.length; ++i, ++index)
            this._addRecord(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);
            this.reset();
            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(new String(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 fileName = "TimelineRawData-" + now.toISO8601Compact() + ".json";
        WebInspector.save(fileName, records.join(",\n"), true);
    },

    reset: function()
    {
        this._records = [];
        this._minimumRecordTime = -1;
        this._maximumRecordTime = -1;
        this.dispatchEventToListeners(WebInspector.TimelineModel.Events.RecordsCleared);
    },

    minimumRecordTime: function()
    {
        return this._minimumRecordTime;
    },

    maximumRecordTime: function()
    {
        return this._maximumRecordTime;
    },

    _updateBoundaries: function(record)
    {
        var startTime = WebInspector.TimelineModel.startTimeInSeconds(record);
        var endTime = WebInspector.TimelineModel.endTimeInSeconds(record);

        if (this._minimumRecordTime === -1 || startTime < this._minimumRecordTime)
            this._minimumRecordTime = startTime;
        if (this._maximumRecordTime === -1 || endTime > this._maximumRecordTime)
            this._maximumRecordTime = endTime;
    },

    /**
     * @param {Object} rawRecord
     */
    recordOffsetInSeconds: function(rawRecord)
    {
        return WebInspector.TimelineModel.startTimeInSeconds(rawRecord) - this._minimumRecordTime;
    }
}

WebInspector.TimelineModel.prototype.__proto__ = WebInspector.Object.prototype;

/* UserAgentSupport.js */

/*
 * Copyright (C) 2012 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
 */
WebInspector.UserAgentSupport = function()
{
    if (WebInspector.settings.deviceMetrics.get())
        this._deviceMetricsChanged();
    WebInspector.settings.deviceMetrics.addChangeListener(this._deviceMetricsChanged, this);
    WebInspector.settings.deviceFitWindow.addChangeListener(this._deviceMetricsChanged, this);
}

/**
 * @constructor
 * @param {number} width
 * @param {number} height
 * @param {number} fontScaleFactor
 */
WebInspector.UserAgentSupport.DeviceMetrics = function(width, height, fontScaleFactor)
{
    this.width = width;
    this.height = height;
    this.fontScaleFactor = fontScaleFactor;
}

/**
 * @return {WebInspector.UserAgentSupport.DeviceMetrics}
 */
WebInspector.UserAgentSupport.DeviceMetrics.parseSetting = function(value)
{
    if (value) {
        var splitMetrics = value.split("x");
        if (splitMetrics.length === 3)
            return new WebInspector.UserAgentSupport.DeviceMetrics(parseInt(splitMetrics[0], 10), parseInt(splitMetrics[1], 10), parseFloat(splitMetrics[2]));
    }
    return new WebInspector.UserAgentSupport.DeviceMetrics(0, 0, 1);
}

/**
 * @return {?WebInspector.UserAgentSupport.DeviceMetrics}
 */
WebInspector.UserAgentSupport.DeviceMetrics.parseUserInput = function(widthString, heightString, fontScaleFactorString)
{
    function isUserInputValid(value, isInteger)
    {
        if (!value)
            return true;
        return isInteger ? /^[0]*[1-9][\d]*$/.test(value) : /^[0]*([1-9][\d]*(\.\d+)?|\.\d+)$/.test(value);
    }

    if (!widthString ^ !heightString)
        return null;

    var isWidthValid = isUserInputValid(widthString, true);
    var isHeightValid = isUserInputValid(heightString, true);
    var isFontScaleFactorValid = isUserInputValid(fontScaleFactorString, false);

    if (!isWidthValid && !isHeightValid && !isFontScaleFactorValid)
        return null;

    var width = isWidthValid ? parseInt(widthString || "0", 10) : -1;
    var height = isHeightValid ? parseInt(heightString || "0", 10) : -1;
    var fontScaleFactor = isFontScaleFactorValid ? parseFloat(fontScaleFactorString) : -1;

    return new WebInspector.UserAgentSupport.DeviceMetrics(width, height, fontScaleFactor);
}

WebInspector.UserAgentSupport.DeviceMetrics.prototype = {
    /**
     * @return {boolean}
     */
    isValid: function()
    {
        return this.isWidthValid() && this.isHeightValid() && this.isFontScaleFactorValid();
    },

    /**
     * @return {boolean}
     */
    isWidthValid: function()
    {
        return this.width >= 0;
    },

    /**
     * @return {boolean}
     */
    isHeightValid: function()
    {
        return this.height >= 0;
    },

    /**
     * @return {boolean}
     */
    isFontScaleFactorValid: function()
    {
        return this.fontScaleFactor > 0;
    },

    /**
     * @return {string}
     */
    toSetting: function()
    {
        if (!this.isValid())
            return "";

        return this.width && this.height ? this.width + "x" + this.height + "x" + this.fontScaleFactor : "";
    },

    /**
     * @return {string}
     */
    widthToInput: function()
    {
        return this.isWidthValid() && this.width ? String(this.width) : "";
    },

    /**
     * @return {string}
     */
    heightToInput: function()
    {
        return this.isHeightValid() && this.height ? String(this.height) : "";
    },

    /**
     * @return {string}
     */
    fontScaleFactorToInput: function()
    {
        return this.isFontScaleFactorValid() && this.fontScaleFactor ? String(this.fontScaleFactor) : "";
    }
}

WebInspector.UserAgentSupport.prototype = {
    _deviceMetricsChanged: function()
    {
        var metrics = WebInspector.UserAgentSupport.DeviceMetrics.parseSetting(WebInspector.settings.deviceMetrics.get());
        if (metrics.isValid())
            PageAgent.setDeviceMetricsOverride(metrics.width, metrics.height, metrics.fontScaleFactor, WebInspector.settings.deviceFitWindow.get());
    }
}
/* 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 = {
    /** @return {string} */
    get id()
    {
        return this._id;
    },

    /** @return {string} */
    get name()
    {
        return this._name;
    },

    set name(x)
    {
        this._name = x;
    },

    /** @return {string} */
    get version()
    {
        return this._version;
    },

    set version(x)
    {
        this._version = x;
    },

    /** @return {string} */
    get domain()
    {
        return this._domain;
    },

    set domain(x)
    {
        this._domain = x;
    },

    /** @return {string} */
    get displayDomain()
    {
        return WebInspector.displayDomain(this._domain);
    },

    /**
     * @param {function(Array.<string>)} callback
     */
    getTableNames: function(callback)
    {
        function sortingCallback(error, names)
        {
            if (!error)
                callback(names.sort());
        }
        DatabaseAgent.getDatabaseTableNames(this._id, sortingCallback);
    },

    /**
     * @param {string} query
     * @param {function(Array.<string>, Array.<*>)} onSuccess
     * @param {function(DatabaseAgent.Error)} onError
     */
    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 = {
    /**
     * @param {DatabaseAgent.Database} payload
     */
    addDatabase: function(payload)
    {
        var database = new WebInspector.Database(
            payload.id,
            payload.domain,
            payload.name,
            payload.version);
        WebInspector.panels.resources.addDatabase(database);
    },

    /**
     * @param {number} transactionId
     * @param {Array.<string>} columnNames
     * @param {Array.<*>} values
     */
    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);
    },

    /**
     * @param {number} transactionId
     * @param {?DatabaseAgent.Error} errorObj
     */
    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 = {
    /** @return {string} */
    get id()
    {
        return this._id;
    },

    /** @return {string} */
    get domain()
    {
        return this._domain;
    },

    /** @return {boolean} */
    get isLocalStorage()
    {
        return this._isLocalStorage;
    },

    /**
     * @param {function(?Protocol.Error, Array.<DOMStorageAgent.Entry>):void=} callback
     */
    getEntries: function(callback)
    {
        DOMStorageAgent.getDOMStorageEntries(this._id, callback);
    },

    /**
     * @param {string} key
     * @param {string} value
     * @param {function(?Protocol.Error, boolean):void=} callback
     */
    setItem: function(key, value, callback)
    {
        DOMStorageAgent.setDOMStorageItem(this._id, key, value, callback);
    },

    /**
     * @param {string} key
     * @param {function(?Protocol.Error, boolean):void=} callback
     */
    removeItem: function(key, callback)
    {
        DOMStorageAgent.removeDOMStorageItem(this._id, key, callback);
    }
}

/**
 * @constructor
 * @implements {DOMStorageAgent.Dispatcher}
 */
WebInspector.DOMStorageDispatcher = function()
{
}

WebInspector.DOMStorageDispatcher.prototype = {

    /**
     * @param {DOMStorageAgent.Entry} payload
     */
    addDOMStorage: function(payload)
    {
        var domStorage = new WebInspector.DOMStorage(
            payload.id,
            payload.host,
            payload.isLocalStorage);
        WebInspector.panels.resources.addDOMStorage(domStorage);
    },

    /**
     * @param {string} storageId
     */
    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.rootNode().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.selectedNode = null;
    this.expandNodesWhenArrowing = false;
    this.setRootNode(new WebInspector.DataGridNode());
    this.indentWidth = 15;
    this.resizers = [];
    this._columnWidthsInitialized = false;
}

WebInspector.DataGrid.Events = {
    SelectedNode: "SelectedNode",
    DeselectedNode: "DeselectedNode"
}

/**
 * @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.rootNode().appendChild(nodes[i]);

    dataGrid.addEventListener("sorting changed", sortDataGrid, this);

    function sortDataGrid()
    {
        var nodes = dataGrid._rootNode.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.rootNode().removeChildren();
        for (var i = 0; i < nodes.length; i++)
            dataGrid._rootNode.appendChild(nodes[i]);
    }
    return dataGrid;
}

WebInspector.DataGrid.prototype = {
    setRootNode: function(rootNode)
    {
        if (this._rootNode) {
            this._rootNode.removeChildren();
            this._rootNode.dataGrid = null;
            this._rootNode._isRoot = false;
        }
        this._rootNode = rootNode;
        rootNode._isRoot = true;
        rootNode.hasChildren = false;
        rootNode._expanded = true;
        rootNode._revealed = true;
        rootNode.dataGrid = this;
    },

    rootNode: function()
    {
        return this._rootNode;
    },

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

    /**
     * @return {?string}
     */
    get sortColumnIdentifier()
    {
        if (!this._sortColumnCell)
            return null;
        return this._sortColumnCell.columnIdentifier;
    },

    /**
     * @return {?string}
     */
    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;

        maxDescentLevel = maxDescentLevel || 0;
        var children = this._enumerateChildren(this._rootNode, [], maxDescentLevel + 1);
        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._isRoot)
            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.rootNode().appendChild(this.creationNode);
},

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._isRoot) {
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.consume(true);
},

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._refreshCallback && (!gridNode || gridNode !== this.creationNode))
contextMenu.appendItem(WebInspector.UIString("Refresh"), this._refreshCallback.bind(this));

if (gridNode && gridNode.selectable && !gridNode.isEventWithinDisclosureTriangle(event)) {

if (this._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._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,

_isRoot: false,

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


nodeHeight: function()
{
var rowHeight = 16;
if (!this.revealed)
return 0;
if (!this.expanded)
return rowHeight;
var result = rowHeight;
for (var i = 0; i < this.children.length; i++)
result += this.children[i].nodeHeight();
return result;
},


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();
if (!this.revealed)
child.revealed = false;
},


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

_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._isRoot)
return;
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._isRoot)
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()
{
if (this._isRoot)
return;
var currentAncestor = this.parent;
while (currentAncestor && !currentAncestor._isRoot) {
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");
this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Events.SelectedNode);
}
},

revealAndSelect: function()
{
if (this._isRoot)
return;
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");
this.dataGrid.dispatchEventToListeners(WebInspector.DataGrid.Events.DeselectedNode);
}
},

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._isRoot && !((!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._isRoot)
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.firstChild;
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);
}
},


nodeHeight: function()
{
return 33;
}
};

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.rootNode().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.rootNode().appendChild(groupNode);
groupNode.element.addStyleClass("row-group");
this._populateNode(groupNode, item.cookies);
groupNode.expand();
} else
this._populateNode(this._dataGrid.rootNode(), 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.rootNode().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.rootNode().appendChild(node);
}
this._dataGrid.rootNode().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.startsWith(cookie.path)
&& (!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;

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.rootNode().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.rootNode().appendChild(node);
if (resource === selectedResource) {
nodeToSelect = node;
nodeToSelect.selected = true;
}
}

if (!nodeToSelect && this._dataGrid.rootNode().children.length)
this._dataGrid.rootNode().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.IndexedDBModel = function()
{
this._indexedDBRequestManager = new WebInspector.IndexedDBRequestManager();

WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameAdded, this._frameNavigated, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameNavigated, this._frameNavigated, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.FrameDetached, this._frameDetached, this);

this._frames = {};
this._databases = new Map();
this._frameIdsBySecurityOrigin = {};
this._databaseNamesBySecurityOrigin = {};

this.refreshDatabaseNames();
}

WebInspector.IndexedDBModel.KeyTypes = {
NumberType:  "number",
StringType:  "string",
DateType:    "date",
ArrayType:   "array"
};


WebInspector.IndexedDBModel.idbKeyFromKey = function(key)
{
var idbKey;
switch (key.type) {
case WebInspector.IndexedDBModel.KeyTypes.NumberType:
idbKey = key.number;
break;
case WebInspector.IndexedDBModel.KeyTypes.StringType:
idbKey = key.string;
break;
case WebInspector.IndexedDBModel.KeyTypes.DateType:
idbKey = new Date(key.date);
break;
case WebInspector.IndexedDBModel.KeyTypes.ArrayType:
idbKey = [];
for (var i = 0; i < key.array.length; ++i)
idbKey.push(WebInspector.IndexedDBModel.idbKeyFromKey(key.array[i]));
break;
}
return idbKey;
}

WebInspector.IndexedDBModel.keyFromIDBKey = function(idbKey)
{
if (typeof(idbKey) === "undefined" || idbKey === null)
return null;

var key = {};
switch (typeof(idbKey)) {
case "number":
key.number = idbKey;
key.type = WebInspector.IndexedDBModel.KeyTypes.NumberType;
break;
case "string":
key.string = idbKey;
key.type = WebInspector.IndexedDBModel.KeyTypes.StringType;
break;
case "object":
if (idbKey instanceof Date) {
key.date = idbKey.getTime();
key.type = WebInspector.IndexedDBModel.KeyTypes.DateType;
} else if (idbKey instanceof Array) {
key.array = [];
for (var i = 0; i < idbKey.length; ++i)
key.array.push(WebInspector.IndexedDBModel.keyFromIDBKey(idbKey[i]));
key.type = WebInspector.IndexedDBModel.KeyTypes.ArrayType;
}
break;
default:
return null;
}
return key;
}

WebInspector.IndexedDBModel.keyRangeFromIDBKeyRange = function(idbKeyRange)
{
var IDBKeyRange = window.IDBKeyRange || window.webkitIDBKeyRange;
if (typeof(idbKeyRange) === "undefined" || idbKeyRange === null)
return null;

var keyRange = {};
keyRange.lower = WebInspector.IndexedDBModel.keyFromIDBKey(idbKeyRange.lower);
keyRange.upper = WebInspector.IndexedDBModel.keyFromIDBKey(idbKeyRange.upper);
keyRange.lowerOpen = idbKeyRange.lowerOpen;
keyRange.upperOpen = idbKeyRange.upperOpen;
return keyRange;
}

WebInspector.IndexedDBModel.EventTypes = {
DatabaseAdded: "DatabaseAdded",
DatabaseRemoved: "DatabaseRemoved",
DatabaseLoaded: "DatabaseLoaded"
}

WebInspector.IndexedDBModel.prototype = {
refreshDatabaseNames: function()
{
this._reset();
if (WebInspector.resourceTreeModel.mainFrame)
this._framesNavigatedRecursively(WebInspector.resourceTreeModel.mainFrame);
},


refreshDatabase: function(databaseId)
{
this._loadDatabase(databaseId);
},


_framesNavigatedRecursively: function(resourceTreeFrame)
{
this._processFrameNavigated(resourceTreeFrame);
for (var i = 0; i < resourceTreeFrame.childFrames.length; ++i)
this._framesNavigatedRecursively(resourceTreeFrame.childFrames[i]);
},


_frameNavigated: function(event)
{
var resourceTreeFrame =   event.data;
this._processFrameNavigated(resourceTreeFrame);
},


_frameDetached: function(event)
{
var resourceTreeFrame =   event.data;
this._originRemovedFromFrame(resourceTreeFrame.id);
this._indexedDBRequestManager._frameDetached(resourceTreeFrame.id);
},

_reset: function()
{
for (var frameId in this._frames)
this._originRemovedFromFrame(frameId);

this._indexedDBRequestManager._reset();
},


_processFrameNavigated: function(resourceTreeFrame)
{
if (resourceTreeFrame.securityOrigin === "null")
return;
if (this._frameIdsBySecurityOrigin[resourceTreeFrame.securityOrigin])
this._originAddedToFrame(resourceTreeFrame.id, resourceTreeFrame.securityOrigin);
else
this._loadDatabaseNamesForFrame(resourceTreeFrame.id);
},


_originAddedToFrame: function(frameId, securityOrigin)
{
if (!this._frameIdsBySecurityOrigin[securityOrigin]) {
this._frameIdsBySecurityOrigin[securityOrigin] = [];
this._frameIdsBySecurityOrigin[securityOrigin].push(frameId);
this._databaseNamesBySecurityOrigin[securityOrigin] = [];
}
this._frames[frameId] = new WebInspector.IndexedDBModel.Frame(frameId, securityOrigin);
},


_originRemovedFromFrame: function(frameId)
{
var currentSecurityOrigin = this._frames[frameId] ? this._frames[frameId].securityOrigin : null;
if (!currentSecurityOrigin)
return;

delete this._frames[frameId];

var frameIdsForOrigin = this._frameIdsBySecurityOrigin[currentSecurityOrigin];
for (var i = 0; i < frameIdsForOrigin; ++i) {
if (frameIdsForOrigin[i] === frameId) {
frameIdsForOrigin.splice(i, 1);
break;
}
}
if (!frameIdsForOrigin.length)
this._originRemoved(currentSecurityOrigin);
},


_originRemoved: function(securityOrigin)
{
var frameIdsForOrigin = this._frameIdsBySecurityOrigin[securityOrigin];
for (var i = 0; i < frameIdsForOrigin; ++i)
delete this._frames[frameIdsForOrigin[i]];
delete this._frameIdsBySecurityOrigin[securityOrigin];
for (var i = 0; i < this._databaseNamesBySecurityOrigin[securityOrigin].length; ++i)
this._databaseRemoved(securityOrigin, this._databaseNamesBySecurityOrigin[securityOrigin][i]);
delete this._databaseNamesBySecurityOrigin[securityOrigin];
},


_updateOriginDatabaseNames: function(securityOrigin, databaseNames)
{
var newDatabaseNames = {};
for (var i = 0; i < databaseNames.length; ++i)
newDatabaseNames[databaseNames[i]] = true;
var oldDatabaseNames = {};
for (var i = 0; i < this._databaseNamesBySecurityOrigin[securityOrigin].length; ++i)
oldDatabaseNames[databaseNames[i]] = true;

this._databaseNamesBySecurityOrigin[securityOrigin] = databaseNames;

for (var databaseName in oldDatabaseNames) {
if (!newDatabaseNames[databaseName])
this._databaseRemoved(securityOrigin, databaseName);
}
for (var databaseName in newDatabaseNames) {
if (!oldDatabaseNames[databaseName])
this._databaseAdded(securityOrigin, databaseName);
}

if (!this._databaseNamesBySecurityOrigin[securityOrigin].length)
this._originRemoved(securityOrigin);
},


_databaseAdded: function(securityOrigin, databaseName)
{
var databaseId = new WebInspector.IndexedDBModel.DatabaseId(securityOrigin, databaseName);
this.dispatchEventToListeners(WebInspector.IndexedDBModel.EventTypes.DatabaseAdded, databaseId);
},


_databaseRemoved: function(securityOrigin, databaseName)
{
this._indexedDBRequestManager._databaseRemoved(this._frameIdsBySecurityOrigin[securityOrigin], databaseName);

var databaseId = new WebInspector.IndexedDBModel.DatabaseId(securityOrigin, databaseName);
this.dispatchEventToListeners(WebInspector.IndexedDBModel.EventTypes.DatabaseRemoved, databaseId);
},


_loadDatabaseNamesForFrame: function(frameId)
{

function callback(securityOriginWithDatabaseNames)
{
var databaseNames = securityOriginWithDatabaseNames.databaseNames;
var oldSecurityOrigin = this._frames[frameId] ? this._frames[frameId].securityOrigin : null;
if (!oldSecurityOrigin || oldSecurityOrigin !== securityOriginWithDatabaseNames.securityOrigin) {
this._originRemovedFromFrame(frameId);
this._originAddedToFrame(frameId, securityOriginWithDatabaseNames.securityOrigin);
}
this._updateOriginDatabaseNames(securityOriginWithDatabaseNames.securityOrigin, securityOriginWithDatabaseNames.databaseNames);
}

this._indexedDBRequestManager.requestDatabaseNamesForFrame(frameId, callback.bind(this));
},


_assertFrameId: function(databaseId)
{
var frameIds = this._frameIdsBySecurityOrigin[databaseId.securityOrigin];
if (!frameIds || !frameIds.length)
return null;

return frameIds[0];
},


_loadDatabase: function(databaseId)
{
var frameId = this._assertFrameId(databaseId);
if (!frameId)
return;


function callback(databaseWithObjectStores)
{
if (!this._frames[frameId])
return;

var databaseModel = new WebInspector.IndexedDBModel.Database(databaseId, databaseWithObjectStores.version);
this._databases.put(databaseId, databaseModel); 
for (var i = 0; i < databaseWithObjectStores.objectStores.length; ++i) {
var objectStore = databaseWithObjectStores.objectStores[i];
var objectStoreModel = new WebInspector.IndexedDBModel.ObjectStore(objectStore.name, objectStore.keyPath);
for (var j = 0; j < objectStore.indexes.length; ++j) {
var index = objectStore.indexes[j];
var indexModel = new WebInspector.IndexedDBModel.Index(index.name, index.keyPath, index.unique, index.multiEntry);
objectStoreModel.indexes[indexModel.name] = indexModel;
}
databaseModel.objectStores[objectStoreModel.name] = objectStoreModel;
}

this.dispatchEventToListeners(WebInspector.IndexedDBModel.EventTypes.DatabaseLoaded, databaseModel);
}

this._indexedDBRequestManager.requestDatabase(frameId, databaseId.name, callback.bind(this));
},


loadObjectStoreData: function(databaseId, objectStoreName, idbKeyRange, skipCount, pageSize, callback)
{
var frameId = this._assertFrameId(databaseId);
if (!frameId)
return;


function innerCallback(dataEntries, hasMore)
{
var entries = [];
for (var i = 0; i < dataEntries.length; ++i) {
var key = WebInspector.IndexedDBModel.idbKeyFromKey(dataEntries[i].key);
var primaryKey = WebInspector.IndexedDBModel.idbKeyFromKey(dataEntries[i].primaryKey);
var value = WebInspector.RemoteObject.fromPayload(dataEntries[i].value);
entries.push(new WebInspector.IndexedDBModel.Entry(key, primaryKey, value));
}
callback(entries, hasMore);
}

this._indexedDBRequestManager.requestObjectStoreData(frameId, databaseId.name, objectStoreName, idbKeyRange, skipCount, pageSize, innerCallback);
},


loadIndexData: function(databaseId, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback)
{
var frameId = this._assertFrameId(databaseId);
if (!frameId)
return;


function innerCallback(dataEntries, hasMore)
{
var entries = [];
for (var i = 0; i < dataEntries.length; ++i) {
var key = WebInspector.IndexedDBModel.idbKeyFromKey(dataEntries[i].key);
var primaryKey = WebInspector.IndexedDBModel.idbKeyFromKey(dataEntries[i].primaryKey);
var value = WebInspector.RemoteObject.fromPayload(dataEntries[i].value);
entries.push(new WebInspector.IndexedDBModel.Entry(key, primaryKey, value));
}
callback(entries, hasMore);
}

this._indexedDBRequestManager.requestIndexData(frameId, databaseId.name, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, innerCallback.bind(this));
}
}

WebInspector.IndexedDBModel.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.IndexedDBModel.Entry = function(key, primaryKey, value)
{
this.key = key;
this.primaryKey = primaryKey;
this.value = value;
}


WebInspector.IndexedDBModel.Frame = function(frameId, securityOrigin)
{
this.frameId = frameId;
this.securityOrigin = securityOrigin;
this.databaseNames = {};
}


WebInspector.IndexedDBModel.DatabaseId = function(securityOrigin, name)
{
this.securityOrigin = securityOrigin;
this.name = name;
}

WebInspector.IndexedDBModel.DatabaseId.prototype = {

equals: function(databaseId)
{
return this.name === databaseId.name && this.securityOrigin === databaseId.securityOrigin;
},
}

WebInspector.IndexedDBModel.Database = function(databaseId, version)
{
this.databaseId = databaseId;
this.version = version;
this.objectStores = {};
}


WebInspector.IndexedDBModel.ObjectStore = function(name, keyPath)
{
this.name = name;
this.keyPath = keyPath;
this.indexes = {};
}


WebInspector.IndexedDBModel.Index = function(name, keyPath, unique, multiEntry)
{
this.name = name;
this.keyPath = keyPath;
this.unique = unique;
this.multiEntry = multiEntry;
}


WebInspector.IndexedDBRequestManager = function()
{
this._lastRequestId = 0;
this._requestDatabaseNamesForFrameCallbacks = {};
this._requestDatabaseCallbacks = {};
this._requestDataCallbacks = {};

IndexedDBAgent.enable();
InspectorBackend.registerIndexedDBDispatcher(new WebInspector.IndexedDBDispatcher(this));
}

WebInspector.IndexedDBRequestManager.prototype = {

requestDatabaseNamesForFrame: function(frameId, callback)
{
var requestId = this._requestId();
var request = new WebInspector.IndexedDBRequestManager.DatabasesForFrameRequest(frameId, callback);
this._requestDatabaseNamesForFrameCallbacks[requestId] = request;

function innerCallback(error)
{
if (error) {
console.error("IndexedDBAgent error: " + error);
return;
}
}

IndexedDBAgent.requestDatabaseNamesForFrame(requestId, frameId, innerCallback);
},


_databaseNamesLoaded: function(requestId, securityOriginWithDatabaseNames)
{
var request = this._requestDatabaseNamesForFrameCallbacks[requestId];
if (!request)
return;

request.callback(securityOriginWithDatabaseNames);
},


requestDatabase: function(frameId, databaseName, callback)
{
var requestId = this._requestId();
var request = new WebInspector.IndexedDBRequestManager.DatabaseRequest(frameId, databaseName, callback);
this._requestDatabaseCallbacks[requestId] = request;

function innerCallback(error)
{
if (error) {
console.error("IndexedDBAgent error: " + error);
return;
}
}

IndexedDBAgent.requestDatabase(requestId, frameId, databaseName, innerCallback);
},


_databaseLoaded: function(requestId, databaseWithObjectStores)
{
var request = this._requestDatabaseCallbacks[requestId];
if (!request)
return;

request.callback(databaseWithObjectStores);
},


_requestData: function(frameId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback)
{
var requestId = this._requestId();
var request = new WebInspector.IndexedDBRequestManager.DataRequest(frameId, databaseName, objectStoreName, indexName, callback);
this._requestDataCallbacks[requestId] = request;

function innerCallback(error)
{
if (error) {
console.error("IndexedDBAgent error: " + error);
return;
}
}

var keyRange = WebInspector.IndexedDBModel.keyRangeFromIDBKeyRange(idbKeyRange);
IndexedDBAgent.requestData(requestId, frameId, databaseName, objectStoreName, indexName, skipCount, pageSize, keyRange ? keyRange : undefined, innerCallback);
},


requestObjectStoreData: function(frameId, databaseName, objectStoreName, idbKeyRange, skipCount, pageSize, callback)
{
this._requestData(frameId, databaseName, objectStoreName, "", idbKeyRange, skipCount, pageSize, callback);
},


_objectStoreDataLoaded: function(requestId, dataEntries, hasMore)
{
var request = this._requestDataCallbacks[requestId];
if (!request.callback)
return;

request.callback(dataEntries, hasMore);
},


requestIndexData: function(frameId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback)
{
this._requestData(frameId, databaseName, objectStoreName, indexName, idbKeyRange, skipCount, pageSize, callback);
},


_indexDataLoaded: function(requestId, dataEntries, hasMore)
{
var request = this._requestDataCallbacks[requestId];
if (!request.callback)
return;

request.callback(dataEntries, hasMore);
},


_requestId: function()
{
return ++this._lastRequestId;
},


_frameDetached: function(frameId)
{
for (var requestId in this._requestDatabaseNamesForFrameCallbacks) {
if (this._requestDatabaseNamesForFrameCallbacks[requestId].frameId === frameId)
delete this._requestDatabaseNamesForFrameCallbacks[requestId];
}

for (var requestId in this._requestDatabaseCallbacks) {
if (this._requestDatabaseCallbacks[requestId].frameId === frameId)
delete this._requestDatabaseCallbacks[requestId];
}

for (var requestId in this._requestDataCallbacks) {
if (this._requestDataCallbacks[requestId].frameId === frameId)
delete this._requestDataCallbacks[requestId];
}
},


_databaseRemoved: function(frameId, databaseName)
{
for (var requestId in this._requestDatabaseCallbacks) {
if (this._requestDatabaseCallbacks[requestId].frameId === frameId && this._requestDatabaseCallbacks[requestId].databaseName === databaseName)
delete this._requestDatabaseCallbacks[requestId];
}

for (var requestId in this._requestDataCallbacks) {
if (this._requestDataCallbacks[requestId].frameId === frameId && this._requestDataCallbacks[requestId].databaseName === databaseName)
delete this._requestDataCallbacks[requestId];
}
},

_reset: function()
{
this._requestDatabaseNamesForFrameCallbacks = {};
this._requestDatabaseCallbacks = {};
this._requestDataCallbacks = {};
}
}


WebInspector.IndexedDBRequestManager.DatabasesForFrameRequest = function(frameId, callback)
{
this.frameId = frameId;
this.callback = callback;
}


WebInspector.IndexedDBRequestManager.DatabaseRequest = function(frameId, databaseName, callback)
{
this.frameId = frameId;
this.databaseName = databaseName;
this.callback = callback;
}


WebInspector.IndexedDBRequestManager.DataRequest = function(frameId, databaseName, objectStoreName, indexName, callback)
{
this.frameId = frameId;
this.databaseName = databaseName;
this.objectStoreName = objectStoreName;
this.indexName = indexName;
this.callback = callback;
}


WebInspector.IndexedDBDispatcher = function(indexedDBRequestManager)
{
this._agentWrapper = indexedDBRequestManager;
}

WebInspector.IndexedDBDispatcher.prototype = {

databaseNamesLoaded: function(requestId, securityOriginWithDatabaseNames)
{
this._agentWrapper._databaseNamesLoaded(requestId, securityOriginWithDatabaseNames);
},


databaseLoaded: function(requestId, databaseWithObjectStores)
{
this._agentWrapper._databaseLoaded(requestId, databaseWithObjectStores);
},


objectStoreDataLoaded: function(requestId, dataEntries, hasMore)
{
this._agentWrapper._objectStoreDataLoaded(requestId, dataEntries, hasMore);
},


indexDataLoaded: function(requestId, dataEntries, hasMore)
{
this._agentWrapper._indexDataLoaded(requestId, dataEntries, hasMore);
}
}







WebInspector.IDBDatabaseView = function(database)
{
WebInspector.View.call(this);
this.registerRequiredCSS("indexedDBViews.css");

this.element.addStyleClass("fill");
this.element.addStyleClass("indexed-db-database-view");

this._headersListElement = this.element.createChild("ol", "outline-disclosure");
this._headersTreeOutline = new TreeOutline(this._headersListElement);
this._headersTreeOutline.expandTreeElementsWhenArrowing = true;

this._securityOriginTreeElement = new TreeElement("", null, false);
this._securityOriginTreeElement.selectable = false;
this._headersTreeOutline.appendChild(this._securityOriginTreeElement);

this._nameTreeElement = new TreeElement("", null, false);
this._nameTreeElement.selectable = false;
this._headersTreeOutline.appendChild(this._nameTreeElement);

this._versionTreeElement = new TreeElement("", null, false);
this._versionTreeElement.selectable = false;
this._headersTreeOutline.appendChild(this._versionTreeElement);

this.update(database);
}

WebInspector.IDBDatabaseView.prototype = {

_formatHeader: function(name, value)
{
var fragment = document.createDocumentFragment();
fragment.createChild("div", "attribute-name").textContent = name + ":";
fragment.createChild("div", "attribute-value source-code").textContent = value;

return fragment;
},

_refreshDatabase: function()
{
this._securityOriginTreeElement.title = this._formatHeader(WebInspector.UIString("Security origin"), this._database.databaseId.securityOrigin);
this._nameTreeElement.title = this._formatHeader(WebInspector.UIString("Name"), this._database.databaseId.name);
this._versionTreeElement.title = this._formatHeader(WebInspector.UIString("Version"), this._database.version);
},


update: function(database)
{
this._database = database;
this._refreshDatabase();
},
}

WebInspector.IDBDatabaseView.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.IDBDataView = function(model, databaseId, objectStore, index)
{
WebInspector.View.call(this);
this.registerRequiredCSS("indexedDBViews.css");

this._model = model;
this._databaseId = databaseId;
this._isIndex = !!index;

this.element.addStyleClass("indexed-db-data-view");

var editorToolbar = this._createEditorToolbar();
this.element.appendChild(editorToolbar);

this._dataGridContainer = this.element.createChild("div", "fill");
this._dataGridContainer.addStyleClass("data-grid-container");

this._refreshButton = new WebInspector.StatusBarButton(WebInspector.UIString("Refresh"), "refresh-storage-status-bar-item");
this._refreshButton.addEventListener("click", this._refreshButtonClicked, this);

this._pageSize = 50;
this._skipCount = 0;

this.update(objectStore, index);
this._entries = [];
}

WebInspector.IDBDataView.prototype = {

_createDataGrid: function()
{
var columns = {};
columns["number"] = {};
columns["number"].title = WebInspector.UIString("#");
columns["number"].width = "50px";

var keyPath = this._isIndex ? this._index.keyPath : this._objectStore.keyPath;
columns["key"] = {};
var keyColumnTitle = WebInspector.UIString("Key") + this._keyPathHeader(keyPath);
columns["key"].title = keyColumnTitle;

if (this._isIndex) {
columns["primaryKey"] = {};
var primaryKeyColumnTitle = WebInspector.UIString("Primary key") + this._keyPathHeader(this._objectStore.keyPath);
columns["primaryKey"].title = primaryKeyColumnTitle;
}

columns["value"] = {};
columns["value"].title = WebInspector.UIString("Value");

var dataGrid = new WebInspector.DataGrid(columns);
return dataGrid;
},


_keyPathHeader: function(keyPath)
{
if (!keyPath)
return "";
return " (" + WebInspector.UIString("keyPath") + ": \"" + keyPath + "\")";
},


_createEditorToolbar: function()
{
var editorToolbar = document.createElement("div");
editorToolbar.addStyleClass("status-bar");
editorToolbar.addStyleClass("data-view-toolbar");

this._pageBackButton = editorToolbar.createChild("button", "back-button");
this._pageBackButton.addStyleClass("status-bar-item");
this._pageBackButton.title = WebInspector.UIString("Show previous page.");
this._pageBackButton.disabled = true;
this._pageBackButton.appendChild(document.createElement("img"));
this._pageBackButton.addEventListener("click", this._pageBackButtonClicked.bind(this), false);
editorToolbar.appendChild(this._pageBackButton);

this._pageForwardButton = editorToolbar.createChild("button", "forward-button");
this._pageForwardButton.addStyleClass("status-bar-item");
this._pageForwardButton.title = WebInspector.UIString("Show next page.");
this._pageForwardButton.disabled = true;
this._pageForwardButton.appendChild(document.createElement("img"));
this._pageForwardButton.addEventListener("click", this._pageForwardButtonClicked.bind(this), false);
editorToolbar.appendChild(this._pageForwardButton);

this._keyInputElement = editorToolbar.createChild("input", "key-input");
this._keyInputElement.placeholder = WebInspector.UIString("Start from key");
this._keyInputElement.addEventListener("paste", this._keyInputChanged.bind(this));
this._keyInputElement.addEventListener("cut", this._keyInputChanged.bind(this));
this._keyInputElement.addEventListener("keypress", this._keyInputChanged.bind(this));
this._keyInputElement.addEventListener("keydown", this._keyInputChanged.bind(this));

return editorToolbar;
},

_pageBackButtonClicked: function()
{
this._skipCount = Math.max(0, this._skipCount - this._pageSize);
this._updateData(false);
},

_pageForwardButtonClicked: function()
{
this._skipCount = this._skipCount + this._pageSize;
this._updateData(false);
},

_keyInputChanged: function()
{
window.setTimeout(this._updateData.bind(this, false), 0);
},


update: function(objectStore, index)
{
this._objectStore = objectStore;
this._index = index;

if (this._dataGrid)
this._dataGrid.detach();
this._dataGrid = this._createDataGrid();
this._dataGrid.show(this._dataGridContainer);

this._skipCount = 0;
this._updateData(true);
},


_parseKey: function(keyString)
{
var result;
try {
result = JSON.parse(keyString);
} catch (e) {
result = keyString;
}
return result;
},


_stringifyKey: function(key)
{
if (typeof(key) === "string")
return key;
return JSON.stringify(key);
},


_updateData: function(force)
{
var key = this._parseKey(this._keyInputElement.value);
var pageSize = this._pageSize;
var skipCount = this._skipCount;

if (!force && this._lastKey === key && this._lastPageSize === pageSize && this._lastSkipCount === skipCount)
return;

if (this._lastKey !== key || this._lastPageSize !== pageSize) {
skipCount = 0;
this._skipCount = 0;
}
this._lastKey = key;
this._lastPageSize = pageSize;
this._lastSkipCount = skipCount;


function callback(entries, hasMore)
{
this.clear();
this._entries = entries;
for (var i = 0; i < entries.length; ++i) {
var data = {};
data["number"] = i + skipCount;
data["key"] = entries[i].key;
data["primaryKey"] = entries[i].primaryKey;
data["value"] = entries[i].value;

var primaryKey = JSON.stringify(this._isIndex ? entries[i].primaryKey : entries[i].key);
var valueTitle = this._objectStore.name + "[" + primaryKey + "]";
var node = new WebInspector.IDBDataGridNode(valueTitle, data);
this._dataGrid.rootNode().appendChild(node);
}

this._pageBackButton.disabled = skipCount === 0;
this._pageForwardButton.disabled = !hasMore;
}

var idbKeyRange = key ? window.webkitIDBKeyRange.lowerBound(key) : null;
if (this._isIndex)
this._model.loadIndexData(this._databaseId, this._objectStore.name, this._index.name, idbKeyRange, skipCount, pageSize, callback.bind(this));
else
this._model.loadObjectStoreData(this._databaseId, this._objectStore.name, idbKeyRange, skipCount, pageSize, callback.bind(this));
},

_refreshButtonClicked: function(event)
{
this._updateData(true);
},

get statusBarItems()
{
return [this._refreshButton.element];
},

clear: function()
{
this._dataGrid.rootNode().removeChildren();
for (var i = 0; i < this._entries.length; ++i) {
var value = this._entries[i].value;
value.release();
}
this._entries = [];
}
}

WebInspector.IDBDataView.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.IDBDataGridNode = function(valueTitle, data)
{
WebInspector.DataGridNode.call(this, data, false);

this._valueTitle = valueTitle;
this.selectable = false;
}

WebInspector.IDBDataGridNode.prototype = {

createCell: function(columnIdentifier)
{
var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);
var value = this.data[columnIdentifier];

switch (columnIdentifier) {
case "value":
cell.removeChildren();
this._formatValue(cell, value);
break;
case "key":
case "primaryKey":
cell.removeChildren();
this._formatValue(cell, new WebInspector.LocalJSONObject(value));
break;
default:
}

return cell;
},

_formatValue: function(cell, value)
{
var type = value.subtype || value.type;
var contents = cell.createChild("div", "source-code console-formatted-" + type);

switch (type) {
case "object":
case "array":
var section = new WebInspector.ObjectPropertiesSection(value, value.description)
section.editable = false;
section.skipProto = true;
contents.appendChild(section.element);
break;
case "string":
contents.addStyleClass("primitive-value");
contents.appendChild(document.createTextNode("\"" + value.description + "\""));
break;
default:
contents.addStyleClass("primitive-value");
contents.appendChild(document.createTextNode(value.description));
}
}
};

WebInspector.IDBDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;






WebInspector.Script = function(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript, sourceMapURL)
{
this.scriptId = scriptId;
this.sourceURL = sourceURL;
this.lineOffset = startLine;
this.columnOffset = startColumn;
this.endLine = endLine;
this.endColumn = endColumn;
this.isContentScript = isContentScript;
this.sourceMapURL = sourceMapURL;
this._locations = [];
}

WebInspector.Script.prototype = {

contentURL: function()
{
return this.sourceURL;
},


requestContent: function(callback)
{
if (this._source) {
callback(this._source, false, "text/javascript");
return;
}


function didGetScriptSource(error, source)
{
this._source = error ? "" : source;
callback(this._source, false, "text/javascript");
}
if (this.scriptId) {

DebuggerAgent.getScriptSource(this.scriptId, didGetScriptSource.bind(this));
} else
callback("", false, "text/javascript");
},


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


rawLocationToUILocation: function(rawLocation)
{
console.assert(rawLocation.scriptId === this.scriptId);
return this._sourceMapping.rawLocationToUILocation(rawLocation);
},


setSourceMapping: function(sourceMapping)
{
this._sourceMapping = sourceMapping;
for (var i = 0; i < this._locations.length; ++i)
this._locations[i].update();
},


createLiveLocation: function(rawLocation, updateDelegate)
{
console.assert(rawLocation.scriptId === this.scriptId);
var location = new WebInspector.Script.Location(this, rawLocation, updateDelegate);
this._locations.push(location);
location.update();
return location;
}
}


WebInspector.Script.Location = function(script, rawLocation, updateDelegate)
{
this._script = script;
this._rawLocation = rawLocation;
this._updateDelegate = updateDelegate;
}

WebInspector.Script.Location.prototype = {
dispose: function()
{
this._script._locations.remove(this);
},

update: function()
{
if (!this._script._sourceMapping)
return;
var uiLocation = this._script._sourceMapping.rawLocationToUILocation(this._rawLocation);
if (uiLocation) {
var oneTime = this._updateDelegate(uiLocation);
if (oneTime)
this.dispose();
}
}
}






WebInspector.Spectrum = function()
{
this._popover = new WebInspector.Popover();
this._popover.setCanShrink(false);
this._popover.element.addEventListener("mousedown", consumeEvent, false);

this._containerElement = document.createElement('div');
this._containerElement.className = "spectrum-container";
this._containerElement.tabIndex = 0;
this._containerElement.addEventListener("keydown", this._onKeyDown.bind(this), false);

var topElement = this._containerElement.createChild("div", "spectrum-top");
topElement.createChild("div", "spectrum-fill");

var topInnerElement = topElement.createChild("div", "spectrum-top-inner fill");
this._draggerElement = topInnerElement.createChild("div", "spectrum-color");
this._dragHelperElement = this._draggerElement.createChild("div", "spectrum-sat fill").createChild("div", "spectrum-val fill").createChild("div", "spectrum-dragger");

this._sliderElement = topInnerElement.createChild("div", "spectrum-hue");
this.slideHelper = this._sliderElement.createChild("div", "spectrum-slider");

var rangeContainer = this._containerElement.createChild("div", "spectrum-range-container");
var alphaLabel = rangeContainer.createChild("label");
alphaLabel.textContent = WebInspector.UIString("\u03B1:");

this._alphaElement = rangeContainer.createChild("input", "spectrum-range");
this._alphaElement.setAttribute("type", "range");
this._alphaElement.setAttribute("min", "0");
this._alphaElement.setAttribute("max", "100");
this._alphaElement.addEventListener("change", alphaDrag.bind(this), false);

var swatchElement = document.createElement("span");
swatchElement.className = "swatch";
this._swatchInnerElement = swatchElement.createChild("span", "swatch-inner");

var displayContainer = this._containerElement.createChild("div");
displayContainer.appendChild(swatchElement);
this._displayElement = displayContainer.createChild("span", "source-code spectrum-display-value");

WebInspector.Spectrum.draggable(this._sliderElement, hueDrag.bind(this));
WebInspector.Spectrum.draggable(this._draggerElement, colorDrag.bind(this));

function hueDrag(element, dragX, dragY)
{
this.hsv[0] = (dragY / this.slideHeight);

this._onchange();
}

function colorDrag(element, dragX, dragY)
{
this.hsv[1] = dragX / this.dragWidth;
this.hsv[2] = (this.dragHeight - dragY) / this.dragHeight;

this._onchange();
}

function alphaDrag()
{
this.hsv[3] = this._alphaElement.value / 100;

this._onchange();
}

this._hideProxy = this.hide.bind(this);
};

WebInspector.Spectrum.Events = {
ColorChanged: "ColorChanged",
Hidden: "Hidden"
};

WebInspector.Spectrum.hsvaToRGBA = function(h, s, v, a)
{
var r, g, b;

var i = Math.floor(h * 6);
var f = h * 6 - i;
var p = v * (1 - s);
var q = v * (1 - f * s);
var t = v * (1 - (1 - f) * s);

switch(i % 6) {
case 0:
r = v, g = t, b = p;
break;
case 1:
r = q, g = v, b = p;
break;
case 2:
r = p, g = v, b = t;
break;
case 3:
r = p, g = q, b = v;
break;
case 4:
r = t, g = p, b = v;
break;
case 5:
r = v, g = p, b = q;
break;
}

return [Math.round(r * 255), Math.round(g * 255), Math.round(b * 255), a];
};

WebInspector.Spectrum.rgbaToHSVA = function(r, g, b, a)
{
r = r / 255;
g = g / 255;
b = b / 255;

var max = Math.max(r, g, b);
var min = Math.min(r, g, b);
var h;
var s;
var v = max;

var d = max - min;
s = max ? d / max : 0;

if(max === min) {

h = 0;
} else {
switch(max) {
case r:
h = (g - b) / d + (g < b ? 6 : 0);
break;
case g:
h = (b - r) / d + 2;
break;
case b:
h = (r - g) / d + 4;
break;
}
h /= 6;
}
return [h, s, v, a];
};



WebInspector.Spectrum.draggable = function(element, onmove, onstart, onstop) {

var doc = document;
var dragging;
var offset;
var scrollOffset;
var maxHeight;
var maxWidth;

function consume(e)
{
e.consume(true);
}

function move(e)
{
if (dragging) {
var dragX = Math.max(0, Math.min(e.pageX - offset.left + scrollOffset.left, maxWidth));
var dragY = Math.max(0, Math.min(e.pageY - offset.top + scrollOffset.top, maxHeight));

if (onmove)
onmove(element, dragX, dragY);
}
}

function start(e)
{
var rightClick = e.which ? (e.which === 3) : (e.button === 2);

if (!rightClick && !dragging) {

if (onstart)
onstart(element, e)

dragging = true;
maxHeight = element.clientHeight;
maxWidth = element.clientWidth;

scrollOffset = element.scrollOffset();
offset = element.totalOffset();

doc.addEventListener("selectstart", consume, false);
doc.addEventListener("dragstart", consume, false);
doc.addEventListener("mousemove", move, false);
doc.addEventListener("mouseup", stop, false);

move(e);
consume(e);
}
}

function stop(e)
{
if (dragging) {
doc.removeEventListener("selectstart", consume, false);
doc.removeEventListener("dragstart", consume, false);
doc.removeEventListener("mousemove", move, false);
doc.removeEventListener("mouseup", stop, false);

if (onstop)
onstop(element, e);
}

dragging = false;
}

element.addEventListener("mousedown", start, false);
};

WebInspector.Spectrum.prototype = {
set color(color)
{
var rgba = (color.rgba || color.rgb).slice(0);

if (rgba.length === 3)
rgba[3] = 1;

this.hsv = WebInspector.Spectrum.rgbaToHSVA(rgba[0], rgba[1], rgba[2], rgba[3]);
},

get color()
{
var rgba = WebInspector.Spectrum.hsvaToRGBA(this.hsv[0], this.hsv[1], this.hsv[2], this.hsv[3]);
var color;

if (rgba[3] === 1)
color = WebInspector.Color.fromRGB(rgba[0], rgba[1], rgba[2]);
else
color = WebInspector.Color.fromRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);

var colorValue = color.toString(this.outputColorFormat);
if (!colorValue)
colorValue = color.toString(); 
return new WebInspector.Color(colorValue);
},

get outputColorFormat()
{
var cf = WebInspector.StylesSidebarPane.ColorFormat;
var format = this._originalFormat;

if (this.hsv[3] === 1) {

if (format === cf.RGBA)
format = cf.RGB;
else if (format === cf.HSLA)
format = cf.HSL;
} else {

if (format === cf.HSL || format === cf.HSLA)
format = cf.HSLA;
else
format = cf.RGBA;
}

return format;
},

get colorHueOnly()
{
var rgba = WebInspector.Spectrum.hsvaToRGBA(this.hsv[0], 1, 1, 1);
return WebInspector.Color.fromRGBA(rgba[0], rgba[1], rgba[2], rgba[3]);
},

set displayText(text)
{
this._displayElement.textContent = text;
},

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

_onchange: function()
{
this._updateUI();
this.dispatchEventToListeners(WebInspector.Spectrum.Events.ColorChanged, this.color);
},

_updateHelperLocations: function()
{
var h = this.hsv[0];
var s = this.hsv[1];
var v = this.hsv[2];


var dragX = s * this.dragWidth;
var dragY = this.dragHeight - (v * this.dragHeight);

dragX = Math.max(-this._dragHelperElementHeight,
Math.min(this.dragWidth - this._dragHelperElementHeight, dragX - this._dragHelperElementHeight));
dragY = Math.max(-this._dragHelperElementHeight,
Math.min(this.dragHeight - this._dragHelperElementHeight, dragY - this._dragHelperElementHeight));

this._dragHelperElement.positionAt(dragX, dragY);


var slideY = (h * this.slideHeight) - this.slideHelperHeight;
this.slideHelper.style.top = slideY + "px";

this._alphaElement.value = this.hsv[3] * 100;
},

_updateUI: function()
{
this._updateHelperLocations();

var rgb = (this.color.rgba || this.color.rgb).slice(0);

if (rgb.length === 3)
rgb[3] = 1;

var rgbHueOnly = this.colorHueOnly.rgb;

var flatColor = "rgb(" + rgbHueOnly[0] + ", " + rgbHueOnly[1] + ", " + rgbHueOnly[2] + ")";
var fullColor = "rgba(" + rgb[0] + ", " + rgb[1] + ", " + rgb[2] + ", " + rgb[3] + ")";

this._draggerElement.style.backgroundColor = flatColor;
this._swatchInnerElement.style.backgroundColor = fullColor;

this._alphaElement.value = this.hsv[3] * 100;
},

toggle: function(element, color, format)
{
if (this.visible)
this.hide();
else
this.show(element, color, format);

return this.visible;
},

show: function(element, color, format)
{
if (this.visible) {
if (this.anchorElement === element)
return false;


this.hide();
}

this.reposition(element);
this.anchorElement = element;

document.addEventListener("mousedown", this._hideProxy, false);
window.addEventListener("blur", this._hideProxy, false);

this.slideHeight = this._sliderElement.offsetHeight;
this.dragWidth = this._draggerElement.offsetWidth;
this.dragHeight = this._draggerElement.offsetHeight;
this._dragHelperElementHeight = this._dragHelperElement.offsetHeight / 2;
this.slideHelperHeight = this.slideHelper.offsetHeight / 2;

this.color = color;
this._originalFormat = format || color.format;

this._updateUI();

return true;
},

reposition: function(element)
{
if (!this._previousFocusElement)
this._previousFocusElement = WebInspector.currentFocusElement();
this._popover.show(this._containerElement, element);
WebInspector.setCurrentFocusElement(this._containerElement);
},

hide: function()
{
this._popover.hide();

document.removeEventListener("mousedown", this._hideProxy, false);
window.removeEventListener("blur", this._hideProxy, false);

this.dispatchEventToListeners(WebInspector.Spectrum.Events.Hidden);

WebInspector.setCurrentFocusElement(this._previousFocusElement);
delete this._previousFocusElement;

delete this.anchorElement;
},

_onKeyDown: function(event)
{
if (event.keyIdentifier === "Enter" || event.keyIdentifier === "U+001B") { 
this.hide();
event.consume(true);
}
}
}

WebInspector.Spectrum.prototype.__proto__ = WebInspector.Object.prototype;






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

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

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._treeElementBeingDragged = treeElement;

WebInspector.domAgent.hideDOMNodeHighlight();

return true;
},

_ondragover: function(event)
{
if (!this._treeElementBeingDragged)
return false;

var treeElement = this._treeElementFromEvent(event);
if (!this._isValidDragSourceOrTarget(treeElement))
return false;

var node = treeElement.representedObject;
while (node) {
if (node === this._treeElementBeingDragged.representedObject)
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 (treeElement)
this._doMove(treeElement);
},

_doMove: function(treeElement)
{
if (!this._treeElementBeingDragged)
return;

var parentNode;
var anchorNode;

if (treeElement._elementCloseTag) {

parentNode = treeElement.representedObject;
} else {
var dragTargetNode = treeElement.representedObject;
parentNode = dragTargetNode.parentNode;
anchorNode = dragTargetNode;
}

var wasExpanded = this._treeElementBeingDragged.expanded;
this._treeElementBeingDragged.representedObject.moveTo(parentNode, anchorNode, this._selectNodeAfterEdit.bind(this, null, wasExpanded));

delete this._treeElementBeingDragged;
},

_ondragend: function(event)
{
event.preventDefault();
this._clearDragOverTreeElementMarker();
delete this._treeElementBeingDragged;
},

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

handleShortcut: function(event)
{
var node = this.selectedDOMNode();
var treeElement = this.getCachedTreeElement(node);
if (!node || !treeElement)
return;

if (event.keyIdentifier === "F2") {
this._toggleEditAsHTML(node);
return;
}

if (WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && node.parentNode) {
if (event.keyIdentifier === "Up" && node.previousSibling) {
node.moveTo(node.parentNode, node.previousSibling, this._selectNodeAfterEdit.bind(this, null, treeElement.expanded));
return;
}
if (event.keyIdentifier === "Down" && node.nextSibling) {
node.moveTo(node.parentNode, node.nextSibling.nextSibling, this._selectNodeAfterEdit.bind(this, null, treeElement.expanded));
return;
}
}

},

_toggleEditAsHTML: function(node)
{
var treeElement = this.getCachedTreeElement(node);
if (!treeElement)
return;

if (treeElement._editing && treeElement._htmlEditElement && WebInspector.isBeingEdited(treeElement._htmlEditElement))
treeElement._editing.commit();
else
treeElement._editAsHTML();
},

_selectNodeAfterEdit: function(fallbackNode, wasExpanded, error, nodeId)
{
if (error)
return;


this._updateModifiedNodes();

var newNode = WebInspector.domAgent.nodeForId(nodeId) || fallbackNode;
if (!newNode)
return;

this.selectDOMNode(newNode, true);

var newTreeItem = this.findTreeElement(newNode);
if (wasExpanded) {
if (newTreeItem)
newTreeItem.expand();
}
return newTreeItem;
}
}

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


if (show) {
for (var i = 0, size = this._highlightResult.length; i < size; ++i)
updateEntryShow(this._highlightResult[i]);
} else {
for (var i = (this._highlightResult.length - 1); i >= 0; --i)
updateEntryHide(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;
},

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

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("Copy XPath"), this._copyXPath.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;

function consume(event)
{
if (event.eventPhase === Event.AT_TARGET)
event.consume(true);
}

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.treeOutline.childrenListElement.parentElement.addEventListener("mousedown", consume, false);

this.updateSelection();

function commit()
{
commitCallback(initialValue, 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.treeOutline.childrenListElement.parentElement.removeEventListener("mousedown", consume, false);
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();
}
}

if (oldText !== newText)
this.representedObject.setAttribute(attributeName, newText, moveToNextAttributeIfNeeded.bind(this));
else
moveToNextAttributeIfNeeded.call(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 newTreeItem = treeOutline._selectNodeAfterEdit(null, wasExpanded, error, nodeId);
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.startsWith("data:"))
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");
if (node.isInShadowTree())
classes.push("shadow");
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.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;
case Node.DOCUMENT_FRAGMENT_NODE:
var fragmentElement = info.titleDOM.createChild("span", "webkit-html-fragment");
fragmentElement.textContent = node.nodeNameInCorrectCase().collapseWhitespace();
if (node.isInShadowTree())
fragmentElement.addStyleClass("shadow");
break;
default:
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();
}

if (!this.representedObject.parentNode || this.representedObject.parentNode.nodeType() === Node.DOCUMENT_NODE)
return;
this.representedObject.removeNode(removeNodeCallback);
},

_editAsHTML: function()
{
var treeOutline = this.treeOutline;
var node = this.representedObject;
var parentNode = node.parentNode;
var index = node.index;
var wasExpanded = this.expanded;

function selectNode(error, nodeId)
{
if (error)
return;


treeOutline._updateModifiedNodes();

var newNode = parentNode ? parentNode.children[index] || parentNode : null;
if (!newNode)
return;

treeOutline.selectDOMNode(newNode, true);

if (wasExpanded) {
var newTreeItem = treeOutline.findTreeElement(newNode);
if (newTreeItem)
newTreeItem.expand();
}
}

function commitChange(initialValue, value)
{
if (initialValue !== value)
node.setOuterHTML(value, selectNode);
else
return;
}

node.getOuterHTML(this._startEditingAsHTML.bind(this, commitChange));
},

_copyHTML: function()
{
this.representedObject.copyNode();
},

_copyXPath: function()
{
this.representedObject.copyXPath(true);
},

_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 = [];
WebInspector.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;

if (parent === this._treeOutline._rootDOMNode) {

this._treeOutline.update();
return;
}

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);
this.expand();
}

WebInspector.SidebarSectionTreeElement.prototype = {
selectable: false,

collapse: function()
{

},

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(event)
{
this.toggleExpanded();
event.consume();
}
}






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.propertiesTreeOutline = new TreeOutline(this.propertiesElement, true);
this.propertiesTreeOutline.setFocusable(false);
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(undefined, typeof value, undefined, 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, doNotPauseOnExceptionsAndMuteConsole:true}, evaluatedCallback.bind(this));


function evaluatedCallback(error, result, wasThrown)
{
if (error || wasThrown) {
callback(error || result.description);
return;
}

function setPropertyValue(propertyName, propertyValue)
{
this[propertyName] = propertyValue;
}

delete result.description; 
RuntimeAgent.callFunctionOn(this._objectId, setPropertyValue.toString(), [{ value:name }, result], true, undefined, propertySetCallback.bind(this));
if (result._objectId)
RuntimeAgent.releaseObject(result._objectId);
}


function propertySetCallback(error, result, wasThrown)
{
if (error || wasThrown) {
callback(error || result.description);
return;
}
callback();
}
},


pushNodeToFrontend: function(callback)
{
if (this._objectId)
WebInspector.domAgent.pushNodeToFrontend(this._objectId, callback);
else
callback(0);
},


callFunction: function(functionDeclaration, args, callback)
{

function mycallback(error, result, wasThrown)
{
callback((error || wasThrown) ? null : WebInspector.RemoteObject.fromPayload(result));
}

RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), args, true, undefined, mycallback);
},


callFunctionJSON: function(functionDeclaration, args, callback)
{

function mycallback(error, result, wasThrown)
{
callback((error || wasThrown) ? null : result.value);
}

RuntimeAgent.callFunctionOn(this._objectId, functionDeclaration.toString(), args, true, true, mycallback);
},

release: function()
{
RuntimeAgent.releaseObject(this._objectId);
},


arrayLength: function()
{
if (this.subtype !== "array")
return 0;

var matches = this._description.match(/\[([0-9]+)\]/);
if (!matches)
return 0;
return parseInt(matches[1], 10);
}
}


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 "date":
this._cachedDescription = "" + this._value;
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";

if (this._value instanceof Date)
return "date";

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


arrayLength: function()
{
return this._value instanceof Array ? this._value.length : 0;
}
}






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;
this.skipProto = false;

WebInspector.PropertiesSection.call(this, title, subtitle);
}

WebInspector.ObjectPropertiesSection._arrayLoadThreshold = 100;

WebInspector.ObjectPropertiesSection.prototype = {
onpopulate: function()
{
this.update();
},

update: function()
{
if (this.object.arrayLength() > WebInspector.ObjectPropertiesSection._arrayLoadThreshold) {
this.propertiesTreeOutline.removeChildren();
WebInspector.ArrayGroupingTreeElement._populateArray(this.propertiesTreeOutline, this.object, 0, this.object.arrayLength() - 1);
return;
}

function callback(properties)
{
if (!properties)
return;
this.updateProperties(properties);
}

if (this.ignoreHasOwnProperty)
this.object.getAllProperties(callback.bind(this));
else
this.object.getOwnProperties(callback.bind(this));
},

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) {
if (this.skipProto && properties[i].name === "__proto__")
continue;
properties[i].parentObject = this.object;
}

this.propertiesForTest = properties;

for (var i = 0; i < properties.length; ++i)
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);
}
}
}

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;

if (this.property.value.arrayLength() > WebInspector.ObjectPropertiesSection._arrayLoadThreshold) {
this.removeChildren();
WebInspector.ArrayGroupingTreeElement._populateArray(this, this.property.value, 0, this.property.value.arrayLength() - 1);
return;
}

function callback(properties)
{
this.removeChildren();
if (!properties)
return;

properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties);
for (var i = 0; i < properties.length; ++i) {
if (this.treeOutline.section.skipProto && properties[i].name === "__proto__")
continue;
properties[i].parentObject = this.property.value;
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(event);
},

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 didGetDetails(error, response)
{
if (error) {
console.error(error);
return;
}
WebInspector.panels.scripts.showFunctionDefinition(response.location);
}

function revealFunction()
{
DebuggerAgent.getFunctionDetails(this.property.value.objectId, didGetDetails.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;
},

renderPromptAsBlock: function()
{
return false;
},


elementAndValueToEdit: function(event)
{
return [this.valueElement, (typeof this.valueElement._originalTextContent === "string") ? this.valueElement._originalTextContent : undefined];
},

startEditing: function(event)
{
var elementAndValueToEdit = this.elementAndValueToEdit(event);
var elementToEdit = elementAndValueToEdit[0];
var valueToEdit = elementAndValueToEdit[1];

if (WebInspector.isBeingEdited(elementToEdit) || !this.treeOutline.section.editable || this._readOnly)
return;


if (typeof valueToEdit !== "undefined")
elementToEdit.textContent = valueToEdit;

var context = { expanded: this.expanded, elementToEdit: elementToEdit, previousContent: elementToEdit.textContent };


this.hasChildren = false;

this.listItemElement.addStyleClass("editing-sub-part");

this._prompt = new WebInspector.ObjectPropertyPrompt(this.editingCommitted.bind(this, null, elementToEdit.textContent, context.previousContent, context), this.editingCancelled.bind(this, null, context), this.renderPromptAsBlock());

function blurListener()
{
this.editingCommitted(null, elementToEdit.textContent, context.previousContent, context);
}

var proxyElement = this._prompt.attachAndStartEditing(elementToEdit, blurListener.bind(this));
window.getSelection().setBaseAndExtent(elementToEdit, 0, elementToEdit, 1);
proxyElement.addEventListener("keydown", this._promptKeyDown.bind(this, context), false);
},

editingEnded: function(context)
{
this._prompt.detach();
delete this._prompt;

this.listItemElement.scrollLeft = 0;
this.listItemElement.removeStyleClass("editing-sub-part");
if (context.expanded)
this.expand();
},

editingCancelled: function(element, context)
{
this.editingEnded(context);
this.update();
},

editingCommitted: function(element, userInput, previousContent, context)
{
if (userInput === previousContent)
return this.editingCancelled(element, context); 

this.editingEnded(context);
this.applyExpression(userInput, true);
},

_promptKeyDown: function(context, event)
{
if (isEnterKey(event)) {
event.consume(true);
return this.editingCommitted(null, context.elementToEdit.textContent, context.previousContent, context);
}
if (event.keyIdentifier === "U+001B") { 
event.consume();
return this.editingCancelled(null, 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.ArrayGroupingTreeElement = function(object, fromIndex, toIndex, propertyCount)
{
TreeElement.call(this, String.sprintf("[%d \u2026 %d]", fromIndex, toIndex), undefined, true);
this._fromIndex = fromIndex;
this._toIndex = toIndex;
this._object = object;
this._readOnly = true;
this._propertyCount = propertyCount;
this._populated = false;
}

WebInspector.ArrayGroupingTreeElement._bucketThreshold = 20;


WebInspector.ArrayGroupingTreeElement._populateArray = function(treeElement, object, fromIndex, toIndex)
{
WebInspector.ArrayGroupingTreeElement._populateRanges(treeElement, object, fromIndex, toIndex, true);
}


WebInspector.ArrayGroupingTreeElement._populateRanges = function(treeElement, object, fromIndex, toIndex, topLevel)
{
object.callFunctionJSON(packRanges, [{value: fromIndex}, {value: toIndex}, {value: WebInspector.ArrayGroupingTreeElement._bucketThreshold}], callback.bind(this));


function packRanges(fromIndex, toIndex, bucketThreshold)
{
var count = 0;
for (var i = fromIndex; i <= toIndex; ++i) {
var value = this[i];
if (typeof value !== "undefined")
++count;
}

var bucketSize;
if (count < bucketThreshold)
bucketSize = count;
else {
bucketSize = Math.ceil(count / bucketThreshold);
if (bucketSize < bucketThreshold)
bucketSize = Math.floor(Math.sqrt(count));
}

var ranges = [];
count = 0;
var groupStart = -1;
var groupEnd = 0;
for (var i = fromIndex; i <= toIndex; ++i) {
var value = this[i];
if (typeof value === "undefined")
continue;

if (groupStart === -1)
groupStart = i;

groupEnd = i;
if (++count === bucketSize) {
ranges.push([groupStart, groupEnd, count]);
count = 0;
groupStart = -1;
}
}

if (count > 0)
ranges.push([groupStart, groupEnd, count]);
return ranges;
}

function callback(ranges)
{
if (ranges.length == 1)
WebInspector.ArrayGroupingTreeElement._populateAsFragment(treeElement, object, ranges[0][0], ranges[0][1]);
else {
for (var i = 0; i < ranges.length; ++i) {
var fromIndex = ranges[i][0];
var toIndex = ranges[i][1];
var count = ranges[i][2];
if (fromIndex == toIndex)
WebInspector.ArrayGroupingTreeElement._populateAsFragment(treeElement, object, fromIndex, toIndex);
else
treeElement.appendChild(new WebInspector.ArrayGroupingTreeElement(object, fromIndex, toIndex, count));
}
}
if (topLevel)
WebInspector.ArrayGroupingTreeElement._populateNonIndexProperties(treeElement, object);
}
}


WebInspector.ArrayGroupingTreeElement._populateAsFragment = function(treeElement, object, fromIndex, toIndex)
{
object.callFunction(buildArrayFragment, [{value: fromIndex}, {value: toIndex}], processArrayFragment.bind(this));


function buildArrayFragment(fromIndex, toIndex)
{
var result = Object.create(null);
for (var i = fromIndex; i <= toIndex; ++i) {
var value = this[i];
if (typeof value !== "undefined")
result[i] = value;
}
return result;
}

function processArrayFragment(arrayFragment)
{
arrayFragment.getAllProperties(processProperties.bind(this));
}


function processProperties(properties)
{
if (!properties)
return;

properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties);
for (var i = 0; i < properties.length; ++i) {
properties[i].parentObject = this._object;
var childTreeElement = new treeElement.treeOutline.section.treeElementConstructor(properties[i]);
childTreeElement._readOnly = true;
treeElement.appendChild(childTreeElement);
}
}
}


WebInspector.ArrayGroupingTreeElement._populateNonIndexProperties = function(treeElement, object)
{
object.callFunction(buildObjectFragment, undefined, processObjectFragment.bind(this));


function buildObjectFragment()
{
var result = Object.create(this.__proto__);
var names = Object.getOwnPropertyNames(this);
for (var i = 0; i < names.length; ++i) {
var name = names[i];
if (!isNaN(name))
continue;
var descriptor = Object.getOwnPropertyDescriptor(this, name);
if (descriptor)
Object.defineProperty(result, name, descriptor);
}
return result;
}

function processObjectFragment(arrayFragment)
{
arrayFragment.getOwnProperties(processProperties.bind(this));
}


function processProperties(properties)
{
if (!properties)
return;

properties.sort(WebInspector.ObjectPropertiesSection.CompareProperties);
for (var i = 0; i < properties.length; ++i) {
properties[i].parentObject = this._object;
var childTreeElement = new treeElement.treeOutline.section.treeElementConstructor(properties[i]);
childTreeElement._readOnly = true;
treeElement.appendChild(childTreeElement);
}
}
}

WebInspector.ArrayGroupingTreeElement.prototype = {
onpopulate: function()
{
if (this._populated)
return;

this._populated = true;

if (this._propertyCount >= WebInspector.ArrayGroupingTreeElement._bucketThreshold) {
WebInspector.ArrayGroupingTreeElement._populateRanges(this, this._object, this._fromIndex, this._toIndex, false);
return;
}
WebInspector.ArrayGroupingTreeElement._populateAsFragment(this, this._object, this._fromIndex, this._toIndex);
},

onattach: function()
{
this.listItemElement.addStyleClass("name");
}
}

WebInspector.ArrayGroupingTreeElement.prototype.__proto__ = TreeElement.prototype;


WebInspector.ObjectPropertyPrompt = function(commitHandler, cancelHandler, renderAsBlock)
{
const ExpressionStopCharacters = " =:[({;,!+-*/&|^<>."; 
WebInspector.TextPrompt.call(this, WebInspector.consoleView.completionsForTextPrompt.bind(WebInspector.consoleView), ExpressionStopCharacters);
this.setSuggestBoxEnabled("generic-suggest");
if (renderAsBlock)
this.renderAsBlock();
}

WebInspector.ObjectPropertyPrompt.prototype.__proto__ = WebInspector.TextPrompt.prototype;






WebInspector.ObjectPopoverHelper = function(panelElement, getAnchor, queryObject, onHide, disableOnClick)
{
WebInspector.PopoverHelper.call(this, panelElement, getAnchor, this._showObjectPopover.bind(this), this._onHideObjectPopover.bind(this), disableOnClick);
this._queryObject = queryObject;
this._onHideCallback = onHide;
this._popoverObjectGroup = "popover";
panelElement.addEventListener("scroll", this.hidePopover.bind(this), true);
};

WebInspector.ObjectPopoverHelper.prototype = {

_showObjectPopover: function(element, popover)
{

function showObjectPopover(result, wasThrown, anchorOverride)
{
if (popover.disposed)
return;
if (wasThrown) {
this.hidePopover();
return;
}

var anchorElement = anchorOverride || element;

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 === "function") {
function didGetDetails(error, response)
{
if (error) {
console.error(error);
return;
}
var container = document.createElement("div");
container.style.display = "inline-block";

var title = container.createChild("div", "function-popover-title source-code");
var functionName = title.createChild("span", "function-name");
functionName.textContent = response.name || response.inferredName || response.displayName || WebInspector.UIString("(anonymous function)");

this._linkifier = new WebInspector.Linkifier();
var link = this._linkifier.linkifyRawLocation(response.location, "function-location-link");
if (link)
title.appendChild(link);

container.appendChild(popoverContentElement);

popover.show(container, anchorElement);
}
DebuggerAgent.getFunctionDetails(result.objectId, didGetDetails.bind(this));
return;
}
if (result.type === "string")
popoverContentElement.textContent = "\"" + popoverContentElement.textContent + "\"";
popover.show(popoverContentElement, anchorElement);
} 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, anchorElement, popoverWidth, popoverHeight);
}
}
this._queryObject(element, showObjectPopover.bind(this), this._popoverObjectGroup);
},

_onHideObjectPopover: function()
{
if (this._linkifier) {
this._linkifier.reset();
delete this._linkifier;
}
if (this._onHideCallback)
this._onHideCallback();
RuntimeAgent.releaseObjectGroup(this._popoverObjectGroup);
},

_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(breakpointManager, showSourceLineDelegate)
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Breakpoints"));

this._breakpointManager = breakpointManager;
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.bodyElement.addEventListener("contextmenu", this._contextMenu.bind(this), false);

this._items = new Map();
this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this);
this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this);
}

WebInspector.JavaScriptBreakpointsSidebarPane.prototype = {

_breakpointAdded: function(event)
{
this._breakpointRemoved(event);

var breakpoint =   event.data.breakpoint;
var uiLocation =   event.data.uiLocation;

var element = document.createElement("li");
element.addStyleClass("cursor-pointer");
element.addEventListener("contextmenu", this._breakpointContextMenu.bind(this, breakpoint), true);
element.addEventListener("click", this._breakpointClicked.bind(this, uiLocation), 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 = uiLocation.uiSourceCode.url;
var displayName = url ? WebInspector.displayNameForURL(url) : WebInspector.UIString("(program)");
var labelElement = document.createTextNode(displayName + ":" + (uiLocation.lineNumber + 1));
element.appendChild(labelElement);

var snippetElement = document.createElement("div");
snippetElement.className = "source-text monospace";
element.appendChild(snippetElement);


function didRequestContent(content, contentEncoded, mimeType)
{
var lineEndings = content.lineEndings();
if (uiLocation.lineNumber < lineEndings.length)
snippetElement.textContent = content.substring(lineEndings[uiLocation.lineNumber - 1], lineEndings[uiLocation.lineNumber]);
}
uiLocation.uiSourceCode.requestContent(didRequestContent.bind(this));

element._data = uiLocation;
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.put(breakpoint, breakpointItem);

if (!this.expanded)
this.expanded = true;
},


_breakpointRemoved: function(event)
{
var breakpoint =   event.data.breakpoint;
var uiLocation =   event.data.uiLocation;
var breakpointItem = this._items.get(breakpoint);
if (!breakpointItem)
return;
this._items.remove(breakpoint);
this._removeListElement(breakpointItem.element);
},


highlightBreakpoint: function(breakpoint)
{
var breakpointItem = this._items.get(breakpoint);
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;
}
},

_breakpointClicked: function(uiLocation, event)
{
this._showSourceLineDelegate(uiLocation.uiSourceCode, uiLocation.lineNumber);
},


_breakpointCheckboxClicked: function(breakpoint, event)
{

event.consume();
breakpoint.setEnabled(event.target.checked);
},


_breakpointContextMenu: function(breakpoint, event)
{
var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendItem(WebInspector.UIString("Remove Breakpoint"), breakpoint.remove.bind(breakpoint));
var removeAllTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove all JavaScript breakpoints" : "Remove All JavaScript Breakpoints");
contextMenu.appendItem(removeAllTitle, this._breakpointManager.removeAllBreakpoints.bind(this._breakpointManager));
contextMenu.show(event);
},

_contextMenu: function(event)
{
var contextMenu = new WebInspector.ContextMenu();
var removeAllTitle = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove all JavaScript breakpoints" : "Remove All JavaScript Breakpoints");
contextMenu.appendItem(removeAllTitle, this._breakpointManager.removeAllBreakpoints.bind(this._breakpointManager));
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.clear();
}
}

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.consume();

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("Animation"), false, ["requestAnimationFrame", "cancelAnimationFrame", "animationFrameFired"]);
this._createCategory(WebInspector.UIString("Control"), true, ["resize", "scroll", "zoom", "focus", "blur", "select", "change", "submit", "reset"]);
this._createCategory(WebInspector.UIString("Clipboard"), true, ["copy", "cut", "paste", "beforecopy", "beforecut", "beforepaste"]);
this._createCategory(WebInspector.UIString("DOM Mutation"), true, ["DOMActivate", "DOMFocusIn", "DOMFocusOut", "DOMAttrModified", "DOMCharacterDataModified", "DOMNodeInserted", "DOMNodeInsertedIntoDocument", "DOMNodeRemoved", "DOMNodeRemovedFromDocument", "DOMSubtreeModified", "DOMContentLoaded"]);
this._createCategory(WebInspector.UIString("Device"), true, ["deviceorientation", "devicemotion"]);
this._createCategory(WebInspector.UIString("Keyboard"), true, ["keydown", "keyup", "keypress", "textInput"]);
this._createCategory(WebInspector.UIString("Load"), true, ["load", "unload", "abort", "error"]);
this._createCategory(WebInspector.UIString("Mouse"), true, ["click", "dblclick", "mousedown", "mouseup", "mouseover", "mousemove", "mouseout", "mousewheel"]);
this._createCategory(WebInspector.UIString("Timer"), false, ["setTimer", "clearTimer", "timerFired"]);
this._createCategory(WebInspector.UIString("Touch"), true, ["touchstart", "touchmove", "touchend", "touchcancel"]);

this._restoreBreakpoints();
}

WebInspector.EventListenerBreakpointsSidebarPane.categotyListener = "listener:";
WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation = "instrumentation:";

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"),
"instrumentation:requestAnimationFrame": WebInspector.UIString("Request Animation Frame"),
"instrumentation:cancelAnimationFrame": WebInspector.UIString("Cancel Animation Frame"),
"instrumentation:animationFrameFired": WebInspector.UIString("Animation Frame Fired")
};
}
return WebInspector.EventListenerBreakpointsSidebarPane._eventNamesForUI[eventName] || eventName.substring(eventName.indexOf(":") + 1);
}

WebInspector.EventListenerBreakpointsSidebarPane.prototype = {
_createCategory: function(name, isDOMEvent, 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 = (isDOMEvent ? WebInspector.EventListenerBreakpointsSidebarPane.categotyListener :  WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation) + 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;
if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categotyListener))
DOMDebuggerAgent.setEventListenerBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categotyListener.length));
else if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation))
DOMDebuggerAgent.setInstrumentationBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation.length));
this._updateCategoryCheckbox(breakpointItem.parent);
},

_removeBreakpoint: function(eventName)
{
var breakpointItem = this._breakpointItems[eventName];
if (!breakpointItem)
return;
breakpointItem.checkbox.checked = false;
if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categotyListener))
DOMDebuggerAgent.removeEventListenerBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categotyListener.length));
else if (eventName.startsWith(WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation))
DOMDebuggerAgent.removeInstrumentationBreakpoint(eventName.substring(WebInspector.EventListenerBreakpointsSidebarPane.categotyInstrumentation.length));
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._breakpointElements = {};
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()
{
WebInspector.SidebarPane.call(this, WebInspector.UIString("Call Stack"));
this._model = WebInspector.debuggerModel;

this.bodyElement.addEventListener("contextmenu", this._contextMenu.bind(this), true);
}

WebInspector.CallStackSidebarPane.prototype = {
update: function(callFrames)
{
this.bodyElement.removeChildren();
this.placards = [];

if (!callFrames) {
var infoElement = document.createElement("div");
infoElement.className = "info";
infoElement.textContent = WebInspector.UIString("Not Paused");
this.bodyElement.appendChild(infoElement);
return;
}

for (var i = 0; i < callFrames.length; ++i) {
var callFrame = callFrames[i];
var placard = new WebInspector.CallStackSidebarPane.Placard(callFrame);
placard.element.addEventListener("click", this._placardSelected.bind(this, placard), false);
this.placards.push(placard);
this.bodyElement.appendChild(placard.element);
}
},

setSelectedCallFrame: function(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.setSelectedCallFrame(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].title + " (" + this.placards[i].subtitle + ")\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.CallStackSidebarPane.Placard = function(callFrame)
{
WebInspector.Placard.call(this, callFrame.functionName || WebInspector.UIString("(anonymous function)"), "");
callFrame.createLiveLocation(this._update.bind(this));
this._callFrame = callFrame;
}

WebInspector.CallStackSidebarPane.Placard.prototype = {
_update: function(uiLocation)
{
this.subtitle = WebInspector.displayNameForURL(uiLocation.uiSourceCode.url) + ":" + (uiLocation.lineNumber + 1);
}
}

WebInspector.CallStackSidebarPane.Placard.prototype.__proto__ = WebInspector.Placard.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 || [];
var exceptionObject =   exception;
extraProperties.push(new WebInspector.RemoteObjectProperty("<exception>", WebInspector.RemoteObject.fromPayload(exceptionObject)));
}
}
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 (current.property) {
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.consume();
this.expanded = true;
this.section.addNewExpressionAndEdit();
},

_refreshButtonClicked: function(event)
{
event.consume();
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.consume();

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._hoveredElement;
}
delete this._lastMouseMovePageY;
},

_updateHoveredElement: function(pageY)
{
var candidateElement = this.propertiesElement.firstChild;
while (true) {
var next = candidateElement.nextSibling;
while (next && !next.clientHeight)
next = next.nextSibling;
if (!next || next.totalOffsetTop() > pageY)
break;
candidateElement = next;
}

if (this._hoveredElement !== candidateElement) {
if (this._hoveredElement)
this._hoveredElement.removeStyleClass("hovered");
if (candidateElement)
candidateElement.addStyleClass("hovered");
this._hoveredElement = candidateElement;
}

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

renderPromptAsBlock: function()
{
return true;
},


elementAndValueToEdit: function(event)
{
return [this.nameElement, this.property.name.trim()];
},

editingCancelled: function(element, context)
{
if (!context.elementToEdit.textContent)
this.treeOutline.section.updateExpression(this, null);

WebInspector.ObjectPropertyTreeElement.prototype.editingCancelled.call(this, element, 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._styleSheetOrMediaQueryResultChanged, this);
WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.MediaQueryResultChanged, this._styleSheetOrMediaQueryResultChanged, 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));
},

_styleSheetOrMediaQueryResultChanged: 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.consume();
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.isSelfOrDescendant(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, true, 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, undefined, 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.consume() }, false);
this.settingsSelectElement.addEventListener("change", this._changeSetting.bind(this), false);

this.titleElement.appendChild(this.settingsSelectElement);

this._linkifier = new WebInspector.Linkifier();
}

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 selectedNodeOnly = "selected" === WebInspector.settings.eventListenersFilter.get();
var sectionNames = [];
var sectionMap = {};
for (var i = 0; i < eventListeners.length; ++i) {
var eventListener = eventListeners[i];
if (selectedNodeOnly && (node.id !== eventListener.nodeId))
continue;
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]];
body.appendChild(section.element);
}
}

if (node)
node.eventListeners(callback);
this._selectedNode = node;
},

willHide: function()
{
delete this._selectedNode;
},

_changeSetting: function()
{
var selectedOption = this.settingsSelectElement[this.settingsSelectElement.selectedIndex];
WebInspector.settings.eventListenersFilter.set(selectedOption.value);
this.update(this._selectedNode);
}
}

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 = {
addListener: function(eventListener)
{
var eventListenerBar = new WebInspector.EventListenerBar(eventListener, this._nodeId, this._linkifier);
this._eventBars.appendChild(eventListenerBar.element);
}
}

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.fromRGB = function(r, g, b)
{
return new WebInspector.Color("rgb(" + r + "," + g + "," + b + ")");
}

WebInspector.Color.prototype = {

get shorthex()
{
if ("_short" in this)
return this._short;

if (!this.simple)
return "";

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

return this._hex;
},

set hex(x)
{
this._hex = x;
},


get rgb()
{
if (this._rgb)
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 (this._hsl)
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 "";
},

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


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


_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._rgbStringsToHex(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].startsWith(prefix))
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].startsWith(prefix)) {
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].startsWith(prefix))
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.colors = function()
{
if (!WebInspector.CSSKeywordCompletions._colorsKeySet)
WebInspector.CSSKeywordCompletions._colorsKeySet = WebInspector.CSSKeywordCompletions._colors.keySet();
return WebInspector.CSSKeywordCompletions._colorsKeySet;
}


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", "box-shadow", "color",
"outline", "outline-color", "text-line-through", "text-line-through-color", "text-overline", "text-overline-color",
"text-shadow", "text-underline", "text-underline-color", "-webkit-box-shadow", "-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"
],
"-webkit-transform": [
"scale", "scaleX", "scaleY", "scale3d", "rotate", "rotateX", "rotateY", "rotateZ", "rotate3d", "skew", "skewX", "skewY", 
"translate", "translateX", "translateY", "translateZ", "translate3d", "matrix", "matrix3d", "perspective"
]
}






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.consume(true); };

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;
computedStylePane._stylesSidebarPane = this;
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);

this._spectrum = new WebInspector.Spectrum();

WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetOrMediaQueryResultChanged, this);
WebInspector.cssModel.addEventListener(WebInspector.CSSStyleModel.Events.MediaQueryResultChanged, this._styleSheetOrMediaQueryResultChanged, 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-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.canonicalPropertyName = function(name)
{
if (!name || name.length < 9 || name.charAt(0) !== "-")
return name;
var match = name.match(/(?:-webkit-|-khtml-|-apple-)(.+)/);
if (!match)
return name;
return match[1];
}

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)
{
if (this._spectrum.visible)
this._spectrum.hide();

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;

if (refresh)
this._refreshUpdate();
else
this._rebuildUpdate();
},


_refreshUpdate: function(editedSection, forceFetchComputedStyle, userCallback)
{
if (this._refreshUpdateInProgress) {
this._lastNodeForInnerRefresh = this.node;
return;
}

var node = this._validateNode(userCallback);
if (!node)
return;

function computedStyleCallback(computedStyle)
{
delete this._refreshUpdateInProgress;

if (this._lastNodeForInnerRefresh) {
delete this._lastNodeForInnerRefresh;
this._refreshUpdate(editedSection, forceFetchComputedStyle, userCallback);
return;
}

if (this.node === node && computedStyle)
this._innerRefreshUpdate(node, computedStyle, editedSection);

if (userCallback)
userCallback();
}

if (this._computedStylePane.expanded || forceFetchComputedStyle) {
this._refreshUpdateInProgress = true;
WebInspector.cssModel.getComputedStyleAsync(node.id, this._forcedPseudoClasses, computedStyleCallback.bind(this));
} else {
this._innerRefreshUpdate(node, null, editedSection);
if (userCallback)
userCallback();
}
},


_rebuildUpdate: function(userCallback)
{
if (this._rebuildUpdateInProgress) {
this._lastNodeForInnerRebuild = this.node;
return;
}

var node = this._validateNode(userCallback);
if (!node)
return;

this._rebuildUpdateInProgress = true;

var resultStyles = {};

function stylesCallback(matchedResult)
{
delete this._rebuildUpdateInProgress;

if (this._lastNodeForInnerRebuild) {
delete this._lastNodeForInnerRebuild;
this._rebuildUpdate(userCallback);
return;
}

if (matchedResult && this.node === node) {
resultStyles.matchedCSSRules = matchedResult.matchedCSSRules;
resultStyles.pseudoElements = matchedResult.pseudoElements;
resultStyles.inherited = matchedResult.inherited;
this._innerRebuildUpdate(node, resultStyles);
}
if (userCallback)
userCallback();
}

function inlineCallback(inlineStyle, attributesStyle)
{
resultStyles.inlineStyle = inlineStyle;
resultStyles.attributesStyle = attributesStyle;
}

function computedCallback(computedStyle)
{
resultStyles.computedStyle = computedStyle;
}

if (this._computedStylePane.expanded)
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));
},

_validateNode: function(userCallback)
{
if (!this.node) {
this._sectionsContainer.removeChildren();
this._computedStylePane.bodyElement.removeChildren();
this.sections = {};
if (userCallback)
userCallback();
return null;
}
return this.node;
},

_styleSheetOrMediaQueryResultChanged: function()
{
if (this._userOperation || this._isEditingStyle)
return;

this._rebuildUpdate();
},

_attributesModified: function(event)
{
if (this.node !== event.data.node)
return;


if (event.data.name === "style")
return;


if (!this._isEditingStyle && !this._userOperation)
this._rebuildUpdate();
},

_attributesRemoved: function(event)
{
if (this.node !== event.data.node)
return;


if (!this._isEditingStyle && !this._userOperation)
this._rebuildUpdate();
},

_styleInvalidated: function(event)
{
if (this.node !== event.data)
return;

if (!this._isEditingStyle && !this._userOperation)
this._rebuildUpdate();
},

_innerRefreshUpdate: function(node, computedStyle, editedSection)
{
for (var pseudoId in this.sections) {
var styleRules = this._refreshStyleRules(this.sections[pseudoId], computedStyle);
var usedProperties = {};
this._markUsedProperties(styleRules, usedProperties);
this._refreshSectionsForStyleRules(styleRules, usedProperties, editedSection);
}
if (computedStyle)
this.sections[0][0].rebuildComputedTrace(this.sections[0]);

this._nodeStylesUpdatedForTest(node, false);
},

_innerRebuildUpdate: function(node, styles)
{
this._sectionsContainer.removeChildren();
this._computedStylePane.bodyElement.removeChildren();

var styleRules = this._rebuildStyleRules(node, styles);
var usedProperties = {};
this._markUsedProperties(styleRules, usedProperties);
this.sections[0] = this._rebuildSectionsForStyleRules(styleRules, usedProperties, 0, null);
var anchorElement = this.sections[0].inheritedPropertiesSeparatorElement;

if (styles.computedStyle)        
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 = {};
this._markUsedProperties(styleRules, usedProperties);
this.sections[pseudoId] = this._rebuildSectionsForStyleRules(styleRules, usedProperties, pseudoId, anchorElement);
}

this._nodeStylesUpdatedForTest(node, true);
},

_nodeStylesUpdatedForTest: function(node, rebuild)
{

},

_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 addAttributesStyle()
{
if (!styles.attributesStyle)
return;
var attrStyle = { style: styles.attributesStyle, editable: false };
attrStyle.selectorText = node.nodeNameInCorrectCase() + "[" + WebInspector.UIString("Attributes Style") + "]";
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 addedAttributesStyle;
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) && !addedAttributesStyle) {

addedAttributesStyle = true;
addAttributesStyle();
}
styleRules.push({ style: rule.style, selectorText: rule.selectorText, media: rule.media, sourceURL: rule.sourceURL, rule: rule, editable: !!(rule.style && rule.style.id) });
}

if (!addedAttributesStyle)
addAttributesStyle();


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)
{
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 canonicalName = WebInspector.StylesSidebarPane.canonicalPropertyName(property.name);

if (!priorityUsed && property.priority.length)
priorityUsed = true;



if (!(canonicalName in usedProperties))
styleRule.usedProperties[canonicalName] = true;
}



for (var canonicalName in styleRules[i].usedProperties)
usedProperties[canonicalName] = 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 canonicalName = WebInspector.StylesSidebarPane.canonicalPropertyName(property.name);
if (property.priority.length) {
if (!(canonicalName in foundPriorityProperties))
styleRules[i].usedProperties[canonicalName] = true;
else
delete styleRules[i].usedProperties[canonicalName];
foundPriorityProperties[canonicalName] = true;
} else if (canonicalName in foundPriorityProperties)
delete styleRules[i].usedProperties[canonicalName];
}
}
}
},

_refreshSectionsForStyleRules: function(styleRules, usedProperties, editedSection)
{

for (var i = 0; i < styleRules.length; ++i) {
var styleRule = styleRules[i];
var section = styleRule.section;
if (styleRule.computedStyle) {
section._usedProperties = usedProperties;
section.update();
} else {
section._usedProperties = styleRule.usedProperties;
section.update(section === editedSection);
}
}
},

_rebuildSectionsForStyleRules: function(styleRules, usedProperties, 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);
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.consume();
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.consume();
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._rebuildUpdate();
}
}
},

_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._rebuildUpdate();
}

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

willHide: function()
{
if (this._spectrum.visible)
this._spectrum.hide();
}
}

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


expand: function()
{
function callback()
{
WebInspector.SidebarPane.prototype.expand.call(this);
}

this._stylesSidebarPane._refreshUpdate(null, true, callback.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 matched-styles 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 lineNumber = media.sourceLine < 0 ? undefined : media.sourceLine;
var anchor = WebInspector.linkifyResourceAsNode(media.sourceURL, lineNumber, "subtitle", media.sourceURL + (isNaN(lineNumber) ? "" : (":" + (lineNumber + 1))));
anchor.preferredPanel = "styles";
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);
selectorContainer.addEventListener("mousedown", this._handleEmptySpaceMouseDown.bind(this), false);
selectorContainer.addEventListener("click", this._handleSelectorContainerClick.bind(this), false);

var closeBrace = document.createElement("div");
closeBrace.textContent = "}";
this.element.appendChild(closeBrace);

this._selectorElement.addEventListener("click", this._handleSelectorClick.bind(this), false);
this.element.addEventListener("mousedown", this._handleEmptySpaceMouseDown.bind(this), false);
this.element.addEventListener("click", this._handleEmptySpaceClick.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);
this._selectorContainer = 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 canonicalName = WebInspector.StylesSidebarPane.canonicalPropertyName(propertyName);
var used = (canonicalName 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 (WebInspector.StylesSidebarPane.canonicalPropertyName(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;
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, 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;
},

_checkWillCancelEditing: function()
{
var willCauseCancelEditing = this._willCauseCancelEditing;
delete this._willCauseCancelEditing;
return willCauseCancelEditing;
},

_handleSelectorContainerClick: function(event)
{
if (this._checkWillCancelEditing())
return;
if (event.target === this._selectorContainer)
this.addNewBlankProperty(0).startEditing();
},


addNewBlankProperty: function(index)
{
var style = this.styleRule.style;
var property = style.newBlankProperty(index);
var item = new WebInspector.StylePropertyTreeElement(this, this._parentPane, this.styleRule, style, property, false, false, false);
index = property.index;
this.propertiesTreeOutline.insertChild(item, index);
item.listItemElement.textContent = "";
item._newProperty = true;
item.updateTitle();
return item;
},

_createRuleOriginNode: function()
{
function linkifyUncopyable(url, line)
{
var link = WebInspector.linkifyResourceAsNode(url, line, "", url + ":" + (line + 1));
link.preferredPanel = "styles";
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);
},

_handleEmptySpaceMouseDown: function(event)
{
this._willCauseCancelEditing = this._parentPane._isEditingStyle;
},

_handleEmptySpaceClick: function(event)
{
if (!this.editable)
return;

if (this._checkWillCancelEditing())
return;

if (event.target.hasStyleClass("header") || this.element.hasStyleClass("read-only") || event.target.enclosingNodeOrSelfWithClass("media")) {
event.consume();
return;
}
this.expand();
this.addNewBlankProperty().startEditing();
},

_handleSelectorClick: function(event)
{
this._startEditingOnMouseEvent();
event.consume(true);
},

_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)
newContent = newContent.trim();
if (newContent === oldContent) {

this._selectorElement.textContent = newContent;
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)
{
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._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);
},

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;
if (!style)
return;

var uniqueProperties = [];
var allProperties = style.allProperties;
for (var i = 0; i < allProperties.length; ++i)
uniqueProperties.push(allProperties[i]);
uniqueProperties.sort(sorter);

this._propertyTreeElements = {};
for (var i = 0; i < uniqueProperties.length; ++i) {
var property = uniqueProperties[i];
var inherited = this._isPropertyInherited(property.name);
var item = new WebInspector.StylePropertyTreeElement(this, 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);

delete this._parentPane._userOperation;
}

this._parentPane._userOperation = true;
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(section, parentPane, styleRule, style, property, shorthand, inherited, overloaded)
{
this.section = section;
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);

this.selectable = false;
}

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();
this.listItemElement.addEventListener("mousedown", this._mouseDown.bind(this));
this.listItemElement.addEventListener("mouseup", this._resetMouseDownElement.bind(this));
this.listItemElement.addEventListener("click", this._mouseClick.bind(this));
},

_mouseDown: function(event)
{
if (this._parentPane) {
this._parentPane._mouseDownTreeElement = this;
this._parentPane._mouseDownTreeElementIsName = this._isNameElement(event.target);
this._parentPane._mouseDownTreeElementIsValue = this._isValueElement(event.target);
}
},

_resetMouseDownElement: function()
{
if (this._parentPane) {
delete this._parentPane._mouseDownTreeElement;
delete this._parentPane._mouseDownTreeElementIsName;
delete this._parentPane._mouseDownTreeElementIsValue;
}
},

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;
nameElement.title = this.property.propertyText;
this.nameElement = nameElement;

this._expandElement = document.createElement("span");
this._expandElement.className = "expand-element";

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 format = getFormat();
var hasSpectrum = self._parentPane;
var spectrum = hasSpectrum ? self._parentPane._spectrum : null;

var swatchElement = document.createElement("span");
var swatchInnerElement = swatchElement.createChild("span", "swatch-inner");
swatchElement.title = WebInspector.UIString("Click to open a colorpicker. Shift-click to change color format");

swatchElement.className = "swatch";

swatchElement.addEventListener("mousedown", consumeEvent, false);
swatchElement.addEventListener("click", swatchClick, false);
swatchElement.addEventListener("dblclick", consumeEvent, false);

swatchInnerElement.style.backgroundColor = text;

var scrollerElement = hasSpectrum ? self._parentPane._computedStylePane.element.parentElement : null;

function spectrumChanged(e)
{
color = e.data;

var colorString = color.toString();

colorValueElement.textContent = colorString;
spectrum.displayText = colorString;
swatchInnerElement.style.backgroundColor = colorString;

self.applyStyleText(nameElement.textContent + ": " + valueElement.textContent, false, false, false);
}

function spectrumHidden()
{
scrollerElement.removeEventListener("scroll", repositionSpectrum, false);
self.applyStyleText(nameElement.textContent + ": " + valueElement.textContent, true, true, false);
spectrum.removeEventListener(WebInspector.Spectrum.Events.ColorChanged, spectrumChanged);
spectrum.removeEventListener(WebInspector.Spectrum.Events.Hidden, spectrumHidden);

delete self._parentPane._isEditingStyle;
}

function repositionSpectrum()
{
spectrum.reposition(swatchElement);
}

function swatchClick(e)
{


if (!spectrum || e.shiftKey)
changeColorDisplay(e);
else {
var visible = spectrum.toggle(swatchElement, color, format);

if (visible) {
spectrum.displayText = color.toString(format);
self._parentPane._isEditingStyle = true;
spectrum.addEventListener(WebInspector.Spectrum.Events.ColorChanged, spectrumChanged);
spectrum.addEventListener(WebInspector.Spectrum.Events.Hidden, spectrumHidden);

scrollerElement.addEventListener("scroll", repositionSpectrum, false);
}
}
e.consume(true);
}

function getFormat()
{
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;

return format;
}

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.parent.root && !this.section.computedStyle)
this.listItemElement.appendChild(enabledCheckboxElement);
this.listItemElement.appendChild(nameElement);
this.listItemElement.appendChild(document.createTextNode(": "));
this.listItemElement.appendChild(this._expandElement);
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");
},

_updatePane: function(userCallback)
{
if (this.treeOutline && this.treeOutline.section && this.treeOutline.section.pane)
this.treeOutline.section.pane._refreshUpdate(this.treeOutline.section, false, 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");

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, this._parentPane, this._styleRule, this.style, liveProperty, false, inherited, overloaded);
this.appendChild(item);
}
},

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

_mouseClick: function(event)
{
event.consume(true);

if (event.target === this.listItemElement) {
if (!this.section.editable) 
return;

if (this.section._checkWillCancelEditing())
return;
this.section.addNewBlankProperty(this.property.index + 1).startEditing();
return;
}

this.startEditing(event.target);
},

_isNameElement: function(element)
{
return element.enclosingNodeOrSelfWithClass("webkit-css-property") === this.nameElement;
},

_isValueElement: function(element)
{
return !!element.enclosingNodeOrSelfWithClass("value");
},

startEditing: function(selectElement)
{

if (this.parent.shorthand)
return;

if (selectElement === this._expandElement)
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)
{
var treeElement = this._parentPane._mouseDownTreeElement;
var moveDirection = "";
if (treeElement === this) {
if (isEditingName && this._parentPane._mouseDownTreeElementIsValue)
moveDirection = "forward";
if (!isEditingName && this._parentPane._mouseDownTreeElementIsName)
moveDirection = "backward";
}
this.editingCommitted(null, event.target.textContent, context.previousContent, context, moveDirection);
}

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.consume();
return;
}

if (!isEditingName)
this._applyFreeFlowStyleTextEdit(false);
},

_applyFreeFlowStyleTextEdit: function(now)
{
if (this._applyFreeFlowStyleTextEditTimer)
clearTimeout(this._applyFreeFlowStyleTextEditTimer);

function apply()
{
var valueText = this.valueElement.textContent;
if (valueText.indexOf(";") === -1)
this.applyStyleText(this.nameElement.textContent + ": " + valueText, false, false, false);
}
if (now)
apply.call(this);
else
this._applyFreeFlowStyleTextEditTimer = setTimeout(apply.bind(this), 100);
},

kickFreeFlowStyleEditForTest: function()
{
this._applyFreeFlowStyleTextEdit(true);
},

editingEnded: function(context)
{
this._resetMouseDownElement();
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();
}
},

_findSibling: function(moveDirection)
{
var target = this;
do {
target = (moveDirection === "forward" ? target.nextSibling : target.previousSibling);
} while(target && target.inherited);

return target;
},

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) {
moveTo = moveTo._findSibling(moveDirection);
if (moveTo)
moveToPropertyName = moveTo.name;
else if (moveDirection === "forward" && (!this._newProperty || userInput))
createNewProperty = true;
else if (moveDirection === "backward")
moveToSelector = true;
}


var moveToIndex = moveTo && this.treeOutline ? this.treeOutline.children.indexOf(moveTo) : -1;
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);
}


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) {
var elementToEdit = !isEditingName ? treeElement.nameElement : treeElement.valueElement;
if (alreadyNew && blankInput)
elementToEdit = moveDirection === "forward" ? treeElement.nameElement : treeElement.valueElement;
treeElement.startEditing(elementToEdit);
return;
} else if (!alreadyNew)
moveToSelector = true;
}
}


if (createNewProperty) {
if (alreadyNew && !valueChanged && (isEditingName ^ (moveDirection === "backward")))
return;

section.addNewBlankProperty().startEditing();
return;
}

if (abandonNewProperty) {
moveTo = this._findSibling(moveDirection);
var sectionToEdit = (moveTo || 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;
}

if (this._newProperty)
this._newPropertyInStyle = true;
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 += ";";
var overwriteProperty = !!(!this._newProperty || this._newPropertyInStyle);
this.property.setText(styleText, majorChange, overwriteProperty, callback.bind(this, userOperationFinishedCallback.bind(null, this._parentPane, updateInterface), this.originalPropertyText));
},

ondblclick: function()
{
return true; 
},

isEventWithinDisclosureTriangle: function(event)
{
if (!this.section.computedStyle)
return event.target === this._expandElement;
return TreeElement.prototype.isEventWithinDisclosureTriangle.call(this, event);
}
}

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.isSelfOrDescendant(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(textPrompt, 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.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();

this._popoverHelper = new WebInspector.PopoverHelper(document.body, this._getPopoverAnchor.bind(this), this._showPopover.bind(this));
this._popoverHelper.setTimeout(0);

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

defaultFocusedElement: function()
{
return this.treeOutline.element;
},

statusBarResized: function()
{
this.updateBreadcrumbSizes();
},

wasShown: function()
{

if (this.treeOutline.element.parentElement !== this.contentElement)
this.contentElement.appendChild(this.treeOutline.element);

WebInspector.Panel.prototype.wasShown.call(this);

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._popoverHelper.hidePopover();


this.contentElement.removeChild(this.treeOutline.element);

for (var pane in this.sidebarPanes) {
if (this.sidebarPanes[pane].willHide)
this.sidebarPanes[pane].willHide();
}

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

this._updateSidebars();

if (selectedNode) {
ConsoleAgent.addInspectedNode(selectedNode.id);
this._lastValidSelectedNode = selectedNode;
}
},

_updateSidebars: function()
{
for (var pane in this.sidebarPanes)
this.sidebarPanes[pane].needsUpdate = true;

this.updateStyles(true);
this.updateMetrics();
this.updateProperties();
this.updateEventListeners();
},

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

_getPopoverAnchor: function(element)
{
var anchor = element.enclosingNodeOrSelfWithClass("webkit-html-resource-link");
if (anchor) {
if (!anchor.href)
return null;

var resource = WebInspector.resourceTreeModel.resourceForURL(anchor.href);
if (!resource || resource.type !== WebInspector.resourceTypes.Image)
return null;

anchor.removeAttribute("title");
}
return anchor;
},

_loadDimensionsForNode: function(treeElement, callback)
{

if (treeElement.treeOutline !== this.treeOutline) {
callback();
return;
}

var node =   treeElement.representedObject;

if (!node.nodeName() || node.nodeName().toLowerCase() !== "img") {
callback();
return;
}

WebInspector.RemoteObject.resolveNode(node, "", resolvedNode);

function resolvedNode(object)
{
if (!object) {
callback();
return;
}

object.callFunctionJSON(dimensions, undefined, callback);
object.release();

function dimensions()
{
return { offsetWidth: this.offsetWidth, offsetHeight: this.offsetHeight, naturalWidth: this.naturalWidth, naturalHeight: this.naturalHeight };
}
}
},


_showPopover: function(anchor, popover)
{
var listItem = anchor.enclosingNodeOrSelfWithNodeNameInArray(["li"]);
if (listItem && listItem.treeElement)
this._loadDimensionsForNode(listItem.treeElement, dimensionsCallback);
else
dimensionsCallback();


function dimensionsCallback(dimensions)
{
var imageElement = document.createElement("img");
imageElement.addEventListener("load", showPopover.bind(null, imageElement, dimensions), false);
var resource = WebInspector.resourceTreeModel.resourceForURL(anchor.href);
if (!resource)
return;

resource.populateImageSource(imageElement);
}


function showPopover(imageElement, dimensions)
{
var contents = buildPopoverContents(imageElement, dimensions);
popover.setCanShrink(false);
popover.show(contents, anchor);
}


function buildPopoverContents(imageElement, nodeDimensions)
{
const maxImageWidth = 100;
const maxImageHeight = 100;
var container = document.createElement("table");
container.className = "image-preview-container";
var naturalWidth = nodeDimensions ? nodeDimensions.naturalWidth : imageElement.naturalWidth;
var naturalHeight = nodeDimensions ? nodeDimensions.naturalHeight : imageElement.naturalHeight;
var offsetWidth = nodeDimensions ? nodeDimensions.offsetWidth : naturalWidth;
var offsetHeight = nodeDimensions ? nodeDimensions.offsetHeight : naturalHeight;
var description;
if (offsetHeight === naturalHeight && offsetWidth === naturalWidth)
description = WebInspector.UIString("%d \xd7 %d pixels", offsetWidth, offsetHeight);
else
description = WebInspector.UIString("%d \xd7 %d pixels (Natural: %d \xd7 %d pixels)", offsetWidth, offsetHeight, naturalWidth, naturalHeight);

if (naturalWidth > naturalHeight) {
if (naturalWidth > maxImageWidth) {
imageElement.style.width = maxImageWidth + "px";
imageElement.style.height = (naturalHeight * maxImageWidth / naturalWidth) + "px";
}
} else {
if (naturalHeight > maxImageHeight) {
imageElement.style.width = (naturalWidth * maxImageHeight / naturalHeight) + "px";
imageElement.style.height = maxImageHeight + "px";
}
}
container.createChild("tr").createChild("td", "image-container").appendChild(imageElement);
container.createChild("tr").createChild("td").createChild("span", "description").textContent = description;
return container;
}
},

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"));
section.addKey(shortcut.shortcutToString(shortcut.Keys.F2), WebInspector.UIString("Toggle edit as HTML"));

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

if (WebInspector.KeyboardShortcut.eventHasCtrlOrMeta(event) && !event.shiftKey && event.keyIdentifier === "U+005A") { 
WebInspector.domAgent.undo(this._updateSidebars.bind(this));
event.handled = true;
return;
}

var isRedoKey = WebInspector.isMac() ? event.metaKey && event.shiftKey && event.keyIdentifier === "U+005A" : 
event.ctrlKey && event.keyIdentifier === "U+0059"; 
if (isRedoKey) {
DOMAgent.redo(this._updateSidebars.bind(this));
event.handled = true;
return;
}

this.treeOutline.handleShortcut(event);
},

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._allowRequestSelection = false;
this._requests = [];
this._requestsById = {};
this._requestsByURL = {};
this._staleRequests = {};
this._requestGridNodes = {};
this._lastRequestGridNodeId = 0;
this._mainRequestLoadTime = -1;
this._mainRequestDOMContentTime = -1;
this._hiddenCategories = {};
this._matchedRequests = [];
this._matchedRequestsMap = {};
this._currentMatchedRequestIndex = -1;

this._createStatusbarButtons();
this._createFilterStatusBarItems();
this._linkifier = new WebInspector.Linkifier();

WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestStarted, this._onRequestStarted, this);
WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestUpdated, this._onRequestUpdated, this);
WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestFinished, this._onRequestUpdated, 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.canClearBrowserCookies(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._setLargerRequests(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._largerRequestsButton.element, this._preserveLogToggle.element, this._clearButton.element, this._filterBarElement];
},

get useLargeRows()
{
return WebInspector.settings.resourcesLargeRows.get();
},

set allowPopover(flag)
{
this._allowPopover = 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.consume() }, 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.RequestPropertyComparator.bind(null, "method", false);
this._sortingFunctions.status = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "statusCode", false);
this._sortingFunctions.type = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "mimeType", false);
this._sortingFunctions.initiator = WebInspector.NetworkDataGridNode.InitiatorComparator;
this._sortingFunctions.size = WebInspector.NetworkDataGridNode.SizeComparator;
this._sortingFunctions.time = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "duration", false);
this._sortingFunctions.timeline = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "startTime", false);
this._sortingFunctions.startTime = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "startTime", false);
this._sortingFunctions.endTime = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "endTime", false);
this._sortingFunctions.responseTime = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "responseReceivedTime", false);
this._sortingFunctions.duration = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "duration", true);
this._sortingFunctions.latency = WebInspector.NetworkDataGridNode.RequestPropertyComparator.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(typeName, label)
{
var categoryElement = document.createElement("li");
categoryElement.typeName = typeName;
categoryElement.className = typeName;
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 typeId in WebInspector.resourceTypes) {
var type = WebInspector.resourceTypes[typeId];
createFilterElement.call(this, type.name(), type.categoryTitle());
}
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._requests.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._requests.length; ++i) {
var request = this._requests[i];
var requestTransferSize = (request.cached || !request.transferSize) ? 0 : request.transferSize;
transferSize += requestTransferSize;
if (!this._hiddenCategories.all || !this._hiddenCategories[request.type.name()]) {
selectedRequestsNumber++;
selectedTransferSize += requestTransferSize;
}
if (request.url === WebInspector.inspectedPageURL)
baseTime = request.startTime;
if (request.endTime > maxTime)
maxTime = request.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._mainRequestLoadTime !== -1 && this._mainRequestDOMContentTime !== -1 && this._mainRequestDOMContentTime > baseTime) {
text += "  \u2758  " + String.sprintf(WebInspector.UIString("%s (onload: %s, DOMContentLoaded: %s)"),
Number.secondsToString(maxTime - baseTime),
Number.secondsToString(this._mainRequestLoadTime - baseTime),
Number.secondsToString(this._mainRequestDOMContentTime - baseTime));
}
this._summaryBarElement.textContent = text;
},

_showCategory: function(typeName)
{
this._dataGrid.element.addStyleClass("filter-" + typeName);
delete this._hiddenCategories[typeName];
},

_hideCategory: function(typeName)
{
this._dataGrid.element.removeStyleClass("filter-" + typeName);
this._hiddenCategories[typeName] = 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.typeName)
continue;

child.removeStyleClass("selected");
this._hideCategory(child.typeName);
}
}

if (target === 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.typeName);
this._updateOffscreenRows();
return;
}

if (target.hasStyleClass("selected")) {


target.removeStyleClass("selected");
this._hideCategory(target.typeName);
} else {


target.addStyleClass("selected");
this._showCategory(target.typeName);
}
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()
{
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 {
this.calculator.setDisplayWindow(this._timelineGrid.element.clientWidth);
proceed = this._timelineGrid.updateDividers(this.calculator);
}
if (!proceed)
return;

if (this.calculator.startAtZero || !this.calculator.computePercentageFromEventTime) {






return;
}

this._timelineGrid.removeEventDividers();
if (this._mainRequestLoadTime !== -1) {
var percent = this.calculator.computePercentageFromEventTime(this._mainRequestLoadTime);

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._mainRequestDOMContentTime !== -1) {
var percent = this.calculator.computePercentageFromEventTime(this._mainRequestDOMContentTime);

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._requests.length; ++i) {
var request = this._requests[i];
this._staleRequests[request.requestId] = request;
}
},

get calculator()
{
return this._calculator;
},

set calculator(x)
{
if (!x || this._calculator === x)
return;

this._calculator = x;
this._calculator.reset();

this._invalidateAllItems();
this.refresh();
},

_requestGridNode: function(request)
{
return this._requestGridNodes[request.__gridNodeId];
},

_createRequestGridNode: function(request)
{
var node = new WebInspector.NetworkDataGridNode(this, request);
request.__gridNodeId = this._lastRequestGridNodeId++;
this._requestGridNodes[request.__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._largerRequestsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Use small resource rows."), "network-larger-resources-status-bar-item");
this._largerRequestsButton.toggled = WebInspector.settings.resourcesLargeRows.get();
this._largerRequestsButton.addEventListener("click", this._toggleLargerRequests, this);
},

_onLoadEventFired: function(event)
{
this._mainRequestLoadTime = event.data || -1;

this._scheduleRefresh();
},

_domContentLoadedEventFired: function(event)
{
this._mainRequestDOMContentTime = 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._mainRequestLoadTime) || boundariesChanged;
boundariesChanged = this.calculator.updateBoundariesForEventTime(this._mainRequestDOMContentTime) || boundariesChanged;
}

for (var requestId in this._staleRequests) {
var request = this._staleRequests[requestId];
var node = this._requestGridNode(request);
if (!node) {

node = this._createRequestGridNode(request);
this._dataGrid.rootNode().appendChild(node);
}
node.refreshRequest();

if (this.calculator.updateBoundaries(request))
boundariesChanged = true;

if (!node.isFilteredOut())
this._updateHighlightIfMatched(request);
}

if (boundariesChanged) {

this._invalidateAllItems();
}

for (var requestId in this._staleRequests)
this._requestGridNode(this._staleRequests[requestId]).refreshGraph(this.calculator);

this._staleRequests = {};
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._requests = [];
this._requestsById = {};
this._requestsByURL = {};
this._staleRequests = {};
this._requestGridNodes = {};

if (this._dataGrid) {
this._dataGrid.rootNode().removeChildren();
this._updateDividersIfNeeded();
this._updateSummaryBar();
}

this._mainRequestLoadTime = -1;
this._mainRequestDOMContentTime = -1;
this._linkifier.reset();
},

get requests()
{
return this._requests;
},

requestById: function(id)
{
return this._requestsById[id];
},

_onRequestStarted: function(event)
{
this._appendRequest(event.data);
},

_appendRequest: function(request)
{
this._requests.push(request);



if (this._requestsById[request.requestId]) {
var oldRequest = request.redirects[request.redirects.length - 1];
this._requestsById[oldRequest.requestId] = oldRequest;

this._updateSearchMatchedListAfterRequestIdChanged(request.requestId, oldRequest.requestId);
}
this._requestsById[request.requestId] = request;

this._requestsByURL[request.url] = request;


if (request.redirects) {
for (var i = 0; i < request.redirects.length; ++i)
this._refreshRequest(request.redirects[i]);
}

this._refreshRequest(request);
},


_onRequestUpdated: function(event)
{
var request =   event.data;
this._refreshRequest(request);
},


_refreshRequest: function(request)
{
this._staleRequests[request.requestId] = request;
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 requestsToPreserve = [];
for (var i = 0; i < this._requests.length; ++i) {
var request = this._requests[i];
if (request.loaderId === loaderId)
requestsToPreserve.push(request);
}

this._reset();


for (var i = 0; i < requestsToPreserve.length; ++i)
this._appendRequest(requestsToPreserve[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();
},

_toggleLargerRequests: function()
{
WebInspector.settings.resourcesLargeRows.set(!WebInspector.settings.resourcesLargeRows.get());
this._setLargerRequests(WebInspector.settings.resourcesLargeRows.get());
},

_setLargerRequests: function(enabled)
{
this._largerRequestsButton.toggled = enabled;
if (!enabled) {
this._largerRequestsButton.title = WebInspector.UIString("Use large resource rows.");
this._dataGrid.element.addStyleClass("small");
this._timelineGrid.element.addStyleClass("small");
} else {
this._largerRequestsButton.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 request = anchor.parentElement.request;
return request && request.timing ? anchor : null;
},


_showPopover: function(anchor, popover)
{
var request = anchor.parentElement.request;
var tableElement = WebInspector.RequestTimingView.createTimingTable(request);
popover.show(tableElement, anchor);
},

_contextMenu: function(event)
{
var contextMenu = new WebInspector.ContextMenu();
var gridNode = this._dataGrid.dataGridNodeFromNode(event.target);
var request = gridNode && gridNode._request;

if (request) {
contextMenu.appendItem(WebInspector.openLinkExternallyLabel(), WebInspector.openResource.bind(WebInspector, request.url, false));
contextMenu.appendSeparator();
contextMenu.appendItem(WebInspector.copyLinkAddressLabel(), this._copyLocation.bind(this, request));
if (request.requestHeadersText)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy request headers" : "Copy Request Headers"), this._copyRequestHeaders.bind(this, request));
if (request.responseHeadersText)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy response headers" : "Copy Response Headers"), this._copyResponseHeaders.bind(this, request));
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy entry as HAR" : "Copy Entry as HAR"), this._copyRequest.bind(this, request));
}
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Copy all as HAR" : "Copy All as HAR"), this._copyAll.bind(this));

if (InspectorFrontendHost.canSave()) {
contextMenu.appendSeparator();
if (request)
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save entry as HAR" : "Save Entry as HAR"), this._exportRequest.bind(this, request));
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._requests)).build()
};
InspectorFrontendHost.copyText(JSON.stringify(harArchive, null, 2));
},

_copyRequest: function(request)
{
var har = (new WebInspector.HAREntry(request)).build();
InspectorFrontendHost.copyText(JSON.stringify(har, null, 2));
},

_copyLocation: function(request)
{
InspectorFrontendHost.copyText(request.url);
},

_copyRequestHeaders: function(request)
{
InspectorFrontendHost.copyText(request.requestHeadersText);
},

_copyResponseHeaders: function(request)
{
InspectorFrontendHost.copyText(request.responseHeadersText);
},

_exportAll: function()
{
var harArchive = {
log: (new WebInspector.HARLog(this._requests)).build()
};

WebInspector.save(WebInspector.inspectedPageDomain + ".har", JSON.stringify(harArchive, null, 2), true);
},

_exportRequest: function(request)
{
var har = (new WebInspector.HAREntry(request)).build();
WebInspector.save(request.displayName + ".har", JSON.stringify(har, null, 2), true);
},

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

_matchRequest: function(request)
{
if (!this._searchRegExp)
return -1;

if ((!request.displayName || !request.displayName.match(this._searchRegExp)) && !request.folder.match(this._searchRegExp))
return -1;

if (request.requestId in this._matchedRequestsMap)
return this._matchedRequestsMap[request.requestId];

var matchedRequestIndex = this._matchedRequests.length;
this._matchedRequestsMap[request.requestId] = matchedRequestIndex;
this._matchedRequests.push(request.requestId);

return matchedRequestIndex;
},

_clearSearchMatchedList: function()
{
this._matchedRequests = [];
this._matchedRequestsMap = {};
this._highlightNthMatchedRequest(-1, false);
},

_updateSearchMatchedListAfterRequestIdChanged: function(oldRequestId, newRequestId)
{
var requestIndex = this._matchedRequestsMap[oldRequestId];
if (requestIndex) {
delete this._matchedRequestsMap[oldRequestId];
this._matchedRequestsMap[newRequestId] = requestIndex;
this._matchedRequests[requestIndex] = newRequestId;
}
},

_updateHighlightIfMatched: function(request)
{
var matchedRequestIndex = this._matchRequest(request);
if (matchedRequestIndex === -1)
return;

this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.SearchCountUpdated, this._matchedRequests.length);

if (this._currentMatchedRequestIndex !== -1 && this._currentMatchedRequestIndex !== matchedRequestIndex)
return;

this._highlightNthMatchedRequest(matchedRequestIndex, false);
},

_highlightNthMatchedRequest: function(matchedRequestIndex, reveal)
{
if (this._highlightedSubstringChanges) {
WebInspector.revertDomChanges(this._highlightedSubstringChanges);
this._highlightedSubstringChanges = null;
}

if (matchedRequestIndex === -1) {
this._currentMatchedRequestIndex = matchedRequestIndex;
return;
}

var request = this._requestsById[this._matchedRequests[matchedRequestIndex]];
if (!request)
return;

var nameMatched = request.displayName && request.displayName.match(this._searchRegExp);
var pathMatched = request.parsedURL.path && request.folder.match(this._searchRegExp);
if (!nameMatched && pathMatched && !this._largerRequestsButton.toggled)
this._toggleLargerRequests();

var node = this._requestGridNode(request);
if (node) {
this._highlightedSubstringChanges = node._highlightMatchedSubstring(this._searchRegExp);
if (reveal)
node.reveal();
this._currentMatcRequestrceIndex = matchedRequestIndex;
}
this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.SearchIndexUpdated, this._currentMatchedRequestIndex);
},

performSearch: function(searchQuery, sortOrFilterApplied)
{
var newMatchedRequestIndex = 0;
var currentMatchedRequestId;
if (this._currentMatchedRequestIndex !== -1)
currentMatchedRequestId = this._matchedRequests[this._currentMatchedRequestIndex];

if (!sortOrFilterApplied)
this._searchRegExp = createPlainTextSearchRegex(searchQuery, "i");

this._clearSearchMatchedList();

var childNodes = this._dataGrid.dataTableBody.childNodes;
var requestNodes = Array.prototype.slice.call(childNodes, 0, childNodes.length - 1); 

for (var i = 0; i < requestNodes.length; ++i) {
var dataGridNode = this._dataGrid.dataGridNodeFromNode(requestNodes[i]);
if (dataGridNode.isFilteredOut())
continue;

if (this._matchRequest(dataGridNode._request) !== -1 && dataGridNode._request.requestId === currentMatchedRequestId)
newMatchedRequestIndex = this._matchedRequests.length - 1;
}

this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.SearchCountUpdated, this._matchedRequests.length);
this._highlightNthMatchedRequest(newMatchedRequestIndex, !sortOrFilterApplied);
},

jumpToPreviousSearchResult: function()
{
if (!this._matchedRequests.length)
return;
this._highlightNthMatchedRequest((this._currentMatchedRequestIndex + this._matchedRequests.length - 1) % this._matchedRequests.length, true);
},

jumpToNextSearchResult: function()
{
if (!this._matchedRequests.length)
return;
this._highlightNthMatchedRequest((this._currentMatchedRequestIndex + 1) % this._matchedRequests.length, true);
},

searchCanceled: function()
{
this._clearSearchMatchedList();
this.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.SearchCountUpdated, 0);
},

revealAndHighlightRequest: function(request)
{
this._removeAllNodeHighlights();

var node = this._requestGridNode(request);
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",
RequestSelected: "RequestSelected",
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.RequestSelected, this._onRequestSelected, 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._viewingRequestMode && 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 requests()
{
return this._networkLogView.requests;
},

requestById: function(id)
{
return this._networkLogView.requestById(id);
},

_requestByAnchor: function(anchor)
{
return anchor.requestId ? this.requestById(anchor.requestId) : this._networkLogView._requestsByURL[anchor.href];
},

canShowAnchorLocation: function(anchor)
{
return !!this._requestByAnchor(anchor);
},

showAnchorLocation: function(anchor)
{
var request = this._requestByAnchor(anchor);
this.revealAndHighlightRequest(request)
},

revealAndHighlightRequest: function(request)
{
this._toggleGridMode();
if (request)
this._networkLogView.revealAndHighlightRequest(request);
},

_onViewCleared: function(event)
{
this._closeVisibleRequest();
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);
},

_onRequestSelected: function(event)
{
this._showRequest(event.data);
},

_showRequest: function(request)
{
if (!request)
return;

this._toggleViewingRequestMode();

if (this.visibleView) {
this.visibleView.detach();
delete this.visibleView;
}

var view = new WebInspector.NetworkItemView(request);
view.show(this._viewsContainerElement);
this.visibleView = view;
},

_closeVisibleRequest: function()
{
this.element.removeStyleClass("viewing-resource");

if (this.visibleView) {
this.visibleView.detach();
delete this.visibleView;
}
},

_toggleGridMode: function()
{
if (this._viewingRequestMode) {
this._viewingRequestMode = false;
this.element.removeStyleClass("viewing-resource");
this.splitView.hideMainElement();
}

this._networkLogView.switchToDetailedView();
this._networkLogView.allowPopover = true;
this._networkLogView._allowRequestSelection = false;
},

_toggleViewingRequestMode: function()
{
if (this._viewingRequestMode)
return;
this._viewingRequestMode = true;

this.element.addStyleClass("viewing-resource");
this.splitView.showMainElement();
this._networkLogView.allowPopover = false;
this._networkLogView._allowRequestSelection = 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 = {
computePosition: function(time)
{
return (time - this.minimumBoundary) / this.boundarySpan * this._workingArea;
},

computeBarGraphPercentages: function(item)
{
return {start: 0, middle: 0, end: (this._value(item) / this.boundarySpan) * 100};
},

computeBarGraphLabels: function(item)
{
const label = this.formatTime(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;
},

formatTime: function(value)
{
return value.toString();
},

setDisplayWindow: function(clientWidth)
{
this._workingArea = clientWidth;
this.paddingLeft = 0;
}
}


WebInspector.NetworkTimeCalculator = function(startAtZero)
{
WebInspector.NetworkBaseCalculator.call(this);
this.startAtZero = startAtZero;
}

WebInspector.NetworkTimeCalculator.prototype = {
computeBarGraphPercentages: function(request)
{
if (request.startTime !== -1)
var start = ((request.startTime - this.minimumBoundary) / this.boundarySpan) * 100;
else
var start = 0;

if (request.responseReceivedTime !== -1)
var middle = ((request.responseReceivedTime - this.minimumBoundary) / this.boundarySpan) * 100;
else
var middle = (this.startAtZero ? start : 100);

if (request.endTime !== -1)
var end = ((request.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(request)
{
var rightLabel = "";
if (request.responseReceivedTime !== -1 && request.endTime !== -1)
rightLabel = this.formatTime(request.endTime - request.responseReceivedTime);

var hasLatency = request.latency > 0;
if (hasLatency)
var leftLabel = this.formatTime(request.latency);
else
var leftLabel = rightLabel;

if (request.timing)
return {left: leftLabel, right: rightLabel};

if (hasLatency && rightLabel) {
var total = this.formatTime(request.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 (request.cached)
tooltip = WebInspector.UIString("%s (from cache)", tooltip);
return {left: leftLabel, right: rightLabel, tooltip: tooltip};
},

updateBoundaries: function(request)
{
var didChange = false;

var lowerBound;
if (this.startAtZero)
lowerBound = 0;
else
lowerBound = this._lowerBound(request);

if (lowerBound !== -1 && (typeof this.minimumBoundary === "undefined" || lowerBound < this.minimumBoundary)) {
this.minimumBoundary = lowerBound;
didChange = true;
}

var upperBound = this._upperBound(request);
if (upperBound !== -1 && (typeof this.maximumBoundary === "undefined" || upperBound > this.maximumBoundary)) {
this.maximumBoundary = upperBound;
didChange = true;
}

return didChange;
},

formatTime: function(value)
{
return Number.secondsToString(value);
},

_lowerBound: function(request)
{
return 0;
},

_upperBound: function(request)
{
return 0;
}
}

WebInspector.NetworkTimeCalculator.prototype.__proto__ = WebInspector.NetworkBaseCalculator.prototype;


WebInspector.NetworkTransferTimeCalculator = function()
{
WebInspector.NetworkTimeCalculator.call(this, false);
}

WebInspector.NetworkTransferTimeCalculator.prototype = {
formatTime: function(value)
{
return Number.secondsToString(value);
},

_lowerBound: function(request)
{
return request.startTime;
},

_upperBound: function(request)
{
return request.endTime;
}
}

WebInspector.NetworkTransferTimeCalculator.prototype.__proto__ = WebInspector.NetworkTimeCalculator.prototype;


WebInspector.NetworkTransferDurationCalculator = function()
{
WebInspector.NetworkTimeCalculator.call(this, true);
}

WebInspector.NetworkTransferDurationCalculator.prototype = {
formatTime: function(value)
{
return Number.secondsToString(value);
},

_upperBound: function(request)
{
return request.duration;
}
}

WebInspector.NetworkTransferDurationCalculator.prototype.__proto__ = WebInspector.NetworkTimeCalculator.prototype;


WebInspector.NetworkDataGridNode = function(parentView, request)
{
WebInspector.DataGridNode.call(this, {});
this._parentView = parentView;
this._request = request;
}

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._request.type.name() in this._parentView._hiddenCategories;
},

select: function()
{
this._parentView.dispatchEventToListeners(WebInspector.NetworkLogView.EventTypes.RequestSelected, this._request);
WebInspector.DataGridNode.prototype.select.apply(this, arguments);
},

_highlightMatchedSubstring: function(regexp)
{
var domChanges = [];
var matchInfo = this._nameCell.textContent.match(regexp);
WebInspector.highlightSearchResult(this._nameCell, matchInfo.index, matchInfo[0].length, domChanges);
return domChanges;
},

_openInNewTab: function()
{
InspectorFrontendHost.openInNewTab(this._request.url);
},

get selectable()
{
return this._parentView._allowRequestSelection && !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.request = this._request;
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);
},

refreshRequest: function()
{
this._refreshNameCell();

this._methodCell.setTextAndTitle(this._request.requestMethod);

this._refreshStatusCell();
this._refreshTypeCell();
if (Capabilities.nativeInstrumentationEnabled)
this._refreshInitiatorCell();
this._refreshSizeCell();
this._refreshTimeCell();

if (this._request.cached)
this._graphElement.addStyleClass("resource-cached");

this._element.addStyleClass("network-item");
if (!this._element.hasStyleClass("network-type-" + this._request.type.name())) {
this._element.removeMatchingStyleClasses("network-type-\\w+");
this._element.addStyleClass("network-type-" + this._request.type.name());
}
},

_refreshNameCell: function()
{
this._nameCell.removeChildren();

if (this._request.type === WebInspector.resourceTypes.Image) {
var previewImage = document.createElement("img");
previewImage.className = "image-network-icon-preview";
this._request.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 = WebInspector.displayDomain(this._request.parsedURL.host);

if (this._request.parsedURL.path)
subtitle += this._request.folder;

this._appendSubtitle(this._nameCell, subtitle);
this._nameCell.title = this._request.url;
},

_fileName: function()
{
var fileName = this._request.displayName;
if (this._request.queryString)
fileName += "?" + this._request.queryString;
return fileName;
},

_refreshStatusCell: function()
{
this._statusCell.removeChildren();

if (this._request.failed) {
var failText = this._request.canceled ? WebInspector.UIString("(canceled)") : WebInspector.UIString("(failed)");
if (this._request.localizedFailDescription) {
this._statusCell.appendChild(document.createTextNode(failText));
this._appendSubtitle(this._statusCell, this._request.localizedFailDescription);
this._statusCell.title = failText + " " + this._request.localizedFailDescription;
} else {
this._statusCell.setTextAndTitle(failText);
}
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._request.statusCode) {
this._statusCell.appendChild(document.createTextNode(this._request.statusCode));
this._appendSubtitle(this._statusCell, this._request.statusText);
this._statusCell.title = this._request.statusCode + " " + this._request.statusText;
if (this._request.statusCode >= 400)
this.element.addStyleClass("network-error-row");
if (this._request.cached)
this._statusCell.addStyleClass("network-dim-cell");
} else {
if (!this._request.isHttpFamily() && this._request.finished)
this._statusCell.setTextAndTitle(WebInspector.UIString("Success"));
else if (this._request.isPingRequest())
this._statusCell.setTextAndTitle(WebInspector.UIString("(ping)"));
else
this._statusCell.setTextAndTitle(WebInspector.UIString("(pending)"));
this._statusCell.addStyleClass("network-dim-cell");
}
},

_refreshTypeCell: function()
{
if (this._request.mimeType) {
this._typeCell.removeStyleClass("network-dim-cell");
this._typeCell.setTextAndTitle(this._request.mimeType);
} else if (this._request.isPingRequest()) {
this._typeCell.removeStyleClass("network-dim-cell");
this._typeCell.setTextAndTitle(this._request.requestContentType());
} else {
this._typeCell.addStyleClass("network-dim-cell");
this._typeCell.setTextAndTitle(WebInspector.UIString("Pending"));
}
},

_refreshInitiatorCell: function()
{
var initiator = this._request.initiator;
if ((initiator && initiator.type !== "other") || this._request.redirectSource) {
this._initiatorCell.removeStyleClass("network-dim-cell");
this._initiatorCell.removeChildren();
if (this._request.redirectSource) {
var redirectSource = this._request.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._request.cached) {
this._sizeCell.setTextAndTitle(WebInspector.UIString("(from cache)"));
this._sizeCell.addStyleClass("network-dim-cell");
} else {
var resourceSize = typeof this._request.resourceSize === "number" ? Number.bytesToString(this._request.resourceSize) : "?";
var transferSize = typeof this._request.transferSize === "number" ? Number.bytesToString(this._request.transferSize) : "?";
this._sizeCell.setTextAndTitle(transferSize);
this._sizeCell.removeStyleClass("network-dim-cell");
this._appendSubtitle(this._sizeCell, resourceSize);
}
},

_refreshTimeCell: function()
{
if (this._request.duration > 0) {
this._timeCell.removeStyleClass("network-dim-cell");
this._timeCell.setTextAndTitle(Number.secondsToString(this._request.duration));
this._appendSubtitle(this._timeCell, Number.secondsToString(this._request.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._request);
this._percentages = percentages;

this._barAreaElement.removeStyleClass("hidden");

if (!this._graphElement.hasStyleClass("network-type-" + this._request.type.name())) {
this._graphElement.removeMatchingStyleClasses("network-type-\\w+");
this._graphElement.addStyleClass("network-type-" + this._request.type.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._request);
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._request.displayName + (a._request.queryString ? a._request.queryString : "");
var bFileName = b._request.displayName + (b._request.queryString ? b._request.queryString : "");
if (aFileName > bFileName)
return 1;
if (bFileName > aFileName)
return -1;
return 0;
}

WebInspector.NetworkDataGridNode.SizeComparator = function(a, b)
{
if (b._request.cached && !a._request.cached)
return 1;
if (a._request.cached && !b._request.cached)
return -1;

if (a._request.resourceSize === b._request.resourceSize)
return 0;

return a._request.resourceSize - b._request.resourceSize;
}

WebInspector.NetworkDataGridNode.InitiatorComparator = function(a, b)
{
if (!a._request.initiator || a._request.initiator.type === "Other")
return -1;
if (!b._request.initiator || b._request.initiator.type === "Other")
return 1;

if (a._request.initiator.url < b._request.initiator.url)
return -1;
if (a._request.initiator.url > b._request.initiator.url)
return 1;

return a._request.initiator.lineNumber - b._request.initiator.lineNumber;
}

WebInspector.NetworkDataGridNode.RequestPropertyComparator = function(propertyName, revert, a, b)
{
var aValue = a._request[propertyName];
var bValue = b._request[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.addEventListener(WebInspector.TextEditorModel.Events.TextChanged, this._textChanged, this);
this._textModel.resetUndoStack();
this._delegate = delegate;
this._url = url;
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("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;
WebInspector.markBeingEdited(this.element, !readOnly);
},

get readOnly()
{
return this._mainPanel.readOnly;
},

get textModel()
{
return this._textModel;
},

defaultFocusedElement: function()
{
return this._mainPanel.defaultFocusedElement();
},

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(event)
{
if (!this._internalTextChangeMode)
this._textModel.resetUndoStack();
this._mainPanel.textChanged(event.data.oldRange, event.data.newRange);
this._gutterPanel.textChanged(event.data.oldRange, event.data.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;
}
},

_registerShortcuts: function()
{
var keys = WebInspector.KeyboardShortcut.Keys;
var modifiers = WebInspector.KeyboardShortcut.Modifiers;

this._shortcuts = {};
var commitEditing = this._commitEditing.bind(this);
this._shortcuts[WebInspector.KeyboardShortcut.makeKey("s", modifiers.CtrlOrMeta)] = commitEditing;

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.consume(true);
},

_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);
}
if (this._url) {
contextMenu.appendItem(WebInspector.UIString("Save"), WebInspector.save.bind(WebInspector, this._url, this._textModel.text, false));
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save as..." : "Save As..."), WebInspector.save.bind(WebInspector, this._url, this._textModel.text, true));
}

contextMenu.show(event);
},

_commitEditing: function()
{
if (this.readOnly)
return false;

this._delegate.commitEditing();
if (this._url && WebInspector.isURLSaved(this._url))
WebInspector.save(this._url, this._textModel.text, false);
return true;
},

wasShown: function()
{
if (!this.readOnly)
WebInspector.markBeingEdited(this.element, true);
},

willHide: function()
{
if (!this.readOnly)
WebInspector.markBeingEdited(this.element, false);
}
}

WebInspector.TextViewer.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.TextViewerDelegate = function()
{
}

WebInspector.TextViewerDelegate.prototype = {
beforeTextChanged: function() { },

afterTextChanged: function(oldRange, newRange) { },

commitEditing: function() { },

populateLineGutterContextMenu: function(contextMenu, lineNumber) { },

populateTextAreaContextMenu: function(contextMenu, lineNumber) { }
}


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();
this._decorations = {};
}

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


for (var lineNumber in this._decorations) {
lineNumber = parseInt(lineNumber, 10);


if (lineNumber < oldRange.startLine)
continue;

if (lineNumber === oldRange.startLine && oldRange.startColumn)
continue;

var lineDecorationsCopy = this._decorations[lineNumber].slice();
for (var i = 0; i < lineDecorationsCopy.length; ++i) {
var decoration = lineDecorationsCopy[i];
this.removeDecoration(lineNumber, decoration);


if (lineNumber < oldRange.endLine)
continue;

this.addDecoration(lineNumber + linesDiff, decoration);
}
}

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

addDecoration: function(lineNumber, decoration)
{
WebInspector.TextEditorChunkedPanel.prototype.addDecoration.call(this, lineNumber, decoration);
var decorations = this._decorations[lineNumber];
if (!decorations) {
decorations = [];
this._decorations[lineNumber] = decorations;
}
decorations.push(decoration);
},

removeDecoration: function(lineNumber, decoration)
{
WebInspector.TextEditorChunkedPanel.prototype.removeDecoration.call(this, lineNumber, decoration);
var decorations = this._decorations[lineNumber];
if (decorations) {
decorations.remove(decoration);
if (!decorations.length)
delete this._decorations[lineNumber];
}
}
}

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.element.addEventListener("focus", this._handleElementFocus.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;
},

_handleElementFocus: function()
{
if (!this._readOnly)
this._container.focus();
},

defaultFocusedElement: function()
{
if (this._readOnly)
return this.element;
return this._container;
},

_updateSelectionOnStartEditing: function()
{




this._container.focus();
var selection = window.getSelection();
if (selection.rangeCount) {
var commonAncestorContainer = selection.getRangeAt(0).commonAncestorContainer;
if (this._container.isSelfOrAncestor(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);

if (!this._readOnly)
this._restoreSelection(new WebInspector.TextRange(lineNumber, 0, lineNumber, 0), false);

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

function before()
{
this._enterTextChangeMode();
}

function after(oldRange, newRange)
{
this._exitTextChangeMode(oldRange, newRange);
}

var range = redo ? this._textModel.redo(before.bind(this), after.bind(this)) : this._textModel.undo(before.bind(this), after.bind(this));

this.endUpdates();


if (range)
this._restoreSelection(range, true);

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;
var rangeWasEmpty = range.isEmpty();
if (shiftKey)
newRange = this._unindentLines(range);
else {
if (rangeWasEmpty)
newRange = this._editRange(range, WebInspector.settings.textEditorIndent.get());
else
newRange = this._indentLines(range);
}

this._exitTextChangeMode(range, newRange);
this.endUpdates();
if (rangeWasEmpty)
newRange.startColumn = newRange.endColumn;
this._restoreSelection(newRange, true);
return true;
},

_indentLines: function(range)
{
var indent = WebInspector.settings.textEditorIndent.get();

if (this._lastEditedRange)
this._textModel.markUndoableState();

var newRange = range.clone();


if (range.startColumn)
newRange.startColumn += indent.length;

var indentEndLine = range.endLine;
if (range.endColumn)
newRange.endColumn += indent.length;
else
indentEndLine--;

for (var lineNumber = range.startLine; lineNumber <= indentEndLine; lineNumber++)
this._textModel.editRange(new WebInspector.TextRange(lineNumber, 0, lineNumber, 0), indent);

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

var indentEndLine = range.endLine;
if (!range.endColumn)
indentEndLine--;

for (var lineNumber = range.startLine; lineNumber <= indentEndLine; 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.editRange(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._editRange(range, lineBreak + indent + lineBreak + currentIndent);
newRange.endLine--;
newRange.endColumn += textEditorIndent.length;
} else
newRange = this._editRange(range, lineBreak + indent);

this._exitTextChangeMode(range, newRange);
this.endUpdates();
this._restoreSelection(newRange.collapseToEnd(), 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 = WebInspector.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.isSelfOrAncestor(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;
}

var dirtyLines = 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 newContent = lines.join("\n");
if (this._textModel.copyRange(oldRange) === newContent) {
delete this._dirtyLines;
return; 
}


this._enterTextChangeMode();

delete this._dirtyLines;

var newRange = this._editRange(oldRange, newContent);

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

_editRange: 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.editRange(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._currentSearchResultIndex = -1;
this._searchResults = [];

this._messages = [];
this._rowMessages = {};
this._messageBubbles = {};

this._textViewer.readOnly = !this.canEditSource();
}

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

willHide: function()
{
WebInspector.View.prototype.willHide.call(this);
if (this.loaded)
this._textViewer.freeCachedElements();

this._clearLineHighlight();
this._clearLineToReveal();
},

defaultFocusedElement: function()
{
return this._textViewer.defaultFocusedElement();
},

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)
{
this._clearLineToReveal();
if (this.loaded)
this._textViewer.highlightLine(line);
else
this._lineToHighlight = line;
},

_clearLineHighlight: function()
{
if (this.loaded)
this._textViewer.clearLineHighlight();
else
delete this._lineToHighlight;
},

revealLine: function(line)
{
this._clearLineHighlight();
if (this.loaded)
this._textViewer.revealLine(line);
else
this._lineToReveal = line;
},

_clearLineToReveal: function()
{
delete this._lineToReveal;
},

beforeTextChanged: function()
{
WebInspector.searchController.cancelSearch();
this.clearMessages();
},

afterTextChanged: function(oldRange, newRange)
{
},


setContent: function(content, contentEncoded, mimeType)
{
this._textViewer.mimeType = mimeType;

this._loaded = true;
this._textModel.setText(content || "");

this._textViewer.beginUpdates();

this._setTextViewerDecorations();

if (typeof this._lineToHighlight === "number") {
this.highlightLine(this._lineToHighlight);
delete this._lineToHighlight;
}

if (typeof this._lineToReveal === "number") {
this.revealLine(this._lineToReveal);
delete this._lineToReveal;
}

if (this._delayedFindSearchMatches) {
this._delayedFindSearchMatches();
delete this._delayedFindSearchMatches;
}

this.onTextViewerContentLoaded();

this._textViewer.endUpdates();
},

onTextViewerContentLoaded: function() {},

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

inheritScrollPositions: function(sourceFrame)
{
this._textViewer.inheritScrollPositions(sourceFrame._textViewer);
},

canEditSource: function()
{
return false;
},

commitEditing: function()
{
function callback(error)
{
this.didEditContent(error, this._textModel.text);
}
this.editContent(this._textModel.text, callback.bind(this));
},

didEditContent: function(error, content)
{
if (error) {
WebInspector.log(error, WebInspector.ConsoleMessage.MessageLevel.Error, true);
return;
}
},

editContent: function(newContent, callback)
{
}
}

WebInspector.SourceFrame.prototype.__proto__ = WebInspector.View.prototype;



WebInspector.TextViewerDelegateForSourceFrame = function(sourceFrame)
{
this._sourceFrame = sourceFrame;
}

WebInspector.TextViewerDelegateForSourceFrame.prototype = {
beforeTextChanged: function()
{
this._sourceFrame.beforeTextChanged();
},

afterTextChanged: function(oldRange, newRange)
{
this._sourceFrame.afterTextChanged(oldRange, newRange);
},

commitEditing: function()
{
this._sourceFrame.commitEditing();
},

populateLineGutterContextMenu: function(contextMenu, lineNumber)
{
this._sourceFrame.populateLineGutterContextMenu(contextMenu, lineNumber);
},

populateTextAreaContextMenu: function(contextMenu, lineNumber)
{
this._sourceFrame.populateTextAreaContextMenu(contextMenu, lineNumber);
}
}

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)
{
if (resource.type.isTextType())
return true; 
if (resource.type === WebInspector.resourceTypes.Other)
return resource.content && !resource.contentEncoded;
return false;
}


WebInspector.ResourceView.nonSourceViewForResource = function(resource)
{
switch (resource.type) {
case WebInspector.resourceTypes.Image:
return new WebInspector.ImageView(resource);
case WebInspector.resourceTypes.Font:
return new WebInspector.FontView(resource);
default:
return new WebInspector.ResourceView(resource);
}
}


WebInspector.ResourceSourceFrame = function(resource)
{
this._resource = resource;
WebInspector.SourceFrame.call(this, resource.url);
this._resource.addEventListener(WebInspector.Resource.Events.RevisionAdded, this._contentChanged, this);
}

WebInspector.ResourceSourceFrame.prototype = {
get resource()
{
return this._resource;
},


requestContent: function(callback)
{

function callbackWrapper(content, contentEncoded, mimeType)
{
callback(content, contentEncoded, mimeType);
}
this.resource.requestContent(callbackWrapper.bind(this));
},

_contentChanged: function(event)
{
this.setContent(this._resource.content, false, this._resource.canonicalMimeType());
}
}

WebInspector.ResourceSourceFrame.prototype.__proto__ = WebInspector.SourceFrame.prototype;


WebInspector.EditableResourceSourceFrame = function(resource)
{
WebInspector.ResourceSourceFrame.call(this, resource);
}

WebInspector.EditableResourceSourceFrame.Events = {
TextEdited: "TextEdited"
}

WebInspector.EditableResourceSourceFrame.prototype = {
canEditSource: function()
{

return this._resource.isEditable() && this._resource.type === WebInspector.resourceTypes.Stylesheet;
},

editContent: function(newText, callback)
{
this._clearIncrementalUpdateTimer();
var majorChange = true;
this._settingContent = true;
function callbackWrapper(text)
{
callback(text);
delete this._settingContent;
}
this.resource.setContent(newText, majorChange, callbackWrapper.bind(this));
},

afterTextChanged: function(oldRange, newRange)
{
function commitIncrementalEdit()
{
var majorChange = false;
this.resource.setContent(this._textModel.text, majorChange, function() {});
this.dispatchEventToListeners(WebInspector.EditableResourceSourceFrame.Events.TextEdited, this);
}
const updateTimeout = 200;
this._incrementalUpdateTimer = setTimeout(commitIncrementalEdit.bind(this), updateTimeout);
},

_clearIncrementalUpdateTimer: function()
{
if (this._incrementalUpdateTimer)
clearTimeout(this._incrementalUpdateTimer);
delete this._incrementalUpdateTimer;
},

_contentChanged: function(event)
{
if (!this._settingContent)
WebInspector.ResourceSourceFrame.prototype._contentChanged.call(this, event);
},

didEditContent: function(error, content)
{
WebInspector.SourceFrame.prototype.didEditContent.call(this, error, content);
this.dispatchEventToListeners(WebInspector.EditableResourceSourceFrame.Events.TextEdited, this);
},

isDirty: function()
{
return this._resource.content !== this.textModel.text;
}
}

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)
{
this._revision.requestContent(callback);
},
}

WebInspector.ResourceRevisionSourceFrame.prototype.__proto__ = WebInspector.ResourceSourceFrame.prototype;






WebInspector.RequestView = function(request)
{
WebInspector.View.call(this);
this.registerRequiredCSS("resourceView.css");

this.element.addStyleClass("resource-view");
this.request = request;
}

WebInspector.RequestView.prototype = {
hasContent: function()
{
return false;
}
}

WebInspector.RequestView.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.RequestView.hasTextContent = function(request)
{
if (request.type.isTextType())
return true; 
if (request.type === WebInspector.resourceTypes.Other || request.hasErrorStatusCode())
return request.content && !request.contentEncoded;
return false;
}


WebInspector.RequestView.nonSourceViewForRequest = function(request)
{
switch (request.type) {
case WebInspector.resourceTypes.Image:
return new WebInspector.ImageView(request);
case WebInspector.resourceTypes.Font:
return new WebInspector.FontView(request);
default:
return new WebInspector.RequestView(request);
}
}






WebInspector.JavaScriptSourceFrame = function(scriptsPanel, model, uiSourceCode)
{
this._scriptsPanel = scriptsPanel;
this._model = model;
this._breakpointManager = this._model.breakpointManager;
this._uiSourceCode = uiSourceCode;
this._breakpoints = {};

var locations = this._breakpointManager.breakpointLocationsForUISourceCode(this._uiSourceCode);
for (var i = 0; i < locations.length; ++i)
this._breakpointAdded({data:locations[i]});

WebInspector.SourceFrame.call(this, uiSourceCode.url);

this._popoverHelper = new WebInspector.ObjectPopoverHelper(this.textViewer.element,
this._getPopoverAnchor.bind(this), this._resolveObjectForPopover.bind(this), this._onHidePopover.bind(this), true);

this.textViewer.element.addEventListener("mousedown", this._onMouseDown.bind(this), true);
this.textViewer.element.addEventListener("keydown", this._onKeyDown.bind(this), true);

this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointAdded, this._breakpointAdded, this);
this._breakpointManager.addEventListener(WebInspector.BreakpointManager.Events.BreakpointRemoved, this._breakpointRemoved, this);

this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.ContentChanged, this._onContentChanged, this);
this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.ConsoleMessageAdded, this._consoleMessageAdded, this);
this._uiSourceCode.addEventListener(WebInspector.UISourceCode.Events.ConsoleMessagesCleared, this._consoleMessagesCleared, this);
}

WebInspector.JavaScriptSourceFrame.prototype = {
get uiSourceCode()
{
return this._uiSourceCode;
},


wasShown: function()
{
WebInspector.SourceFrame.prototype.wasShown.call(this);
this._setScriptSourceIsDirty(this._isDirty);
},

willHide: function()
{
WebInspector.SourceFrame.prototype.willHide.call(this);
this._popoverHelper.hidePopover();
},


requestContent: function(callback)
{

function mycallback(content, contentEncoded, mimeType)
{
this._originalContent = content;
callback(content, contentEncoded, mimeType);
}
this._uiSourceCode.requestContent(mycallback.bind(this));
},

canEditSource: function()
{
return this._model.canEditScriptSource(this._uiSourceCode);
},

editContent: function(newContent, callback)
{
this._editingContent = true;
this._model.setScriptSource(this._uiSourceCode, newContent, callback);
},


_onContentChanged: function(event)
{
if (this._editingContent)
return;
var oldContent =   event.data.oldContent;
var content =   event.data.content;

var breakpoints = {};
for (var lineNumber in this._breakpoints) {
breakpoints[lineNumber] = this._breakpoints[lineNumber];
this._breakpoints[lineNumber].remove();
}
this.setContent(content, false, "text/javascript");
this._updateBreakpointsAfterLiveEdit(oldContent, content, breakpoints);
},

populateLineGutterContextMenu: function(contextMenu, lineNumber)
{
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Continue to here" : "Continue to Here"), this._continueToLine.bind(this, lineNumber));

var breakpoint = this._breakpoints[lineNumber];
if (!breakpoint) {

contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add breakpoint" : "Add Breakpoint"), this._setBreakpoint.bind(this, lineNumber, "", true));
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add conditional breakpoint…" : "Add Conditional Breakpoint…"), this._editBreakpointCondition.bind(this, lineNumber));
} else {

contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove breakpoint" : "Remove Breakpoint"), breakpoint.remove.bind(this));
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Edit breakpoint…" : "Edit Breakpoint…"), this._editBreakpointCondition.bind(this, lineNumber, breakpoint));
if (breakpoint.enabled())
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Disable breakpoint" : "Disable Breakpoint"), breakpoint.setEnabled.bind(breakpoint, false));
else
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Enable breakpoint" : "Enable Breakpoint"), breakpoint.setEnabled.bind(breakpoint, true));
}
},

populateTextAreaContextMenu: function(contextMenu, lineNumber)
{
WebInspector.SourceFrame.prototype.populateTextAreaContextMenu.call(this, contextMenu, lineNumber);
var selection = window.getSelection();
if (selection.type === "Range" && !selection.isCollapsed) {
var addToWatchLabel = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Add to watch" : "Add to Watch");
contextMenu.appendItem(addToWatchLabel, this._scriptsPanel.addToWatch.bind(this._scriptsPanel, selection.toString()));
var evaluateLabel = WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Evaluate in console" : "Evaluate in Console");
contextMenu.appendItem(evaluateLabel, WebInspector.evaluateInConsole.bind(WebInspector, selection.toString()));
}
},

afterTextChanged: function(oldRange, newRange)
{
var isDirty = this.textModel.text !== this._originalContent;
if (isDirty)
this._setScriptSourceIsDirty(true);
else
this.didEditContent(null, this._originalContent);
},

_setScriptSourceIsDirty: function(isDirty)
{
this._scriptsPanel.setScriptSourceIsDirty(this._uiSourceCode, isDirty);
this._isDirty = isDirty;
},

beforeTextChanged: function()
{
if (!this._isDirty) {

for (var lineNumber = 0; lineNumber < this.textModel.linesCount; ++lineNumber) {
var breakpointAttribute = this.textModel.getAttribute(lineNumber, "breakpoint");
if (breakpointAttribute) {
var breakpoint = this._breakpoints[lineNumber];
if (breakpoint)
breakpoint.remove();

this._addBreakpointDecoration(lineNumber, breakpointAttribute.condition, breakpointAttribute.enabled, true);
}
}
}

this._isDirty = true;
WebInspector.SourceFrame.prototype.beforeTextChanged.call(this);
},

didEditContent: function(error, content)
{
delete this._editingContent;

WebInspector.SourceFrame.prototype.didEditContent.call(this, error, content);
if (error)
return;

this._originalContent = content;
this._isDirty = false;


for (var lineNumber = 0; lineNumber < this.textModel.linesCount; ++lineNumber) {
var breakpointDecoration = this.textModel.getAttribute(lineNumber, "breakpoint");
if (breakpointDecoration) {

this._removeBreakpointDecoration(lineNumber);

this._setBreakpoint(lineNumber, breakpointDecoration.condition, breakpointDecoration.enabled);
}
}
this._setScriptSourceIsDirty(false);
},

_getPopoverAnchor: function(element, event)
{
if (!WebInspector.debuggerModel.isPaused())
return null;
if (window.getSelection().type === "Range")
return null;
var lineElement = element.enclosingNodeOrSelfWithClass("webkit-line-content");
if (!lineElement)
return null;

if (element.hasStyleClass("webkit-javascript-ident"))
return element;

if (element.hasStyleClass("source-frame-token"))
return element;


if (element.hasStyleClass("webkit-javascript-keyword"))
return element.textContent === "this" ? element : null;

if (element !== lineElement || lineElement.childElementCount)
return null;



var lineContent = lineElement.textContent;
var ranges = [];
var regex = new RegExp("[a-zA-Z_\$0-9]+", "g");
var match;
while (regex.lastIndex < lineContent.length && (match = regex.exec(lineContent)))
ranges.push({offset: match.index, length: regex.lastIndex - match.index});


var changes = [];
WebInspector.highlightRangesWithStyleClass(lineElement, ranges, "source-frame-token", changes);
var lineOffsetLeft = lineElement.totalOffsetLeft();
for (var child = lineElement.firstChild; child; child = child.nextSibling) {
if (child.nodeType !== Node.ELEMENT_NODE || !child.hasStyleClass("source-frame-token"))
continue;
if (event.x > lineOffsetLeft + child.offsetLeft && event.x < lineOffsetLeft + child.offsetLeft + child.offsetWidth) {
var text = child.textContent;
return (text === "this" || !WebInspector.SourceJavaScriptTokenizer.Keywords[text]) ? child : null;
}
}
return null;
},

_resolveObjectForPopover: function(element, showCallback, objectGroupName)
{
this._highlightElement = this._highlightExpression(element);


function showObjectPopover(result, wasThrown)
{
if (!WebInspector.debuggerModel.isPaused()) {
this._popoverHelper.hidePopover();
return;
}
showCallback(WebInspector.RemoteObject.fromPayload(result), wasThrown, this._highlightElement);

if (this._highlightElement)
this._highlightElement.addStyleClass("source-frame-eval-expression");
}

if (!WebInspector.debuggerModel.isPaused()) {
this._popoverHelper.hidePopover();
return;
}
var selectedCallFrame = WebInspector.debuggerModel.selectedCallFrame();
selectedCallFrame.evaluate(this._highlightElement.textContent, objectGroupName, false, true, 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;
},

_highlightExpression: function(element)
{

var tokens = [ element ];
var token = element.previousSibling;
while (token && (token.className === "webkit-javascript-ident" || token.className === "source-frame-token" || 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;
},


_addBreakpointDecoration: function(lineNumber, condition, enabled, mutedWhileEditing)
{
var breakpoint = {
condition: condition,
enabled: enabled
};
this.textModel.setAttribute(lineNumber, "breakpoint", breakpoint);

this.textViewer.beginUpdates();
this.textViewer.addDecoration(lineNumber, "webkit-breakpoint");
if (!enabled || mutedWhileEditing)
this.textViewer.addDecoration(lineNumber, "webkit-breakpoint-disabled");
else
this.textViewer.removeDecoration(lineNumber, "webkit-breakpoint-disabled");
if (!!condition)
this.textViewer.addDecoration(lineNumber, "webkit-breakpoint-conditional");
else
this.textViewer.removeDecoration(lineNumber, "webkit-breakpoint-conditional");
this.textViewer.endUpdates();
},

_removeBreakpointDecoration: function(lineNumber)
{
this.textModel.removeAttribute(lineNumber, "breakpoint");
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();
},

_onMouseDown: function(event)
{
if (this._isDirty)
return;

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._breakpoints[lineNumber];
if (breakpoint) {
if (event.shiftKey)
breakpoint.setEnabled(!breakpoint.enabled());
else
breakpoint.remove();
} else
this._setBreakpoint(lineNumber, "", true);
event.preventDefault();
},

_onKeyDown: function(event)
{
if (event.keyIdentifier === "U+001B") { 
if (this._popoverHelper.isPopoverVisible()) {
this._popoverHelper.hidePopover();
event.consume();
}
}
},


_editBreakpointCondition: function(lineNumber, breakpoint)
{
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;
if (breakpoint)
breakpoint.setCondition(newText);
else
this._setBreakpoint(lineNumber, newText, true);
}

var config = new WebInspector.EditingConfig(finishEditing.bind(this, true), finishEditing.bind(this, false));
WebInspector.startEditing(this._conditionEditorElement, config);
this._conditionEditorElement.value = breakpoint ? breakpoint.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)
{
this._executionLineNumber = lineNumber;
if (this.loaded) {
this.textViewer.addDecoration(lineNumber, "webkit-execution-line");
this.revealLine(this._executionLineNumber);
}
},

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

_breakpointAdded: function(event)
{
var uiLocation =   event.data.uiLocation;

if (uiLocation.uiSourceCode !== this._uiSourceCode)
return;

var breakpoint =   event.data.breakpoint;
this._breakpoints[uiLocation.lineNumber] = breakpoint;
if (this.loaded)
this._addBreakpointDecoration(uiLocation.lineNumber, breakpoint.condition(), breakpoint.enabled(), false);
},

_breakpointRemoved: function(event)
{
var uiLocation =   event.data.uiLocation;
if (uiLocation.uiSourceCode !== this._uiSourceCode)
return;

var breakpoint =   event.data.breakpoint;
if (this._breakpoints[uiLocation.lineNumber] !== breakpoint)
return;
delete this._breakpoints[uiLocation.lineNumber];
if (this.loaded)
this._removeBreakpointDecoration(uiLocation.lineNumber);
},

_consoleMessageAdded: function(event)
{
var message = event.data;
if (this.loaded)
this.addMessageToSource(message.lineNumber, message.originalMessage);
},

_consoleMessagesCleared: function(event)
{
this.clearMessages();
},

onTextViewerContentLoaded: function()
{
if (typeof this._executionLineNumber === "number")
this.setExecutionLine(this._executionLineNumber);

for (var lineNumber in this._breakpoints) {
var breakpoint = this._breakpoints[lineNumber];
this._addBreakpointDecoration(parseInt(lineNumber, 10), breakpoint.condition(), breakpoint.enabled(), false);
}

var messages = this._uiSourceCode.consoleMessages();
for (var i = 0; i < messages.length; ++i) {
var message = messages[i];
this.addMessageToSource(message.lineNumber, message.originalMessage);
}
},


_setBreakpoint: function(lineNumber, condition, enabled)
{
this._breakpointManager.setBreakpoint(this._uiSourceCode, lineNumber, condition, enabled);
},


_continueToLine: function(lineNumber)
{
this._model.continueToLine(this._uiSourceCode, lineNumber);
},


_updateBreakpointsAfterLiveEdit: function(oldSource, newSource, breakpoints)
{

var diff = Array.diff(oldSource.split("\n"), newSource.split("\n"));
for (var lineNumber in breakpoints) {
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) {
var breakpoint = breakpoints[lineNumber];
this._setBreakpoint(newLineNumber, breakpoint.condition(), breakpoint.enabled());
}
}
}
}

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();
this.doResize();
},

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();
this.doResize();
},

hideSidebarElement: function()
{
if (this._sidebarElementHidden)
return;

if (this._mainElementHidden)
this.showMainElement();

this.sidebarElement.addStyleClass("hidden");
this._sidebarElementHidden = true;
this._updateResizer();
this._restoreSidebarWidth();
this.doResize();
},

showSidebarElement: function()
{
if (!this._sidebarElementHidden)
return;

this.sidebarElement.removeStyleClass("hidden");
this._sidebarElementHidden = false;
this._updateResizer();
this._restoreSidebarWidth();
this.doResize();
},

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.TabbedEditorContainerDelegate = function() { }

WebInspector.TabbedEditorContainerDelegate.prototype = {

viewForFile: function(uiSourceCode) { }
}


WebInspector.TabbedEditorContainer = function(delegate, settingName)
{
this._delegate = delegate;

this._tabbedPane = new WebInspector.TabbedPane();
this._tabbedPane.closeableTabs = true;
this._tabbedPane.element.id = "scripts-editor-container-tabbed-pane";

this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabClosed, this._tabClosed, this);
this._tabbedPane.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this);

this._tabIds = new Map();
this._files = {};
this._loadedURLs = {};

this._previouslyViewedFilesSetting = WebInspector.settings.createSetting(settingName, []);
this._history = new WebInspector.TabbedEditorContainer.History(this._previouslyViewedFilesSetting.get());
}


WebInspector.TabbedEditorContainer.Events = {
EditorSelected: "EditorSelected",
EditorClosed: "EditorClosed"
}

WebInspector.TabbedEditorContainer._tabId = 0;

WebInspector.TabbedEditorContainer.maximalPreviouslyViewedFilesCount = 30;

WebInspector.TabbedEditorContainer.prototype = {

get view()
{
return this._tabbedPane;
},


get visibleView()
{
return this._tabbedPane.visibleView;
},


show: function(parentElement)
{
this._tabbedPane.show(parentElement);
},


showFile: function(uiSourceCode)
{
this._innerShowFile(uiSourceCode, true);
},


_innerShowFile: function(uiSourceCode, userGesture)
{
if (this._currentFile === uiSourceCode)
return;
this._currentFile = uiSourceCode;

var tabId = this._tabIds.get(uiSourceCode) || this._appendFileTab(uiSourceCode, userGesture);

this._tabbedPane.selectTab(tabId, userGesture);
if (userGesture)
this._editorSelectedByUserAction();

this.dispatchEventToListeners(WebInspector.TabbedEditorContainer.Events.EditorSelected, this._currentFile);
},


_titleForFile: function(uiSourceCode)
{
const maxDisplayNameLength = 30;
const minDisplayQueryParamLength = 5;

var parsedURL = uiSourceCode.parsedURL;
if (!parsedURL.isValid)
return parsedURL.url ? parsedURL.url.trimMiddle(maxDisplayNameLength) : WebInspector.UIString("(program)");

var maxDisplayQueryParamLength = Math.max(minDisplayQueryParamLength, maxDisplayNameLength - parsedURL.lastPathComponent.length);
var displayQueryParams = parsedURL.queryParams ? "?" + parsedURL.queryParams.trimEnd(maxDisplayQueryParamLength - 1) : "";
var displayLastPathComponent = parsedURL.lastPathComponent.trimMiddle(maxDisplayNameLength - displayQueryParams.length);
var displayName = displayLastPathComponent + displayQueryParams;
return displayName || WebInspector.UIString("(program)");
},


uiSourceCodeAdded: function(uiSourceCode)
{
if (this._userSelectedFiles || this._loadedURLs[uiSourceCode.url])
return;
this._loadedURLs[uiSourceCode.url] = true;

var index = this._history.index(uiSourceCode.url)
if (index === -1)
return;

var tabId = this._tabIds.get(uiSourceCode) || this._appendFileTab(uiSourceCode, false);


if (index === 0)
this._innerShowFile(uiSourceCode, false);
},


_editorClosedByUserAction: function(uiSourceCode)
{
this._userSelectedFiles = true;
this._history.remove(uiSourceCode.url);
this._updateHistory();
},

_editorSelectedByUserAction: function()
{
this._userSelectedFiles = true;
this._updateHistory();
},

_updateHistory: function()
{
var tabIds = this._tabbedPane.lastOpenedTabIds(WebInspector.TabbedEditorContainer.maximalPreviouslyViewedFilesCount);

function tabIdToURL(tabId)
{
return this._files[tabId].url;
}

this._history.update(tabIds.map(tabIdToURL.bind(this)));
this._history.save(this._previouslyViewedFilesSetting);
},


_tooltipForFile: function(uiSourceCode)
{
return uiSourceCode.url;
},


_appendFileTab: function(uiSourceCode, userGesture)
{
var view = this._delegate.viewForFile(uiSourceCode);
var title = this._titleForFile(uiSourceCode);
var tooltip = this._tooltipForFile(uiSourceCode);

var tabId = this._generateTabId();
this._tabIds.put(uiSourceCode, tabId);
this._files[tabId] = uiSourceCode;

this._tabbedPane.appendTab(tabId, title, view, tooltip, userGesture);
return tabId;
},


_removeFileTab: function(uiSourceCode)
{
var tabId = this._tabIds.get(uiSourceCode);

if (tabId)
this._tabbedPane.closeTab(tabId);
},


_tabClosed: function(event)
{
var tabId =   event.data.tabId;
var userGesture =   event.data.isUserGesture;

var uiSourceCode = this._files[tabId];
this._tabIds.remove(uiSourceCode);
delete this._files[tabId];
delete this._currentFile;

this.dispatchEventToListeners(WebInspector.TabbedEditorContainer.Events.EditorClosed, uiSourceCode);

if (userGesture)
this._editorClosedByUserAction(uiSourceCode);
},


_tabSelected: function(event)
{
var tabId =   event.data.tabId;
var userGesture =   event.data.isUserGesture;

var uiSourceCode = this._files[tabId];
this._innerShowFile(uiSourceCode, userGesture);
},


_replaceFileTab: function(oldUISourceCode, newUISourceCode)
{
var tabId = this._tabIds.get(oldUISourceCode);

if (!tabId)
return;

delete this._files[this._tabIds.get(oldUISourceCode)]
this._tabIds.remove(oldUISourceCode);
this._tabIds.put(newUISourceCode, tabId);
this._files[tabId] = newUISourceCode;

this._tabbedPane.changeTabTitle(tabId, this._titleForFile(newUISourceCode));
this._tabbedPane.changeTabView(tabId, this._delegate.viewForFile(newUISourceCode));
this._tabbedPane.changeTabTooltip(tabId, this._tooltipForFile(newUISourceCode));
},


replaceFiles: function(oldUISourceCodeList, uiSourceCodeList)
{
var mainFile;
for (var i = 0; i < oldUISourceCodeList.length; ++i) {
var tabId = this._tabIds.get(oldUISourceCodeList[i]);
if (tabId && (!mainFile || this._tabbedPane.selectedTabId === tabId)) {
mainFile = oldUISourceCodeList[i];
break;
} 
}

if (!mainFile)
return;

this._replaceFileTab(mainFile, uiSourceCodeList[0]);
for (var i = 0; i < oldUISourceCodeList.length; ++i)
this._removeFileTab(oldUISourceCodeList[i]);
},


setFileIsDirty: function(uiSourceCode, isDirty)
{
var tabId = this._tabIds.get(uiSourceCode);
if (tabId) {
var title = this._titleForFile(uiSourceCode);
if (isDirty)
title += "*";
this._tabbedPane.changeTabTitle(tabId, title);
}
},

reset: function()
{
this._tabbedPane.closeAllTabs();
this._tabIds = new Map();
this._files = {};
delete this._currentFile;
delete this._userSelectedFiles;
this._loadedURLs = {};
},


_generateTabId: function()
{
return "tab_" + (WebInspector.TabbedEditorContainer._tabId++);
}
}

WebInspector.TabbedEditorContainer.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.TabbedEditorContainer.History = function(urls)
{
this._urls = urls;
}

WebInspector.TabbedEditorContainer.History.prototype = {

index: function(url)
{
return this._urls.indexOf(url);
},


update: function(urls)
{
for (var i = urls.length - 1; i >= 0; --i) {
var index = this._urls.indexOf(urls[i]);
if (index !== -1)
this._urls.splice(index, 1);
this._urls.unshift(urls[i]);
}
},


remove: function(url)
{
var index = this._urls.indexOf(url);
if (index !== -1)
this._urls.splice(index, 1);
},


save: function(setting)
{
setting.set(this._urls);
}
}

WebInspector.TabbedEditorContainer.History.prototype.__proto__ = WebInspector.Object.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);
WebInspector.settings.navigatorWasOnceHidden = WebInspector.settings.createSetting("navigatorWasOnceHidden", false);

this._presentationModel = presentationModel;

function viewGetter()
{
return this.visibleView;
}
WebInspector.GoToLineDialog.install(this, viewGetter.bind(this));
WebInspector.JavaScriptOutlineDialog.install(this, viewGetter.bind(this));

this.debugToolbar = this._createDebugToolbar();

const initialDebugSidebarWidth = 225;
const maximalDebugSidebarWidthPercent = 50;
this.createSplitView(this.element, WebInspector.SplitView.SidebarPosition.Right, initialDebugSidebarWidth);
this.splitView.element.id = "scripts-split-view";
this.splitView.minimalSidebarWidth = Preferences.minScriptsSidebarWidth;
this.splitView.minimalMainWidthPercent = 100 - maximalDebugSidebarWidthPercent;

this.sidebarElement.appendChild(this.debugToolbar);

this.debugSidebarResizeWidgetElement = document.createElement("div");
this.debugSidebarResizeWidgetElement.id = "scripts-debug-sidebar-resizer-widget";
this.splitView.installResizer(this.debugSidebarResizeWidgetElement);


const initialNavigatorWidth = 225;
const minimalViewsContainerWidthPercent = 50;
this.editorView = new WebInspector.SplitView(WebInspector.SplitView.SidebarPosition.Left, "scriptsPanelNavigatorSidebarWidth", initialNavigatorWidth);
this.editorView.element.tabIndex = 0;

this.editorView.minimalSidebarWidth = Preferences.minScriptsSidebarWidth;
this.editorView.minimalMainWidthPercent = minimalViewsContainerWidthPercent;
this.editorView.show(this.splitView.mainElement);

this._navigator = new WebInspector.ScriptsNavigator();
this._navigator.view.show(this.editorView.sidebarElement);

this._editorContainer = new WebInspector.TabbedEditorContainer(this, "previouslyViewedFiles");
this._editorContainer.show(this.editorView.mainElement);
WebInspector.OpenScriptDialog.install(this, this._presentationModel, this.editorView.mainElement);

this._navigatorController = new WebInspector.NavigatorOverlayController(this, this.editorView, this._navigator.view, this._editorContainer.view);

this._navigator.addEventListener(WebInspector.ScriptsNavigator.Events.ScriptSelected, this._scriptSelected, this);
this._editorContainer.addEventListener(WebInspector.TabbedEditorContainer.Events.EditorSelected, this._editorSelected, this);
this._editorContainer.addEventListener(WebInspector.TabbedEditorContainer.Events.EditorClosed, this._editorClosed, this);

this.splitView.mainElement.appendChild(this.debugSidebarResizeWidgetElement);

this.sidebarPanes = {};
this.sidebarPanes.watchExpressions = new WebInspector.WatchExpressionsSidebarPane();
this.sidebarPanes.callstack = new WebInspector.CallStackSidebarPane();
this.sidebarPanes.scopechain = new WebInspector.ScopeChainSidebarPane();
this.sidebarPanes.jsBreakpoints = new WebInspector.JavaScriptBreakpointsSidebarPane(this._presentationModel.breakpointManager, 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 openResourceShortcut = WebInspector.OpenResourceDialog.createShortcut();
helpSection.addKey(openResourceShortcut.name, WebInspector.UIString("Open script"));

var scriptOutlineShortcut = WebInspector.JavaScriptOutlineDialog.createShortcut();
helpSection.addKey(scriptOutlineShortcut.name, WebInspector.UIString("Go to function"));

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._sourceFramesByUISourceCode = new Map();
this._reset(false);

WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasEnabled, this._debuggerWasEnabled, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.DebuggerWasDisabled, this._debuggerWasDisabled, 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.CallFrameSelected, this._callFrameSelected, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame, this._consoleCommandEvaluatedInSelectedCallFrame, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.ExecutionLineChanged, this._executionLineChanged, this);
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._reset.bind(this, false));
WebInspector.debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointsActiveStateChanged, this._breakpointsActiveStateChanged, this);

this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.UISourceCodeAdded, this._handleUISourceCodeAdded, this)
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.UISourceCodeReplaced, this._uiSourceCodeReplaced, this);
this._presentationModel.addEventListener(WebInspector.DebuggerPresentationModel.Events.UISourceCodeRemoved, this._uiSourceCodeRemoved, this);

var enableDebugger = !Capabilities.debuggerCausesRecompilation || WebInspector.settings.debuggerEnabled.get();
if (enableDebugger)
WebInspector.debuggerModel.enableDebugger();

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

defaultFocusedElement: function()
{
return this._navigator.view.defaultFocusedElement();
},

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

this._navigatorController.wasShown();
},

_didBuildOutlineChunk: function(event)
{
WebInspector.JavaScriptOutlineDialog.didAddChunk(event.data);
if (event.data.total === event.data.index) {
if (this._outlineWorker) {
this._outlineWorker.terminate();
delete this._outlineWorker;
}
}
},


_handleUISourceCodeAdded: function(event)
{
var uiSourceCode =   event.data;
this._uiSourceCodeAdded(uiSourceCode);
},

_loadUISourceCodes: function()
{
var uiSourceCodes = this._presentationModel.uiSourceCodes();
for (var i = 0; i < uiSourceCodes.length; ++i)
this._uiSourceCodeAdded(uiSourceCodes[i]);
},


_uiSourceCodeAdded: function(uiSourceCode)
{
if (!uiSourceCode.url || uiSourceCode.isSnippetEvaluation) {

return;
}

this._addUISourceCode(uiSourceCode);
},


_addUISourceCode: function(uiSourceCode)
{
this._navigator.addUISourceCode(uiSourceCode);
this._editorContainer.uiSourceCodeAdded(uiSourceCode);
},

_uiSourceCodeRemoved: function(event)
{
var uiSourceCode =   event.data;
this._removeSourceFrame(uiSourceCode);
},


setScriptSourceIsDirty: function(uiSourceCode, isDirty)
{
this._navigator.setScriptSourceIsDirty(uiSourceCode, isDirty);
this._editorContainer.setFileIsDirty(uiSourceCode, isDirty);
},

_consoleCommandEvaluatedInSelectedCallFrame: function(event)
{
this.sidebarPanes.scopechain.update(WebInspector.debuggerModel.selectedCallFrame());
},

_debuggerPaused: function(event)
{
var details =   event.data;

this._paused = true;
this._waitingToPause = false;
this._stepping = false;

this._updateDebuggerButtons();

WebInspector.inspectorView.setCurrentPanel(this);
this.sidebarPanes.callstack.update(details.callFrames);

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)
{
var breakpoint = this._presentationModel.breakpointManager.findBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber);
if (!breakpoint)
return;
this.sidebarPanes.jsBreakpoints.highlightBreakpoint(breakpoint);
this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a JavaScript breakpoint."));
}
details.callFrames[0].createLiveLocation(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)
{
delete this.currentQuery;
this.searchCanceled();

this._debuggerResumed();

delete this._currentUISourceCode;
this._navigator.reset();
this._editorContainer.reset();
this._updateScriptViewStatusBarItems();

this.sidebarPanes.jsBreakpoints.reset();
this.sidebarPanes.watchExpressions.reset();
if (!preserveItems && this.sidebarPanes.workers)
this.sidebarPanes.workers.reset();
this._loadUISourceCodes();
},

get visibleView()
{
return this._editorContainer.visibleView;
},

_updateScriptViewStatusBarItems: function()
{
this._scriptViewStatusBarItemsContainer.removeChildren();

var sourceFrame = this.visibleView;
if (sourceFrame) {
var statusBarItems = sourceFrame.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);
},

showUISourceCode: function(uiSourceCode)
{
this._showSourceLine(uiSourceCode);
},


_showSourceLine: function(uiSourceCode, lineNumber)
{
var sourceFrame = this._showFile(uiSourceCode);
if (typeof lineNumber === "number")
sourceFrame.highlightLine(lineNumber);
sourceFrame.focus();
},


_showFile: function(uiSourceCode)
{
if (!this._navigator.isScriptSourceAdded(uiSourceCode))
return null;

var sourceFrame = this._getOrCreateSourceFrame(uiSourceCode);
if (this._currentUISourceCode === uiSourceCode)
return sourceFrame;
this._currentUISourceCode = uiSourceCode;

this._navigator.revealUISourceCode(uiSourceCode);
this._editorContainer.showFile(uiSourceCode);
this._updateScriptViewStatusBarItems();

return sourceFrame;
},

requestVisibleScriptOutline: function()
{


function contentCallback(content, contentEncoded, mimeType)
{
if (this._outlineWorker)
this._outlineWorker.terminate();
this._outlineWorker = new Worker("ScriptFormatterWorker.js");
this._outlineWorker.onmessage = this._didBuildOutlineChunk.bind(this);
const method = "outline";
this._outlineWorker.postMessage({ method: method, params: { content: content, id: this.visibleView.uiSourceCode.id } });
}

if (this.visibleView.uiSourceCode)
this.visibleView.uiSourceCode.requestContent(contentCallback.bind(this));
},


_createSourceFrame: function(uiSourceCode)
{
var sourceFrame = new WebInspector.JavaScriptSourceFrame(this, this._presentationModel, uiSourceCode);

sourceFrame._uiSourceCode = uiSourceCode;
this._sourceFramesByUISourceCode.put(uiSourceCode, sourceFrame);
return sourceFrame;
},


_getOrCreateSourceFrame: function(uiSourceCode)
{
return this._sourceFramesByUISourceCode.get(uiSourceCode) || this._createSourceFrame(uiSourceCode);
},


viewForFile: function(uiSourceCode)
{
return this._getOrCreateSourceFrame(uiSourceCode);
},


_removeSourceFrame: function(uiSourceCode)
{
var sourceFrame = this._sourceFramesByUISourceCode.get(uiSourceCode);
if (!sourceFrame)
return;
this._sourceFramesByUISourceCode.remove(uiSourceCode);
sourceFrame.detach();
},


_uiSourceCodeReplaced: function(event)
{
var oldUISourceCodeList =   event.data.oldUISourceCodeList;
var uiSourceCodeList =   event.data.uiSourceCodeList;

this._navigator.replaceUISourceCodes(oldUISourceCodeList, uiSourceCodeList);
this._editorContainer.replaceFiles(oldUISourceCodeList, uiSourceCodeList);
for (var i = 0; i < oldUISourceCodeList.length; ++i)
this._removeSourceFrame(oldUISourceCodeList[i]);
},

_clearCurrentExecutionLine: function()
{
if (this._executionSourceFrame)
this._executionSourceFrame.clearExecutionLine();
delete this._executionSourceFrame;
},

_executionLineChanged: function(event)
{
var uiLocation = event.data;

this._clearCurrentExecutionLine();
if (!uiLocation)
return;
var sourceFrame = this._getOrCreateSourceFrame(uiLocation.uiSourceCode);
sourceFrame.setExecutionLine(uiLocation.lineNumber);
this._executionSourceFrame = sourceFrame;
},

_revealExecutionLine: function(uiLocation)
{

this._addUISourceCode(uiLocation.uiSourceCode);
var sourceFrame = this._showFile(uiLocation.uiSourceCode);
sourceFrame.revealLine(uiLocation.lineNumber);
},

_callFrameSelected: function(event)
{
var callFrame = event.data;

if (!callFrame)
return;

this.sidebarPanes.scopechain.update(callFrame);
this.sidebarPanes.watchExpressions.refreshExpressions();
this.sidebarPanes.callstack.setSelectedCallFrame(callFrame);
callFrame.createLiveLocation(this._revealExecutionLine.bind(this));
},

_editorClosed: function(event)
{
this._navigatorController.hideNavigatorOverlay();
var uiSourceCode =   event.data;

if (this._currentUISourceCode === uiSourceCode)
delete this._currentUISourceCode;


this._updateScriptViewStatusBarItems();
},

_editorSelected: function(event)
{
var uiSourceCode =   event.data;
this._showFile(uiSourceCode);
this._navigatorController.hideNavigatorOverlay();
},

_scriptSelected: function(event)
{
var uiSourceCode =   event.data.uiSourceCode;
var sourceFrame = this._showFile(uiSourceCode);
this._navigatorController.hideNavigatorOverlay();
if (sourceFrame && event.data.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 = "";
}
},

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

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(event)
{
WebInspector.debuggerModel.setBreakpointsActive(!WebInspector.debuggerModel.breakpointsActive());
},

_breakpointsActiveStateChanged: function(event)
{
var active = event.data;
this._toggleBreakpointsButton.toggled = active;
if (active) {
this._toggleBreakpointsButton.title = WebInspector.UIString("Deactivate all breakpoints.");
WebInspector.inspectorView.element.removeStyleClass("breakpoints-deactivated");
} else {
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());
},

_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.ScriptsNavigator = function()
{
WebInspector.Object.call(this);

this._tabbedPane = new WebInspector.TabbedPane();
this._tabbedPane.shrinkableTabs = true;
this._tabbedPane.element.addStyleClass("navigator-tabbed-pane");

this._scriptsView = new WebInspector.NavigatorView();
this._scriptsView.addEventListener(WebInspector.NavigatorView.Events.ItemSelected, this._scriptSelected, this);

this._contentScriptsView = new WebInspector.NavigatorView();
this._contentScriptsView.addEventListener(WebInspector.NavigatorView.Events.ItemSelected, this._scriptSelected, this);

this._snippetsView = new WebInspector.SnippetsNavigatorView();
this._snippetsView.addEventListener(WebInspector.NavigatorView.Events.ItemSelected, this._scriptSelected, this);

this._tabbedPane.appendTab(WebInspector.ScriptsNavigator.ScriptsTab, WebInspector.UIString("Scripts"), this._scriptsView);
this._tabbedPane.selectTab(WebInspector.ScriptsNavigator.ScriptsTab);
this._tabbedPane.appendTab(WebInspector.ScriptsNavigator.ContentScriptsTab, WebInspector.UIString("Content scripts"), this._contentScriptsView);
if (WebInspector.experimentsSettings.snippetsSupport.isEnabled())
this._tabbedPane.appendTab(WebInspector.ScriptsNavigator.SnippetsTab, WebInspector.UIString("Snippets"), this._snippetsView);
}

WebInspector.ScriptsNavigator.Events = {
ScriptSelected: "ScriptSelected"
}

WebInspector.ScriptsNavigator.ScriptsTab = "scripts";
WebInspector.ScriptsNavigator.ContentScriptsTab = "contentScripts";
WebInspector.ScriptsNavigator.SnippetsTab = "snippets";

WebInspector.ScriptsNavigator.prototype = {

get view()
{
return this._tabbedPane;
},


addUISourceCode: function(uiSourceCode)
{
if (uiSourceCode.isContentScript)
this._contentScriptsView.addUISourceCode(uiSourceCode);
else if (uiSourceCode.isSnippet || uiSourceCode.isSnippetEvaluation)
this._snippetsView.addUISourceCode(uiSourceCode);
else
this._scriptsView.addUISourceCode(uiSourceCode);
},


isScriptSourceAdded: function(uiSourceCode)
{
if (uiSourceCode.isContentScript)
return this._contentScriptsView.isScriptSourceAdded(uiSourceCode);
if (uiSourceCode.isSnippet || uiSourceCode.isSnippetEvaluation)
return this._snippetsView.isScriptSourceAdded(uiSourceCode);
return this._scriptsView.isScriptSourceAdded(uiSourceCode);
},


revealUISourceCode: function(uiSourceCode)
{
if (uiSourceCode.isContentScript) {
this._contentScriptsView.revealUISourceCode(uiSourceCode);
this._tabbedPane.selectTab(WebInspector.ScriptsNavigator.ContentScriptsTab);
} else if (uiSourceCode.isSnippet || uiSourceCode.isSnippetEvaluation) {
this._snippetsView.revealUISourceCode(uiSourceCode);
this._tabbedPane.selectTab(WebInspector.ScriptsNavigator.SnippetsTab);
} else {
this._scriptsView.revealUISourceCode(uiSourceCode);
this._tabbedPane.selectTab(WebInspector.ScriptsNavigator.ScriptsTab);
}
},


setScriptSourceIsDirty: function(uiSourceCode, isDirty)
{

},


replaceUISourceCodes: function(oldUISourceCodeList, uiSourceCodeList)
{
this._scriptsView.replaceUISourceCodes(oldUISourceCodeList, uiSourceCodeList);
this._contentScriptsView.replaceUISourceCodes(oldUISourceCodeList, uiSourceCodeList);
this._snippetsView.replaceUISourceCodes(oldUISourceCodeList, uiSourceCodeList);
},


_scriptSelected: function(event)
{
this.dispatchEventToListeners(WebInspector.ScriptsNavigator.Events.ScriptSelected, event.data);
},

reset: function()
{
this._scriptsView.reset();
this._contentScriptsView.reset();
this._snippetsView.reset();
}
}

WebInspector.ScriptsNavigator.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.SnippetsNavigatorView = function()
{
WebInspector.NavigatorView.call(this);
this.element.addEventListener("contextmenu", this.handleContextMenu.bind(this), false);
}

WebInspector.SnippetsNavigatorView.prototype = {

getOrCreateFolderTreeElement: function(uiSourceCode)
{
if (uiSourceCode.isSnippet)
return this._scriptsTree;
if (uiSourceCode.isSnippetEvaluation)
return this._getOrCreateSnippetEvaluationsFolderTreeElement();
return WebInspector.NavigatorView.prototype.getOrCreateFolderTreeElement.call(this, uiSourceCode);
},

_getOrCreateSnippetEvaluationsFolderTreeElement: function()
{
const snippetEvaluationsFolderIdentifier = "snippetEvaluationsFolder";
var folderTreeElement = this._folderTreeElements[snippetEvaluationsFolderIdentifier];
if (folderTreeElement)
return folderTreeElement;
return this.createFolderTreeElement(this._scriptsTree, snippetEvaluationsFolderIdentifier, "", WebInspector.UIString("Evaluated snippets"));
},


handleContextMenu: function(event, uiSourceCode)
{
var contextMenu = new WebInspector.ContextMenu();
if (uiSourceCode) {
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Evaluate snippet" : "Evaluate Snippet"), this._handleEvaluateSnippet.bind(this, uiSourceCode));
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Rename snippet" : "Rename Snippet"), this._handleRenameSnippet.bind(this, uiSourceCode));
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Remove snippet" : "Remove Snippet"), this._handleRemoveSnippet.bind(this, uiSourceCode));
contextMenu.appendSeparator();
}
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Create snippet" : "Create Snippet"), this._handleCreateSnippet.bind(this));
contextMenu.show(event);
},


_handleEvaluateSnippet: function(uiSourceCode, event)
{

},


_handleRenameSnippet: function(uiSourceCode, event)
{
this.rename(uiSourceCode);
},


_handleRemoveSnippet: function(uiSourceCode, event)
{

},


_handleCreateSnippet: function(event)
{

}
}

WebInspector.SnippetsNavigatorView.prototype.__proto__ = WebInspector.NavigatorView.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.indexedDBListTreeElement = new WebInspector.IndexedDBTreeElement(this);
this.sidebarTree.appendChild(this.indexedDBListTreeElement);

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


showIndexedDB: function(view)
{
this._innerShowView(view);
},

showDOMStorage: function(domStorage)
{
if (!domStorage)
return;

var view;
view = domStorage._domStorageView;
if (!view) {
view = new WebInspector.DOMStorageItemsView(domStorage);
domStorage._domStorageView = view;
}

this._innerShowView(view);
},

showCookies: function(treeElement, cookieDomain)
{
var view = this._cookieViews[cookieDomain];
if (!view) {
view = new WebInspector.CookieItemsView(treeElement, cookieDomain);
this._cookieViews[cookieDomain] = view;
}

this._innerShowView(view);
},

showApplicationCache: function(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 === view)
return;

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 = new WebInspector.ParsedURL(frame.url).displayName;

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.type.name();
var categoryElement = resource.type === WebInspector.resourceTypes.Document ? this : this._categoryElements[categoryName];
if (!categoryElement) {
categoryElement = new WebInspector.StorageCategoryTreeElement(this._storagePanel, resource.type.categoryTitle(), categoryName, null, true);
this._categoryElements[resource.type.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-type-" + resource.type.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)
{
InspectorFrontendHost.openInNewTab(this._resource.url);
},

onattach: function()
{
WebInspector.BaseStorageTreeElement.prototype.onattach.call(this);

if (this._resource.type === WebInspector.resourceTypes.Image) {
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));
contextMenu.appendItem(WebInspector.copyLinkAddressLabel(), InspectorFrontendHost.copyText.bind(InspectorFrontendHost, this._resource.url));
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.request)
return;

contextMenu.appendItem(WebInspector.openInNetworkPanelLabel(), WebInspector.openRequestInNetworkPanel.bind(WebInspector, this._resource.request));
},

_appendSaveAsAction: function(contextMenu, event)
{
if (!InspectorFrontendHost.canSave())
return;

if (this._resource.type !== WebInspector.resourceTypes.Document &&
this._resource.type !== WebInspector.resourceTypes.Stylesheet &&
this._resource.type !== WebInspector.resourceTypes.Script)
return;

function doSave(forceSaveAs, content)
{
WebInspector.save(this._resource.url, content, forceSaveAs);
}

function save(forceSaveAs)
{
this._resource.requestContent(doSave.bind(this, forceSaveAs));
}

contextMenu.appendSeparator();
contextMenu.appendItem(WebInspector.UIString("Save"), save.bind(this, false));
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save as..." : "Save As..."), save.bind(this, true));
},

_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.subtitleText = "";
this.insertChild(new WebInspector.ResourceRevisionTreeElement(this._storagePanel, revision), 0);
if (this._sourceView === this._storagePanel.visibleView)
this._storagePanel._showResourceView(this._resource);
},

sourceView: function()
{
if (!this._sourceView) {
this._sourceView = new WebInspector.EditableResourceSourceFrame(this._resource);
if (this._resource.messages) {
for (var i = 0; i < this._resource.messages.length; i++)
this._sourceView.addMessage(this._resource.messages[i]);
}
this._sourceView.addEventListener(WebInspector.EditableResourceSourceFrame.Events.TextEdited, this._sourceViewTextEdited, this);
}
return this._sourceView;
},

_sourceViewTextEdited: function(event)
{
var sourceFrame = event.data;
this.subtitleText = sourceFrame.isDirty() ? "*" : "";
}
}

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

onexpand: function()
{
this._updateChildren();
},

_updateChildren: 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.IndexedDBTreeElement = function(storagePanel)
{
WebInspector.StorageCategoryTreeElement.call(this, storagePanel, WebInspector.UIString("IndexedDB"), "IndexedDB", ["indexed-db-storage-tree-item"]);
}

WebInspector.IndexedDBTreeElement.prototype = {
onexpand: function()
{
WebInspector.StorageCategoryTreeElement.prototype.onexpand.call(this);
if (!this._indexedDBModel)
this._createIndexedDBModel();
},

onattach: function()
{
WebInspector.StorageCategoryTreeElement.prototype.onattach.call(this);
this.listItemElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), true);
},

_handleContextMenuEvent: function(event)
{
var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendItem(WebInspector.UIString("Refresh IndexedDB"), this.refreshIndexedDB.bind(this));
contextMenu.show(event);
},

_createIndexedDBModel: function()
{
this._indexedDBModel = new WebInspector.IndexedDBModel();
this._idbDatabaseTreeElements = [];
this._indexedDBModel.addEventListener(WebInspector.IndexedDBModel.EventTypes.DatabaseAdded, this._indexedDBAdded, this);
this._indexedDBModel.addEventListener(WebInspector.IndexedDBModel.EventTypes.DatabaseRemoved, this._indexedDBRemoved, this);
this._indexedDBModel.addEventListener(WebInspector.IndexedDBModel.EventTypes.DatabaseLoaded, this._indexedDBLoaded, this);
},

refreshIndexedDB: function()
{
if (!this._indexedDBModel) {
this._createIndexedDBModel();
return;
}

this._indexedDBModel.refreshDatabaseNames();
},


_indexedDBAdded: function(event)
{
var databaseId =   event.data;

var idbDatabaseTreeElement = new WebInspector.IDBDatabaseTreeElement(this._storagePanel, this._indexedDBModel, databaseId);
this._idbDatabaseTreeElements.push(idbDatabaseTreeElement);
this.appendChild(idbDatabaseTreeElement);

this._indexedDBModel.refreshDatabase(databaseId);
},


_indexedDBRemoved: function(event)
{
var databaseId =   event.data;

var idbDatabaseTreeElement = this._idbDatabaseTreeElement(databaseId)
if (!idbDatabaseTreeElement)
return;

idbDatabaseTreeElement.clear();
this.removeChild(idbDatabaseTreeElement);
this._idbDatabaseTreeElements.remove(idbDatabaseTreeElement);
},


_indexedDBLoaded: function(event)
{
var database =   event.data;

var idbDatabaseTreeElement = this._idbDatabaseTreeElement(database.databaseId)
if (!idbDatabaseTreeElement)
return;

idbDatabaseTreeElement.update(database);
},


_idbDatabaseTreeElement: function(databaseId)
{
var index = -1;
for (var i = 0; i < this._idbDatabaseTreeElements.length; ++i) {
if (this._idbDatabaseTreeElements[i]._databaseId.equals(databaseId)) {
index = i;
break;
}
}
if (index !== -1)
return this._idbDatabaseTreeElements[i];
return null;
}
}

WebInspector.IndexedDBTreeElement.prototype.__proto__ = WebInspector.StorageCategoryTreeElement.prototype;


WebInspector.IDBDatabaseTreeElement = function(storagePanel, model, databaseId)
{
WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, databaseId.name + " - " + databaseId.securityOrigin, ["indexed-db-storage-tree-item"]);
this._model = model;
this._databaseId = databaseId;
this._idbObjectStoreTreeElements = {};
}

WebInspector.IDBDatabaseTreeElement.prototype = {
get itemURL()
{
return "indexedDB://" + this._databaseId.securityOrigin + "/" + this._databaseId.name;
},

onattach: function()
{
WebInspector.BaseStorageTreeElement.prototype.onattach.call(this);
this.listItemElement.addEventListener("contextmenu", this._handleContextMenuEvent.bind(this), true);
},

_handleContextMenuEvent: function(event)
{
var contextMenu = new WebInspector.ContextMenu();
contextMenu.appendItem(WebInspector.UIString("Refresh IndexedDB"), this._refreshIndexedDB.bind(this));
contextMenu.show(event);
},

_refreshIndexedDB: function(event)
{
this._model.refreshDatabaseNames();
},


update: function(database)
{
this._database = database;
var objectStoreNames = {};
for (var objectStoreName in this._database.objectStores) {
var objectStore = this._database.objectStores[objectStoreName];
objectStoreNames[objectStore.name] = true;
if (!this._idbObjectStoreTreeElements[objectStore.name]) {
var idbObjectStoreTreeElement = new WebInspector.IDBObjectStoreTreeElement(this._storagePanel, this._model, this._databaseId, objectStore);
this._idbObjectStoreTreeElements[objectStore.name] = idbObjectStoreTreeElement;
this.appendChild(idbObjectStoreTreeElement);
}
this._idbObjectStoreTreeElements[objectStore.name].update(objectStore);
}
for (var objectStoreName in this._idbObjectStoreTreeElements) {
if (!objectStoreNames[objectStoreName])
this._objectStoreRemoved(objectStoreName);
}

if (this.children.length) {
this.hasChildren = true;
this.expand();
}

if (this._view)
this._view.update(database);

this._updateTooltip();
},

_updateTooltip: function()
{
this.tooltip = WebInspector.UIString("Version") + ": " + this._database.version;
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
if (!this._view)
this._view = new WebInspector.IDBDatabaseView(this._database);

this._storagePanel.showIndexedDB(this._view);
},


_objectStoreRemoved: function(objectStoreName)
{
var objectStoreTreeElement = this._idbObjectStoreTreeElements[objectStoreName];
objectStoreTreeElement.clear();
this.removeChild(objectStoreTreeElement);
delete this._idbObjectStoreTreeElements[objectStoreName];
},

clear: function()
{
for (var objectStoreName in this._idbObjectStoreTreeElements)
this._objectStoreRemoved(objectStoreName);
}
}

WebInspector.IDBDatabaseTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;


WebInspector.IDBObjectStoreTreeElement = function(storagePanel, model, databaseId, objectStore)
{
WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, objectStore.name, ["indexed-db-object-store-storage-tree-item"]);
this._model = model;
this._databaseId = databaseId;
this._idbIndexTreeElements = {};
}

WebInspector.IDBObjectStoreTreeElement.prototype = {
get itemURL()
{
return "indexedDB://" + this._databaseId.securityOrigin + "/" + this._databaseId.name + "/" + this._objectStore.name;
},


update: function(objectStore)
{
this._objectStore = objectStore;

var indexNames = {};
for (var indexName in this._objectStore.indexes) {
var index = this._objectStore.indexes[indexName];
indexNames[index.name] = true;
if (!this._idbIndexTreeElements[index.name]) {
var idbIndexTreeElement = new WebInspector.IDBIndexTreeElement(this._storagePanel, this._model, this._databaseId, this._objectStore, index);
this._idbIndexTreeElements[index.name] = idbIndexTreeElement;
this.appendChild(idbIndexTreeElement);
}
this._idbIndexTreeElements[index.name].update(index);
}
for (var indexName in this._idbIndexTreeElements) {
if (!indexNames[indexName])
this._indexRemoved(indexName);
}
for (var indexName in this._idbIndexTreeElements) {
if (!indexNames[indexName]) {
this.removeChild(this._idbIndexTreeElements[indexName]);
delete this._idbIndexTreeElements[indexName];
}
}

if (this.children.length) {
this.hasChildren = true;
this.expand();
}

if (this._view)
this._view.update(this._objectStore);

this._updateTooltip();
},

_updateTooltip: function()
{
this.tooltip = this._objectStore.keyPath ? (WebInspector.UIString("Key path") + ": " + this._objectStore.keyPath) : "";
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
if (!this._view)
this._view = new WebInspector.IDBDataView(this._model, this._databaseId, this._objectStore, null);

this._storagePanel.showIndexedDB(this._view);
},


_indexRemoved: function(indexName)
{
var indexTreeElement = this._idbIndexTreeElements[indexName];
indexTreeElement.clear();
this.removeChild(indexTreeElement);
delete this._idbIndexTreeElements[indexName];
},

clear: function()
{
for (var indexName in this._idbIndexTreeElements)
this._indexRemoved(indexName);
if (this._view)
this._view.clear();
}
}

WebInspector.IDBObjectStoreTreeElement.prototype.__proto__ = WebInspector.BaseStorageTreeElement.prototype;


WebInspector.IDBIndexTreeElement = function(storagePanel, model, databaseId, objectStore, index)
{
WebInspector.BaseStorageTreeElement.call(this, storagePanel, null, index.name, ["indexed-db-index-storage-tree-item"]);
this._model = model;
this._databaseId = databaseId;
this._objectStore = objectStore;
this._index = index;
}

WebInspector.IDBIndexTreeElement.prototype = {
get itemURL()
{
return "indexedDB://" + this._databaseId.securityOrigin + "/" + this._databaseId.name + "/" + this._objectStore.name + "/" + this._index.name;
},


update: function(index)
{
this._index = index;

if (this._view)
this._view.update(this._index);

this._updateTooltip();
},

_updateTooltip: function()
{
var tooltipLines = [];
tooltipLines.push(WebInspector.UIString("Key path") + ": " + this._index.keyPath);
if (this._index.unique)
tooltipLines.push(WebInspector.UIString("unique"));
if (this._index.multiEntry)
tooltipLines.push(WebInspector.UIString("multiEntry"));
this.tooltip = tooltipLines.join("\n");
},

onselect: function()
{
WebInspector.BaseStorageTreeElement.prototype.onselect.call(this);
if (!this._view)
this._view = new WebInspector.IDBDataView(this._model, this._databaseId, this._objectStore, this._index);

this._storagePanel.showIndexedDB(this._view);
},

clear: function()
{
if (this._view)
this._view.clear();
}
}

WebInspector.IDBIndexTreeElement.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 = new WebInspector.ParsedURL(manifestURL).displayName;
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 = new WebInspector.ParsedURL(frame.url).displayName;
},

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-type-" + revision.resource.type.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.canSave()) {
function doSave(forceSaveAs, content)
{
WebInspector.save(this._revision.resource.url, content, forceSaveAs);
}

function save(forceSaveAs)
{
this._revision.requestContent(doSave.bind(this, forceSaveAs));
}

contextMenu.appendSeparator();
contextMenu.appendItem(WebInspector.UIString("Save"), save.bind(this, false));
contextMenu.appendItem(WebInspector.UIString(WebInspector.useLowerCaseMenuTitles() ? "Save as..." : "Save As..."), save.bind(this, true));
}

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 id()
{
return this._id;
},

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

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

buttonClicked: function()
{
},

viewForProfile: function(profile)
{
if (!profile._profileView)
profile._profileView = this.createView(profile);
return profile._profileView;
},

reset: function()
{
},

get description()
{
return "";
},


createView: function(profile)
{
throw new Error("Needs implemented.");
},


createSidebarTreeElementForProfile: function(profile)
{
throw new Error("Needs implemented.");
},


createTemporaryProfile: function()
{
throw new Error("Needs implemented.");
},


createProfile: 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.ProfileHeader = function(profileType, title, uid)
{
this.typeId = profileType,
this.title = title;
if (uid === undefined) {
this.uid = -1;
this.isTemporary = true;
} else {
this.uid = uid;
this.isTemporary = false;
}
}


WebInspector.HeapProfileHeader = function(profileType, title, uid, maxJSObjectId)
{
WebInspector.ProfileHeader.call(this, profileType, title, uid);
this.maxJSObjectId = maxJSObjectId;
}


WebInspector.ProfilesPanel = function()
{
WebInspector.Panel.call(this, "profiles");
this.registerRequiredCSS("panelEnablerView.css");
this.registerRequiredCSS("heapProfiler.css");
this.registerRequiredCSS("profilesPanel.css");

this.createSplitViewWithSidebarTree();

this.profilesItemTreeElement = new WebInspector.ProfilesSidebarTreeElement(this);
this.sidebarTree.appendChild(this.profilesItemTreeElement);

this._profileTypesByIdMap = {};

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, this);
if (!Capabilities.profilerCausesRecompilation)
this.enableToggleButton.element.addStyleClass("hidden");

this.recordButton = new WebInspector.StatusBarButton("", "record-profile-status-bar-item");
this.recordButton.addEventListener("click", this.toggleRecordButton, this);

this.clearResultsButton = new WebInspector.StatusBarButton(WebInspector.UIString("Clear all profiles."), "clear-status-bar-item");
this.clearResultsButton.addEventListener("click", this._clearProfiles, this);

this.profileViewStatusBarItemsContainer = document.createElement("div");
this.profileViewStatusBarItemsContainer.className = "status-bar-items";

this._profiles = [];
this._profilerEnabled = !Capabilities.profilerCausesRecompilation;

this._launcherView = new WebInspector.ProfileLauncherView(this);
this._launcherView.addEventListener(WebInspector.ProfileLauncherView.EventTypes.ProfileTypeSelected, this._onProfileTypeSelected, this);
this._reset();
this._launcherView.setUpEventListeners();

this._registerProfileType(new WebInspector.CPUProfileType());
if (!WebInspector.WorkerManager.isWorkerFrontend())
this._registerProfileType(new WebInspector.CSSSelectorProfileType());
if (Capabilities.heapProfilerPresent)
this._registerProfileType(new WebInspector.HeapSnapshotProfileType());

InspectorBackend.registerProfilerDispatcher(new WebInspector.ProfilerDispatcher(this));

if (!Capabilities.profilerCausesRecompilation || WebInspector.settings.profilerEnabled.get())
ProfilerAgent.enable(this._profilerWasEnabled.bind(this));
}

WebInspector.ProfilesPanel.EventTypes = {
ProfileStarted: "profile-started",
ProfileFinished: "profile-finished"
}

WebInspector.ProfilesPanel.prototype = {
get toolbarItemLabel()
{
return WebInspector.UIString("Profiles");
},

get statusBarItems()
{
return [this.enableToggleButton.element, this.recordButton.element, this.clearResultsButton.element, this.profileViewStatusBarItemsContainer];
},

toggleRecordButton: function()
{
this._selectedProfileType.buttonClicked();
},

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

_onProfileTypeSelected: function(event)
{
this._selectedProfileType = event.data;
this.recordButton.title = this._selectedProfileType.buttonTooltip;
},

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

for (var id in this._profileTypesByIdMap) {
var profileType = this._profileTypesByIdMap[id];
var treeElement = profileType.treeElement;
treeElement.removeChildren();
treeElement.hidden = true;
profileType.reset();
}

this._profiles = [];
this._profilesIdMap = {};
this._profileGroups = {};
this._profileGroupsForLinks = {};
this._profilesWereRequested = false;

this.sidebarTreeElement.removeStyleClass("some-expandable");

this.profileViews.removeChildren();
this.profileViewStatusBarItemsContainer.removeChildren();

this.removeAllListeners();
this._launcherView.setUpEventListeners();

this._updateInterface();
this.profilesItemTreeElement.select();
this._showLauncherView();
},

_showLauncherView: function()
{
this.closeVisibleView();
this.profileViewStatusBarItemsContainer.removeChildren();
this._launcherView.show(this.splitView.mainElement);
this.visibleView = this._launcherView;
},

_clearProfiles: function()
{
ProfilerAgent.clearProfiles();
this._reset();
},

_registerProfileType: function(profileType)
{
this._profileTypesByIdMap[profileType.id] = profileType;
this._launcherView.addProfileType(profileType);
profileType.treeElement = new WebInspector.SidebarSectionTreeElement(profileType.treeItemTitle, null, true);
profileType.treeElement.hidden = true;
this.sidebarTree.appendChild(profileType.treeElement);
},

_makeKey: function(text, profileTypeId)
{
return escape(text) + '/' + escape(profileTypeId);
},


addProfileHeader: function(profile)
{
this._removeTemporaryProfile(profile.typeId);

var typeId = profile.typeId;
var profileType = this.getProfileType(typeId);
var sidebarParent = profileType.treeElement;
sidebarParent.hidden = false;
var small = false;
var alternateTitle;

profile.__profilesPanelProfileType = profileType;
this._profiles.push(profile);
this._profilesIdMap[this._makeKey(profile.uid, typeId)] = profile;

if (!profile.title.startsWith(UserInitiatedProfileName)) {
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) {
if (!this.visibleView)
this.showProfile(profile);
this.dispatchEventToListeners("profile added");
this.dispatchEventToListeners(WebInspector.ProfilesPanel.EventTypes.ProfileFinished);
this.recordButton.toggled = false;
} else {
this.dispatchEventToListeners(WebInspector.ProfilesPanel.EventTypes.ProfileStarted);
this.recordButton.toggled = true;
}

this.recordButton.title = this._selectedProfileType.buttonTooltip;
},

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

findTemporaryProfile: 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 this._profiles[i];
return null;
},

_removeTemporaryProfile: function(typeId)
{
var temporaryProfile = this.findTemporaryProfile(typeId);
if (temporaryProfile)
this._removeProfileHeader(temporaryProfile);
},

hasProfile: function(profile)
{
return !!this._profilesIdMap[this._makeKey(profile.uid, profile.typeId)];
},

getProfile: function(typeId, uid)
{
return this._profilesIdMap[this._makeKey(uid, typeId)];
},

loadHeapSnapshot: function(uid, callback)
{
var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.TypeId)];
if (!profile)
return;

if (!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.HeapSnapshotProfileType.TypeId)];
if (!profile || !profile.proxy)
return;
profile.proxy.pushJSONChunk(chunk);
},

_finishHeapSnapshot: function(uid)
{
var profile = this._profilesIdMap[this._makeKey(uid, WebInspector.HeapSnapshotProfileType.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;
var worker =   snapshotProxy.worker;
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])]);
},

closeVisibleView: function()
{
if (this.visibleView)
this.visibleView.detach();
delete this.visibleView;
},

displayTitleForProfileLink: function(title, typeId)
{
title = unescape(title);
if (title.startsWith(UserInitiatedProfileName)) {
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 visibleView = this.visibleView;

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 (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;
this.recordButton.visible = true;
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;
this.recordButton.visible = false;
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) {
var profileHeader = profileHeaders[i];
if (!this.hasProfile(profileHeader)) {
var profileType = this.getProfileType(profileHeader.typeId);
this.addProfileHeader(profileType.createProfile(profileHeader));
}
}
}

ProfilerAgent.getProfileHeaders(populateCallback.bind(this));

this._profilesWereRequested = true;
},

sidebarResized: function(event)
{
var width = event.data;

this.profileViewStatusBarItemsContainer.style.left = Math.max(5 * 31, width) + "px";
},

setRecordingProfile: function(profileType, isProfiling)
{
var profileTypeObject = this.getProfileType(profileType);
profileTypeObject.setRecordingProfile(isProfiling);
var temporaryProfile = this.findTemporaryProfile(profileType);
if (!!temporaryProfile === isProfiling)
return;
if (!temporaryProfile)
temporaryProfile = profileTypeObject.createTemporaryProfile();
if (isProfiling)
this.addProfileHeader(temporaryProfile);
else
this._removeTemporaryProfile(profileType);
},

takeHeapSnapshot: function()
{
var temporaryRecordingProfile = this.findTemporaryProfile(WebInspector.HeapSnapshotProfileType.TypeId);
if (!temporaryRecordingProfile) {
var profileTypeObject = this.getProfileType(WebInspector.HeapSnapshotProfileType.TypeId);
this.addProfileHeader(profileTypeObject.createTemporaryProfile());
}
ProfilerAgent.takeHeapSnapshot();
WebInspector.userMetrics.ProfilesHeapProfileTaken.record();
},

_reportHeapSnapshotProgress: function(done, total)
{
var temporaryProfile = this.findTemporaryProfile(WebInspector.HeapSnapshotProfileType.TypeId);
if (temporaryProfile) {
temporaryProfile.sidebarElement.subtitle = WebInspector.UIString("%.2f%", (done / total) * 100);
temporaryProfile.sidebarElement.wait = true;
if (done >= total)
this._removeTemporaryProfile(WebInspector.HeapSnapshotProfileType.TypeId);
}
}
}

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)
{
var profileType = this._profiler.getProfileType(profile.typeId);
this._profiler.addProfileHeader(profileType.createProfile(profile));
},

addHeapSnapshotChunk: function(uid, chunk)
{
this._profiler._addHeapSnapshotChunk(uid, chunk);
},

finishHeapSnapshot: function(uid)
{
this._profiler._finishHeapSnapshot(uid);
},

setRecordingProfile: function(isProfiling)
{
this._profiler.setRecordingProfile(WebInspector.CPUProfileType.TypeId, 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.startsWith(UserInitiatedProfileName))
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.startsWith(UserInitiatedProfileName))
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.ProfilesSidebarTreeElement = function(panel)
{
this._panel = panel;
this.small = false;

WebInspector.SidebarTreeElement.call(this, "profile-launcher-view-tree-item", WebInspector.UIString("Profiles"), "", null, false);
}

WebInspector.ProfilesSidebarTreeElement.prototype = {
onselect: function()
{
this._panel._showLauncherView();
},

get selectable()
{
return true;
}
}

WebInspector.ProfilesSidebarTreeElement.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, this._dispatch.bind(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 ConsoleAPI();

this.onReset = new EventSink(events.Reset);
}


InspectorExtensionAPI.prototype = {
log: function(message)
{
extensionServer.sendRequest({ command: commands.Log, message: message });
}
}


function ConsoleAPI()
{
this.onMessageAdded = new EventSink(events.ConsoleMessageAdded);
}

ConsoleAPI.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, panelGetter.bind(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 && callback.bind(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 = this._nodeFactory.bind(null, "url");
this.createSnippet = this._nodeFactory.bind(null, "snippet");
this.createText = this._nodeFactory.bind(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", this._onCallback.bind(this));

var channel = new MessageChannel();
this._port = channel.port1;
this._port.addEventListener("message", this._onMessage.bind(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 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] = descriptor.value.bind(implementation);
else if (typeof descriptor.get === "function")
interface.__defineGetter__(member, descriptor.get.bind(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();

return new InspectorExtensionAPI();
}


function buildPlatformExtensionAPI(extensionInfo)
{
function platformExtensionAPI(coreAPI)
{
window.webInspector = coreAPI;
}
return platformExtensionAPI.toString();
}


function buildExtensionAPIInjectedScript(extensionInfo)
{
return "(function(injectedScriptHost, inspectedWindow, injectedScriptId){ " +
defineCommonExtensionSymbols.toString() + ";" +
injectedExtensionAPI.toString() + ";" +
buildPlatformExtensionAPI(extensionInfo) + ";" +
"platformExtensionAPI(injectedExtensionAPI(injectedScriptId));" +
"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.toString();
}  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.requests;
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: resource.type.name()
};
},

_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, contentEncoded, mimeType)
{
var response = {
encoding: contentEncoded ? "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.RequestFinished, 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)
{
for (var i = 0; i < extensions.length; ++i)
this._addExtension(extensions[i]);
},

_addExtension: function(extensionInfo)
{
const urlOriginRegExp = new RegExp("([^:]+:\/\/[^/]*)\/"); 
var startPage = extensionInfo.startPage;
var name = extensionInfo.name;

try {
var originMatch = urlOriginRegExp.exec(startPage);
if (!originMatch) {
console.error("Skipping extension with invalid URL: " + startPage);
return false;
}
var extensionOrigin = originMatch[1];
if (!this._registeredExtensions[extensionOrigin]) {

InspectorFrontendHost.setInjectedScriptForOrigin(extensionOrigin, buildExtensionAPIInjectedScript(extensionInfo));
this._registeredExtensions[extensionOrigin] = { 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;
},

_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 = function(page, name)
{
WebInspector.extensionServer._addExtension({
startPage: page,
name: name,
});
}






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

defaultFocusedElement: function()
{
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("panelEnablerView.css");
this.registerRequiredCSS("auditsPanel.css");

this.createSplitViewWithSidebarTree();
this.auditsTreeElement = new WebInspector.SidebarSectionTreeElement("", {}, true);
this.sidebarTree.appendChild(this.auditsTreeElement);
this.auditsTreeElement.listItemElement.addStyleClass("hidden");

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), this.terminateAudit.bind(this));
for (var id in this.categoriesById)
this._launcherView.addCategory(this.categoriesById[id]);

WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.OnLoad, this._didMainResourceLoad, this);
}

WebInspector.AuditsPanel.prototype = {
get toolbarItemLabel()
{
return WebInspector.UIString("Audits");
},

get statusBarItems()
{
return [this.clearResultsButton.element];
},

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 requests = WebInspector.networkLog.requests;

var rulesRemaining = 0;
for (var i = 0; i < categories.length; ++i)
rulesRemaining += categories[i].ruleCount;

this._progressMonitor.setTotalWork(rulesRemaining);

var results = [];
var mainResourceURL = WebInspector.inspectedPageURL;

function ruleResultReadyCallback(categoryResult, ruleResult)
{
if (this._progressMonitor.canceled)
return;

if (ruleResult && ruleResult.children)
categoryResult.addRuleResult(ruleResult);

--rulesRemaining;
this._progressMonitor.worked(1);

if (this._progressMonitor.done() && resultCallback)
resultCallback(mainResourceURL, results);
}

if (this._progressMonitor.done()) {
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(requests, ruleResultReadyCallback.bind(this, result), this._progressMonitor);
}
},

_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 (!this._progressMonitor.canceled && launcherCallback)
launcherCallback();
},

initiateAudit: function(categoryIds, progressElement, runImmediately, launcherCallback)
{
if (!categoryIds || !categoryIds.length)
return;

this._progressMonitor = new WebInspector.AuditProgressMonitor(progressElement);

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

terminateAudit: function(launcherCallback)
{
this._progressMonitor.canceled = true;
launcherCallback();
},

_reloadResources: function(callback)
{
this._pageReloadCallback = callback;
PageAgent.reload(false);
},

_didMainResourceLoad: function()
{
if (this._pageReloadCallback) {
var callback = this._pageReloadCallback;
delete this._pageReloadCallback;
callback();
}
},

showResults: function(categoryResults)
{
if (!categoryResults._resultView)
categoryResults._resultView = new WebInspector.AuditResultView(categoryResults);

this.visibleView = categoryResults._resultView;
},

showLauncherView: function()
{
this.visibleView = this._launcherView;
},

get visibleView()
{
return this._visibleView;
},

set visibleView(x)
{
if (this._visibleView === x)
return;

if (this._visibleView)
this._visibleView.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(requests, callback, progressMonitor)
{
this._ensureInitialized();
for (var i = 0; i < this._rules.length; ++i)
this._rules[i].run(requests, callback, progressMonitor);
},

_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(requests, callback, progressMonitor)
{
if (progressMonitor.canceled)
return;

var result = new WebInspector.AuditRuleResult(this.displayName);
result.severity = this._severity;
this.doRun(requests, result, callback, progressMonitor);
},


doRun: function(requests, result, callback, progressMonitor)
{
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.AuditProgressMonitor = function(progressElement)
{
this._element = progressElement;
this.setTotalWork(WebInspector.AuditProgressMonitor.INDETERMINATE);
}

WebInspector.AuditProgressMonitor.INDETERMINATE = -1;

WebInspector.AuditProgressMonitor.prototype = {
setTotalWork: function(total)
{
if (this.canceled || this._total === total)
return;
this._total = total;
this._value = 0;
this._element.max = total;
if (total === WebInspector.AuditProgressMonitor.INDETERMINATE)
this._element.removeAttribute("value");
else
this._element.value = 0;
},

worked: function(items)
{
if (this.canceled || this.indeterminate || this.done())
return;
this._value += items;
if (this._value > this._total)
this._value = this._total;
this._element.value = this._value;
},

get indeterminate()
{
return this._total === WebInspector.AuditProgressMonitor.INDETERMINATE;
},

done: function()
{
return !this.indeterminate && (this.canceled || this._value === this._total);
},

get canceled()
{
return !!this._canceled;
},

set canceled(x)
{
if (this._canceled === x)
return;
if (x)
this.setTotalWork(WebInspector.AuditProgressMonitor.INDETERMINATE);
this._canceled = x;
}
}


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, stopCallback)
{
WebInspector.View.call(this);

this._runnerCallback = runnerCallback;
this._stopCallback = stopCallback;
this._categoryIdPrefix = "audit-category-item-";
this._auditRunning = false;

this.element.addStyleClass("audit-launcher-view");
this.element.addStyleClass("panel-enabler-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.RequestStarted, this._onRequestStarted, this);
WebInspector.networkManager.addEventListener(WebInspector.NetworkManager.EventTypes.RequestFinished, this._onRequestFinished, this);
}

WebInspector.AuditLauncherView.prototype = {
_resetResourceCount: function()
{
this._loadedResources = 0;
this._totalResources = 0;
},

_onRequestStarted: function(event)
{
var request =   event.data;

if (request.type === WebInspector.resourceTypes.WebSocket)
return;
++this._totalResources;
this._updateResourceProgress();
},

_onRequestFinished: function(event)
{
var request =   event.data;

if (request.type === WebInspector.resourceTypes.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;
delete this._stopRequested;
this._updateButton();
this._updateResourceProgress();
},

_launchButtonClicked: function(event)
{
if (!this._auditRunning) {
var catIds = [];
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._resourceProgressElement, this._auditPresentStateElement.checked, this._setAuditRunning.bind(this, false));
} else {
this._stopRequested = true;
this._stopCallback(this._setAuditRunning.bind(this, false));
this._updateButton();
}
},

_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 = this._contentElement.createChild("div", "audit-categories-container");
this._currentCategoriesCount = 0;

this._contentElement.createChild("div", "flexible-space");

this._buttonContainerElement = this._contentElement.createChild("div", "button-container");

var labelElement = this._buttonContainerElement.createChild("label");
this._auditPresentStateElement = labelElement.createChild("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._auditPresentStateLabelElement);

labelElement = this._buttonContainerElement.createChild("label");
this.auditReloadedStateElement = labelElement.createChild("input");
this.auditReloadedStateElement.name = "audit-mode";
this.auditReloadedStateElement.type = "radio";
labelElement.appendChild(document.createTextNode("Reload Page and Audit on Load"));

this._launchButton = this._buttonContainerElement.createChild("button");
this._launchButton.textContent = WebInspector.UIString("Run");
this._launchButton.addEventListener("click", this._launchButtonClicked.bind(this), false);

this._resourceProgressContainer = this._buttonContainerElement.createChild("span", "resource-progress");
this._resourceProgressElement = this._resourceProgressContainer.createChild("progress");
this._resourceProgressContainer.appendChild(document.createTextNode(" "));
this._resourceProgressTextElement = this._resourceProgressContainer.createChild("span");


this._selectAllClicked(this._selectAllCheckboxElement.checked);
this._updateButton();
this._updateResourceProgress();
},

_updateResourceProgress: function()
{
if (!this._resourceProgressContainer)
return;

if (!this._auditRunning || this._stopRequested) {
this._resetResourceCount();
this._resourceProgressContainer.addStyleClass("hidden");
} else
this._resourceProgressContainer.removeStyleClass("hidden");
if (this._loadedResources)
this._resourceProgressTextElement.textContent = WebInspector.UIString("Loading (%d of %d)", this._loadedResources, this._totalResources);
else
this._resourceProgressTextElement.textContent = "";
},

_updateButton: function()
{
this._launchButton.textContent = this._auditRunning ? WebInspector.UIString("Stop") : WebInspector.UIString("Run");
this._launchButton.disabled = !this._currentCategoriesCount || (this._auditRunning && this._stopRequested);
}
}

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(requests, types, needFullResources)
{
var domainToResourcesMap = {};
for (var i = 0, size = requests.length; i < size; ++i) {
var request = requests[i];
if (types && types.indexOf(request.type) === -1)
continue;
var parsedURL = request.url.asParsedURL();
if (!parsedURL)
continue;
var domain = parsedURL.host;
var domainResources = domainToResourcesMap[domain];
if (domainResources === undefined) {
domainResources = [];
domainToResourcesMap[domain] = domainResources;
}
domainResources.push(needFullResources ? request : request.url);
}
return domainToResourcesMap;
}


WebInspector.AuditRules.GzipRule = function()
{
WebInspector.AuditRule.call(this, "network-gzip", "Enable gzip compression");
}

WebInspector.AuditRules.GzipRule.prototype = {

doRun: function(requests, result, callback, progressMonitor)
{
var totalSavings = 0;
var compressedSize = 0;
var candidateSize = 0;
var summary = result.addChild("", true);
for (var i = 0, length = requests.length; i < length; ++i) {
var request = requests[i];
if (request.statusCode === 304)
continue; 
if (this._shouldCompress(request)) {
var size = request.resourceSize;
candidateSize += size;
if (this._isCompressed(request)) {
compressedSize += size;
continue;
}
var savings = 2 * size / 3;
totalSavings += savings;
summary.addFormatted("%r could save ~%s", request.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(request)
{
var encodingHeader = request.responseHeaders["Content-Encoding"];
if (!encodingHeader)
return false;

return /\b(?:gzip|deflate)\b/.test(encodingHeader);
},

_shouldCompress: function(request)
{
return request.type.isTextType() && request.parsedURL.host && request.resourceSize !== undefined && request.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(requests, result, callback, progressMonitor)
{
var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(requests, [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.resourceTypes.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.resourceTypes.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(requests, result, callback, progressMonitor)
{
var summary = result.addChild("");
var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(requests, 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(requests, result, callback, progressMonitor)
{
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(
requests,
[WebInspector.resourceTypes.Stylesheet, WebInspector.resourceTypes.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 requestCountAboveThreshold = busiestHostResourceCount - this._minRequestThreshold;
if (requestCountAboveThreshold <= 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 = (requestCountAboveThreshold / avgResourcesPerHost) - 1.0;
var minBalanceThreshold = this._minBalanceThreshold;
if (pctAboveAvg < minBalanceThreshold)
return callback(null);

var requestsOnBusiestHost = 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 < requestsOnBusiestHost.length; ++i)
entry.addURL(requestsOnBusiestHost[i].url);

result.violationCount = requestsOnBusiestHost.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(requests, result, callback, progressMonitor)
{
var self = this;

function evalCallback(styleSheets) {
if (progressMonitor.canceled)
return;

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)
{
if (progressMonitor.canceled)
return;

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.request && resource.request.type == WebInspector.resourceTypes.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) {
if (progressMonitor.canceled)
return;
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 (progressMonitor.canceled)
return;

if (styleSheet) {
styleSheet.sourceURL = sourceURL;
styleSheets.push(styleSheet);
}
if (continuation)
continuation(styleSheets);
}

function allStylesCallback(error, styleSheetInfos)
{
if (progressMonitor.canceled)
return;

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(requests, result, callback, progressMonitor)
{
var cacheableAndNonCacheableResources = this._cacheableAndNonCacheableResources(requests);
if (cacheableAndNonCacheableResources[0].length)
this.runChecks(cacheableAndNonCacheableResources[0], result);
this.handleNonCacheableResources(cacheableAndNonCacheableResources[1], result);

callback(result);
},

handleNonCacheableResources: function(requests, result)
{
},

_cacheableAndNonCacheableResources: function(requests)
{
var processedResources = [[], []];
for (var i = 0; i < requests.length; ++i) {
var request = requests[i];
if (!this.isCacheableResource(request))
continue;
if (this._isExplicitlyNonCacheable(request))
processedResources[1].push(request);
else
processedResources[0].push(request);
}
return processedResources;
},

execCheck: function(messageText, requestCheckFunction, requests, result)
{
var requestCount = requests.length;
var urls = [];
for (var i = 0; i < requestCount; ++i) {
if (requestCheckFunction.call(this, requests[i]))
urls.push(requests[i].url);
}
if (urls.length) {
var entry = result.addChild(messageText, true);
entry.addURLs(urls);
result.violationCount += urls.length;
}
},

freshnessLifetimeGreaterThan: function(request, timeMs)
{
var dateHeader = this.responseHeader(request, "Date");
if (!dateHeader)
return false;

var dateHeaderMs = Date.parse(dateHeader);
if (isNaN(dateHeaderMs))
return false;

var freshnessLifetimeMs;
var maxAgeMatch = this.responseHeaderMatch(request, "Cache-Control", "max-age=(\\d+)");

if (maxAgeMatch)
freshnessLifetimeMs = (maxAgeMatch[1]) ? 1000 * maxAgeMatch[1] : 0;
else {
var expiresHeader = this.responseHeader(request, "Expires");
if (expiresHeader) {
var expDate = Date.parse(expiresHeader);
if (!isNaN(expDate))
freshnessLifetimeMs = expDate - dateHeaderMs;
}
}

return (isNaN(freshnessLifetimeMs)) ? false : freshnessLifetimeMs > timeMs;
},

responseHeader: function(request, header)
{
return request.responseHeaders[header];
},

hasResponseHeader: function(request, header)
{
return request.responseHeaders[header] !== undefined;
},

isCompressible: function(request)
{
return request.type.isTextType();
},

isPubliclyCacheable: function(request)
{
if (this._isExplicitlyNonCacheable(request))
return false;

if (this.responseHeaderMatch(request, "Cache-Control", "public"))
return true;

return request.url.indexOf("?") == -1 && !this.responseHeaderMatch(request, "Cache-Control", "private");
},

responseHeaderMatch: function(request, header, regexp)
{
return request.responseHeaders[header]
? request.responseHeaders[header].match(new RegExp(regexp, "im"))
: undefined;
},

hasExplicitExpiration: function(request)
{
return this.hasResponseHeader(request, "Date") &&
(this.hasResponseHeader(request, "Expires") || this.responseHeaderMatch(request, "Cache-Control", "max-age"));
},

_isExplicitlyNonCacheable: function(request)
{
var hasExplicitExp = this.hasExplicitExpiration(request);
return this.responseHeaderMatch(request, "Cache-Control", "(no-cache|no-store|must-revalidate)") ||
this.responseHeaderMatch(request, "Pragma", "no-cache") ||
(hasExplicitExp && !this.freshnessLifetimeGreaterThan(request, 0)) ||
(!hasExplicitExp && request.url && request.url.indexOf("?") >= 0) ||
(!hasExplicitExp && !this.isCacheableResource(request));
},

isCacheableResource: function(request)
{
return request.statusCode !== undefined && WebInspector.AuditRules.CacheableResponseCodes[request.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(requests, result)
{
if (requests.length) {
var entry = result.addChild("The following resources are explicitly non-cacheable. Consider making them cacheable if possible:", true);
result.violationCount += requests.length;
for (var i = 0; i < requests.length; ++i)
entry.addURL(requests[i].url);
}
},

runChecks: function(requests, 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, requests, result);
this.execCheck("The following resources specify a \"Vary\" header that disables caching in most versions of Internet Explorer:",
this._varyCheck, requests, result);
this.execCheck("The following cacheable resources have a short freshness lifetime:",
this._oneMonthExpirationCheck, requests, result);


this.execCheck("To further improve cache hit rate, specify an expiration one year in the future for the following cacheable resources:",
this._oneYearExpirationCheck, requests, result);
},

_missingExpirationCheck: function(request)
{
return this.isCacheableResource(request) && !this.hasResponseHeader(request, "Set-Cookie") && !this.hasExplicitExpiration(request);
},

_varyCheck: function(request)
{
var varyHeader = this.responseHeader(request, "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(request) && this.freshnessLifetimeGreaterThan(request, 0);
},

_oneMonthExpirationCheck: function(request)
{
return this.isCacheableResource(request) &&
!this.hasResponseHeader(request, "Set-Cookie") &&
!this.freshnessLifetimeGreaterThan(request, WebInspector.AuditRules.CacheControlRule.MillisPerMonth) &&
this.freshnessLifetimeGreaterThan(request, 0);
},

_oneYearExpirationCheck: function(request)
{
return this.isCacheableResource(request) &&
!this.hasResponseHeader(request, "Set-Cookie") &&
!this.freshnessLifetimeGreaterThan(request, 11 * WebInspector.AuditRules.CacheControlRule.MillisPerMonth) &&
this.freshnessLifetimeGreaterThan(request, 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(requests, result, callback)
{
this.execCheck("Resources with a \"?\" in the URL are not cached by most proxy caching servers:",
this._questionMarkCheck, requests, result);
this.execCheck("Consider adding a \"Cache-Control: public\" header to the following resources:",
this._publicCachingCheck, requests, 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, requests, result);
},

_questionMarkCheck: function(request)
{
return request.url.indexOf("?") >= 0 && !this.hasResponseHeader(request, "Set-Cookie") && this.isPubliclyCacheable(request);
},

_publicCachingCheck: function(request)
{
return this.isCacheableResource(request) &&
!this.isCompressible(request) &&
!this.responseHeaderMatch(request, "Cache-Control", "public") &&
!this.hasResponseHeader(request, "Set-Cookie");
},

_setCookieCacheableCheck: function(request)
{
return this.hasResponseHeader(request, "Set-Cookie") && this.isPubliclyCacheable(request);
}
}

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(requests, result, callback, progressMonitor)
{
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)
{
if (progressMonitor.canceled)
return;

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

if (styles.attributesStyle) {
var widthFound = !!styles.attributesStyle.getLiveProperty("width");
var heightFound = !!styles.attributesStyle.getLiveProperty("height");
}

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)
{
if (progressMonitor.canceled)
return;
var targetResult = {};

function inlineCallback(inlineStyle, attributesStyle)
{
targetResult.inlineStyle = inlineStyle;
targetResult.attributesStyle = attributesStyle;
}

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)
{
if (progressMonitor.canceled)
return;
WebInspector.domAgent.querySelectorAll(root.id, "img[src]", getStyles);
}

if (progressMonitor.canceled)
return;
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(requests, result, callback, progressMonitor)
{
function evalCallback(evalResult)
{
if (progressMonitor.canceled)
return;

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 (progressMonitor.canceled)
return;

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 (progressMonitor.canceled)
return;

if (!nodeIds)
return;
WebInspector.domAgent.querySelectorAll(root.id, "body link[rel~='stylesheet'][href]", externalStylesheetsReceived.bind(null, root, nodeIds));
}

function onDocumentAvailable(root)
{
if (progressMonitor.canceled)
return;

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(requests, result, callback, progressMonitor)
{
function evalCallback(resultValue)
{
if (progressMonitor.canceled)
return;

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 (progressMonitor.canceled)
return;

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 (progressMonitor.canceled)
return;

if (!nodeIds)
return;

WebInspector.domAgent.querySelectorAll(root.id, "head link[rel~='stylesheet'][href] ~ script:not([src])", cssBeforeInlineReceived.bind(null, nodeIds));
}

function onDocumentAvailable(root)
{
if (progressMonitor.canceled)
return;

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.CSSRuleBase = function(id, name)
{
WebInspector.AuditRule.call(this, id, name);
}

WebInspector.AuditRules.CSSRuleBase.prototype = {
doRun: function(requests, result, callback, progressMonitor)
{
CSSAgent.getAllStyleSheets(sheetsCallback.bind(this));

function sheetsCallback(error, headers)
{
if (error)
return callback(null);

for (var i = 0; i < headers.length; ++i) {
var header = headers[i];
if (header.disabled)
continue; 

this._visitStyleSheet(header.styleSheetId, i === headers.length - 1 ? finishedCallback : null, result, progressMonitor);
}
}

function finishedCallback()
{
callback(result);
}
},

_visitStyleSheet: function(styleSheetId, callback, result, progressMonitor)
{
WebInspector.CSSStyleSheet.createForId(styleSheetId, sheetCallback.bind(this));

function sheetCallback(styleSheet)
{
if (progressMonitor.canceled)
return;

if (!styleSheet) {
if (callback)
callback();
return;
}

this.visitStyleSheet(styleSheet, result);

for (var i = 0; i < styleSheet.rules.length; ++i)
this._visitRule(styleSheet, styleSheet.rules[i], result);

this.didVisitStyleSheet(styleSheet, result);

if (callback)
callback();
}
},

_visitRule: function(styleSheet, rule, result)
{
this.visitRule(styleSheet, rule, result);
var allProperties = rule.style.allProperties;
for (var i = 0; i < allProperties.length; ++i)
this.visitProperty(styleSheet, allProperties[i], result);
this.didVisitRule(styleSheet, rule, result);
},

visitStyleSheet: function(styleSheet, result)
{

},

didVisitStyleSheet: function(styleSheet, result)
{

},

visitRule: function(styleSheet, rule, result)
{

},

didVisitRule: function(styleSheet, rule, result)
{

},

visitProperty: function(styleSheet, property, result)
{

}
}

WebInspector.AuditRules.CSSRuleBase.prototype.__proto__ = WebInspector.AuditRule.prototype;


WebInspector.AuditRules.VendorPrefixedCSSProperties = function()
{
WebInspector.AuditRules.CSSRuleBase.call(this, "page-vendorprefixedcss", "Use normal CSS property names instead of vendor-prefixed ones");
this._webkitPrefix = "-webkit-";
}

WebInspector.AuditRules.VendorPrefixedCSSProperties.supportedProperties = [
"background-clip", "background-origin", "background-size",
"border-radius", "border-bottom-left-radius", "border-bottom-right-radius", "border-top-left-radius", "border-top-right-radius",
"box-shadow", "box-sizing", "opacity", "text-shadow"
].keySet();

WebInspector.AuditRules.VendorPrefixedCSSProperties.prototype = {
didVisitStyleSheet: function(styleSheet)
{
delete this._styleSheetResult;
},

visitRule: function(rule)
{
this._mentionedProperties = {};
},

didVisitRule: function()
{
delete this._ruleResult;
delete this._mentionedProperties;
},

visitProperty: function(styleSheet, property, result)
{
if (!property.name.startsWith(this._webkitPrefix))
return;

var normalPropertyName = property.name.substring(this._webkitPrefix.length).toLowerCase(); 
if (WebInspector.AuditRules.VendorPrefixedCSSProperties.supportedProperties[normalPropertyName] && !this._mentionedProperties[normalPropertyName]) {
var style = property.ownerStyle;
var liveProperty = style.getLiveProperty(normalPropertyName);
if (liveProperty && !liveProperty.styleBased)
return; 

var rule = style.parentRule;
this._mentionedProperties[normalPropertyName] = true;
if (!this._styleSheetResult)
this._styleSheetResult = result.addChild(rule.sourceURL ? WebInspector.linkifyResourceAsNode(rule.sourceURL) : "<unknown>");
if (!this._ruleResult) {
var anchor = WebInspector.linkifyURLAsNode(rule.sourceURL, rule.selectorText);
anchor.preferredPanel = "resources";
anchor.lineNumber = rule.sourceLine;
this._ruleResult = this._styleSheetResult.addChild(anchor);
}
++result.violationCount;
this._ruleResult.addSnippet(String.sprintf("\"" + this._webkitPrefix + "%s\" is used, but \"%s\" is supported.", normalPropertyName, normalPropertyName));
}
}
}

WebInspector.AuditRules.VendorPrefixedCSSProperties.prototype.__proto__ = WebInspector.AuditRules.CSSRuleBase.prototype;


WebInspector.AuditRules.CookieRuleBase = function(id, name)
{
WebInspector.AuditRule.call(this, id, name);
}

WebInspector.AuditRules.CookieRuleBase.prototype = {
doRun: function(requests, result, callback, progressMonitor)
{
var self = this;
function resultCallback(receivedCookies, isAdvanced) {
if (progressMonitor.canceled)
return;

self.processCookies(isAdvanced ? receivedCookies : [], requests, result);
callback(result);
}

WebInspector.Cookies.getCookiesAsync(resultCallback);
},

mapResourceCookies: function(requestsByDomain, allCookies, callback)
{
for (var i = 0; i < allCookies.length; ++i) {
for (var requestDomain in requestsByDomain) {
if (WebInspector.Cookies.cookieDomainMatchesResourceDomain(allCookies[i].domain, requestDomain))
this._callbackForResourceCookiePairs(requestsByDomain[requestDomain], allCookies[i], callback);
}
}
},

_callbackForResourceCookiePairs: function(requests, cookie, callback)
{
if (!requests)
return;
for (var i = 0; i < requests.length; ++i) {
if (WebInspector.Cookies.cookieMatchesResourceURL(cookie, requests[i].url))
callback(requests[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, requests, result)
{
function maxSizeSorter(a, b)
{
return b.maxCookieSize - a.maxCookieSize;
}

function avgSizeSorter(a, b)
{
return b.avgCookieSize - a.avgCookieSize;
}

var cookiesPerResourceDomain = {};

function collectorCallback(request, cookie)
{
var cookies = cookiesPerResourceDomain[request.parsedURL.host];
if (!cookies) {
cookies = [];
cookiesPerResourceDomain[request.parsedURL.host] = cookies;
}
cookies.push(cookie);
}

if (!allCookies.length)
return;

var sortedCookieSizes = [];

var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(requests,
null,
true);
var matchingResourceData = {};
this.mapResourceCookies(domainToResourcesMap, allCookies, collectorCallback.bind(this));

for (var requestDomain in cookiesPerResourceDomain) {
var cookies = cookiesPerResourceDomain[requestDomain];
sortedCookieSizes.push({
domain: requestDomain,
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, requests, result)
{
var domainToResourcesMap = WebInspector.AuditRules.getDomainToResourcesMap(requests,
[WebInspector.resourceTypes.Stylesheet,
WebInspector.resourceTypes.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, request, cookie)
{
matchingResourceData[request.url] = (matchingResourceData[request.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);
this.addRule(new WebInspector.AuditRules.VendorPrefixedCSSProperties(), WebInspector.AuditRule.Severity.Warning);
}
}

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(request)
{
WebInspector.TabbedPane.call(this);
this.element.addStyleClass("network-item-view");

var headersView = new WebInspector.RequestHeadersView(request);
this.appendTab("headers", WebInspector.UIString("Headers"), headersView);

var responseView = new WebInspector.RequestResponseView(request);
var previewView = new WebInspector.RequestPreviewView(request, responseView);

this.appendTab("preview", WebInspector.UIString("Preview"), previewView);
this.appendTab("response", WebInspector.UIString("Response"), responseView);

if (request.requestCookies || request.responseCookies) {
this._cookiesView = new WebInspector.RequestCookiesView(request);
this.appendTab("cookies", WebInspector.UIString("Cookies"), this._cookiesView);
}

if (request.timing) {
var timingView = new WebInspector.RequestTimingView(request);
this.appendTab("timing", WebInspector.UIString("Timing"), timingView);
}

if (request.frames().length > 0) {
var frameView = new WebInspector.ResourceWebSocketFrameView(request);
this.appendTab("webSocketFrames", WebInspector.UIString("WebSocket Frames"), frameView);
}

this.addEventListener(WebInspector.TabbedPane.EventTypes.TabSelected, this._tabSelected, this);
}

WebInspector.NetworkItemView.prototype = {
wasShown: function()
{
WebInspector.TabbedPane.prototype.wasShown.call(this);
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.RequestContentView = function(request)
{
WebInspector.RequestView.call(this, request);
}

WebInspector.RequestContentView.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(content, contentEncoded, mimeType)
{
this._innerViewShowRequested = false;
this.contentLoaded();
}

this.request.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.RequestContentView.prototype.__proto__ = WebInspector.RequestView.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.RequestHeadersView = function(request)
{
WebInspector.View.call(this);
this.registerRequiredCSS("resourceView.css");
this.element.addStyleClass("resource-headers-view");

this._request = request;

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

request.addEventListener(WebInspector.NetworkRequest.Events.RequestHeadersChanged, this._refreshRequestHeaders, this);
request.addEventListener(WebInspector.NetworkRequest.Events.ResponseHeadersChanged, this._refreshResponseHeaders, this);
request.addEventListener(WebInspector.NetworkRequest.Events.FinishedLoading, this._refreshHTTPInformation, this);

this._refreshURL();
this._refreshQueryString();
this._refreshUrlFragment();
this._refreshRequestHeaders();
this._refreshResponseHeaders();
this._refreshHTTPInformation();
}

WebInspector.RequestHeadersView.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._request.url);
},

_refreshQueryString: function()
{
var queryParameters = this._request.queryParameters;
this._queryStringTreeElement.hidden = !queryParameters;
if (queryParameters)
this._refreshParms(WebInspector.UIString("Query String Parameters"), queryParameters, this._queryStringTreeElement);
},

_refreshUrlFragment: function()
{
var urlFragment = this._request.parsedURL.fragment;
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._request.requestFormData;
if (!formData)
return;

var formParameters = this._request.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._request.webSocketRequestKey3 !== "undefined")
additionalRow = {header: "(Key3)", value: this._request.webSocketRequestKey3};
if (this._showRequestHeadersText)
this._refreshHeadersText(WebInspector.UIString("Request Headers"), this._request.sortedRequestHeaders, this._request.requestHeadersText, this._requestHeadersTreeElement);
else
this._refreshHeaders(WebInspector.UIString("Request Headers"), this._request.sortedRequestHeaders, additionalRow, this._requestHeadersTreeElement);

if (this._request.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._request.webSocketChallengeResponse !== "undefined")
additionalRow = {header: "(Challenge Response)", value: this._request.webSocketChallengeResponse};
if (this._showResponseHeadersText)
this._refreshHeadersText(WebInspector.UIString("Response Headers"), this._request.sortedResponseHeaders, this._request.responseHeadersText, this._responseHeadersTreeElement);
else
this._refreshHeaders(WebInspector.UIString("Response Headers"), this._request.sortedResponseHeaders, additionalRow, this._responseHeadersTreeElement);

if (this._request.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._request.statusCode;
var statusCodeElement = this._statusCodeTreeElement;
statusCodeElement.hidden = !this._request.statusCode;

if (this._request.statusCode) {
var statusImageSource = "";
if (this._request.statusCode < 300 || this._request.statusCode === 304)
statusImageSource = "Images/successGreenDot.png";
else if (this._request.statusCode < 400)
statusImageSource = "Images/warningOrangeDot.png";
else
statusImageSource = "Images/errorRedDot.png";

requestMethodElement.title = this._formatHeader(WebInspector.UIString("Request Method"), this._request.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._request.statusCode + " " + this._request.statusText;
var value = statusCodeFragment.createChild("div", "header-value source-code");
value.textContent = this._request.statusCode + " " + this._request.statusText;
if (this._request.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.RequestHeadersView.prototype.__proto__ = WebInspector.View.prototype;






WebInspector.RequestCookiesView = function(request)
{
WebInspector.View.call(this);
this.element.addStyleClass("resource-cookies-view");

this._request = request;

request.addEventListener(WebInspector.NetworkRequest.Events.RequestHeadersChanged, this._refreshCookies, this);
request.addEventListener(WebInspector.NetworkRequest.Events.ResponseHeadersChanged, this._refreshCookies, this);
}

WebInspector.RequestCookiesView.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._request.requestCookies || this._request.responseCookies);
},

_buildCookiesTable: function()
{
this.detachChildViews();

this._cookiesTable = new WebInspector.CookiesTable(null, true);
this._cookiesTable.addCookiesFolder(WebInspector.UIString("Request Cookies"), this._request.requestCookies);
this._cookiesTable.addCookiesFolder(WebInspector.UIString("Response Cookies"), this._request.responseCookies);
this._cookiesTable.show(this.element);
},

_refreshCookies: function()
{
delete this._cookiesTable;
if (!this._gotCookies || !this.isShowing())
return;
this._buildCookiesTable();
this._cookiesTable.updateWidths();
}
}

WebInspector.RequestCookiesView.prototype.__proto__ = WebInspector.View.prototype;






WebInspector.RequestTimingView = function(request)
{
WebInspector.View.call(this);
this.element.addStyleClass("resource-timing-view");

this._request = request;

request.addEventListener(WebInspector.NetworkRequest.Events.TimingChanged, this._refresh, this);
}

WebInspector.RequestTimingView.prototype = {
wasShown: function()
{
if (!this._request.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.RequestTimingView.createTimingTable(this._request);
this.element.appendChild(this._tableElement);
}
}

WebInspector.RequestTimingView.createTimingTable = function(request)
{
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 (request.timing.proxyStart !== -1)
addRow(WebInspector.UIString("Proxy"), "proxy", request.timing.proxyStart, request.timing.proxyEnd);

if (request.timing.dnsStart !== -1)
addRow(WebInspector.UIString("DNS Lookup"), "dns", request.timing.dnsStart, request.timing.dnsEnd);

if (request.timing.connectStart !== -1) {
if (request.connectionReused)
addRow(WebInspector.UIString("Blocking"), "connecting", request.timing.connectStart, request.timing.connectEnd);
else {
var connectStart = request.timing.connectStart;

if (request.timing.dnsStart !== -1)
connectStart += request.timing.dnsEnd - request.timing.dnsStart;
addRow(WebInspector.UIString("Connecting"), "connecting", connectStart, request.timing.connectEnd);
}
}

if (request.timing.sslStart !== -1)
addRow(WebInspector.UIString("SSL"), "ssl", request.timing.sslStart, request.timing.sslEnd);

var sendStart = request.timing.sendStart;
if (request.timing.sslStart !== -1)
sendStart += request.timing.sslEnd - request.timing.sslStart;

addRow(WebInspector.UIString("Sending"), "sending", request.timing.sendStart, request.timing.sendEnd);
addRow(WebInspector.UIString("Waiting"), "waiting", request.timing.sendEnd, request.timing.receiveHeadersEnd);
addRow(WebInspector.UIString("Receiving"), "receiving", (request.responseReceivedTime - request.timing.requestTime) * 1000, (request.endTime - request.timing.requestTime) * 1000);

const chartWidth = 200;
var total = (request.endTime - request.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.RequestTimingView.prototype.__proto__ = WebInspector.View.prototype;






WebInspector.RequestJSONView = function(request, parsedJSON)
{
WebInspector.RequestView.call(this, request);
this._parsedJSON = parsedJSON;
this.element.addStyleClass("json");
}

WebInspector.RequestJSONView.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.RequestJSONView.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.RequestJSONView.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.RequestJSONView.prototype.__proto__ = WebInspector.RequestView.prototype;


WebInspector.ParsedJSON = function(data, prefix, suffix)
{
this.data = data;
this.prefix = prefix;
this.suffix = suffix;
}






WebInspector.RequestHTMLView = function(request)
{
WebInspector.RequestView.call(this, request);
this.element.addStyleClass("html");
}

WebInspector.RequestHTMLView.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.request.content;
}
}

WebInspector.RequestHTMLView.prototype.__proto__ = WebInspector.RequestView.prototype;






WebInspector.RequestResponseView = function(request)
{
WebInspector.RequestContentView.call(this, request);
}

WebInspector.RequestResponseView.prototype = {
get sourceView()
{
if (!this._sourceView && WebInspector.RequestView.hasTextContent(this.request))
this._sourceView = new WebInspector.ResourceSourceFrame(this.request);
return this._sourceView;
},

contentLoaded: function()
{
if (!this.request.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.RequestResponseView.prototype.__proto__ = WebInspector.RequestContentView.prototype;






WebInspector.RequestPreviewView = function(request, responseView)
{
WebInspector.RequestContentView.call(this, request);
this._responseView = responseView;
}

WebInspector.RequestPreviewView.prototype = {
contentLoaded: function()
{
if (!this.request.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.request.hasErrorStatusCode() && this.request.content)
return new WebInspector.RequestHTMLView(this.request);

if (this.request.type === WebInspector.resourceTypes.XHR && this.request.content) {
var parsedJSON = WebInspector.RequestJSONView.parseJSON(this.request.content);
if (parsedJSON)
return new WebInspector.RequestJSONView(this.request, parsedJSON);
}

if (this.request.content && this.request.type === WebInspector.resourceTypes.Script && this.request.mimeType === "application/json") {
var parsedJSONP = WebInspector.RequestJSONView.parseJSONP(this.request.content);
if (parsedJSONP)
return new WebInspector.RequestJSONView(this.request, parsedJSONP);
}

if (this._responseView.sourceView)
return this._responseView.sourceView;

if (this.request.type === WebInspector.resourceTypes.Other)
return this._createEmptyView();

return WebInspector.RequestView.nonSourceViewForRequest(this.request);
}
}

WebInspector.RequestPreviewView.prototype.__proto__ = WebInspector.RequestContentView.prototype;






WebInspector.ResourceWebSocketFrameView = function(resource)
{
WebInspector.View.call(this);
this.element.addStyleClass("html");
this.resource = resource;
this.element.removeChildren();
var table = document.createElement("table");
var header = document.createElement("thead");

var headerRow = document.createElement("tr");
headerRow.createChild("td");

var timeHeader = document.createElement("td");
timeHeader.innerText = WebInspector.UIString("Time");
headerRow.appendChild(timeHeader);

var opCodeHeader = document.createElement("td");
opCodeHeader.innerText = WebInspector.UIString("OpCode");
headerRow.appendChild(opCodeHeader);

var maskHeader = document.createElement("td");
maskHeader.innerText = WebInspector.UIString("Mask");
headerRow.appendChild(maskHeader);

var lengthHeader = document.createElement("td");
lengthHeader.innerText = WebInspector.UIString("Length");
headerRow.appendChild(lengthHeader);

var dataHeader = document.createElement("td");
dataHeader.innerText = WebInspector.UIString("Data");
headerRow.appendChild(dataHeader);
table.appendChild(headerRow);

var frames = this.resource.frames();
for (var i = 0; i < frames.length; i++) {
var payload = frames[i];

var row = document.createElement("tr");

var count = document.createElement("td");
count.innerText = i + 1;
row.appendChild(count);

var dateCell = document.createElement("td");
var date = new Date();
date.setTime(payload.time * 1000);
dateCell.innerText = String.sprintf("%s %s", (payload.sent ? "\u2192" : (payload.errorMessage ? "" : "\u2190")), date.toISOString());
row.appendChild(dateCell);

if (payload.errorMessage) {
var spanCell = document.createElement("td");
spanCell.setAttribute("colspan", 4);
spanCell.innerText = payload.errorMessage;
row.appendChild(spanCell);
} else {
var opcode = document.createElement("td");
opcode.innerText = payload.opcode;
row.appendChild(opcode);

var mask = document.createElement("td");
mask.innerText = payload.mask;
row.appendChild(mask);

var length = document.createElement("td");
length.innerText = payload.payloadData.length;
row.appendChild(length);

var data = document.createElement("td");
data.textContent = payload.payloadData;
row.appendChild(data);
}
table.appendChild(row);
}
this.element.appendChild(table);
}

WebInspector.ResourceWebSocketFrameView.prototype.__proto__ = WebInspector.View.prototype;






WebInspector.ScriptFormatter = function()
{
this._tasks = [];
}


WebInspector.ScriptFormatter.locationToPosition = function(lineEndings, lineNumber, columnNumber)
{
var position = lineNumber ? lineEndings[lineNumber - 1] + 1 : 0;
return position + columnNumber;
}


WebInspector.ScriptFormatter.positionToLocation = function(lineEndings, position)
{
var lineNumber = lineEndings.upperBound(position - 1);
if (!lineNumber)
var columnNumber = position;
else
var columnNumber = position - lineEndings[lineNumber - 1] - 1;
return [lineNumber, columnNumber];
}

WebInspector.ScriptFormatter.prototype = {

formatContent: function(mimeType, content, callback)
{
content = content.replace(/\r\n?|[\n\u2028\u2029]/g, "\n").replace(/^\uFEFF/, '');
const method = "format";
var parameters = { mimeType: mimeType, content: content, indentString: "    "  };
this._tasks.push({ data: parameters, callback: callback });
this._worker.postMessage({ method: method, params: parameters });
},

_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(lineNumber, columnNumber)
{
var originalPosition = WebInspector.ScriptFormatter.locationToPosition(this._originalLineEndings, lineNumber, columnNumber);
var formattedPosition = this._convertPosition(this._mapping.original, this._mapping.formatted, originalPosition);
return WebInspector.ScriptFormatter.positionToLocation(this._formattedLineEndings, formattedPosition);
},


formattedToOriginal: function(lineNumber, columnNumber)
{
var formattedPosition = WebInspector.ScriptFormatter.locationToPosition(this._formattedLineEndings, lineNumber, columnNumber);
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.TextEditorCommand = function(newRange, originalText)
{
this.newRange = newRange;
this.originalText = originalText;
}


WebInspector.TextEditorModel = function()
{
this._lines = [""];
this._attributes = [];

this._undoStack = [];
this._noPunctuationRegex = /[^ !%&()*+,-.:;<=>?\[\]\^{|}~]+/;
this._lineBreak = "\n";
}

WebInspector.TextEditorModel.Indent = {
TwoSpaces: "  ",
FourSpaces: "    ",
EightSpaces: "        ",
TabCharacter: "\t"
}

WebInspector.TextEditorModel.Events = {
TextChanged: "TextChanged"
}

WebInspector.TextEditorModel.endsWithBracketRegex = /[{(\[]\s*$/;

WebInspector.TextEditorModel.prototype = {

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(text)
{
text = text || "";
var 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 newRange = this._innerSetText(range, text);
this.dispatchEventToListeners(WebInspector.TextEditorModel.Events.TextChanged, { oldRange: range, newRange: newRange});
},


editRange: function(range, text)
{
var originalText = this.copyRange(range);
if (text === originalText)
return range; 

var newRange = this._innerSetText(range, text);
this._pushUndoableCommand(newRange, originalText);
this.dispatchEventToListeners(WebInspector.TextEditorModel.Events.TextChanged, { oldRange: range, newRange: newRange });
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]);
this._insertLines(range, newLines);
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);
},


_insertLines: function(range, newLines)
{
var lines = new Array(this._lines.length + newLines.length - 1);
for (var i = 0; i <= range.startLine; ++i)
lines[i] = this._lines[i];

for (var i = 1; i < newLines.length; ++i)
lines[range.startLine + i] = newLines[i];
for (var i = range.startLine + newLines.length; i < lines.length; ++i)
lines[i] = this._lines[i - newLines.length + 1];
this._lines = lines;


var attributes = new Array(lines.length);
var insertionIndex = range.startColumn ? range.startLine + 1 : range.startLine;
for (var i = 0; i < insertionIndex; ++i)
attributes[i] = this._attributes[i];
for (var i = insertionIndex + newLines.length - 1; i < attributes.length; ++i)
attributes[i] = this._attributes[i - newLines.length + 1];
this._attributes = attributes;
},


_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._lines.splice(range.startLine + 1, range.endLine - range.startLine);

this._attributes.splice(range.startColumn ? range.startLine + 1 : range.startLine, range.endLine - range.startLine);
}
this._setLine(range.startLine, prefix + suffix);
},


_setLine: function(lineNumber, text)
{
this._lines[lineNumber] = text;
},


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(newRange, originalText)
{
var command = new WebInspector.TextEditorCommand(newRange.clone(), originalText);
if (this._inUndo)
this._redoStack.push(command);
else {
if (!this._inRedo)
this._redoStack = [];
this._undoStack.push(command);
}
return command;
},


undo: function(beforeCallback, afterCallback)
{
if (!this._undoStack.length)
return null;

this._markRedoableState();

this._inUndo = true;
var range = this._doUndo(this._undoStack, beforeCallback, afterCallback);
delete this._inUndo;

return range;
},


redo: function(beforeCallback, afterCallback)
{
if (!this._redoStack || !this._redoStack.length)
return null;
this.markUndoableState();

this._inRedo = true;
var range = this._doUndo(this._redoStack, beforeCallback, afterCallback);
delete this._inRedo;

return range;
},


_doUndo: function(stack, beforeCallback, afterCallback)
{
var range = null;
for (var i = stack.length - 1; i >= 0; --i) {
var command = stack[i];
stack.length = i;

if (beforeCallback)
beforeCallback();

range = this.editRange(command.newRange, command.originalText);

if (afterCallback)
afterCallback(command.newRange, 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.TextEditorModel.prototype.__proto__ = WebInspector.Object.prototype;

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._colorKeywords = WebInspector.CSSKeywordCompletions.colors();

this._valueKeywords = [
"above", "absolute", "activeborder", "activecaption", "afar", "after-white-space", "ahead", "alias", "all", "all-scroll",
"alternate", "always", "amharic", "amharic-abegede", "antialiased", "appworkspace", "arabic-indic", "armenian", "asterisks",
"auto", "avoid", "background", "backwards", "baseline", "below", "bidi-override", "binary", "bengali", "blink",
"block", "block-axis", "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", "geometricPrecision",
"georgian", "graytext", "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", "line-through", "linear", "lines",
"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", "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", "open-quote", "optimizeLegibility",
"optimizeSpeed", "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",
"push-button", "radio", "read-only", "read-write", "read-write-plaintext-only", "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", "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", "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,
AT_MEDIA_RULE: 4
};

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 = 34; continue; };
if (yych <= '$') { gotoCase = 31; continue; };
if (yych >= '\'') { gotoCase = 35; continue; };
}
} else {
if (yych <= '.') {
if (yych <= ',') { gotoCase = 29; continue; };
if (yych <= '-') { gotoCase = 36; continue; };
{ gotoCase = 37; continue; };
} else {
if (yych <= '/') { gotoCase = 38; continue; };
if (yych <= '9') { gotoCase = 39; continue; };
if (yych <= ':') { gotoCase = 41; continue; };
{ gotoCase = 43; 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 = 45; continue; };
if (yych == '}') { gotoCase = 47; continue; };
}
}
}
case 29:
++cursor;
case 30:
{ this.tokenType = null; return cursor; }
case 31:
++cursor;
yych = this._charAt(cursor);
{ gotoCase = 50; continue; };
case 32:
{
var token = this._line.substring(cursorOnEnter, cursor);
if (this._condition.parseCondition === this._parseConditions.INITIAL) {
if (token === "@media") {
this.tokenType = "css-at-rule";
this._condition.parseCondition = this._parseConditions.AT_MEDIA_RULE;
} else if (token.startsWith("@")) {
this.tokenType = "css-at-rule";
this._condition.parseCondition = this._parseConditions.AT_RULE;
} else
this.tokenType = "css-selector";
} else if ((this._condition.parseCondition === this._parseConditions.AT_MEDIA_RULE || 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()) {
if (token in this._valueKeywords)
this.tokenType = "css-keyword";
else if (token in this._colorKeywords) {

this.tokenType = "css-color";
} 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 = 128; continue; };
} else {
if (yych <= '\r') { gotoCase = 32; continue; };
if (yych <= ' ') { gotoCase = 128; continue; };
{ gotoCase = 126; continue; };
}
} else {
if (yych <= '$') {
if (yych <= '"') { gotoCase = 115; continue; };
if (yych <= '#') { gotoCase = 128; continue; };
{ gotoCase = 126; continue; };
} else {
if (yych == '\'') { gotoCase = 126; continue; };
if (yych <= ',') { gotoCase = 128; continue; };
{ gotoCase = 126; continue; };
}
}
} else {
if (yych <= '[') {
if (yych <= '<') {
if (yych <= '.') { gotoCase = 128; continue; };
if (yych <= '9') { gotoCase = 126; continue; };
{ gotoCase = 128; continue; };
} else {
if (yych <= '=') { gotoCase = 126; continue; };
if (yych <= '?') { gotoCase = 128; continue; };
{ gotoCase = 126; continue; };
}
} else {
if (yych <= '^') {
if (yych <= '\\') { gotoCase = 130; continue; };
if (yych <= ']') { gotoCase = 126; continue; };
{ gotoCase = 128; continue; };
} else {
if (yych == '`') { gotoCase = 128; continue; };
if (yych <= 'z') { gotoCase = 126; continue; };
{ gotoCase = 128; continue; };
}
}
}
case 34:
yych = this._charAt(++cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 30; continue; };
if (yych <= '9') { gotoCase = 123; continue; };
{ gotoCase = 30; continue; };
} else {
if (yych <= 'F') { gotoCase = 123; continue; };
if (yych <= '`') { gotoCase = 30; continue; };
if (yych <= 'f') { gotoCase = 123; continue; };
{ gotoCase = 30; continue; };
}
case 35:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych <= '-') {
if (yych <= '"') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 32; continue; };
{ gotoCase = 117; continue; };
} else {
if (yych <= '\r') { gotoCase = 32; continue; };
if (yych <= ' ') { gotoCase = 117; continue; };
{ gotoCase = 113; continue; };
}
} else {
if (yych <= '&') {
if (yych == '$') { gotoCase = 113; continue; };
{ gotoCase = 117; continue; };
} else {
if (yych <= '\'') { gotoCase = 115; continue; };
if (yych <= ',') { gotoCase = 117; continue; };
{ gotoCase = 113; continue; };
}
}
} else {
if (yych <= '[') {
if (yych <= '<') {
if (yych <= '.') { gotoCase = 117; continue; };
if (yych <= '9') { gotoCase = 113; continue; };
{ gotoCase = 117; continue; };
} else {
if (yych <= '=') { gotoCase = 113; continue; };
if (yych <= '?') { gotoCase = 117; continue; };
{ gotoCase = 113; continue; };
}
} else {
if (yych <= '^') {
if (yych <= '\\') { gotoCase = 119; continue; };
if (yych <= ']') { gotoCase = 113; continue; };
{ gotoCase = 117; continue; };
} else {
if (yych == '`') { gotoCase = 117; continue; };
if (yych <= 'z') { gotoCase = 113; continue; };
{ gotoCase = 117; continue; };
}
}
}
case 36:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych == '.') { gotoCase = 66; continue; };
if (yych <= '/') { gotoCase = 50; continue; };
if (yych <= '9') { gotoCase = 51; continue; };
{ gotoCase = 50; continue; };
case 37:
yych = this._charAt(++cursor);
if (yych <= '/') { gotoCase = 30; continue; };
if (yych <= '9') { gotoCase = 69; continue; };
{ gotoCase = 30; continue; };
case 38:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
if (yych == '*') { gotoCase = 105; continue; };
{ gotoCase = 50; continue; };
case 39:
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 = 49; continue; };
case '%':    { gotoCase = 68; continue; };
case '.':    { gotoCase = 66; continue; };
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':    { gotoCase = 51; continue; };
case 'H':    { gotoCase = 53; continue; };
case '_':    { gotoCase = 54; continue; };
case 'c':    { gotoCase = 55; continue; };
case 'd':    { gotoCase = 56; continue; };
case 'e':    { gotoCase = 57; continue; };
case 'g':    { gotoCase = 58; continue; };
case 'i':    { gotoCase = 59; continue; };
case 'k':    { gotoCase = 60; continue; };
case 'm':    { gotoCase = 61; continue; };
case 'p':    { gotoCase = 62; continue; };
case 'r':    { gotoCase = 63; continue; };
case 's':    { gotoCase = 64; continue; };
case 't':    { gotoCase = 65; continue; };
default:    { gotoCase = 40; continue; };
}
case 40:
{
if (this._isPropertyValue())
this.tokenType = "css-number";
else
this.tokenType = null;
return cursor;
}
case 41:
++cursor;
{
this.tokenType = null;
if (this._condition.parseCondition === this._parseConditions.PROPERTY)
this._condition.parseCondition = this._parseConditions.PROPERTY_VALUE;
return cursor;
}
case 43:
++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 45:
++cursor;
{
this.tokenType = null;
if (this._condition.parseCondition === this._parseConditions.AT_MEDIA_RULE)
this._condition.parseCondition = this._parseConditions.INITIAL;
else
this._condition.parseCondition = this._parseConditions.PROPERTY;
return cursor;
}
case 47:
++cursor;
{
this.tokenType = null;
this._condition.parseCondition = this._parseConditions.INITIAL;
return cursor;
}
case 49:
++cursor;
yych = this._charAt(cursor);
case 50:
if (yych <= '9') {
if (yych <= '&') {
if (yych <= '"') {
if (yych <= ' ') { gotoCase = 32; continue; };
{ gotoCase = 49; continue; };
} else {
if (yych == '$') { gotoCase = 49; continue; };
{ gotoCase = 32; continue; };
}
} else {
if (yych <= ',') {
if (yych <= '\'') { gotoCase = 49; continue; };
{ gotoCase = 32; continue; };
} else {
if (yych == '.') { gotoCase = 32; continue; };
{ gotoCase = 49; continue; };
}
}
} else {
if (yych <= '\\') {
if (yych <= '=') {
if (yych <= '<') { gotoCase = 32; continue; };
{ gotoCase = 49; continue; };
} else {
if (yych <= '?') { gotoCase = 32; continue; };
if (yych <= '[') { gotoCase = 49; continue; };
{ gotoCase = 32; continue; };
}
} else {
if (yych <= '_') {
if (yych == '^') { gotoCase = 32; continue; };
{ gotoCase = 49; continue; };
} else {
if (yych <= '`') { gotoCase = 32; continue; };
if (yych <= 'z') { gotoCase = 49; continue; };
{ gotoCase = 32; continue; };
}
}
}
case 51:
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 = 49; continue; };
case '%':    { gotoCase = 68; continue; };
case '.':    { gotoCase = 66; continue; };
case '0':
case '1':
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':    { gotoCase = 51; continue; };
case 'H':    { gotoCase = 53; continue; };
case '_':    { gotoCase = 54; continue; };
case 'c':    { gotoCase = 55; continue; };
case 'd':    { gotoCase = 56; continue; };
case 'e':    { gotoCase = 57; continue; };
case 'g':    { gotoCase = 58; continue; };
case 'i':    { gotoCase = 59; continue; };
case 'k':    { gotoCase = 60; continue; };
case 'm':    { gotoCase = 61; continue; };
case 'p':    { gotoCase = 62; continue; };
case 'r':    { gotoCase = 63; continue; };
case 's':    { gotoCase = 64; continue; };
case 't':    { gotoCase = 65; continue; };
default:    { gotoCase = 40; continue; };
}
case 53:
yych = this._charAt(++cursor);
if (yych == 'z') { gotoCase = 64; continue; };
{ gotoCase = 50; continue; };
case 54:
yych = this._charAt(++cursor);
if (yych == '_') { gotoCase = 102; continue; };
{ gotoCase = 50; continue; };
case 55:
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 64; continue; };
{ gotoCase = 50; continue; };
case 56:
yych = this._charAt(++cursor);
if (yych == 'e') { gotoCase = 101; continue; };
{ gotoCase = 50; continue; };
case 57:
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 64; continue; };
if (yych == 'x') { gotoCase = 64; continue; };
{ gotoCase = 50; continue; };
case 58:
yych = this._charAt(++cursor);
if (yych == 'r') { gotoCase = 99; continue; };
{ gotoCase = 50; continue; };
case 59:
yych = this._charAt(++cursor);
if (yych == 'n') { gotoCase = 64; continue; };
{ gotoCase = 50; continue; };
case 60:
yych = this._charAt(++cursor);
if (yych == 'H') { gotoCase = 98; continue; };
{ gotoCase = 50; continue; };
case 61:
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 64; continue; };
if (yych == 's') { gotoCase = 64; continue; };
{ gotoCase = 50; continue; };
case 62:
yych = this._charAt(++cursor);
if (yych <= 's') {
if (yych == 'c') { gotoCase = 64; continue; };
{ gotoCase = 50; continue; };
} else {
if (yych <= 't') { gotoCase = 64; continue; };
if (yych == 'x') { gotoCase = 64; continue; };
{ gotoCase = 50; continue; };
}
case 63:
yych = this._charAt(++cursor);
if (yych == 'a') { gotoCase = 96; continue; };
if (yych == 'e') { gotoCase = 97; continue; };
{ gotoCase = 50; continue; };
case 64:
yych = this._charAt(++cursor);
if (yych <= '9') {
if (yych <= '&') {
if (yych <= '"') {
if (yych <= ' ') { gotoCase = 40; continue; };
{ gotoCase = 49; continue; };
} else {
if (yych == '$') { gotoCase = 49; continue; };
{ gotoCase = 40; continue; };
}
} else {
if (yych <= ',') {
if (yych <= '\'') { gotoCase = 49; continue; };
{ gotoCase = 40; continue; };
} else {
if (yych == '.') { gotoCase = 40; continue; };
{ gotoCase = 49; continue; };
}
}
} else {
if (yych <= '\\') {
if (yych <= '=') {
if (yych <= '<') { gotoCase = 40; continue; };
{ gotoCase = 49; continue; };
} else {
if (yych <= '?') { gotoCase = 40; continue; };
if (yych <= '[') { gotoCase = 49; continue; };
{ gotoCase = 40; continue; };
}
} else {
if (yych <= '_') {
if (yych == '^') { gotoCase = 40; continue; };
{ gotoCase = 49; continue; };
} else {
if (yych <= '`') { gotoCase = 40; continue; };
if (yych <= 'z') { gotoCase = 49; continue; };
{ gotoCase = 40; continue; };
}
}
}
case 65:
yych = this._charAt(++cursor);
if (yych == 'u') { gotoCase = 94; continue; };
{ gotoCase = 50; continue; };
case 66:
yych = this._charAt(++cursor);
if (yych <= '/') { gotoCase = 67; continue; };
if (yych <= '9') { gotoCase = 69; continue; };
case 67:
cursor = YYMARKER;
if (yyaccept <= 0) {
{ gotoCase = 32; continue; };
} else {
{ gotoCase = 40; continue; };
}
case 68:
yych = this._charAt(++cursor);
{ gotoCase = 40; continue; };
case 69:
yyaccept = 1;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych <= 'f') {
if (yych <= 'H') {
if (yych <= '/') {
if (yych == '%') { gotoCase = 68; continue; };
{ gotoCase = 40; continue; };
} else {
if (yych <= '9') { gotoCase = 69; continue; };
if (yych <= 'G') { gotoCase = 40; continue; };
{ gotoCase = 81; continue; };
}
} else {
if (yych <= 'b') {
if (yych == '_') { gotoCase = 73; continue; };
{ gotoCase = 40; continue; };
} else {
if (yych <= 'c') { gotoCase = 75; continue; };
if (yych <= 'd') { gotoCase = 78; continue; };
if (yych >= 'f') { gotoCase = 40; continue; };
}
}
} else {
if (yych <= 'm') {
if (yych <= 'i') {
if (yych <= 'g') { gotoCase = 79; continue; };
if (yych <= 'h') { gotoCase = 40; continue; };
{ gotoCase = 77; continue; };
} else {
if (yych == 'k') { gotoCase = 82; continue; };
if (yych <= 'l') { gotoCase = 40; continue; };
{ gotoCase = 76; continue; };
}
} else {
if (yych <= 'q') {
if (yych == 'p') { gotoCase = 74; continue; };
{ gotoCase = 40; continue; };
} else {
if (yych <= 'r') { gotoCase = 72; continue; };
if (yych <= 's') { gotoCase = 68; continue; };
if (yych <= 't') { gotoCase = 80; continue; };
{ gotoCase = 40; continue; };
}
}
}
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 68; continue; };
if (yych == 'x') { gotoCase = 68; continue; };
{ gotoCase = 67; continue; };
case 72:
yych = this._charAt(++cursor);
if (yych == 'a') { gotoCase = 92; continue; };
if (yych == 'e') { gotoCase = 93; continue; };
{ gotoCase = 67; continue; };
case 73:
yych = this._charAt(++cursor);
if (yych == '_') { gotoCase = 89; continue; };
{ gotoCase = 67; continue; };
case 74:
yych = this._charAt(++cursor);
if (yych <= 's') {
if (yych == 'c') { gotoCase = 68; continue; };
{ gotoCase = 67; continue; };
} else {
if (yych <= 't') { gotoCase = 68; continue; };
if (yych == 'x') { gotoCase = 68; continue; };
{ gotoCase = 67; continue; };
}
case 75:
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 68; continue; };
{ gotoCase = 67; continue; };
case 76:
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 68; continue; };
if (yych == 's') { gotoCase = 68; continue; };
{ gotoCase = 67; continue; };
case 77:
yych = this._charAt(++cursor);
if (yych == 'n') { gotoCase = 68; continue; };
{ gotoCase = 67; continue; };
case 78:
yych = this._charAt(++cursor);
if (yych == 'e') { gotoCase = 88; continue; };
{ gotoCase = 67; continue; };
case 79:
yych = this._charAt(++cursor);
if (yych == 'r') { gotoCase = 86; continue; };
{ gotoCase = 67; continue; };
case 80:
yych = this._charAt(++cursor);
if (yych == 'u') { gotoCase = 84; continue; };
{ gotoCase = 67; continue; };
case 81:
yych = this._charAt(++cursor);
if (yych == 'z') { gotoCase = 68; continue; };
{ gotoCase = 67; continue; };
case 82:
yych = this._charAt(++cursor);
if (yych != 'H') { gotoCase = 67; continue; };
yych = this._charAt(++cursor);
if (yych == 'z') { gotoCase = 68; continue; };
{ gotoCase = 67; continue; };
case 84:
yych = this._charAt(++cursor);
if (yych != 'r') { gotoCase = 67; continue; };
yych = this._charAt(++cursor);
if (yych == 'n') { gotoCase = 68; continue; };
{ gotoCase = 67; continue; };
case 86:
yych = this._charAt(++cursor);
if (yych != 'a') { gotoCase = 67; continue; };
yych = this._charAt(++cursor);
if (yych == 'd') { gotoCase = 68; continue; };
{ gotoCase = 67; continue; };
case 88:
yych = this._charAt(++cursor);
if (yych == 'g') { gotoCase = 68; continue; };
{ gotoCase = 67; continue; };
case 89:
yych = this._charAt(++cursor);
if (yych != 'q') { gotoCase = 67; continue; };
yych = this._charAt(++cursor);
if (yych != 'e') { gotoCase = 67; continue; };
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 68; continue; };
{ gotoCase = 67; continue; };
case 92:
yych = this._charAt(++cursor);
if (yych == 'd') { gotoCase = 68; continue; };
{ gotoCase = 67; continue; };
case 93:
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 68; continue; };
{ gotoCase = 67; continue; };
case 94:
yych = this._charAt(++cursor);
if (yych != 'r') { gotoCase = 50; continue; };
yych = this._charAt(++cursor);
if (yych == 'n') { gotoCase = 64; continue; };
{ gotoCase = 50; continue; };
case 96:
yych = this._charAt(++cursor);
if (yych == 'd') { gotoCase = 64; continue; };
{ gotoCase = 50; continue; };
case 97:
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 64; continue; };
{ gotoCase = 50; continue; };
case 98:
yych = this._charAt(++cursor);
if (yych == 'z') { gotoCase = 64; continue; };
{ gotoCase = 50; continue; };
case 99:
yych = this._charAt(++cursor);
if (yych != 'a') { gotoCase = 50; continue; };
yych = this._charAt(++cursor);
if (yych == 'd') { gotoCase = 64; continue; };
{ gotoCase = 50; continue; };
case 101:
yych = this._charAt(++cursor);
if (yych == 'g') { gotoCase = 64; continue; };
{ gotoCase = 50; continue; };
case 102:
yych = this._charAt(++cursor);
if (yych != 'q') { gotoCase = 50; continue; };
yych = this._charAt(++cursor);
if (yych != 'e') { gotoCase = 50; continue; };
yych = this._charAt(++cursor);
if (yych == 'm') { gotoCase = 64; continue; };
{ gotoCase = 50; continue; };
case 105:
++cursor;
yych = this._charAt(cursor);
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 109; continue; };
{ gotoCase = 105; continue; };
} else {
if (yych <= '\r') { gotoCase = 109; continue; };
if (yych != '*') { gotoCase = 105; continue; };
}
case 107:
++cursor;
yych = this._charAt(cursor);
if (yych == '*') { gotoCase = 107; continue; };
if (yych == '/') { gotoCase = 111; continue; };
{ gotoCase = 105; continue; };
case 109:
++cursor;
this.setLexCondition(this._lexConditions.COMMENT);
{ this.tokenType = "css-comment"; return cursor; }
case 111:
++cursor;
{ this.tokenType = "css-comment"; return cursor; }
case 113:
yyaccept = 0;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
if (yych <= '-') {
if (yych <= '"') {
if (yych <= '\f') {
if (yych == '\n') { gotoCase = 32; continue; };
{ gotoCase = 117; continue; };
} else {
if (yych <= '\r') { gotoCase = 32; continue; };
if (yych <= ' ') { gotoCase = 117; continue; };
{ gotoCase = 113; continue; };
}
} else {
if (yych <= '&') {
if (yych == '$') { gotoCase = 113; continue; };
{ gotoCase = 117; continue; };
} else {
if (yych <= '\'') { gotoCase = 115; continue; };
if (yych <= ',') { gotoCase = 117; continue; };
{ gotoCase = 113; continue; };
}
}
} else {
if (yych <= '[') {
if (yych <= '<') {
if (yych <= '.') { gotoCase = 117; continue; };
if (yych <= '9') { gotoCase = 113; continue; };
{ gotoCase = 117; continue; };
} else {
if (yych <= '=') { gotoCase = 113; continue; };
if (yych <= '?') { gotoCase = 117; continue; };
{ gotoCase = 113; continue; };
}
} else {
if (yych <= '^') {
if (yych <= '\\') { gotoCase = 119; continue; };
if (yych <= ']') { gotoCase = 113; continue; };
{ gotoCase = 117; continue; };
} else {
if (yych == '`') { gotoCase = 117; continue; };
if (yych <= 'z') { gotoCase = 113; continue; };
{ gotoCase = 117; continue; };
}
}
}
case 115:
++cursor;
if ((yych = this._charAt(cursor)) <= '9') {
if (yych <= '&') {
if (yych <= '"') {
if (yych >= '!') { gotoCase = 49; continue; };
} else {
if (yych == '$') { gotoCase = 49; continue; };
}
} else {
if (yych <= ',') {
if (yych <= '\'') { gotoCase = 49; continue; };
} else {
if (yych != '.') { gotoCase = 49; continue; };
}
}
} else {
if (yych <= '\\') {
if (yych <= '=') {
if (yych >= '=') { gotoCase = 49; continue; };
} else {
if (yych <= '?') { gotoCase = 116; continue; };
if (yych <= '[') { gotoCase = 49; continue; };
}
} else {
if (yych <= '_') {
if (yych != '^') { gotoCase = 49; continue; };
} else {
if (yych <= '`') { gotoCase = 116; continue; };
if (yych <= 'z') { gotoCase = 49; continue; };
}
}
}
case 116:
{ return this._stringToken(cursor, true); }
case 117:
++cursor;
yych = this._charAt(cursor);
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 67; continue; };
if (yych <= '\f') { gotoCase = 117; continue; };
{ gotoCase = 67; continue; };
} else {
if (yych <= '\'') {
if (yych <= '&') { gotoCase = 117; continue; };
{ gotoCase = 122; continue; };
} else {
if (yych != '\\') { gotoCase = 117; continue; };
}
}
case 119:
++cursor;
yych = this._charAt(cursor);
if (yych <= 'a') {
if (yych <= '!') {
if (yych <= '\n') {
if (yych <= '\t') { gotoCase = 67; continue; };
} else {
if (yych != '\r') { gotoCase = 67; continue; };
}
} else {
if (yych <= '\'') {
if (yych <= '"') { gotoCase = 117; continue; };
if (yych <= '&') { gotoCase = 67; continue; };
{ gotoCase = 117; continue; };
} else {
if (yych == '\\') { gotoCase = 117; continue; };
{ gotoCase = 67; continue; };
}
}
} else {
if (yych <= 'q') {
if (yych <= 'f') {
if (yych <= 'b') { gotoCase = 117; continue; };
if (yych <= 'e') { gotoCase = 67; continue; };
{ gotoCase = 117; continue; };
} else {
if (yych == 'n') { gotoCase = 117; continue; };
{ gotoCase = 67; continue; };
}
} else {
if (yych <= 't') {
if (yych == 's') { gotoCase = 67; continue; };
{ gotoCase = 117; continue; };
} else {
if (yych == 'v') { gotoCase = 117; continue; };
{ gotoCase = 67; continue; };
}
}
}
++cursor;
this.setLexCondition(this._lexConditions.SSTRING);
{ return this._stringToken(cursor); }
case 122:
yych = this._charAt(++cursor);
{ gotoCase = 116; continue; };
case 123:
++cursor;
yych = this._charAt(cursor);
if (yych <= '@') {
if (yych <= '/') { gotoCase = 125; continue; };
if (yych <= '9') { gotoCase = 123; continue; };
} else {
if (yych <= 'F') { gotoCase = 123; continue; };
if (yych <= '`') { gotoCase = 125; continue; };
if (yych <= 'f') { gotoCase = 123; continue; };
}
case 125:
{
if (this._isPropertyValue())
this.tokenType = "css-color";
else
this.tokenType = null;
return cursor;
}
case 126:
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 = 126; continue; };
}
} else {
if (yych <= '$') {
if (yych <= '"') { gotoCase = 115; continue; };
if (yych >= '$') { gotoCase = 126; continue; };
} else {
if (yych == '\'') { gotoCase = 126; continue; };
if (yych >= '-') { gotoCase = 126; continue; };
}
}
} else {
if (yych <= '[') {
if (yych <= '<') {
if (yych <= '.') { gotoCase = 128; continue; };
if (yych <= '9') { gotoCase = 126; continue; };
} else {
if (yych <= '=') { gotoCase = 126; continue; };
if (yych >= '@') { gotoCase = 126; continue; };
}
} else {
if (yych <= '^') {
if (yych <= '\\') { gotoCase = 130; continue; };
if (yych <= ']') { gotoCase = 126; continue; };
} else {
if (yych == '`') { gotoCase = 128; continue; };
if (yych <= 'z') { gotoCase = 126; continue; };
}
}
}
case 128:
++cursor;
yych = this._charAt(cursor);
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 67; continue; };
if (yych <= '\f') { gotoCase = 128; continue; };
{ gotoCase = 67; continue; };
} else {
if (yych <= '"') {
if (yych <= '!') { gotoCase = 128; continue; };
{ gotoCase = 122; continue; };
} else {
if (yych != '\\') { gotoCase = 128; continue; };
}
}
case 130:
++cursor;
yych = this._charAt(cursor);
if (yych <= 'a') {
if (yych <= '!') {
if (yych <= '\n') {
if (yych <= '\t') { gotoCase = 67; continue; };
} else {
if (yych != '\r') { gotoCase = 67; continue; };
}
} else {
if (yych <= '\'') {
if (yych <= '"') { gotoCase = 128; continue; };
if (yych <= '&') { gotoCase = 67; continue; };
{ gotoCase = 128; continue; };
} else {
if (yych == '\\') { gotoCase = 128; continue; };
{ gotoCase = 67; continue; };
}
}
} else {
if (yych <= 'q') {
if (yych <= 'f') {
if (yych <= 'b') { gotoCase = 128; continue; };
if (yych <= 'e') { gotoCase = 67; continue; };
{ gotoCase = 128; continue; };
} else {
if (yych == 'n') { gotoCase = 128; continue; };
{ gotoCase = 67; continue; };
}
} else {
if (yych <= 't') {
if (yych == 's') { gotoCase = 67; continue; };
{ gotoCase = 128; continue; };
} else {
if (yych == 'v') { gotoCase = 128; continue; };
{ gotoCase = 67; 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 = 137; continue; };
if (yych <= '\f') { gotoCase = 136; continue; };
{ gotoCase = 137; continue; };
} else {
if (yych <= '\'') {
if (yych <= '&') { gotoCase = 136; continue; };
{ gotoCase = 139; continue; };
} else {
if (yych == '\\') { gotoCase = 141; continue; };
{ gotoCase = 136; continue; };
}
}
case 135:
{ return this._stringToken(cursor); }
case 136:
yyaccept = 0;
yych = this._charAt(YYMARKER = ++cursor);
{ gotoCase = 143; continue; };
case 137:
++cursor;
case 138:
{ this.tokenType = null; return cursor; }
case 139:
++cursor;
case 140:
this.setLexCondition(this._lexConditions.INITIAL);
{ return this._stringToken(cursor, true); }
case 141:
yych = this._charAt(++cursor);
if (yych <= 'e') {
if (yych <= '\'') {
if (yych == '"') { gotoCase = 142; 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 >= 'g') { gotoCase = 138; continue; };
} else {
if (yych <= 'n') { gotoCase = 142; continue; };
if (yych <= 'q') { gotoCase = 138; continue; };
}
} else {
if (yych <= 't') {
if (yych <= 's') { gotoCase = 138; continue; };
} else {
if (yych != 'v') { gotoCase = 138; continue; };
}
}
}
case 142:
yyaccept = 0;
YYMARKER = ++cursor;
yych = this._charAt(cursor);
case 143:
if (yych <= '\r') {
if (yych == '\n') { gotoCase = 135; continue; };
if (yych <= '\f') { gotoCase = 142; continue; };
{ gotoCase = 135; continue; };
} else {
if (yych <= '\'') {
if (yych <= '&') { gotoCase = 142; continue; };
{ gotoCase = 146; continue; };
} else {
if (yych != '\\') { gotoCase = 142; continue; };
}
}
++cursor;
yych = this._charAt(cursor);
if (yych <= 'e') {
if (yych <= '\'') {
if (yych == '"') { gotoCase = 142; continue; };
if (yych >= '\'') { gotoCase = 142; continue; };
} else {
if (yych <= '\\') {
if (yych >= '\\') { gotoCase = 142; continue; };
} else {
if (yych == 'b') { gotoCase = 142; continue; };
}
}
} else {
if (yych <= 'r') {
if (yych <= 'm') {
if (yych <= 'f') { gotoCase = 142; continue; };
} else {
if (yych <= 'n') { gotoCase = 142; continue; };
if (yych >= 'r') { gotoCase = 142; continue; };
}
} else {
if (yych <= 't') {
if (yych >= 't') { gotoCase = 142; continue; };
} else {
if (yych == 'v') { gotoCase = 142; continue; };
}
}
}
cursor = YYMARKER;
{ gotoCase = 135; continue; };
case 146:
++cursor;
yych = this._charAt(cursor);
{ gotoCase = 140; 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._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.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();

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 (WebInspector.SourceJavaScriptTokenizer.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 (WebInspector.SourceJavaScriptTokenizer.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)
{
InspectorFrontendHost.openInNewTab(this.resource.url);
}
}

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


_escapeTableName: function(tableName)
{
return tableName.replace(/\"/g, "\"\"");
},

update: function()
{
this.database.executeSql("SELECT * FROM \"" + this._escapeTableName(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.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);

this.element.addEventListener("click", this._messagesClicked.bind(this), true);
}

WebInspector.DatabaseQueryView.Events = {
SchemaUpdated: "SchemaUpdated"
}

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

completions: function(textPrompt, 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.startsWith(prefix))
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.consume(true);

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 (typeof error === "string")
var message = error;
else 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.ProfileLauncherView = function(profilesPanel)
{
WebInspector.View.call(this);

this._panel = profilesPanel;
this._profileRunning = false;
this._optionIdPrefix = "profile-type-";

this.element.addStyleClass("profile-launcher-view");
this.element.addStyleClass("panel-enabler-view");

this._contentElement = document.createElement("div");
this._contentElement.className = "profile-launcher-view-content";
this.element.appendChild(this._contentElement);

var header = this._contentElement.createChild("h1");
header.textContent = WebInspector.UIString("Select profiling type");

this._profileTypeSelectorForm = this._contentElement.createChild("form");
this._contentElement.createChild("div", "flexible-space");

this._boundProfileTypeChangeListener = this._profileTypeChanged.bind(this);

this._controlButton = this._contentElement.createChild("button", "control-profiling");
this._controlButton.addEventListener("click", this._controlButtonClicked.bind(this), false);
this._updateControls();
}

WebInspector.ProfileLauncherView.EventTypes = {
ProfileTypeSelected: "profile-type-selected"
}

WebInspector.ProfileLauncherView.prototype = {
setUpEventListeners: function()
{
this._panel.addEventListener(WebInspector.ProfilesPanel.EventTypes.ProfileStarted, this._onProfileStarted, this);
this._panel.addEventListener(WebInspector.ProfilesPanel.EventTypes.ProfileFinished, this._onProfileFinished, this);
},

addProfileType: function(profileType)
{
var checked = !this._profileTypeSelectorForm.children.length;
var labelElement = this._profileTypeSelectorForm.createChild("label");
labelElement.textContent = profileType.name;
var optionElement = document.createElement("input");
labelElement.insertBefore(optionElement, labelElement.firstChild);
optionElement.type = "radio";
optionElement.name = "profile-type";
var optionId = this._optionIdPrefix + profileType.id;
optionElement.id = optionId;
if (checked) {
optionElement.checked = checked;
this.dispatchEventToListeners(WebInspector.ProfileLauncherView.EventTypes.ProfileTypeSelected, profileType);
}
optionElement.addEventListener("change", this._boundProfileTypeChangeListener, false);
var descriptionElement = labelElement.createChild("p");
descriptionElement.textContent = profileType.description;
},

_controlButtonClicked: function()
{
this._panel.toggleRecordButton();
},

_updateControls: function()
{
if (this._isProfiling) {
this._profileTypeSelectorForm.disabled = true;
this._controlButton.addStyleClass("running");
this._controlButton.textContent = WebInspector.UIString("Stop");
} else {
this._profileTypeSelectorForm.disabled = false;
this._controlButton.removeStyleClass("running");
this._controlButton.textContent = WebInspector.UIString("Start");
}
},

_profileTypeChanged: function(event)
{
var selectedProfileType = this._panel.getProfileType(event.target.id.substring(this._optionIdPrefix.length));
this.dispatchEventToListeners(WebInspector.ProfileLauncherView.EventTypes.ProfileTypeSelected, selectedProfileType);
},

_onProfileStarted: function(event)
{
this._isProfiling = true;
this._updateControls();
},

_onProfileFinished: function(event)
{
this._isProfiling = false;
this._updateControls();
}
}

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

WebInspector.ProfileDataGridTree.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(this.profileNode);
},

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


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


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


var any =  this;
var node =  any;
WebInspector.BottomUpProfileDataGridNode.prototype._populate.call(node);

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;

var any =  this;
var node =  any;
WebInspector.TopDownProfileDataGridNode.prototype._populate.call(node);
}

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;

var any =  this;
var node =  any;
WebInspector.TopDownProfileDataGridNode.prototype._exclude.call(node, 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._sortProfile, 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, this);

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

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

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

this.profile = profile;

function profileCallback(error, profile)
{
if (error)
return;

if (!profile.head) {

return;
}
this.profile.head = profile.head;
this._assignParentsInProfile();
this._changeView();
this._updatePercentButton();
}

this._linkifier = new WebInspector.Linkifier(new WebInspector.Linkifier.DefaultFormatter(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();
},

willHide: function()
{
this._currentSearchResultIndex = -1;
},

refresh: function()
{
var selectedProfileNode = this.dataGrid.selectedNode ? this.dataGrid.selectedNode.profileNode : null;

this.dataGrid.rootNode().removeChildren();

var children = this.profileDataGridTree.children;
var count = children.length;

for (var index = 0; index < count; ++index)
this.dataGrid.rootNode().appendChild(children[index]);

if (selectedProfileNode)
selectedProfileNode.selected = true;
},

refreshVisibleData: function()
{
var child = this.dataGrid.rootNode().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.startsWith(">"));
var lessThan = (query.startsWith("<"));
var equalTo = (query.startsWith("=") || ((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;
},

_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.consume(true);
},

_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("Collect JavaScript CPU Profile"));
this._recording = false;
WebInspector.CPUProfileType.instance = this;
}

WebInspector.CPUProfileType.TypeId = "CPU";

WebInspector.CPUProfileType.prototype = {
get buttonTooltip()
{
return this._recording ? WebInspector.UIString("Stop CPU profiling.") : WebInspector.UIString("Start CPU profiling.");
},

buttonClicked: function()
{
if (this._recording) {
this.stopRecordingProfile();
WebInspector.networkManager.enableResourceTracking();
} else {
WebInspector.networkManager.disableResourceTracking();
this.startRecordingProfile();
}
},

get treeItemTitle()
{
return WebInspector.UIString("CPU PROFILES");
},

get description()
{
return WebInspector.UIString("CPU profiles show where the execution time is spent in your page's JavaScript functions.");
},

isRecordingProfile: function()
{
return this._recording;
},

startRecordingProfile: function()
{
this._recording = true;
WebInspector.userMetrics.ProfilesCPUProfileTaken.record();
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);
},

createTemporaryProfile: function()
{
return new WebInspector.ProfileHeader(WebInspector.CPUProfileType.TypeId, WebInspector.UIString("Recording\u2026"));
},

createProfile: function(profile)
{
return new WebInspector.ProfileHeader(profile.typeId, profile.title, profile.uid);
}
}

WebInspector.CPUProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype;






WebInspector.CSSSelectorDataGridNode = function(profileView, data)
{
WebInspector.DataGridNode.call(this, data, false);
this._profileView = profileView;
}

WebInspector.CSSSelectorDataGridNode.prototype = {
get data()
{
var data = {};
data.selector = this._data.selector;
data.matches = this._data.matchCount;

if (this._profileView.showTimeAsPercent.get())
data.time = Number(this._data.timePercent).toFixed(1) + "%";
else
data.time = Number.secondsToString(this._data.time / 1000, true);

return data;
},

get rawData()
{
return this._data;
},

createCell: function(columnIdentifier)
{
var cell = WebInspector.DataGridNode.prototype.createCell.call(this, columnIdentifier);
if (columnIdentifier === "selector" && cell.firstChild) {
cell.firstChild.title = this.rawData.selector;
return cell;
}

if (columnIdentifier !== "source")
return cell;

cell.removeChildren();

if (this.rawData.url) {
var wrapperDiv = cell.createChild("div");
wrapperDiv.appendChild(WebInspector.linkifyResourceAsNode(this.rawData.url, this.rawData.lineNumber));
}

return cell;
}
}

WebInspector.CSSSelectorDataGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;


WebInspector.CSSSelectorProfileView = function(profile)
{
WebInspector.View.call(this);

this.element.addStyleClass("profile-view");

this.showTimeAsPercent = WebInspector.settings.createSetting("selectorProfilerShowTimeAsPercent", true);

var columns = { "selector": { title: WebInspector.UIString("Selector"), width: "550px", sortable: true },
"source": { title: WebInspector.UIString("Source"), width: "100px", sortable: true },
"time": { title: WebInspector.UIString("Total"), width: "72px", sort: "descending", sortable: true },
"matches": { title: WebInspector.UIString("Matches"), width: "72px", sortable: true } };

this.dataGrid = new WebInspector.DataGrid(columns);
this.dataGrid.element.addStyleClass("selector-profile-view");
this.dataGrid.addEventListener("sorting changed", this._sortProfile, this);
this.dataGrid.element.addEventListener("mousedown", this._mouseDownInDataGrid.bind(this), true);
this.dataGrid.show(this.element);

this.percentButton = new WebInspector.StatusBarButton("", "percent-time-status-bar-item");
this.percentButton.addEventListener("click", this._percentClicked, this);

this.profile = profile;

this._createProfileNodes();
this._sortProfile();
this._updatePercentButton();
}

WebInspector.CSSSelectorProfileView.prototype = {
get statusBarItems()
{
return [this.percentButton.element];
},

get profile()
{
return this._profile;
},

set profile(profile)
{
this._profile = profile;
},

_createProfileNodes: function()
{
var data = this.profile.data;
if (!data) {

return;
}

this.profile.children = [];
for (var i = 0; i < data.length; ++i) {
data[i].timePercent = data[i].time * 100 / this.profile.totalTime;
var node = new WebInspector.CSSSelectorDataGridNode(this, data[i]);
this.profile.children.push(node);
}
},

rebuildGridItems: function()
{
this.dataGrid.rootNode().removeChildren();

var children = this.profile.children;
var count = children.length;

for (var index = 0; index < count; ++index)
this.dataGrid.rootNode().appendChild(children[index]);
},

refreshData: function()
{
var child = this.dataGrid.rootNode().children[0];
while (child) {
child.refresh();
child = child.traverseNextNode(false, null, true);
}
},

refreshShowAsPercents: function()
{
this._updatePercentButton();
this.refreshData();
},

_percentClicked: function(event)
{
this.showTimeAsPercent.set(!this.showTimeAsPercent.get());
this.refreshShowAsPercents();
},

_updatePercentButton: function()
{
if (this.showTimeAsPercent.get()) {
this.percentButton.title = WebInspector.UIString("Show absolute times.");
this.percentButton.toggled = true;
} else {
this.percentButton.title = WebInspector.UIString("Show times as percentages.");
this.percentButton.toggled = false;
}
},

_sortProfile: function()
{
var sortAscending = this.dataGrid.sortOrder === "ascending";
var sortColumnIdentifier = this.dataGrid.sortColumnIdentifier;

function selectorComparator(a, b)
{
var result = b.rawData.selector.localeCompare(a.rawData.selector);
return sortAscending ? -result : result;
}

function sourceComparator(a, b)
{
var aRawData = a.rawData;
var bRawData = b.rawData;
var result = bRawData.url.localeCompare(aRawData.url);
if (!result)
result = bRawData.lineNumber - aRawData.lineNumber;
return sortAscending ? -result : result;
}

function timeComparator(a, b)
{
const result = b.rawData.time - a.rawData.time;
return sortAscending ? -result : result;
}

function matchesComparator(a, b)
{
const result = b.rawData.matchCount - a.rawData.matchCount;
return sortAscending ? -result : result;
}

var comparator;
switch (sortColumnIdentifier) {
case "time":
comparator = timeComparator;
break;
case "matches":
comparator = matchesComparator;
break;
case "selector":
comparator = selectorComparator;
break;
case "source":
comparator = sourceComparator;
break;
}

this.profile.children.sort(comparator);

this.rebuildGridItems();
},

_mouseDownInDataGrid: function(event)
{
if (event.detail < 2)
return;

var cell = event.target.enclosingNodeOrSelfWithNodeName("td");
if (!cell)
return;

if (cell.hasStyleClass("time-column"))
this.showTimeAsPercent.set(!this.showTimeAsPercent.get());
else
return;

this.refreshShowAsPercents();

event.consume(true);
}
}

WebInspector.CSSSelectorProfileView.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.CSSSelectorProfileType = function()
{
WebInspector.ProfileType.call(this, WebInspector.CSSSelectorProfileType.TypeId, WebInspector.UIString("Collect CSS Selector Profile"));
this._recording = false;
this._profileUid = 1;
WebInspector.CSSSelectorProfileType.instance = this;
}

WebInspector.CSSSelectorProfileType.TypeId = "SELECTOR";

WebInspector.CSSSelectorProfileType.prototype = {
get buttonTooltip()
{
return this._recording ? WebInspector.UIString("Stop CSS selector profiling.") : WebInspector.UIString("Start CSS selector profiling.");
},

buttonClicked: function()
{
if (this._recording)
this.stopRecordingProfile();
else
this.startRecordingProfile();
},

get treeItemTitle()
{
return WebInspector.UIString("CSS SELECTOR PROFILES");
},

get description()
{
return WebInspector.UIString("CSS selector profiles show how long the selector matching has taken in total and how many times a certain selector has matched DOM elements (the results are approximate due to matching algorithm optimizations.)");
},

reset: function()
{
this._profileUid = 1;
},

isRecordingProfile: function()
{
return this._recording;
},

setRecordingProfile: function(isProfiling)
{
this._recording = isProfiling;
},

startRecordingProfile: function()
{
this._recording = true;
CSSAgent.startSelectorProfiler();
WebInspector.panels.profiles.setRecordingProfile(WebInspector.CSSSelectorProfileType.TypeId, true);
},

stopRecordingProfile: function()
{
function callback(error, profile)
{
if (error)
return;

profile.uid = this._profileUid++;
profile.title = WebInspector.UIString("Profile %d", profile.uid) + String.sprintf(" (%s)", Number.secondsToString(profile.totalTime / 1000));
profile.typeId = WebInspector.CSSSelectorProfileType.TypeId;
WebInspector.panels.profiles.addProfileHeader(profile);
WebInspector.panels.profiles.setRecordingProfile(WebInspector.CSSSelectorProfileType.TypeId, false);
}

this._recording = false;
CSSAgent.stopSelectorProfiler(callback.bind(this));
},

createSidebarTreeElementForProfile: function(profile)
{
return new WebInspector.ProfileSidebarTreeElement(profile, profile.title, "profile-sidebar-tree-item");
},

createView: function(profile)
{
return new WebInspector.CSSSelectorProfileView(profile);
},

createTemporaryProfile: function()
{
return new WebInspector.ProfileHeader(WebInspector.CSSSelectorProfileType.TypeId, WebInspector.UIString("Recording\u2026"));
},

createProfile: function(profile)
{
return new WebInspector.ProfileHeader(profile.typeId, profile.title, profile.uid);
}
}

WebInspector.CSSSelectorProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype;






WebInspector.Uint32Array = function(size)
{
const preallocateSize = 1000;
size = size || preallocateSize;
this._usedSize = 0;
this._array = new Uint32Array(preallocateSize);
}

WebInspector.Uint32Array.prototype = {
push: function(value)
{
if (this._usedSize + 1 > this._array.length) {
var tempArray = new Uint32Array(this._array.length * 2);
tempArray.set(this._array);
this._array = tempArray;
}
this._array[this._usedSize++] = value;
},

get array()
{
return this._array.subarray(0, this._usedSize);
}
}


WebInspector.HeapSnapshotArraySlice = function(array, start, end)
{
this._array = array;
this._start = start;
this.length = end - start;
}

WebInspector.HeapSnapshotArraySlice.prototype = {
item: function(index)
{
return this._array[this._start + index];
},

slice: function(start, end)
{
if (typeof end === "undefined")
end = this.length;
return this._array.subarray(this._start + start, this._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 isWeak()
{
return this._type() === this._snapshot._edgeWeakType;
},

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 "weak": 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 && !this.isWeak;
},

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, retainedNodeIndex, retainerIndex)
{
this._snapshot = snapshot;
this._retainedNodeIndex = retainedNodeIndex;

var retainedNodeOrdinal = retainedNodeIndex / snapshot._nodeFieldCount;
this._firstRetainer = snapshot._firstRetainerIndex[retainedNodeOrdinal];
this._retainersCount = snapshot._firstRetainerIndex[retainedNodeOrdinal + 1] - this._firstRetainer;

this.retainerIndex = retainerIndex;
}

WebInspector.HeapSnapshotRetainerEdge.prototype = {
clone: function()
{
return new WebInspector.HeapSnapshotRetainerEdge(this._snapshot, this._retainedNodeIndex, 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 isWeak()
{
return this._edge.isWeak;
},

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.edgeIndex = newIndex;
}
},

set edgeIndex(edgeIndex)
{
var retainerIndex = this._firstRetainer + edgeIndex;
this._globalEdgeIndex = this._snapshot._retainingEdges[retainerIndex];
this._nodeIndex = this._snapshot._retainingNodes[retainerIndex];
delete this._edgeInstance;
delete this._nodeInstance;
},

get _node()
{
if (!this._nodeInstance)
this._nodeInstance = new WebInspector.HeapSnapshotNode(this._snapshot, this._nodeIndex);
return this._nodeInstance;
},

get _edge()
{
if (!this._edgeInstance) {
var edgeIndex = this._globalEdgeIndex - this._node._edgeIndexesStart();
this._edgeInstance = new WebInspector.HeapSnapshotEdge(this._snapshot, this._node.rawEdges, edgeIndex);
}
return this._edgeInstance;
},

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

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 distanceToWindow()
{
return this._snapshot._distancesToWindow[this.nodeIndex];
},

get className()
{
switch (this.type) {
case "hidden":
return WebInspector.UIString("(system)");
case "object":
case "native":
return this.name;
case "code":
return WebInspector.UIString("(compiled code)");
default:
return "(" + this.type + ")";
}
},

get classIndex()
{
var type = this._type();
switch (type) {
case this._snapshot._nodeObjectType:
case this._snapshot._nodeNativeType:
return this._name();
default:
return -1 - 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._edgeIndexesEnd() - this._edgeIndexesStart()) / this._snapshot._edgeFieldsCount;
},

get flags()
{
return this._snapshot._flagsOfNode(this);
},

get id()
{
return this._nodes[this.nodeIndex + this._snapshot._nodeIdOffset];
},

get isHidden()
{
return this._type() === this._snapshot._nodeHiddenType;
},

get isNative()
{
return this._type() === this._snapshot._nodeNativeType;
},

get isSynthetic()
{
return this._type() === this._snapshot._nodeSyntheticType;
},

get isWindow()
{
const windowRE = /^Window/;
return windowRE.test(this.name);
},

get isDetachedDOMTreesRoot()
{
return this.name === "(Detached DOM trees)";
},

get isDetachedDOMTree()
{
const detachedDOMTreeRE = /^Detached DOM tree/;
return detachedDOMTreeRE.test(this.className);
},

get isRoot()
{
return this.nodeIndex === this._snapshot._rootNodeIndex;
},

get name()
{
return this._snapshot._strings[this._name()];
},

get rawEdges()
{
return new WebInspector.HeapSnapshotArraySlice(this._snapshot._containmentEdges, this._edgeIndexesStart(), this._edgeIndexesEnd());
},

get retainedSize()
{
return this._nodes[this.nodeIndex + this._snapshot._nodeRetainedSizeOffset];
},

get retainers()
{
return new WebInspector.HeapSnapshotRetainerEdgeIterator(new WebInspector.HeapSnapshotRetainerEdge(this._snapshot, this.nodeIndex, 0));
},

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

_edgeIndexesStart: function()
{
return this._snapshot._onlyNodes[this.nodeIndex + this._snapshot._firstEdgeIndexOffset];
},

_edgeIndexesEnd: function()
{
var nextNodeIndex = this._nextNodeIndex;
if (nextNodeIndex < this._snapshot._onlyNodes.length)
return this._snapshot._onlyNodes[nextNodeIndex + this._snapshot._firstEdgeIndexOffset]
return this._snapshot._containmentEdges.length;
},

get _nextNodeIndex()
{
return this.nodeIndex + this._snapshot._nodeFieldCount;
},

_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._onlyNodes = profile.onlyNodes;
this._containmentEdges = profile.containmentEdges;

this._metaNode = profile.snapshot.meta;
this._strings = profile.strings;

this._snapshotDiffs = {};
this._aggregatesForDiff = null;

this._init();
}


function HeapSnapshotMetainfo()
{

this.node_fields = [];
this.node_types = [];
this.edge_fields = [];
this.edge_types = [];


this.fields = [];
this.types = [];
}


function HeapSnapshotHeader()
{

this.title = "";
this.uid = 0;
this.meta = new HeapSnapshotMetainfo();
this.node_count = 0;
this.edge_count = 0;
}

WebInspector.HeapSnapshot.prototype = {
_init: function()
{
var meta = this._metaNode;
if (meta.separate_edges) {
this._rootNodeIndex = 0;

this._nodeTypeOffset = meta.node_fields.indexOf("type");
this._nodeNameOffset = meta.node_fields.indexOf("name");
this._nodeIdOffset = meta.node_fields.indexOf("id");
this._nodeSelfSizeOffset = meta.node_fields.indexOf("self_size");
this._nodeRetainedSizeOffset = meta.node_fields.indexOf("retained_size");
this._dominatorOffset = meta.node_fields.indexOf("dominator");
this._firstEdgeIndexOffset = meta.node_fields.indexOf("edges_index");
this._nodeFieldCount = meta.node_fields.length;

this._nodeTypes = meta.node_types[this._nodeTypeOffset];
this._nodeHiddenType = this._nodeTypes.indexOf("hidden");
this._nodeObjectType = this._nodeTypes.indexOf("object");
this._nodeNativeType = this._nodeTypes.indexOf("native");
this._nodeCodeType = this._nodeTypes.indexOf("code");
this._nodeSyntheticType = this._nodeTypes.indexOf("synthetic");

this._edgeFieldsCount = meta.edge_fields.length;
this._edgeTypeOffset = meta.edge_fields.indexOf("type");
this._edgeNameOffset = meta.edge_fields.indexOf("name_or_index");
this._edgeToNodeOffset = meta.edge_fields.indexOf("to_node");

this._edgeTypes = meta.edge_types[this._edgeTypeOffset];
this._edgeTypes.push("invisible");
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._edgeWeakType = this._edgeTypes.indexOf("weak");
this._edgeInvisibleType = this._edgeTypes.indexOf("invisible");
} else {
this._rootNodeIndex = 1; 
this._nodeTypeOffset = meta.fields.indexOf("type");
this._nodeNameOffset = meta.fields.indexOf("name");
this._nodeIdOffset = meta.fields.indexOf("id");
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._firstEdgeIndexOffset = this._edgesCountOffset;
this._firstEdgeOffset = meta.fields.indexOf("children");
this._nodeFieldCount = this._firstEdgeOffset;
this._nodeTypes = meta.types[this._nodeTypeOffset];
this._nodeHiddenType = this._nodeTypes.indexOf("hidden");
this._nodeObjectType = this._nodeTypes.indexOf("object");
this._nodeNativeType = this._nodeTypes.indexOf("native");
this._nodeCodeType = this._nodeTypes.indexOf("code");
this._nodeSyntheticType = this._nodeTypes.indexOf("synthetic");
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._edgeWeakType = this._edgeTypes.indexOf("weak");
this._edgeInvisibleType = this._edgeTypes.length;
this._edgeTypes.push("invisible");
}

this._nodeFlags = { 
canBeQueried: 1,
detachedDOMTreeNode: 2,
};

if (meta.separate_edges) {
this.nodeCount = this._onlyNodes.length / this._nodeFieldCount;
this._edgeCount = this._containmentEdges.length / this._edgeFieldsCount;
} else {
this._splitNodesAndContainmentEdges();
this._rootNodeIndex = 0;
}

this._markInvisibleEdges();
this._buildRetainers();
if (this._dominatorOffset !== -1) 
this._buildDominatedNodes()
this._calculateFlags();
this._calculateObjectToWindowDistance();
},

_splitNodesAndContainmentEdges: function()
{

var totalEdgeCount = 0;
var totalNodeCount = 0;
for (var index = this._rootNodeIndex; index < this._nodes.length; ) {
++totalNodeCount;
var edgesCount = this._nodes[index + this._edgesCountOffset];
totalEdgeCount += edgesCount;
index += this._firstEdgeOffset + edgesCount * this._edgeFieldsCount;
}
this.nodeCount = totalNodeCount;
this._edgeCount = totalEdgeCount;
this._createOnlyNodesArray();
this._createContainmentEdgesArray();
delete this._nodes;
},

_createOnlyNodesArray: function()
{

this._onlyNodes = new Uint32Array(this.nodeCount * this._nodeFieldCount);
var dstIndex = 0;
var srcIndex = this._rootNodeIndex;
while (srcIndex < this._nodes.length) {
var srcNodeTypeIndex = srcIndex + this._nodeTypeOffset;
var currentDstIndex = dstIndex;
var edgesCount = this._nodes[srcIndex + this._edgesCountOffset];
for (var i = 0; i < this._nodeFieldCount; i++)
this._onlyNodes[dstIndex++] = this._nodes[srcIndex++];

this._nodes[srcNodeTypeIndex] = currentDstIndex;
srcIndex += edgesCount * this._edgeFieldsCount;
}

for (var dominatorSlotIndex = this._dominatorOffset; dominatorSlotIndex < this._onlyNodes.length; dominatorSlotIndex += this._nodeFieldCount) {
var dominatorIndex = this._onlyNodes[dominatorSlotIndex];
this._onlyNodes[dominatorSlotIndex] = this._nodes[dominatorIndex + this._nodeTypeOffset];
}
},

_createContainmentEdgesArray: function()
{

var containmentEdges = this._containmentEdges = new Uint32Array(this._edgeCount * this._edgeFieldsCount);


var nodes = this._nodes;
var onlyNodes = this._onlyNodes;
var firstEdgeIndexOffset = this._firstEdgeIndexOffset;
var edgeFieldsCount = this._edgeFieldsCount;
var edgeToNodeOffset = this._edgeToNodeOffset;
var edgesCountOffset = this._edgesCountOffset;
var nodeTypeOffset = this._nodeTypeOffset;
var firstEdgeOffset = this._firstEdgeOffset;

var edgeArrayIndex = 0;
var srcIndex = this._rootNodeIndex;
while (srcIndex < nodes.length) {
var srcNodeNewIndex = nodes[srcIndex + nodeTypeOffset];

onlyNodes[srcNodeNewIndex + firstEdgeIndexOffset] = edgeArrayIndex;


var edgesCount = nodes[srcIndex + edgesCountOffset];
srcIndex += firstEdgeOffset;
var nextNodeIndex = srcIndex + edgesCount * edgeFieldsCount;
while (srcIndex < nextNodeIndex) {
containmentEdges[edgeArrayIndex] = nodes[srcIndex];

if (edgeArrayIndex % edgeFieldsCount === edgeToNodeOffset) {
var toNodeIndex = containmentEdges[edgeArrayIndex];
containmentEdges[edgeArrayIndex] = nodes[toNodeIndex + nodeTypeOffset];
}
++edgeArrayIndex;
++srcIndex;
}
}
},

_buildRetainers: function()
{
var retainingNodes = this._retainingNodes = new Uint32Array(this._edgeCount);
var retainingEdges = this._retainingEdges = new Uint32Array(this._edgeCount);


var firstRetainerIndex = this._firstRetainerIndex = new Uint32Array(this.nodeCount + 1);

var containmentEdges = this._containmentEdges;
var edgeFieldsCount = this._edgeFieldsCount;
var nodeFieldCount = this._nodeFieldCount;
var edgeToNodeOffset = this._edgeToNodeOffset;
var onlyNodes = this._onlyNodes;
var firstEdgeIndexOffset = this._firstEdgeIndexOffset;

for (var toNodeFieldIndex = edgeToNodeOffset, l = containmentEdges.length; toNodeFieldIndex < l; toNodeFieldIndex += edgeFieldsCount) {
var toNodeIndex = containmentEdges[toNodeFieldIndex];
if (toNodeIndex % nodeFieldCount)
throw new Error("Invalid toNodeIndex " + toNodeIndex);
++firstRetainerIndex[toNodeIndex / nodeFieldCount];
}
for (var i = 0, firstUnusedRetainerSlot = 0, l = this.nodeCount; i < l; i++) {
var retainersCount = firstRetainerIndex[i];
firstRetainerIndex[i] = firstUnusedRetainerSlot;
retainingNodes[firstUnusedRetainerSlot] = retainersCount;
firstUnusedRetainerSlot += retainersCount;
}
firstRetainerIndex[this.nodeCount] = retainingNodes.length;

var srcNodeIndex = 0;
var nextNodeFirstEdgeIndex = onlyNodes[firstEdgeIndexOffset];
var onlyNodesLength = onlyNodes.length;
while (srcNodeIndex < onlyNodesLength) {
var firstEdgeIndex = nextNodeFirstEdgeIndex;
var nextNodeIndex = srcNodeIndex + nodeFieldCount;
nextNodeFirstEdgeIndex = nextNodeIndex < onlyNodesLength
? onlyNodes[nextNodeIndex + firstEdgeIndexOffset]
: containmentEdges.length;
for (var edgeIndex = firstEdgeIndex; edgeIndex < nextNodeFirstEdgeIndex; edgeIndex += edgeFieldsCount) {
var toNodeIndex = containmentEdges[edgeIndex + edgeToNodeOffset];
if (toNodeIndex % nodeFieldCount)
throw new Error("Invalid toNodeIndex " + toNodeIndex);
var firstRetainerSlotIndex = firstRetainerIndex[toNodeIndex / nodeFieldCount];
var nextUnusedRetainerSlotIndex = firstRetainerSlotIndex + (--retainingNodes[firstRetainerSlotIndex]);
retainingNodes[nextUnusedRetainerSlotIndex] = srcNodeIndex;
retainingEdges[nextUnusedRetainerSlotIndex] = edgeIndex;
}
srcNodeIndex = nextNodeIndex;
}
},

dispose: function()
{
delete this._nodes;
delete this._strings;
delete this._retainingEdges;
delete this._retainingNodes;
delete this._firstRetainerIndex;
if (this._aggregates) {
delete this._aggregates;
delete this._aggregatesSortedFlags;
}
delete this._dominatedNodes;
delete this._firstDominatedNodeIndex;
delete this._flags;
delete this._distancesToWindow;
},

get _allNodes()
{
return new WebInspector.HeapSnapshotNodeIterator(this.rootNode);
},

get rootNode()
{
return new WebInspector.HeapSnapshotNode(this, this._rootNodeIndex);
},

get rootNodeIndex()
{
return this._rootNodeIndex;
},

get totalSize()
{
return this.rootNode.retainedSize;
},

_getDominatedIndex: function(nodeIndex)
{
if (nodeIndex % this._nodeFieldCount)
throw new Error("Invalid nodeIndex: " + nodeIndex);
return this._firstDominatedNodeIndex[nodeIndex / this._nodeFieldCount];
},

_dominatedNodesOfNode: function(node)
{
var dominatedIndexFrom = this._getDominatedIndex(node.nodeIndex);
var dominatedIndexTo = this._getDominatedIndex(node._nextNodeIndex);
return new WebInspector.HeapSnapshotArraySlice(this._dominatedNodes, dominatedIndexFrom, dominatedIndexTo);
},

_flagsOfNode: function(node)
{
return this._flags[node.nodeIndex];
},


aggregates: function(sortedIndexes, key, filterString)
{
if (!this._aggregates) {
this._aggregates = {};
this._aggregatesSortedFlags = {};
}

var aggregatesByClassName = this._aggregates[key];
if (aggregatesByClassName) {
if (sortedIndexes && !this._aggregatesSortedFlags[key]) {
this._sortAggregateIndexes(aggregatesByClassName);
this._aggregatesSortedFlags[key] = sortedIndexes;
}
return aggregatesByClassName;
}

var filter;
if (filterString)
filter = this._parseFilter(filterString);

var aggregates = this._buildAggregates(filter);
this._calculateClassesRetainedSize(aggregates.aggregatesByClassIndex, filter);
aggregatesByClassName = aggregates.aggregatesByClassName;

if (sortedIndexes)
this._sortAggregateIndexes(aggregatesByClassName);

this._aggregatesSortedFlags[key] = sortedIndexes;
this._aggregates[key] = aggregatesByClassName;

return aggregatesByClassName;
},

aggregatesForDiff: function()
{
if (this._aggregatesForDiff)
return this._aggregatesForDiff;

var aggregatesByClassName = this.aggregates(true, "allObjects");
this._aggregatesForDiff  = {};

var node = new WebInspector.HeapSnapshotNode(this);
for (var className in aggregatesByClassName) {
var aggregate = aggregatesByClassName[className];
var indexes = aggregate.idxs;
var ids = new Array(indexes.length);
var selfSizes = new Array(indexes.length);
for (var i = 0; i < indexes.length; i++) {
node.nodeIndex = indexes[i];
ids[i] = node.id;
selfSizes[i] = node.selfSize;
}

this._aggregatesForDiff[className] = {
indexes: indexes,
ids: ids,
selfSizes: selfSizes
};
}
return this._aggregatesForDiff;
},

_calculateObjectToWindowDistance: function()
{
this._distancesToWindow = new Array(this.nodeCount);


var list = [];
for (var iter = this.rootNode.edges; iter.hasNext(); iter.next()) {
var node = iter.edge.node;
if (node.isWindow) {
if (node.nodeIndex % this._nodeFieldCount)
throw new Error("Invalid nodeIndex: " + node.nodeIndex);
list.push(node.nodeIndex);
this._distancesToWindow[node.nodeIndex] = 0;
}
}
this._bfs(list);


list = [];
list.push(this._rootNodeIndex);
this._distancesToWindow[this._rootNodeIndex] = 0;
this._bfs(list);
},

_bfs: function(list)
{

var edgeFieldsCount = this._edgeFieldsCount;
var containmentEdges = this._containmentEdges;
var nodeFieldCount = this._nodeFieldCount;
var firstEdgeIndexOffset = this._firstEdgeIndexOffset;
var edgeToNodeOffset = this._edgeToNodeOffset;
var distancesToWindow = this._distancesToWindow;
var onlyNodes = this._onlyNodes;

var index = 0;
while (index < list.length) {
var nodeIndex = list[index++]; 
if (index > 100000) {
list = list.slice(index);
index = 0;
}
var distance = distancesToWindow[nodeIndex] + 1;

var firstEdgeIndex = onlyNodes[nodeIndex + firstEdgeIndexOffset];
var edgesEnd = nodeIndex < onlyNodes.length
? onlyNodes[nodeIndex + nodeFieldCount + firstEdgeIndexOffset]
: containmentEdges.length;
for (var edgeToNodeIndex = firstEdgeIndex + edgeToNodeOffset; edgeToNodeIndex < edgesEnd; edgeToNodeIndex += edgeFieldsCount) {
var childNodeIndex = containmentEdges[edgeToNodeIndex];
if (childNodeIndex % nodeFieldCount)
throw new Error("Invalid childNodeIndex: " + childNodeIndex);
if (childNodeIndex in distancesToWindow)
continue;
distancesToWindow[childNodeIndex] = distance;
list.push(childNodeIndex);
}
}
},

_buildAggregates: function(filter)
{
var aggregates = {};
var aggregatesByClassName = {};
var onlyNodes = this._onlyNodes;
var onlyNodesLength = onlyNodes.length;
var nodeNativeType = this._nodeNativeType;
var nodeFieldsCount = this._nodeFieldCount;
var selfSizeOffset = this._nodeSelfSizeOffset;
var nodeTypeOffset = this._nodeTypeOffset;
var node = new WebInspector.HeapSnapshotNode(this, this._rootNodeIndex);
var distancesToWindow = this._distancesToWindow;

for (var nodeIndex = this._rootNodeIndex; nodeIndex < onlyNodesLength; nodeIndex += nodeFieldsCount) {
node.nodeIndex = nodeIndex;
var selfSize = onlyNodes[nodeIndex + selfSizeOffset];
if (filter && !filter(node))
continue;
if (!selfSize && onlyNodes[nodeIndex + nodeTypeOffset] !== nodeNativeType)
continue;
var classIndex = node.classIndex;
if (!(classIndex in aggregates)) {
var nodeType = node.type;
var nameMatters = nodeType === "object" || nodeType === "native";
var value = {
count: 1,
distanceToWindow: distancesToWindow[nodeIndex],
self: selfSize,
maxRet: 0,
type: nodeType,
name: nameMatters ? node.name : null,
idxs: [nodeIndex]
};
aggregates[classIndex] = value;
aggregatesByClassName[node.className] = value;
} else {
var clss = aggregates[classIndex];
clss.distanceToWindow = Math.min(clss.distanceToWindow, distancesToWindow[nodeIndex]);
++clss.count;
clss.self += selfSize;
clss.idxs.push(nodeIndex);
}
}


for (var classIndex in aggregates)
aggregates[classIndex].idxs = aggregates[classIndex].idxs.slice(0);
return {aggregatesByClassName: aggregatesByClassName, aggregatesByClassIndex: aggregates};
},

_calculateClassesRetainedSize: function(aggregates, filter)
{
var rootNodeIndex = this._rootNodeIndex;
var node = new WebInspector.HeapSnapshotNode(this, rootNodeIndex);
var list = [rootNodeIndex];
var sizes = [-1];
var classes = [];
var seenClassNameIndexes = {};
var nodeFieldCount = this._nodeFieldCount;
var nodeTypeOffset = this._nodeTypeOffset;
var nodeNativeType = this._nodeNativeType;
var dominatedNodes = this._dominatedNodes;
var onlyNodes = this._onlyNodes;
var firstDominatedNodeIndex = this._firstDominatedNodeIndex;

while (list.length) {
var nodeIndex = list.pop();
node.nodeIndex = nodeIndex;
var classIndex = node.classIndex;
var seen = !!seenClassNameIndexes[classIndex];
var nodeOrdinal = nodeIndex / nodeFieldCount;
var dominatedIndexFrom = firstDominatedNodeIndex[nodeOrdinal];
var dominatedIndexTo = firstDominatedNodeIndex[nodeOrdinal + 1];

if (!seen &&
(!filter || filter(node)) &&
(node.selfSize || onlyNodes[nodeIndex + nodeTypeOffset] === nodeNativeType)
) {
aggregates[classIndex].maxRet += node.retainedSize;
if (dominatedIndexFrom !== dominatedIndexTo) {
seenClassNameIndexes[classIndex] = true;
sizes.push(list.length);
classes.push(classIndex);
}
}
for (var i = dominatedIndexFrom; i < dominatedIndexTo; i++)
list.push(dominatedNodes[i]);

var l = list.length;
while (sizes[sizes.length - 1] === l) {
sizes.pop();
classIndex = classes.pop();
seenClassNameIndexes[classIndex] = false;
}
}
},

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

_buildDominatedNodes: function()
{





var indexArray = this._firstDominatedNodeIndex = new Uint32Array(this.nodeCount + 1);

var dominatedNodes = this._dominatedNodes = new Uint32Array(this.nodeCount - 1);



for (var nodeIndex = this._nodeFieldCount; nodeIndex < this._onlyNodes.length; nodeIndex += this._nodeFieldCount) {
var dominatorIndex = this._onlyNodes[nodeIndex + this._dominatorOffset];
if (dominatorIndex % this._nodeFieldCount)
throw new Error("Wrong dominatorIndex " + dominatorIndex + " nodeIndex = " + nodeIndex + " nodeCount = " + this.nodeCount);
++indexArray[dominatorIndex / this._nodeFieldCount];
}


var firstDominatedNodeIndex = 0;
for (var i = 0; i < this.nodeCount; ++i) {
var dominatedCount = dominatedNodes[firstDominatedNodeIndex] = indexArray[i];
indexArray[i] = firstDominatedNodeIndex;
firstDominatedNodeIndex += dominatedCount;
}
indexArray[this.nodeCount] = dominatedNodes.length;


for (var nodeIndex = this._nodeFieldCount; nodeIndex < this._onlyNodes.length; nodeIndex += this._nodeFieldCount) {
var dominatorIndex = this._onlyNodes[nodeIndex + this._dominatorOffset];
if (dominatorIndex % this._nodeFieldCount)
throw new Error("Wrong dominatorIndex " + dominatorIndex);
var dominatorPos = dominatorIndex / this._nodeFieldCount;
var dominatedRefIndex = indexArray[dominatorPos];
dominatedRefIndex += (--dominatedNodes[dominatedRefIndex]);
dominatedNodes[dominatedRefIndex] = nodeIndex;
}
},

_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._containmentEdges[globalObjEdge._edges._start + globalObjEdge.edgeIndex + this._edgeTypeOffset] = this._edgeInvisibleType;
}
}
},

_numbersComparator: function(a, b)
{
return a < b ? -1 : (a > b ? 1 : 0);
},

_markDetachedDOMTreeNodes: function()
{
var flag = this._nodeFlags.detachedDOMTreeNode;
var detachedDOMTreesRoot;
for (var iter = this.rootNode.edges; iter.hasNext(); iter.next()) {
var node = iter.edge.node;
if (node.isDetachedDOMTreesRoot) {
detachedDOMTreesRoot = node;
break;
}
}

if (!detachedDOMTreesRoot)
return;

for (var iter = detachedDOMTreesRoot.edges; iter.hasNext(); iter.next()) {
var node = iter.edge.node;
if (node.isDetachedDOMTree) {
for (var edgesIter = node.edges; edgesIter.hasNext(); edgesIter.next())
this._flags[edgesIter.edge.node.nodeIndex] |= flag;
}
}
},

_markQueriableHeapObjects: function()
{



var flag = this._nodeFlags.canBeQueried;

var list = [];
for (var iter = this.rootNode.edges; iter.hasNext(); iter.next()) {
if (iter.edge.node.isWindow)
list.push(iter.edge.node.nodeIndex);
}

var edge = new WebInspector.HeapSnapshotEdge(this, undefined);
var node = new WebInspector.HeapSnapshotNode(this);
while (list.length) {
var nodeIndex = list.pop();
if (this._flags[nodeIndex] & flag)
continue;
node.nodeIndex = nodeIndex;
this._flags[nodeIndex] |= flag;
var edgesCount = node.edgesCount;
edge._edges = node.rawEdges;
for (var j = 0; j < edgesCount; ++j) {
edge.edgeIndex = j * this._edgeFieldsCount;
nodeIndex = edge.nodeIndex;
if (this._flags[nodeIndex] & flag)
continue;
if (edge.isHidden || edge.isInvisible)
continue;
if (edge.isInternal)
continue;
var name = edge.name;
if (!name)
continue;
list.push(nodeIndex);
}
}
},

_calculateFlags: function()
{
this._flags = new Array(this.nodeCount);
this._markDetachedDOMTreeNodes();
this._markQueriableHeapObjects();
},

calculateSnapshotDiff: function(baseSnapshotId, baseSnapshotAggregates)
{
var snapshotDiff = this._snapshotDiffs[baseSnapshotId];
if (snapshotDiff)
return snapshotDiff;
snapshotDiff = {};

var aggregates = this.aggregates(true, "allObjects");
for (var className in baseSnapshotAggregates) {
var baseAggregate = baseSnapshotAggregates[className];
var diff = this._calculateDiffForClass(baseAggregate, aggregates[className]);
if (diff)
snapshotDiff[className] = diff;
}
var emptyBaseAggregate = { ids: [], indexes: [], selfSizes: [] };
for (var className in aggregates) {
if (className in baseSnapshotAggregates)
continue;
snapshotDiff[className] = this._calculateDiffForClass(emptyBaseAggregate, aggregates[className]);
}

this._snapshotDiffs[baseSnapshotId] = snapshotDiff;
return snapshotDiff;
},

_calculateDiffForClass: function(baseAggregate, aggregate)
{
var baseIds = baseAggregate.ids;
var baseIndexes = baseAggregate.indexes;
var baseSelfSizes = baseAggregate.selfSizes;

var indexes = aggregate ? aggregate.idxs : [];

var i = 0, l = baseIds.length;
var j = 0, m = indexes.length;
var diff = { addedCount: 0,
removedCount: 0,
addedSize: 0,
removedSize: 0,
deletedIndexes: [],
addedIndexes: [] };

var nodeB = new WebInspector.HeapSnapshotNode(this, indexes[j]);
while (i < l && j < m) {
var nodeAId = baseIds[i];
if (nodeAId < nodeB.id) {
diff.deletedIndexes.push(baseIndexes[i]);
diff.removedCount++;
diff.removedSize += baseSelfSizes[i];
++i;
} else if (nodeAId > nodeB.id) { 
diff.addedIndexes.push(indexes[j]);
diff.addedCount++;
diff.addedSize += nodeB.selfSize;
nodeB.nodeIndex = indexes[++j];
} else { 
++i;
nodeB.nodeIndex = indexes[++j];
}
}
while (i < l) {
diff.deletedIndexes.push(baseIndexes[i]);
diff.removedCount++;
diff.removedSize += baseSelfSizes[i];
++i;
}
while (j < m) {
diff.addedIndexes.push(indexes[j]);
diff.addedCount++;
diff.addedSize += nodeB.selfSize;
nodeB.nodeIndex = indexes[++j];
}
diff.countDelta = diff.addedCount - diff.removedCount;
diff.sizeDelta = diff.addedSize - diff.removedSize;
if (!diff.addedCount && !diff.removedCount)
return null;
return diff;
},

_parseFilter: function(filter)
{
if (!filter)
return null;
var parsedFilter = eval("(function(){return " + filter + "})()");
return parsedFilter.bind(this);
},

createEdgesProvider: function(nodeIndex, filter)
{
var node = new WebInspector.HeapSnapshotNode(this, nodeIndex);
return new WebInspector.HeapSnapshotEdgesProvider(this, this._parseFilter(filter), node.edges);
},

createRetainingEdgesProvider: function(nodeIndex, filter)
{
var node = new WebInspector.HeapSnapshotNode(this, nodeIndex);
return new WebInspector.HeapSnapshotEdgesProvider(this, this._parseFilter(filter), node.retainers);
},

createAddedNodesProvider: function(baseSnapshotId, className)
{
var snapshotDiff = this._snapshotDiffs[baseSnapshotId];
var diffForClass = snapshotDiff[className];
return new WebInspector.HeapSnapshotNodesProvider(this, null, diffForClass.addedIndexes);
},

createDeletedNodesProvider: function(nodeIndexes)
{
return new WebInspector.HeapSnapshotNodesProvider(this, null, nodeIndexes);
},

createNodesProviderForClass: function(className, aggregatesKey)
{
return new WebInspector.HeapSnapshotNodesProvider(this, null, this.aggregates(false, aggregatesKey)[className].idxs);
},

createNodesProviderForDominator: function(nodeIndex)
{
var node = new WebInspector.HeapSnapshotNode(this, nodeIndex);
return new WebInspector.HeapSnapshotNodesProvider(this, null, this._dominatedNodesOfNode(node));
},

updateStaticData: function()
{
return {nodeCount: this.nodeCount, rootNodeIndex: this._rootNodeIndex, totalSize: this.totalSize, uid: this.uid, nodeFlags: this._nodeFlags};
}
};


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

serializeSubsequentItems: 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, filter, edgesIter)
{
this.snapshot = snapshot;
WebInspector.HeapSnapshotFilteredOrderedIterator.call(this, edgesIter, filter);
}

WebInspector.HeapSnapshotEdgesProvider.prototype = {
_serialize: function(edge)
{
return {
name: edge.name,
propertyAccessor: edge.toString(),
node: WebInspector.HeapSnapshotNodesProvider.prototype._serialize(edge.node),
nodeIndex: edge.nodeIndex,
type: edge.type,
distanceToWindow: edge.node.distanceToWindow
};
},

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 compareEdgeFieldName(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 compareNodeField(fieldName, ascending, indexA, indexB)
{
edgeA.edgeIndex = indexA;
nodeA.nodeIndex = edgeA.nodeIndex;
var valueA = nodeA[fieldName];

edgeB.edgeIndex = indexB;
nodeB.nodeIndex = edgeB.nodeIndex;
var valueB = nodeB[fieldName];

var result = valueA < valueB ? -1 : (valueA > valueB ? 1 : 0);
return ascending ? result : -result;
}

function compareEdgeAndNode(indexA, indexB) {
var result = compareEdgeFieldName(ascending1, indexA, indexB);
if (result === 0)
result = compareNodeField(fieldName2, ascending2, indexA, indexB);
return result;
}

function compareNodeAndEdge(indexA, indexB) {
var result = compareNodeField(fieldName1, ascending1, indexA, indexB);
if (result === 0)
result = compareEdgeFieldName(ascending2, indexA, indexB);
return result;
}

function compareNodeAndNode(indexA, indexB) {
var result = compareNodeField(fieldName1, ascending1, indexA, indexB);
if (result === 0)
result = compareNodeField(fieldName2, ascending2, indexA, indexB);
return result;
}

if (fieldName1 === "!edgeName")
this._iterationOrder.sortRange(compareEdgeAndNode, leftBound, rightBound, count);
else if (fieldName2 === "!edgeName")
this._iterationOrder.sortRange(compareNodeAndEdge, leftBound, rightBound, count);
else
this._iterationOrder.sortRange(compareNodeAndNode, 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,
distanceToWindow: node.distanceToWindow,
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)
{
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) {
nodeA.nodeIndex = indexA;
nodeB.nodeIndex = indexB;
var result = sortByNodeField(fieldName1, ascending1);
if (result === 0)
result = sortByNodeField(fieldName2, ascending2);
return result;
}

this._iterationOrder.sortRange(sortByComparator, leftBound, rightBound, count);
}
};

WebInspector.HeapSnapshotNodesProvider.prototype.__proto__ = WebInspector.HeapSnapshotFilteredOrderedIterator.prototype;






WebInspector.HeapSnapshotWorkerWrapper = function()
{
}

WebInspector.HeapSnapshotWorkerWrapper.prototype =  {
postMessage: function(message)
{
},
terminate: function()
{
}
}

WebInspector.HeapSnapshotWorkerWrapper.prototype.__proto__ = WebInspector.Object.prototype;


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

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 (event.data.error) {
if (event.data.errorMethodName)
WebInspector.log(WebInspector.UIString("An error happened when a call for method '%s' was requested", event.data.errorMethodName));
WebInspector.log(event.data.errorCallStack);
delete this._callbacks[data.callId];
return;
}
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, var_args)
{
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, var_args)
{
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;
var self = this;
function updateStaticData(snapshotProxy)
{
this.dispose();
snapshotProxy.updateStaticData(this._callLoadCallbacks.bind(this, loadCallbacks));
}
this.callFactoryMethod(updateStaticData.bind(this), "finishLoading", "WebInspector.HeapSnapshotProxy");
return true;
},

_callLoadCallbacks: function(loadCallbacks, snapshotProxy)
{
for (var i = 0; i < loadCallbacks.length; ++i)
loadCallbacks[i](snapshotProxy);
},

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

aggregatesForDiff: function(callback)
{
this.callMethod(callback, "aggregatesForDiff");
},

calculateSnapshotDiff: function(baseSnapshotId, baseSnapshotAggregates, callback)
{
this.callMethod(callback, "calculateSnapshotDiff", baseSnapshotId, baseSnapshotAggregates);
},

createEdgesProvider: function(nodeIndex, filter)
{
return this.callFactoryMethod(null, "createEdgesProvider", "WebInspector.HeapSnapshotProviderProxy", nodeIndex, filter);
},

createRetainingEdgesProvider: function(nodeIndex, filter)
{
return this.callFactoryMethod(null, "createRetainingEdgesProvider", "WebInspector.HeapSnapshotProviderProxy", nodeIndex, filter);
},

createAddedNodesProvider: function(baseSnapshotId, className)
{
return this.callFactoryMethod(null, "createAddedNodesProvider", "WebInspector.HeapSnapshotProviderProxy", baseSnapshotId, className);
},

createDeletedNodesProvider: function(nodeIndexes)
{
return this.callFactoryMethod(null, "createDeletedNodesProvider", "WebInspector.HeapSnapshotProviderProxy", nodeIndexes);
},

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)
{
return this.callFactoryMethod(null, "createNodesProviderForDominator", "WebInspector.HeapSnapshotProviderProxy", nodeIndex);
},

dispose: function()
{
this.disposeWorker();
},

finishLoading: function()
{
return false;
},

get loaded()
{
return !!this._objectId;
},

get nodeCount()
{
return this._staticData.nodeCount;
},

get nodeFlags()
{
return this._staticData.nodeFlags;
},

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

serializeSubsequentItems: function(count, callback)
{
this.callMethod(callback, "serializeSubsequentItems", count);
},

sortAndRewind: function(comparator, callback)
{
this.callMethod(callback, "sortAndRewind", comparator);
}
};

WebInspector.HeapSnapshotProviderProxy.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;
var response = {callId: data.callId};
try {
switch (data.disposition) {
case "create": {
var constructorFunction = this._findFunction(data.methodName);
this._objects[data.objectId] = new constructorFunction();
break;
}
case "dispose": {
delete this._objects[data.objectId];
break;
}
case "getter": {
var object = this._objects[data.objectId];
var result = object[data.methodName];
response.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;
response.result = !!result;
break;
}
case "method": {
var object = this._objects[data.objectId];
response.result = object[data.methodName].apply(object, data.methodArguments);
break;
}
}
} catch (e) {
response.error = e.toString();
response.errorCallStack = e.stack;
if (data.methodName)
response.errorMethodName = data.methodName;
}
this._postMessage(response);
}
};






WebInspector.HeapSnapshotGridNode = function(tree, hasChildren, provider)
{
WebInspector.DataGridNode.call(this, null, hasChildren);

this._provider = provider;
this._dataGrid = tree;
this._instanceCount = 0;
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;
},

collapse: function()
{
WebInspector.DataGridNode.prototype.collapse.call(this);
this._dataGrid.updateVisibleNodes();
},

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

_toPercentString: function(num)
{
return num.toFixed(0) + "\u2009%"; 
},

_createValueCell: function(columnIdentifier)
{
var cell = document.createElement("td");
cell.className = columnIdentifier + "-column";
if (this.dataGrid.snapshot.totalSize !== 0) {
var div = document.createElement("div");
var valueSpan = document.createElement("span");
valueSpan.textContent = this.data[columnIdentifier];
div.appendChild(valueSpan);
var percentColumn = columnIdentifier + "-percent";
if (percentColumn in this.data) {
var percentSpan = document.createElement("span");
percentSpan.className = "percent-column";
percentSpan.textContent = this.data[percentColumn];
div.appendChild(percentSpan);
}
cell.appendChild(div);
}
return cell;
},

_populate: function(event)
{
this.removeEventListener("populate", this._populate, this);
function sorted(ignored)
{
this._populateChildren();
}
this._provider.sortAndRewind(this.comparator(), sorted.bind(this));
},


_populateChildren: function(howMany, atIndex, afterPopulate)
{
howMany = howMany || this._dataGrid.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._dataGrid.defaultPopulateCount();
this._provider.serializeSubsequentItems(this._dataGrid.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), atIndex++);
}
this._instanceCount += items.length;
if (part < howMany) {
setTimeout(callSerialize.bind(this), 0);
return;
}

if (items.hasNext)
this.insertChild(new WebInspector.ShowMoreDataGridNode(this._populateChildren.bind(this), this._dataGrid.defaultPopulateCount(), length), atIndex++);
if (afterPopulate)
afterPopulate();
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();
}
var instanceCount = this._instanceCount;
this._instanceCount = 0;
this._populateChildren(instanceCount, null, afterPopulate.bind(this));
}
this._provider.sortAndRewind(this.comparator(), afterSort.bind(this));
}
};

WebInspector.HeapSnapshotGridNode.prototype.__proto__ = WebInspector.DataGridNode.prototype;


WebInspector.HeapSnapshotGenericObjectNode = function(tree, node, provider)
{
WebInspector.HeapSnapshotGridNode.call(this, tree, false, provider);

if (!node)
return;
this._name = node.name;
this._type = node.type;
this._distanceToWindow = node.distanceToWindow;
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.isWindow(this._name)) {
this._name = this.shortenWindowURL(this._name, false);
this.hasHoverMessage = true;
} else if (node.flags & tree.snapshot.nodeFlags.canBeQueried)
this.hasHoverMessage = true;
if (node.flags & tree.snapshot.nodeFlags.detachedDOMTreeNode)
this.detachedDOMTreeNode = true;
};

WebInspector.HeapSnapshotGenericObjectNode.prototype = {
createCell: function(columnIdentifier)
{
var cell = columnIdentifier !== "object" ? this._createValueCell(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 = "visible";
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);
var idSpan = document.createElement("span");
idSpan.className = "console-formatted-id";
idSpan.textContent = " @" + data["nodeId"];
div.appendChild(idSpan);
if (this._postfixObjectCell)
this._postfixObjectCell(div, data);
cell.appendChild(div);
cell.addStyleClass("disclosure");
if (this.depth)
cell.style.setProperty("padding-left", (this.depth * this.dataGrid.indentWidth) + "px");
return cell;
},

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 ? " " : "") + 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";
if (value === "Object")
value = "";
if (this.detachedDOMTreeNode)
valueStyle += " detached-dom-tree-node";
data["object"] = { valueStyle: valueStyle, value: value, nodeId: this.snapshotNodeId };

var view = this.dataGrid.snapshotView;
data["distanceToWindow"] =  this._distanceToWindow;
data["shallowSize"] = Number.withThousandsSeparator(this._shallowSize);
data["retainedSize"] = Number.withThousandsSeparator(this._retainedSize);
data["shallowSize-percent"] = this._toPercentString(this._shallowSizePercent);
data["retainedSize-percent"] = this._toPercentString(this._retainedSizePercent);

return this._enhanceData ? this._enhanceData(data) : data;
},

queryObjectContent: function(callback, objectGroupName)
{
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, objectGroupName, 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));
},

isWindow: function(fullName)
{
return fullName.substr(0, 9) === "Window";
},

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, parentGridNode)
{
WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, edge.node,
WebInspector.HeapSnapshotObjectNode._createProvider(isFromBaseSnapshot, edge.nodeIndex, tree));
this._referenceName = edge.name;
this._referenceType = edge.type;
this._propertyAccessor = edge.propertyAccessor;
this._distanceToWindow = edge.distanceToWindow;
this.showRetainingEdges = tree.showRetainingEdges;
this._isFromBaseSnapshot = isFromBaseSnapshot;

this._parentGridNode = parentGridNode;
this._cycledWithAncestorGridNode = this._findAncestorWithSameSnapshotNodeId();
if (!this._cycledWithAncestorGridNode)
this.updateHasChildren();
}

WebInspector.HeapSnapshotObjectNode._createProvider = function(isFromBaseSnapshot, nodeIndex, tree)
{
var showHiddenData = WebInspector.settings.showHeapSnapshotObjectsHiddenProperties.get();
var filter = "function(edge) {\n" +
"    return !edge.isInvisible\n" +
"        && (" + !tree.showRetainingEdges + " || (edge.node.id !== 1 && !edge.node.isSynthetic))\n" +
"        && (" + showHiddenData + " || (!edge.isHidden && !edge.node.isHidden));\n" +
"}\n";
var snapshot = isFromBaseSnapshot ? tree.baseSnapshot : tree.snapshot;
if (tree.showRetainingEdges)
return snapshot.createRetainingEdgesProvider(nodeIndex, filter);
else
return snapshot.createEdgesProvider(nodeIndex, filter);
}

WebInspector.HeapSnapshotObjectNode.prototype = {
_findAncestorWithSameSnapshotNodeId: function()
{
var ancestor = this._parentGridNode;
while (ancestor) {
if (ancestor.snapshotNodeId === this.snapshotNodeId)
return ancestor;
ancestor = ancestor._parentGridNode;
}
return null;
},

_createChildNode: function(item)
{
return new WebInspector.HeapSnapshotObjectNode(this._dataGrid, this._isFromBaseSnapshot, item, this);
},

_childHashForEntity: function(edge)
{
var prefix = this.showRetainingEdges ? edge.node.id + "#" : "";
return prefix + edge.type + "#" + edge.name;
},

_childHashForNode: function(childNode)
{
var prefix = this.showRetainingEdges ? childNode.snapshotNodeId + "#" : "";
return prefix + 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],
distanceToWindow: ["distanceToWindow", sortAscending, "_name", 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;
case "element":
name = "[" + name + "]";
break;
}
data["object"].nameClass = nameClass;
data["object"].name = name;
data["distanceToWindow"] = this._distanceToWindow;
return data;
},

_prefixObjectCell: function(div, data)
{
if (this._cycledWithAncestorGridNode)
div.className += " cycled-ancessor-node";

var nameSpan = document.createElement("span");
nameSpan.className = data.nameClass;
nameSpan.textContent = data.name;
div.appendChild(nameSpan);

var separatorSpan = document.createElement("span");
separatorSpan.className = "grayed";
separatorSpan.textContent = this.showRetainingEdges ? " in " : " :: ";
div.appendChild(separatorSpan);
}
}

WebInspector.HeapSnapshotObjectNode.prototype.__proto__ = WebInspector.HeapSnapshotGenericObjectNode.prototype;


WebInspector.HeapSnapshotInstanceNode = function(tree, baseSnapshot, snapshot, node)
{
WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node,
WebInspector.HeapSnapshotInstanceNode._createProvider(baseSnapshot || snapshot, node.nodeIndex));
this._isDeletedNode = !!baseSnapshot;
this.updateHasChildren();
};

WebInspector.HeapSnapshotInstanceNode._createProvider = function(snapshot, nodeIndex)
{
var showHiddenData = WebInspector.settings.showHeapSnapshotObjectsHiddenProperties.get();
return snapshot.createEdgesProvider(
nodeIndex,
"function(edge) {" +
"    return !edge.isInvisible" +
"        && (" + showHiddenData + " || (!edge.isHidden && !edge.node.isHidden));" +
"}");
}

WebInspector.HeapSnapshotInstanceNode.prototype = {
_createChildNode: function(item)
{
return new WebInspector.HeapSnapshotObjectNode(this._dataGrid, this._isDeletedNode, item, null);
},

_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],
distanceToWindow: ["distanceToWindow", 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.withThousandsSeparator(this._shallowSize);
} else {
data["addedCount"] = "\u2022";
data["addedSize"] = Number.withThousandsSeparator(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,
tree.snapshot.createNodesProviderForClass(className, aggregatesKey));
this._name = className;
this._distanceToWindow = aggregate.distanceToWindow;
this._count = aggregate.count;
this._shallowSize = aggregate.self;
this._retainedSize = aggregate.maxRet;
}

WebInspector.HeapSnapshotConstructorNode.prototype = {
createCell: function(columnIdentifier)
{
var cell = columnIdentifier !== "object" ? this._createValueCell(columnIdentifier) : WebInspector.HeapSnapshotGridNode.prototype.createCell.call(this, columnIdentifier);
if (this._searchMatched)
cell.addStyleClass("highlight");
return cell;
},

_createChildNode: function(item)
{
return new WebInspector.HeapSnapshotInstanceNode(this._dataGrid, null, this._dataGrid.snapshot, item);
},

comparator: function()
{
var sortAscending = this._dataGrid.sortOrder === "ascending";
var sortColumnIdentifier = this._dataGrid.sortColumnIdentifier;
var sortFields = {
object: ["id", sortAscending, "retainedSize", false],
distanceToWindow: ["distanceToWindow", true, "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 };
var view = this.dataGrid.snapshotView;
data["count"] =  Number.withThousandsSeparator(this._count);
data["distanceToWindow"] =  this._distanceToWindow;
data["shallowSize"] = Number.withThousandsSeparator(this._shallowSize);
data["retainedSize"] = Number.withThousandsSeparator(this._retainedSize);
data["count-percent"] =  this._toPercentString(this._countPercent);
data["shallowSize-percent"] = this._toPercentString(this._shallowSizePercent);
data["retainedSize-percent"] = this._toPercentString(this._retainedSizePercent);
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.HeapSnapshotDiffNodesProvider = function(addedNodesProvider, deletedNodesProvider, addedCount, removedCount)
{
this._addedNodesProvider = addedNodesProvider;
this._deletedNodesProvider = deletedNodesProvider;
this._addedCount = addedCount;
this._removedCount = removedCount;
this._serializedItemsCount = 0;
}

WebInspector.HeapSnapshotDiffNodesProvider.prototype = {
dispose: function()
{
this._addedNodesProvider.dispose();
this._deletedNodesProvider.dispose();
},

isEmpty: function(callback)
{
callback(false);
},

serializeSubsequentItems: function(count, callback)
{
function didReceiveAllItems(items)
{
this._serializedItemsCount += items.length;
items.totalLength = this._addedCount + this._removedCount;
callback(items);
}

function didReceiveDeletedItems(addedItems, items)
{
for (var i = 0; i < items.length; i++) {
items[i].isAddedNotRemoved = false;
addedItems.push(items[i]);
}
addedItems.hasNext = items.hasNext;
didReceiveAllItems.call(this, addedItems);
}

function didReceiveAddedItems(items)
{
for (var i = 0; i < items.length; i++)
items[i].isAddedNotRemoved = true;
if (items.length < count)
return this._deletedNodesProvider.serializeSubsequentItems(count - items.length, didReceiveDeletedItems.bind(this, items));

items.totalLength = this._addedCount + this._removedCount;
if (!items.hasNext)
items.hasNext = !!this._removedCount;
didReceiveAllItems.call(this, items);
}

if (this._serializedItemsCount < this._addedCount)
this._addedNodesProvider.serializeSubsequentItems(count, didReceiveAddedItems.bind(this));
else
this._deletedNodesProvider.serializeSubsequentItems(count, didReceiveDeletedItems.bind(this, []));
},

sortAndRewind: function(comparator, callback)
{
this._serializedItemsCount = 0;

function afterSort(ignored)
{
this._deletedNodesProvider.sortAndRewind(comparator, callback);
}
this._addedNodesProvider.sortAndRewind(comparator, afterSort.bind(this));
}
};


WebInspector.HeapSnapshotDiffNode = function(tree, className, diffForClass)
{
WebInspector.HeapSnapshotGridNode.call(this, tree, true,
WebInspector.HeapSnapshotDiffNode._createProvider(tree, className, diffForClass.deletedIndexes, diffForClass.addedCount, diffForClass.removedCount));
this._name = className;

this._addedCount = diffForClass.addedCount;
this._removedCount = diffForClass.removedCount;
this._countDelta = diffForClass.countDelta;
this._addedSize = diffForClass.addedSize;
this._removedSize = diffForClass.removedSize;
this._sizeDelta = diffForClass.sizeDelta;
}

WebInspector.HeapSnapshotDiffNode._createProvider = function(tree, className, deletedIndexes, addedCount, removedCount)
{
var result =  new WebInspector.HeapSnapshotDiffNodesProvider(
tree.snapshot.createAddedNodesProvider(tree.baseSnapshot.uid, className),
tree.baseSnapshot.createDeletedNodesProvider(deletedIndexes),
addedCount, removedCount);
return result;
}

WebInspector.HeapSnapshotDiffNode.prototype = {
_createChildNode: function(item)
{
if (item.isAddedNotRemoved)
return new WebInspector.HeapSnapshotInstanceNode(this._dataGrid, null, this._dataGrid.snapshot, item);
else
return new WebInspector.HeapSnapshotInstanceNode(this._dataGrid, this._dataGrid.baseSnapshot, null, item);
},

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

_signForDelta: function(delta)
{
if (delta === 0)
return "";
if (delta > 0)
return "+";
else
return "\u2212";  
},

get data()
{
var data = {object: this._name};

data["addedCount"] = Number.withThousandsSeparator(this._addedCount);
data["removedCount"] = Number.withThousandsSeparator(this._removedCount);
data["countDelta"] = this._signForDelta(this._countDelta) + Number.withThousandsSeparator(Math.abs(this._countDelta));
data["addedSize"] = Number.withThousandsSeparator(this._addedSize);
data["removedSize"] = Number.withThousandsSeparator(this._removedSize);
data["sizeDelta"] = this._signForDelta(this._sizeDelta) + Number.withThousandsSeparator(Math.abs(this._sizeDelta));

return data;
}
};

WebInspector.HeapSnapshotDiffNode.prototype.__proto__ = WebInspector.HeapSnapshotGridNode.prototype;


WebInspector.HeapSnapshotDominatorObjectNode = function(tree, node)
{
WebInspector.HeapSnapshotGenericObjectNode.call(this, tree, node,
tree.snapshot.createNodesProviderForDominator(node.nodeIndex));
this.updateHasChildren();
};

WebInspector.HeapSnapshotDominatorObjectNode.prototype = {
_createChildNode: function(item)
{
return new WebInspector.HeapSnapshotDominatorObjectNode(this._dataGrid, item);
},

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






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

_parseUintArray: 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);
return false;
}
++index;
}
if (index === length) {
this._json = "";
return true;
}
var nextNumber = 0;
var startIndex = index;
while (index < length) {
var code = this._json.charCodeAt(index);
if (char0 > code || code > char9)
break;
nextNumber *= 10;
nextNumber += (code - char0);
++index;
}
if (index === length) {
this._json = this._json.slice(startIndex);
return true;
}
this._array.push(nextNumber);
}
},

_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);
if (this._snapshot.snapshot.meta) {
var node_fields_count = this._snapshot.snapshot.meta.node_fields.length;
var nodes_length = this._snapshot.snapshot.node_count * node_fields_count;
this._array = new WebInspector.Uint32Array(nodes_length);
this._snapshot.snapshot.meta.separate_edges = true;
this._state = "parse-nodes";
} else {
this._state = "parse-nodes-meta-info";
}
this.pushJSONChunk("");
break;
}
case "parse-nodes-meta-info": {
var closingBracketIndex = this._findBalancedCurlyBrackets();
if (closingBracketIndex === -1)
return;
this._snapshot.snapshot.meta = JSON.parse(this._json.slice(0, closingBracketIndex));
this._json = this._json.slice(closingBracketIndex);
this._array = new WebInspector.Uint32Array();
this._array.push(0);
this._state = "parse-nodes";
this.pushJSONChunk("");
break;
}
case "parse-nodes": {
if (this._parseUintArray())
return;
if (this._snapshot.snapshot.meta.separate_edges) {
this._snapshot.onlyNodes = this._array.array;
this._state = "find-edges";
} else {
this._snapshot.nodes = this._array.array;
this._state = "find-strings";
}
this._array = null;
this.pushJSONChunk("");
break;
}
case "find-edges": {
var edgesToken = "\"edges\"";
var edgesTokenIndex = this._json.indexOf(edgesToken);
if (edgesTokenIndex === -1)
return;
var bracketIndex = this._json.indexOf("[", edgesTokenIndex);
if (bracketIndex === -1)
return;
this._json = this._json.slice(bracketIndex + 1);
var edge_fields_count = this._snapshot.snapshot.meta.edge_fields.length;
var edges_length = this._snapshot.snapshot.edge_count * edge_fields_count;
this._array = new WebInspector.Uint32Array(edges_length);
this._state = "parse-edges";
this.pushJSONChunk("");
break;
}
case "parse-edges": {
if (this._parseUintArray())
return;
this._snapshot.containmentEdges = this._array.array;
this._array = null;
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.HeapSnapshotSortableDataGrid = function(columns)
{
WebInspector.DataGrid.call(this, columns);


this._recursiveSortingDepth = 0;
this.addEventListener("sorting changed", this.sortingChanged, this);
}

WebInspector.HeapSnapshotSortableDataGrid.prototype = {

defaultPopulateCount: function()
{
return 100;
},

dispose: function()
{
var children = this.topLevelNodes();
for (var i = 0, l = children.length; i < l; ++i)
children[i].dispose();
},

resetSortingCache: function()
{
delete this._lastSortColumnIdentifier;
delete this._lastSortAscending;
},

topLevelNodes: function()
{
return this.rootNode().children;
},

changeNameFilter: function(filter)
{
filter = filter.toLowerCase();
var children = this.topLevelNodes();
for (var i = 0, l = children.length; i < l; ++i) {
var node = children[i];
if (node.depth === 0)
node.revealed = node._name.toLowerCase().indexOf(filter) !== -1;
}
this.updateVisibleNodes();
},

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._topLevelNodes;
this.rootNode().removeChildren();
children.sort(sortFunction);
for (var i = 0, l = children.length; i < l; ++i) {
var child = children[i];
this.appendChildAfterSorting(child);
if (child.expanded)
child.sort();
}
this.recursiveSortingLeave();
this.updateVisibleNodes();
},

appendChildAfterSorting: function(child)
{
var revealed = child.revealed;
this.rootNode().appendChild(child);
child.revealed = revealed;
},

updateVisibleNodes: function()
{
},

recursiveSortingEnter: function()
{
++this._recursiveSortingDepth;
},

recursiveSortingLeave: function()
{
if (!this._recursiveSortingDepth)
return;
if (!--this._recursiveSortingDepth)
this.dispatchEventToListeners("sorting complete");
}
};

WebInspector.HeapSnapshotSortableDataGrid.prototype.__proto__ = WebInspector.DataGrid.prototype;



WebInspector.HeapSnapshotViewportDataGrid = function(columns)
{
WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
this.scrollContainer.addEventListener("scroll", this._onScroll.bind(this), true);
this._topLevelNodes = [];
this._topPadding = new WebInspector.HeapSnapshotPaddingNode();
this._bottomPadding = new WebInspector.HeapSnapshotPaddingNode();
}

WebInspector.HeapSnapshotViewportDataGrid.prototype = {
topLevelNodes: function()
{
return this._topLevelNodes;
},

appendChildAfterSorting: function(child)
{

},

updateVisibleNodes: function()
{
var scrollTop = this.scrollContainer.scrollTop;

var viewPortHeight = this.scrollContainer.offsetHeight;

this._removePaddingRows();

var children = this._topLevelNodes;

var i = 0;
var topPadding = 0;
while (i < children.length) {
if (children[i].revealed) {
var newTop = topPadding + children[i].nodeHeight();
if (newTop > scrollTop)
break;
topPadding = newTop;
}
++i;
}

this.rootNode().removeChildren();

var heightToFill = viewPortHeight + (scrollTop - topPadding);
var filledHeight = 0;
while (i < children.length && filledHeight < heightToFill) {
if (children[i].revealed) {
this.rootNode().appendChild(children[i]);
filledHeight += children[i].nodeHeight();
}
++i;
}

var bottomPadding = 0;
while (i < children.length) {
bottomPadding += children[i].nodeHeight();
++i;
}

this._addPaddingRows(topPadding, bottomPadding);
},

appendTopLevelNode: function(node)
{
this._topLevelNodes.push(node);
},

removeTopLevelNodes: function()
{
this.rootNode().removeChildren();
this._topLevelNodes = [];
},

_addPaddingRows: function(top, bottom)
{
if (this._topPadding.element.parentNode !== this.dataTableBody)
this.dataTableBody.insertBefore(this._topPadding.element, this.dataTableBody.firstChild);
if (this._bottomPadding.element.parentNode !== this.dataTableBody)
this.dataTableBody.insertBefore(this._bottomPadding.element, this.dataTableBody.lastChild);
this._topPadding.setHeight(top);
this._bottomPadding.setHeight(bottom);
},

_removePaddingRows: function()
{
this._bottomPadding.removeFromTable();
this._topPadding.removeFromTable();
},

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

_onScroll: function(event)
{
this.updateVisibleNodes();
}
}

WebInspector.HeapSnapshotViewportDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype;


WebInspector.HeapSnapshotPaddingNode = function()
{
this.element = document.createElement("tr");
this.element.addStyleClass("revealed");
}

WebInspector.HeapSnapshotPaddingNode.prototype = {
setHeight: function(height)
{
this.element.style.height = height + "px";
},
removeFromTable: function()
{
var parent = this.element.parentNode;
if (parent)
parent.removeChild(this.element);
}
}



WebInspector.HeapSnapshotContainmentDataGrid = function(columns)
{
columns = columns || {
object: { title: WebInspector.UIString("Object"), disclosure: true, sortable: true },
shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "120px", sortable: true },
retainedSize: { title: WebInspector.UIString("Retained Size"), width: "120px", sortable: true, sort: "descending" }
};
WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
}

WebInspector.HeapSnapshotContainmentDataGrid.prototype = {
setDataSource: function(snapshotView, snapshot, nodeIndex)
{
this.snapshotView = snapshotView;
this.snapshot = snapshot;
var fakeEdge = { nodeIndex: nodeIndex || this.snapshot.rootNodeIndex };
this.setRootNode(new WebInspector.HeapSnapshotObjectNode(this, false, fakeEdge, null));
this.rootNode().sort();
},

sortingChanged: function()
{
this.rootNode().sort();
}
};

WebInspector.HeapSnapshotContainmentDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype;


WebInspector.HeapSnapshotRetainmentDataGrid = function()
{
this.showRetainingEdges = true;
var columns = {
object: { title: WebInspector.UIString("Object"), disclosure: true, sortable: true },
shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "120px", sortable: true },
retainedSize: { title: WebInspector.UIString("Retained Size"), width: "120px", sortable: true },
distanceToWindow: { title: WebInspector.UIString("Distance"), width: "80px", sortable: true, sort: "ascending" }
};
WebInspector.HeapSnapshotContainmentDataGrid.call(this, columns);
}

WebInspector.HeapSnapshotRetainmentDataGrid.prototype = {
_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],
distanceToWindow: ["_distanceToWindow", sortAscending, "_name", true]
}[sortColumn];
},

reset: function()
{
this.rootNode().removeChildren();
this.resetSortingCache();
},
}

WebInspector.HeapSnapshotRetainmentDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotContainmentDataGrid.prototype;


WebInspector.HeapSnapshotConstructorsDataGrid = function()
{
var columns = {
object: { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true },
distanceToWindow: { title: WebInspector.UIString("Distance"), width: "90px", sortable: true },
count: { title: WebInspector.UIString("Objects Count"), width: "90px", sortable: true },
shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "120px", sortable: true },
retainedSize: { title: WebInspector.UIString("Retained Size"), width: "120px", sort: "descending", sortable: true }
};
WebInspector.HeapSnapshotViewportDataGrid.call(this, columns);
this._profileIndex = -1;
this._topLevelNodes = [];
}

WebInspector.HeapSnapshotConstructorsDataGrid.prototype = {
_sortFields: function(sortColumn, sortAscending)
{
return {
object: ["_name", sortAscending, "_count", false],
distanceToWindow: ["_distanceToWindow", sortAscending, "_retainedSize", true],
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._profileIndex === -1)
this._populateChildren();
},

_populateChildren: function()
{
function aggregatesReceived(key, aggregates)
{
for (var constructor in aggregates)
this.appendTopLevelNode(new WebInspector.HeapSnapshotConstructorNode(this, constructor, aggregates[constructor], key));
this.sortingChanged();
}

this.dispose();
this.removeTopLevelNodes();
this.resetSortingCache();

var key = this._profileIndex === -1 ? "allObjects" : this._minNodeId + ".." + this._maxNodeId;
var filter = this._profileIndex === -1 ? null : "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(profiles, profileIndex)
{
this._profileIndex = profileIndex;

delete this._maxNodeId;
delete this._minNodeId;

if (this._profileIndex !== -1) {
this._minNodeId = profileIndex > 0 ? profiles[profileIndex - 1].maxJSObjectId : 0;
this._maxNodeId = profiles[profileIndex].maxJSObjectId;
}

this._populateChildren();
},

};

WebInspector.HeapSnapshotConstructorsDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotViewportDataGrid.prototype;


WebInspector.HeapSnapshotDiffDataGrid = function()
{
var columns = {
object: { title: WebInspector.UIString("Constructor"), disclosure: true, sortable: true },
addedCount: { title: WebInspector.UIString("# New"), width: "72px", sortable: true },
removedCount: { title: WebInspector.UIString("# Deleted"), width: "72px", sortable: true },
countDelta: { title: "# Delta", width: "64px", sortable: true },
addedSize: { title: WebInspector.UIString("Alloc. Size"), width: "72px", sortable: true, sort: "descending" },
removedSize: { title: WebInspector.UIString("Freed Size"), width: "72px", sortable: true },
sizeDelta: { title: "Size Delta", width: "72px", sortable: true }
};
WebInspector.HeapSnapshotViewportDataGrid.call(this, columns);
}

WebInspector.HeapSnapshotDiffDataGrid.prototype = {

defaultPopulateCount: function()
{
return 50;
},

_sortFields: function(sortColumn, sortAscending)
{
return {
object: ["_name", sortAscending, "_count", false],
addedCount: ["_addedCount", sortAscending, "_name", true],
removedCount: ["_removedCount", sortAscending, "_name", true],
countDelta: ["_countDelta", sortAscending, "_name", true],
addedSize: ["_addedSize", sortAscending, "_name", true],
removedSize: ["_removedSize", sortAscending, "_name", true],
sizeDelta: ["_sizeDelta", sortAscending, "_name", true]
}[sortColumn];
},

setDataSource: function(snapshotView, snapshot)
{
this.snapshotView = snapshotView;
this.snapshot = snapshot;
},


setBaseDataSource: function(baseSnapshot)
{
this.baseSnapshot = baseSnapshot;
this.dispose();
this.removeTopLevelNodes();
this.resetSortingCache();
if (this.baseSnapshot === this.snapshot) {
this.dispatchEventToListeners("sorting complete");
return;
}
this._populateChildren();
},

_populateChildren: function()
{
function aggregatesForDiffReceived(aggregatesForDiff)
{
this.snapshot.calculateSnapshotDiff(this.baseSnapshot.uid, aggregatesForDiff, didCalculateSnapshotDiff.bind(this));
function didCalculateSnapshotDiff(diffByClassName)
{
for (var className in diffByClassName) {
var diff = diffByClassName[className];
this.appendTopLevelNode(new WebInspector.HeapSnapshotDiffNode(this, className, diff));
}
this.sortingChanged();
}
}



this.baseSnapshot.aggregatesForDiff(aggregatesForDiffReceived.bind(this));
}
};

WebInspector.HeapSnapshotDiffDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotViewportDataGrid.prototype;


WebInspector.HeapSnapshotDominatorsDataGrid = function()
{
var columns = {
object: { title: WebInspector.UIString("Object"), disclosure: true, sortable: true },
shallowSize: { title: WebInspector.UIString("Shallow Size"), width: "120px", sortable: true },
retainedSize: { title: WebInspector.UIString("Retained Size"), width: "120px", sort: "descending", sortable: true }
};
WebInspector.HeapSnapshotSortableDataGrid.call(this, columns);
}

WebInspector.HeapSnapshotDominatorsDataGrid.prototype = {

defaultPopulateCount: function()
{
return 25;
},

setDataSource: function(snapshotView, snapshot)
{
this.snapshotView = snapshotView;
this.snapshot = snapshot;

var fakeNode = { nodeIndex: this.snapshot.rootNodeIndex };
this.setRootNode(new WebInspector.HeapSnapshotDominatorObjectNode(this, fakeNode));
this.rootNode().sort();
},

sortingChanged: function()
{
this.rootNode().sort();
}
};

WebInspector.HeapSnapshotDominatorsDataGrid.prototype.__proto__ = WebInspector.HeapSnapshotSortableDataGrid.prototype;






WebInspector.HeapSnapshotView = function(parent, profile)
{
WebInspector.View.call(this);

this.element.addStyleClass("heap-snapshot-view");

this.parent = parent;
this.parent.addEventListener("profile added", this._updateBaseOptions, this);
this.parent.addEventListener("profile added", this._updateFilterOptions, this);

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("mousedown", this._mouseDownInContentsGrid.bind(this), true);
this.containmentDataGrid.show(this.containmentView.element);
this.containmentDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this);

this.constructorsView = new WebInspector.View();
this.constructorsView.element.addStyleClass("view");
this.constructorsView.element.appendChild(this._createToolbarWithClassNameFilter());

this.constructorsDataGrid = new WebInspector.HeapSnapshotConstructorsDataGrid();
this.constructorsDataGrid.element.addStyleClass("class-view-grid");
this.constructorsDataGrid.element.addEventListener("mousedown", this._mouseDownInContentsGrid.bind(this), true);
this.constructorsDataGrid.show(this.constructorsView.element);
this.constructorsDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this);

this.diffView = new WebInspector.View();
this.diffView.element.addStyleClass("view");
this.diffView.element.appendChild(this._createToolbarWithClassNameFilter());

this.diffDataGrid = new WebInspector.HeapSnapshotDiffDataGrid();
this.diffDataGrid.element.addStyleClass("class-view-grid");
this.diffDataGrid.show(this.diffView.element);
this.diffDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this);

this.dominatorView = new WebInspector.View();
this.dominatorView.element.addStyleClass("view");
this.dominatorDataGrid = new WebInspector.HeapSnapshotDominatorsDataGrid();
this.dominatorDataGrid.element.addEventListener("mousedown", this._mouseDownInContentsGrid.bind(this), true);
this.dominatorDataGrid.show(this.dominatorView.element);
this.dominatorDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._selectionChanged, this);

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("Object's retaining tree");
retainingPathsTitleDiv.appendChild(retainingPathsTitle);
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.HeapSnapshotRetainmentDataGrid();
this.retainmentDataGrid.show(this.retainmentView.element);
this.retainmentDataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._inspectedObjectChanged, this);
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.helpButton = new WebInspector.StatusBarButton("", "heap-snapshot-help-status-bar-item status-bar-item");
this.helpButton.addEventListener("click", this._helpClicked, this);

this._popoverHelper = new WebInspector.ObjectPopoverHelper(this.element, this._getHoverAnchor.bind(this), this._resolveObjectForPopover.bind(this), undefined, 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);
}
}

WebInspector.HeapSnapshotView.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.helpButton.element];
},

get profile()
{
return this.parent.getProfile(WebInspector.HeapSnapshotProfileType.TypeId, this._profileUid);
},

get profileWrapper()
{
return this.profile.proxy;
},

get baseProfile()
{
return this.parent.getProfile(WebInspector.HeapSnapshotProfileType.TypeId, this._baseProfileUid);
},

get baseProfileWrapper()
{
return this.baseProfile.proxy;
},

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;
this._popoverHelper.hidePopover();
if (this.helpPopover && this.helpPopover.visible)
this.helpPopover.hide();
},

onResize: function()
{
var height = this.retainmentView.element.clientHeight;
this._updateRetainmentViewHeight(height);
},

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.rootNode().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.rootNode().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;
var dataGrid =   this.dataGrid;
this._loadProfile(this._baseProfileUid, dataGrid.setBaseDataSource.bind(dataGrid));

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._profiles(), profileIndex);

if (!this.currentQuery || !this._searchFinishedCallback || !this._searchResults)
return;




this._searchFinishedCallback(this, -this._searchResults.length);
this.performSearch(this.currentQuery, this._searchFinishedCallback);
},

_createToolbarWithClassNameFilter: function()
{
var toolbar = document.createElement("div");
toolbar.addStyleClass("class-view-toolbar");
var classNameFilter = document.createElement("input");
classNameFilter.addStyleClass("class-name-filter");
classNameFilter.setAttribute("placeholder", WebInspector.UIString("Class filter"));
classNameFilter.addEventListener("keyup", this._changeNameFilter.bind(this, classNameFilter), false);
toolbar.appendChild(classNameFilter);
return toolbar;
},

_changeNameFilter: function(classNameInputElement)
{
var filter = classNameInputElement.value;
this.dataGrid.changeNameFilter(filter);
},

_profiles: function()
{
return WebInspector.panels.profiles.getProfiles(WebInspector.HeapSnapshotProfileType.TypeId);
},

_loadProfile: function(profileUid, callback)
{
WebInspector.panels.profiles.loadHeapSnapshot(profileUid, callback);
},

isDetailedSnapshot: function(snapshot)
{
var s = new WebInspector.HeapSnapshot(snapshot);
for (var iter = s.rootNode.edges; iter.hasNext(); iter.next())
if (iter.edge.node.name === "(GC roots)")
return true;
return false;
},

processLoadedSnapshot: function(profile, snapshot)
{
profile.nodes = snapshot.nodes;
profile.strings = snapshot.strings;
var s = new WebInspector.HeapSnapshot(profile);
profile.sidebarElement.subtitle = Number.bytesToString(s.totalSize);
},

_selectionChanged: function(event)
{
var selectedNode = event.target.selectedNode;
this._setRetainmentDataGridSource(selectedNode);
this._inspectedObjectChanged(event);
},

_inspectedObjectChanged: function(event)
{
var selectedNode = event.target.selectedNode;
if (selectedNode instanceof WebInspector.HeapSnapshotGenericObjectNode)
ConsoleAgent.addInspectedHeapObject(selectedNode.snapshotNodeId);
},

_setRetainmentDataGridSource: function(nodeItem)
{
if (nodeItem && nodeItem.snapshotNodeIndex)
this.retainmentDataGrid.setDataSource(this, nodeItem.isDeletedNode ? nodeItem.dataGrid.baseSnapshot : nodeItem.dataGrid.snapshot, nodeItem.snapshotNodeIndex);
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;

event.consume(true);
},

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

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

_resolveObjectForPopover: function(element, showCallback, objectGroupName)
{
element.node.queryObjectContent(showCallback, objectGroupName);
},

_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 = "heap-snapshot-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);

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

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();
}
if (this.helpPopover.visible)
this.helpPopover.hide();
else
this.helpPopover.show(this._helpPopoverContentElement, this.helpButton.element);
},

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

WebInspector.elementDragStart(this.retainmentViewHeader, this._retainersHeaderDragging.bind(this), this._endRetainersHeaderDragging.bind(this), event, "row-resize");
this._previousDragPosition = event.pageY;
event.consume();
},

_retainersHeaderDragging: function(event)
{
var height = this.retainmentView.element.clientHeight;
height += this._previousDragPosition - event.pageY;
this._previousDragPosition = event.pageY;
this._updateRetainmentViewHeight(height);
event.consume(true);
},

_endRetainersHeaderDragging: function(event)
{
WebInspector.elementDragEnd(event);
delete this._previousDragPosition;
event.consume();
},

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

WebInspector.HeapSnapshotView.prototype.__proto__ = WebInspector.View.prototype;

WebInspector.settings.showHeapSnapshotObjectsHiddenProperties = WebInspector.settings.createSetting("showHeaSnapshotObjectsHiddenProperties", false);


WebInspector.HeapSnapshotProfileType = function()
{
WebInspector.ProfileType.call(this, WebInspector.HeapSnapshotProfileType.TypeId, WebInspector.UIString("Take Heap Snapshot"));
}

WebInspector.HeapSnapshotProfileType.TypeId = "HEAP";

WebInspector.HeapSnapshotProfileType.prototype = {
get buttonTooltip()
{
return WebInspector.UIString("Take heap snapshot.");
},

buttonClicked: function()
{
WebInspector.panels.profiles.takeHeapSnapshot();
},

get treeItemTitle()
{
return WebInspector.UIString("HEAP SNAPSHOTS");
},

get description()
{
return WebInspector.UIString("Heap snapshot profiles show memory distribution among your page's JavaScript objects and related DOM nodes.");
},

createSidebarTreeElementForProfile: function(profile)
{
return new WebInspector.ProfileSidebarTreeElement(profile, WebInspector.UIString("Snapshot %d"), "heap-snapshot-sidebar-tree-item");
},

createView: function(profile)
{
return new WebInspector.HeapSnapshotView(WebInspector.panels.profiles, profile);
},

createTemporaryProfile: function()
{
return new WebInspector.ProfileHeader(WebInspector.HeapSnapshotProfileType.TypeId, WebInspector.UIString("Snapshotting\u2026"));
},

createProfile: function(profile)
{
return new WebInspector.HeapProfileHeader(profile.typeId, profile.title, profile.uid, profile.maxJSObjectId);
}
}

WebInspector.HeapSnapshotProfileType.prototype.__proto__ = WebInspector.ProfileType.prototype;






WebInspector.DebuggerModel = function()
{
this._debuggerPausedDetails = null;

this._scripts = {};
this._scriptsBySourceURL = {};

this._canSetScriptSource = false;
this._breakpointsActive = true;

InspectorBackend.registerDebuggerDispatcher(new WebInspector.DebuggerDispatcher(this));
}


WebInspector.DebuggerModel.Location = function(script, lineNumber, columnNumber)
{
this.scriptId = script.scriptId;
this.lineNumber = lineNumber;
this.columnNumber = columnNumber;
}

WebInspector.DebuggerModel.Events = {
DebuggerWasEnabled: "DebuggerWasEnabled",
DebuggerWasDisabled: "DebuggerWasDisabled",
DebuggerPaused: "DebuggerPaused",
DebuggerResumed: "DebuggerResumed",
ParsedScriptSource: "ParsedScriptSource",
FailedToParseScriptSource: "FailedToParseScriptSource",
BreakpointResolved: "BreakpointResolved",
GlobalObjectCleared: "GlobalObjectCleared",
CallFrameSelected: "CallFrameSelected",
ExecutionLineChanged: "ExecutionLineChanged",
ConsoleCommandEvaluatedInSelectedCallFrame: "ConsoleCommandEvaluatedInSelectedCallFrame",
BreakpointsActiveStateChanged: "BreakpointsActiveStateChanged"
}

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.scriptForId(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;
var scripts = this._scriptsBySourceURL[url] || [];
for (var i = 0, l = scripts.length; i < l; ++i) {
var script = scripts[i];
if (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._setDebuggerPausedDetails(null);
this._reset();
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.GlobalObjectCleared);
},

_reset: function()
{
this._scripts = {};
this._scriptsBySourceURL = {};
},


get scripts()
{
return this._scripts;
},


scriptForId: function(scriptId)
{
return this._scripts[scriptId] || null;
},


setScriptSource: function(scriptId, newSource, callback)
{
this._scripts[scriptId].editSource(newSource, this._didEditScriptSource.bind(this, scriptId, newSource, callback));
},


_didEditScriptSource: function(scriptId, newSource, callback, error, callFrames)
{
callback(error);
if (!error && callFrames && callFrames.length)
this._pausedScript(callFrames, this._debuggerPausedDetails.reason, this._debuggerPausedDetails.auxData);
},


get callFrames()
{
return this._debuggerPausedDetails ? this._debuggerPausedDetails.callFrames : null;
},


debuggerPausedDetails: function()
{
return this._debuggerPausedDetails;
},


_setDebuggerPausedDetails: function(debuggerPausedDetails)
{
if (this._debuggerPausedDetails)
this._debuggerPausedDetails.dispose();
this._debuggerPausedDetails = debuggerPausedDetails;
if (this._debuggerPausedDetails)
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerPaused, this._debuggerPausedDetails);
if (debuggerPausedDetails)
this.setSelectedCallFrame(debuggerPausedDetails.callFrames[0]);
else
this.setSelectedCallFrame(null);
},


_pausedScript: function(callFrames, reason, auxData)
{
this._setDebuggerPausedDetails(new WebInspector.DebuggerPausedDetails(this, callFrames, reason, auxData));
},

_resumedScript: function()
{
this._setDebuggerPausedDetails(null);
if (this._executionLineLiveLocation)
this._executionLineLiveLocation.dispose();
this._executionLineLiveLocation = null;
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.DebuggerResumed);
},


_parsedScriptSource: function(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript, sourceMapURL)
{
var script = new WebInspector.Script(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, isContentScript, sourceMapURL);
this._registerScript(script);
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.ParsedScriptSource, script);
},


_registerScript: function(script)
{
this._scripts[script.scriptId] = script;
if (script.sourceURL) {
var scripts = this._scriptsBySourceURL[script.sourceURL];
if (!scripts) {
scripts = [];
this._scriptsBySourceURL[script.sourceURL] = scripts;
}
scripts.push(script);
}
},


_failedToParseScriptSource: function(sourceURL, source, startingLine, errorLine, errorMessage)
{
var script = new WebInspector.Script("", sourceURL, startingLine, 0, 0, 0, false);
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.FailedToParseScriptSource, script);
},


createRawLocation: function(script, lineNumber, columnNumber)
{
if (script.sourceURL)
return this.createRawLocationByURL(script.sourceURL, lineNumber, columnNumber)
return new WebInspector.DebuggerModel.Location(script, lineNumber, columnNumber);
},


createRawLocationByURL: function(sourceURL, lineNumber, columnNumber)
{
var closestScript = null;
var scripts = this._scriptsBySourceURL[sourceURL] || [];
for (var i = 0, l = scripts.length; i < l; ++i) {
var script = scripts[i];
if (!closestScript)
closestScript = script;
if (script.lineOffset > lineNumber || (script.lineOffset === lineNumber && script.columnOffset > columnNumber))
continue;
if (script.endLine < lineNumber || (script.endLine === lineNumber && script.endColumn <= columnNumber))
continue;
closestScript = script;
break;
}
return closestScript ? new WebInspector.DebuggerModel.Location(closestScript, lineNumber, columnNumber) : null;
},


isPaused: function()
{
return !!this.debuggerPausedDetails();
},


setSelectedCallFrame: function(callFrame)
{
if (this._executionLineLiveLocation)
this._executionLineLiveLocation.dispose();
delete this._executionLineLiveLocation;

this._selectedCallFrame = callFrame;
if (!this._selectedCallFrame)
return;

this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.CallFrameSelected, callFrame);

function updateExecutionLine(uiLocation)
{
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.ExecutionLineChanged, uiLocation);
}
this._executionLineLiveLocation = callFrame.script.createLiveLocation(callFrame._payload.location, updateExecutionLine.bind(this));
},


selectedCallFrame: function()
{
return this._selectedCallFrame;
},


evaluateOnSelectedCallFrame: function(code, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, 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.DebuggerModel.Events.ConsoleCommandEvaluatedInSelectedCallFrame);
}

this.selectedCallFrame().evaluate(code, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, 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);
}
},


setBreakpointsActive: function(active)
{
if (this._breakpointsActive === active)
return;
this._breakpointsActive = active;
DebuggerAgent.setBreakpointsActive(active);
this.dispatchEventToListeners(WebInspector.DebuggerModel.Events.BreakpointsActiveStateChanged, active);
},


breakpointsActive: function()
{
return this._breakpointsActive;
},


createLiveLocation: function(location, updateDelegate)
{
var script = this._scripts[location.scriptId];
return script.createLiveLocation(location, updateDelegate);
},


rawLocationToUILocation: function(rawLocation)
{
var script = this._scripts[rawLocation.scriptId];
if (!script)
return null;
return script.rawLocationToUILocation(rawLocation);
}
}

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, sourceMapURL)
{
this._debuggerModel._parsedScriptSource(scriptId, sourceURL, startLine, startColumn, endLine, endColumn, !!isContentScript, sourceMapURL);
},


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.CallFrame = function(script, payload)
{
this._script = script;
this._payload = payload;
this._locations = [];
}

WebInspector.DebuggerModel.CallFrame.prototype = {

get script()
{
return this._script;
},


get type()
{
return this._payload.type;
},


get scopeChain()
{
return this._payload.scopeChain;
},


get this()
{
return this._payload.this;
},


get functionName()
{
return this._payload.functionName;
},


get location()
{
return this._payload.location;
},


evaluate: function(code, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, callback)
{

function didEvaluateOnCallFrame(error, result, wasThrown)
{
if (error) {
console.error(error);
callback(null, false);
return;
}
callback(result, wasThrown);
}
DebuggerAgent.evaluateOnCallFrame(this._payload.callFrameId, code, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, didEvaluateOnCallFrame.bind(this));
},


createLiveLocation: function(updateDelegate)
{
var location = this._script.createLiveLocation(this._payload.location, updateDelegate);
this._locations.push(location);
return location;
},

dispose: function(updateDelegate)
{
for (var i = 0; i < this._locations.length; ++i)
this._locations[i].dispose();
this._locations = [];
}
}


WebInspector.DebuggerPausedDetails = function(model, callFrames, reason, auxData)
{
this.callFrames = [];
for (var i = 0; i < callFrames.length; ++i) {
var callFrame = callFrames[i];
var script = model.scriptForId(callFrame.location.scriptId);
if (script)
this.callFrames.push(new WebInspector.DebuggerModel.CallFrame(script, callFrame));
}
this.reason = reason;
this.auxData = auxData;
}

WebInspector.DebuggerPausedDetails.prototype = {
dispose: function()
{
for (var i = 0; i < this.callFrames.length; ++i) {
var callFrame = this.callFrames[i];
callFrame.dispose();
}
}
}


WebInspector.debuggerModel = null;






WebInspector.UILocation = function(uiSourceCode, lineNumber, columnNumber)
{
this.uiSourceCode = uiSourceCode;
this.lineNumber = lineNumber;
this.columnNumber = columnNumber;
}


WebInspector.LiveLocation = function()
{
}

WebInspector.LiveLocation.prototype = {
update: function(rawLocation) { },

dispose: function() { }
}


WebInspector.SourceMapping = function()
{
}

WebInspector.SourceMapping.prototype = {

rawLocationToUILocation: function(rawLocation) { },


uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) { }
}


WebInspector.ScriptMapping = function()
{
}

WebInspector.ScriptMapping.Events = {
UISourceCodeListChanged: "ui-source-code-list-changed"
}

WebInspector.ScriptMapping.prototype = {

rawLocationToUILocation: function(rawLocation) {},


uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber) {},


uiSourceCodeList: function() {}
}

WebInspector.ScriptMapping.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.MainScriptMapping = function()
{
this._mappings = [];

this._resourceMapping = new WebInspector.ResourceScriptMapping();
this._mappings.push(this._resourceMapping);
this._compilerMapping = new WebInspector.CompilerScriptMapping();
this._mappings.push(this._compilerMapping);
this._snippetsMapping = new WebInspector.SnippetsScriptMapping();
this._mappings.push(this._snippetsMapping);

for (var i = 0; i < this._mappings.length; ++i)
this._mappings[i].addEventListener(WebInspector.ScriptMapping.Events.UISourceCodeListChanged, this._handleUISourceCodeListChanged, this);

this._mappingForScriptId = {};
this._mappingForUISourceCode = new Map();
}

WebInspector.MainScriptMapping.Events = {
UISourceCodeListChanged: "ui-source-code-list-changed"
}

WebInspector.MainScriptMapping.prototype = {

rawLocationToUILocation: function(rawLocation)
{
return this._mappingForScriptId[rawLocation.scriptId].rawLocationToUILocation(rawLocation);
},


uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
{
return this._mappingForUISourceCode.get(uiSourceCode).uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber);
},


uiSourceCodeList: function()
{
var result = [];
for (var i = 0; i < this._mappings.length; ++i) {
var uiSourceCodeList = this._mappings[i].uiSourceCodeList();
for (var j = 0; j < uiSourceCodeList.length; ++j)
result.push(uiSourceCodeList[j]);
}
return result;
},


addScript: function(script)
{
var mapping = this._mappingForScript(script);
this._mappingForScriptId[script.scriptId] = mapping;
mapping.addScript(script);
},


_mappingForScript: function(script)
{
if (WebInspector.experimentsSettings.snippetsSupport.isEnabled()) {
if (WebInspector.snippetsModel.snippetIdForSourceURL(script.sourceURL))
return this._snippetsMapping;
}

if (WebInspector.settings.sourceMapsEnabled.get() && script.sourceMapURL) {
if (this._compilerMapping.loadSourceMapForScript(script))
return this._compilerMapping;
}

return this._resourceMapping;
},


_handleUISourceCodeListChanged: function(event)
{
var scriptMapping =   event.target;
var removedItems =   event.data["removedItems"];
var addedItems =   event.data["addedItems"];

for (var i = 0; i < removedItems.length; ++i)
this._mappingForUISourceCode.remove(removedItems[i]);
for (var i = 0; i < addedItems.length; ++i)
this._mappingForUISourceCode.put(addedItems[i], scriptMapping);
this.dispatchEventToListeners(WebInspector.MainScriptMapping.Events.UISourceCodeListChanged, event.data);
},


setFormatSource: function(formatSource)
{
this._resourceMapping.setFormatSource(formatSource);
},


forceUpdateSourceMapping: function(rawLocation)
{
if (this._mappingForScriptId[rawLocation.scriptId] === this._resourceMapping)
this._resourceMapping.forceUpdateSourceMapping(rawLocation);
},

reset: function()
{
for (var i = 0; i < this._mappings.length; ++i)
this._mappings[i].reset();
this._mappingForScriptId = {};
this._mappingForUISourceCode = new Map();
}
}

WebInspector.MainScriptMapping.prototype.__proto__ = WebInspector.Object.prototype;







WebInspector.UISourceCode = function(id, url, contentProvider)
{
this._id = id;
this._url = url;
this._parsedURL = new WebInspector.ParsedURL(url);
this._contentProvider = contentProvider;
this.isContentScript = false;
this.isEditable = false;

this._requestContentCallbacks = [];
}

WebInspector.UISourceCode.Events = {
ContentChanged: "ContentChanged",
ConsoleMessageAdded: "ConsoleMessageAdded",
ConsoleMessagesCleared: "ConsoleMessagesCleared"
}

WebInspector.UISourceCode.prototype = {

get id()
{
return this._id;
},


get url()
{
return this._url;
},


get parsedURL()
{
return this._parsedURL;
},


requestContent: function(callback)
{
if (this._contentLoaded) {
callback(this._content, false, this._mimeType);
return;
}

this._requestContentCallbacks.push(callback);
if (this._requestContentCallbacks.length === 1)
this._contentProvider.requestContent(this._didRequestContent.bind(this));
},


contentChanged: function(newContent)
{
console.assert(this._contentLoaded);
var oldContent = this._content;
this._content = newContent;
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.ContentChanged, {oldContent: oldContent, content: newContent});
},


searchInContent: function(query, caseSensitive, isRegex, callback)
{
this._contentProvider.searchInContent(query, caseSensitive, isRegex, callback);
},


_didRequestContent: function(content, contentEncoded, mimeType)
{
this._contentLoaded = true;
this._mimeType = mimeType;
this._content = content;

for (var i = 0; i < this._requestContentCallbacks.length; ++i)
this._requestContentCallbacks[i](content, contentEncoded, mimeType);
this._requestContentCallbacks = [];
},


consoleMessages: function() {}
}

WebInspector.UISourceCode.prototype.__proto__ = WebInspector.Object.prototype;






WebInspector.JavaScriptSource = function(id, url, contentProvider)
{
WebInspector.UISourceCode.call(this, id, url, contentProvider);


this._consoleMessages = [];
}

WebInspector.JavaScriptSource.prototype = {

consoleMessages: function()
{
return this._consoleMessages;
},


consoleMessageAdded: function(message)
{
this._consoleMessages.push(message);
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.ConsoleMessageAdded, message);
},

consoleMessagesCleared: function()
{
this._consoleMessages = [];
this.dispatchEventToListeners(WebInspector.UISourceCode.Events.ConsoleMessagesCleared);
}
}

WebInspector.JavaScriptSource.prototype.__proto__ = WebInspector.UISourceCode.prototype;






WebInspector.LinkifierFormatter = function()
{
}

WebInspector.LinkifierFormatter.prototype = {

formatLiveAnchor: function(anchor, uiLocation) { }
}


WebInspector.Linkifier = function(formatter)
{
this._formatter = formatter || new WebInspector.Linkifier.DefaultFormatter();
this._liveLocations = [];
}

WebInspector.Linkifier.prototype = {

linkifyLocation: function(sourceURL, lineNumber, columnNumber, classes)
{
var rawLocation = WebInspector.debuggerModel.createRawLocationByURL(sourceURL, lineNumber, columnNumber || 0);
if (!rawLocation)
return WebInspector.linkifyResourceAsNode(sourceURL, lineNumber, classes);
return this.linkifyRawLocation(rawLocation, classes);
},


linkifyRawLocation: function(rawLocation, classes)
{
var script = WebInspector.debuggerModel.scriptForId(rawLocation.scriptId);
if (!script)
return null;
var anchor = WebInspector.linkifyURLAsNode("", "", classes, false);
var liveLocation = script.createLiveLocation(rawLocation, this._updateAnchor.bind(this, anchor));
this._liveLocations.push(liveLocation);
return anchor;
},

reset: function()
{
for (var i = 0; i < this._liveLocations.length; ++i)
this._liveLocations[i].dispose();
this._liveLocations = [];
},


_updateAnchor: function(anchor, uiLocation)
{
anchor.preferredPanel = "scripts";
anchor.href = uiLocation.uiSourceCode.url;
anchor.uiSourceCode = uiLocation.uiSourceCode;
anchor.lineNumber = uiLocation.lineNumber;
this._formatter.formatLiveAnchor(anchor, uiLocation);
}
}


WebInspector.Linkifier.DefaultFormatter = function(maxLength)
{
this._maxLength = maxLength;
}

WebInspector.Linkifier.DefaultFormatter.prototype = {

formatLiveAnchor: function(anchor, uiLocation)
{
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.Linkifier.DefaultFormatter.prototype.__proto__ = WebInspector.LinkifierFormatter.prototype;






WebInspector.DebuggerPresentationModel = function()
{
this._scriptMapping = new WebInspector.MainScriptMapping();
this._scriptMapping.addEventListener(WebInspector.MainScriptMapping.Events.UISourceCodeListChanged, this._handleUISourceCodeListChanged, this);

this._presentationCallFrames = [];

this._breakpointManager = new WebInspector.BreakpointManager(WebInspector.settings.breakpoints, WebInspector.debuggerModel, this._scriptMapping);
this._breakpointsActive = true;

this._pendingConsoleMessages = {};
this._consoleMessageLiveLocations = [];

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.CallFrameSelected, this._callFrameSelected, 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"
}

WebInspector.DebuggerPresentationModel.prototype = {
get breakpointManager()
{
return this._breakpointManager;
},


rawLocationToUILocation: function(rawLocation)
{
return this._scriptMapping.rawLocationToUILocation(rawLocation);
},


uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
{
return this._scriptMapping.uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber);
},


createLiveLocation: function(rawLocation, updateDelegate)
{
var script = WebInspector.debuggerModel.scriptForId(rawLocation.scriptId);
return script.createLiveLocation(rawLocation, updateDelegate);
},


_parsedScriptSource: function(event)
{
var script =   event.data;
this._scriptMapping.addScript(script);
this._addPendingConsoleMessagesToScript(script);
},


_failedToParseScriptSource: function(event)
{
this._parsedScriptSource(event);
},

_callFrameSelected: function(event)
{
var callFrame =   event.data;
this._scriptMapping.forceUpdateSourceMapping(callFrame.location);
},


uiSourceCodes: function()
{
return this._scriptMapping.uiSourceCodeList();
},


_handleUISourceCodeListChanged: function(event)
{
var removedItems =   event.data["removedItems"];
var addedItems =   event.data["addedItems"];

for (var i = 0; i < addedItems.length; ++i)
WebInspector.debuggerPresentationModel.breakpointManager.restoreBreakpoints(addedItems[i]);

if (!removedItems.length) {
for (var i = 0; i < addedItems.length; ++i)
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.UISourceCodeAdded, addedItems[i]);
} else if (!addedItems.length) {
for (var i = 0; i < addedItems.length; ++i)
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.UISourceCodeRemoved, removedItems[i]);
} else {
var eventData = { uiSourceCodeList: addedItems, oldUISourceCodeList: removedItems };
this.dispatchEventToListeners(WebInspector.DebuggerPresentationModel.Events.UISourceCodeReplaced, eventData);
}
},


canEditScriptSource: function(uiSourceCode)
{
return WebInspector.debuggerModel.canSetScriptSource() && uiSourceCode.isEditable;
},


setScriptSource: function(uiSourceCode, newSource, callback)
{
var rawLocation = this.uiLocationToRawLocation(uiSourceCode, 0, 0);
var script = WebInspector.debuggerModel.scriptForId(rawLocation.scriptId);


function didEditScriptSource(error)
{
callback(error);
if (error)
return;

var resource = WebInspector.resourceForURL(script.sourceURL);
if (resource)
resource.addRevision(newSource);

uiSourceCode.contentChanged(newSource);
}
WebInspector.debuggerModel.setScriptSource(script.scriptId, newSource, didEditScriptSource.bind(this));
},


setFormatSource: function(formatSource)
{
this._breakpointManager.reset();
this._scriptMapping.setFormatSource(formatSource);
},


_consoleMessageAdded: function(event)
{
var message =   event.data;
if (!message.url || !message.isErrorOrWarning())
return;

var rawLocation = message.location();
if (rawLocation)
this._addConsoleMessageToScript(message, rawLocation);
else
this._addPendingConsoleMessage(message);
},


_addConsoleMessageToScript: function(message, rawLocation)
{
function updateLocation(uiLocation)
{
var presentationMessage = new WebInspector.PresentationConsoleMessage(uiLocation.uiSourceCode, uiLocation.lineNumber, message);
uiLocation.uiSourceCode.consoleMessageAdded(presentationMessage);
}
var liveLocation = this.createLiveLocation(rawLocation, updateLocation.bind(this));
this._consoleMessageLiveLocations.push(liveLocation);
},


_addPendingConsoleMessage: function(message)
{
if (!this._pendingConsoleMessages[message.url])
this._pendingConsoleMessages[message.url] = [];
this._pendingConsoleMessages[message.url].push(message);
},


_addPendingConsoleMessagesToScript: function(script)
{
var messages = this._pendingConsoleMessages[script.sourceURL];
if (!messages)
return;

var pendingMessages = [];
for (var i = 0; i < messages.length; i++) {
var message = messages[i];
var rawLocation = message.location();
if (script.scriptId === rawLocation.scriptId)
this._addConsoleMessageToScript(message, rawLocation);
else
pendingMessages.push(message);
}

if (pendingMessages.length)
this._pendingConsoleMessages[script.sourceURL] = pendingMessages;
else
delete this._pendingConsoleMessages[script.sourceURL];
},

_consoleCleared: function()
{
this._pendingConsoleMessages = {};
for (var i = 0; i < this._consoleMessageLiveLocations.length; ++i)
this._consoleMessageLiveLocations[i].dispose();
this._consoleMessageLiveLocations = [];
var uiSourceCodes = this.uiSourceCodes();
for (var i = 0; i < uiSourceCodes.length; ++i)
uiSourceCodes[i].consoleMessagesCleared();
},


continueToLine: function(uiSourceCode, lineNumber)
{
var rawLocation = this.uiLocationToRawLocation(uiSourceCode, lineNumber, 0);
WebInspector.debuggerModel.continueToLocation(rawLocation);
},

removeAllBreakpoints: function()
{
this._breakpointManager.removeAllBreakpoints();
},

_debuggerReset: function()
{
this._scriptMapping.reset();
this._pendingConsoleMessages = {};
this._consoleMessageLiveLocations = [];
}
}

WebInspector.DebuggerPresentationModel.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.PresentationConsoleMessage = function(uiSourceCode, lineNumber, originalMessage)
{
this.uiSourceCode = uiSourceCode;
this.lineNumber = lineNumber;
this.originalMessage = originalMessage;
}


WebInspector.DebuggerPresentationModelResourceBinding = function(model)
{
this._presentationModel = model;
WebInspector.Resource.registerDomainModelBinding(WebInspector.resourceTypes.Script, this);
}

WebInspector.DebuggerPresentationModelResourceBinding.prototype = {

canSetContent: function(resource)
{
var uiSourceCode = this._uiSourceCodeForResource(resource);
return !!uiSourceCode && this._presentationModel.canEditScriptSource(uiSourceCode);
},


setContent: function(resource, content, majorChange, userCallback)
{
if (!majorChange)
return;

var uiSourceCode = this._uiSourceCodeForResource(resource);
if (!uiSourceCode) {
userCallback("Resource is not editable");
return;
}

resource.requestContent(this._setContentWithInitialContent.bind(this, uiSourceCode, content, userCallback));
},


_uiSourceCodeForResource: function(resource)
{
var uiSourceCodes = this._presentationModel.uiSourceCodes();
for (var i = 0; i < uiSourceCodes.length; ++i) {
if (uiSourceCodes[i].url === resource.url)
return uiSourceCodes[i];
}
return null;
},


_setContentWithInitialContent: function(uiSourceCode, content, userCallback, oldContent, oldContentEncoded, mimeType)
{

function callback(error)
{
if (userCallback)
userCallback(error);
}
this._presentationModel.setScriptSource(uiSourceCode, content, callback.bind(this));
}
}

WebInspector.DebuggerPresentationModelResourceBinding.prototype.__proto__ = WebInspector.ResourceDomainModelBinding.prototype;


WebInspector.debuggerPresentationModel = null;






WebInspector.BreakpointManager = function(breakpointStorage, debuggerModel, sourceMapping)
{
this._storage = new WebInspector.BreakpointManager.Storage(this, breakpointStorage);
this._debuggerModel = debuggerModel;
this._sourceMapping = sourceMapping;

this._breakpoints = [];
this._breakpointForDebuggerId = {};
this._breakpointForUILocation = {};
this._uiSourceCodeIds = {};

this._debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.BreakpointResolved, this._breakpointResolved, this);
this._debuggerModel.addEventListener(WebInspector.DebuggerModel.Events.GlobalObjectCleared, this._debuggerReset, this);
}

WebInspector.BreakpointManager.Events = {
BreakpointAdded: "breakpoint-added",
BreakpointRemoved: "breakpoint-removed"
}

WebInspector.BreakpointManager.prototype = {

restoreBreakpoints: function(uiSourceCode)
{
if (!uiSourceCode.id || this._uiSourceCodeIds[uiSourceCode.id])
return;
this._uiSourceCodeIds[uiSourceCode.id] = true;


for (var debuggerId in this._breakpointForDebuggerId) {
var breakpoint = this._breakpointForDebuggerId[debuggerId];
if (breakpoint._primaryUILocation.uiSourceCode.id !== uiSourceCode.id)
continue;
this._debuggerModel.removeBreakpoint(debuggerId);
delete this._breakpointForDebuggerId[debuggerId];
}
this._storage.restoreBreakpoints(uiSourceCode);
},


setBreakpoint: function(uiSourceCode, lineNumber, condition, enabled, doNotActivateBreakpoints)
{
if (!doNotActivateBreakpoints)
this._debuggerModel.setBreakpointsActive(true);

var breakpoint = this.findBreakpoint(uiSourceCode, lineNumber);
if (breakpoint) {
breakpoint._updateBreakpoint(condition, enabled);
return breakpoint;
}
breakpoint = new WebInspector.BreakpointManager.Breakpoint(this, uiSourceCode, lineNumber, condition, enabled);
this._breakpoints.push(breakpoint);
return breakpoint;
},


findBreakpoint: function(uiSourceCode, lineNumber)
{
return this._breakpointForUILocation[uiSourceCode.id + ":" + lineNumber];
},


breakpointLocationsForUISourceCode: function(uiSourceCode)
{
var result = [];
for (var i = 0; i < this._breakpoints.length; ++i) {
var breakpoint = this._breakpoints[i];
var uiLocations = breakpoint._uiLocations.values();
for (var j = 0; j < uiLocations.length; ++j) {
var uiLocation = uiLocations[j];
if (uiLocation.uiSourceCode === uiSourceCode)
result.push({breakpoint: breakpoint, uiLocation: uiLocation});
}
}
return result;
},

removeAllBreakpoints: function()
{
var breakpoints = this._breakpoints.slice();
for (var i = 0; i < breakpoints.length; ++i)
breakpoints[i].remove();
},

reset: function()
{

this._storage._muted = true;
this.removeAllBreakpoints();
delete this._storage._muted;


for (var debuggerId in this._breakpointForDebuggerId)
this._debuggerModel.removeBreakpoint(debuggerId);
this._breakpointForDebuggerId = {};
this._uiSourceCodeIds = {};
},

_debuggerReset: function()
{
var breakpoints = this._breakpoints.slice();
for (var i = 0; i < breakpoints.length; ++i)
breakpoints[i]._resetLocations();
this._breakpoints = [];
this._breakpointForUILocation = {};
this._uiSourceCodeIds = {};
},

_breakpointResolved: function(event)
{
var breakpointId =   event.data.breakpointId;
var location =   event.data.location;
var breakpoint = this._breakpointForDebuggerId[breakpointId];
if (!breakpoint) {

return;
}
breakpoint._addResolvedLocation(location);
},


_removeBreakpoint: function(breakpoint, removeFromStorage)
{
console.assert(!breakpoint._debuggerId)
this._breakpoints.remove(breakpoint);
if (removeFromStorage)
this._storage._removeBreakpoint(breakpoint);
},


_uiLocationAdded: function(breakpoint, uiLocation)
{
this._breakpointForUILocation[uiLocation.uiSourceCode.id + ":" + uiLocation.lineNumber] = breakpoint;
this.dispatchEventToListeners(WebInspector.BreakpointManager.Events.BreakpointAdded, {breakpoint: breakpoint, uiLocation: uiLocation});
},


_uiLocationRemoved: function(breakpoint, uiLocation)
{
delete this._breakpointForUILocation[uiLocation.uiSourceCode.id + ":" + uiLocation.lineNumber];
this.dispatchEventToListeners(WebInspector.BreakpointManager.Events.BreakpointRemoved, {breakpoint: breakpoint, uiLocation: uiLocation});
}
}

WebInspector.BreakpointManager.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.BreakpointManager.Breakpoint = function(breakpointManager, uiSourceCode, lineNumber, condition, enabled)
{
this._breakpointManager = breakpointManager;
this._primaryUILocation = new WebInspector.UILocation(uiSourceCode, lineNumber, 0);
this._liveLocations = [];
this._uiLocations = new Map();


this._condition;
this._enabled;
this._updateBreakpoint(condition, enabled);
}

WebInspector.BreakpointManager.Breakpoint.prototype = {

primaryUILocation: function()
{
return this._primaryUILocation;
},


_addResolvedLocation: function(location)
{
this._liveLocations.push(this._breakpointManager._debuggerModel.createLiveLocation(location, this._locationUpdated.bind(this, location)));
},


_locationUpdated: function(location, uiLocation)
{
var oldUILocation =   this._uiLocations.get(location);
if (oldUILocation)
this._breakpointManager._uiLocationRemoved(this, oldUILocation);
this._uiLocations.put(location, uiLocation);
this._breakpointManager._uiLocationAdded(this, uiLocation);
},


enabled: function()
{
return this._enabled;
},


setEnabled: function(enabled)
{
this._updateBreakpoint(this._condition, enabled);
},


condition: function()
{
return this._condition;
},


setCondition: function(condition)
{
this._updateBreakpoint(condition, this._enabled);
},


_updateBreakpoint: function(condition, enabled)
{
if (this._enabled === enabled && this._condition === condition)
return;

if (this._enabled)
this._removeFromDebugger();

this._enabled = enabled;
this._condition = condition;
this._breakpointManager._storage._updateBreakpoint(this);

if (this._enabled) {
this._setInDebugger();
return;
}

this._fakeBreakpointAtPrimaryLocation();
},

remove: function()
{
this._resetLocations();
this._removeFromDebugger();
this._breakpointManager._removeBreakpoint(this, true);
},

_setInDebugger: function()
{
var rawLocation = this._breakpointManager._sourceMapping.uiLocationToRawLocation(this._primaryUILocation.uiSourceCode, this._primaryUILocation.lineNumber, 0);
this._breakpointManager._debuggerModel.setBreakpointByScriptLocation(rawLocation, this._condition, didSetBreakpoint.bind(this));

function didSetBreakpoint(breakpointId, locations)
{
if (!breakpointId) {
this._resetLocations();
this._breakpointManager._removeBreakpoint(this, false);
return;
}

this._debuggerId = breakpointId;
this._breakpointManager._breakpointForDebuggerId[breakpointId] = this;

if (!locations.length) {
this._fakeBreakpointAtPrimaryLocation();
return;
}

this._resetLocations();
for (var i = 0; i < locations.length; ++i) {
var script = this._breakpointManager._debuggerModel.scriptForId(locations[i].scriptId);
var uiLocation = script.rawLocationToUILocation(locations[i]);
if (this._breakpointManager.findBreakpoint(uiLocation.uiSourceCode, uiLocation.lineNumber)) {

this.remove();
return;
}
}

for (var i = 0; i < locations.length; ++i)
this._addResolvedLocation(locations[i]);
}
},

_removeFromDebugger: function()
{
if (this._debuggerId) {
this._breakpointManager._debuggerModel.removeBreakpoint(this._debuggerId);
delete this._breakpointManager._breakpointForDebuggerId[this._debuggerId];
delete this._debuggerId;
}
},

_resetLocations: function()
{
var uiLocations = this._uiLocations.values();
for (var i = 0; i < uiLocations.length; ++i)
this._breakpointManager._uiLocationRemoved(this, uiLocations[i]);

for (var i = 0; i < this._liveLocations.length; ++i)
this._liveLocations[i].dispose();
this._liveLocations = [];

this._uiLocations = new Map();
},


_breakpointStorageId: function()
{
return this._primaryUILocation.uiSourceCode.id + ":" + this._primaryUILocation.lineNumber;
},

_fakeBreakpointAtPrimaryLocation: function()
{
this._resetLocations();
this._uiLocations.put({}, this._primaryUILocation);
this._breakpointManager._uiLocationAdded(this, this._primaryUILocation);
}
}


WebInspector.BreakpointManager.Storage = function(breakpointManager, setting)
{
this._breakpointManager = breakpointManager;
this._setting = setting;
var breakpoints = this._setting.get();

this._breakpoints = {};
for (var i = 0; i < breakpoints.length; ++i) {
var breakpoint =   breakpoints[i];
this._breakpoints[breakpoint.sourceFileId + ":" + breakpoint.lineNumber] = breakpoint;
}
}

WebInspector.BreakpointManager.Storage.prototype = {

restoreBreakpoints: function(uiSourceCode)
{
this._muted = true;
for (var id in this._breakpoints) {
var breakpoint = this._breakpoints[id];
if (breakpoint.sourceFileId === uiSourceCode.id)
this._breakpointManager.setBreakpoint(uiSourceCode, breakpoint.lineNumber, breakpoint.condition, breakpoint.enabled, true);
}
delete this._muted;
},


_updateBreakpoint: function(breakpoint)
{
if (this._muted)
return;
this._breakpoints[breakpoint._breakpointStorageId()] = new WebInspector.BreakpointManager.Storage.Item(breakpoint);
this._save();
},


_removeBreakpoint: function(breakpoint)
{
if (this._muted)
return;
delete this._breakpoints[breakpoint._breakpointStorageId()];
this._save();
},

_save: function()
{
var breakpointsArray = [];
for (var id in this._breakpoints)
breakpointsArray.push(this._breakpoints[id]);
this._setting.set(breakpointsArray);
}
}


WebInspector.BreakpointManager.Storage.Item = function(breakpoint)
{
var primaryUILocation = breakpoint.primaryUILocation();
this.sourceFileId = primaryUILocation.uiSourceCode.id;
this.lineNumber = primaryUILocation.lineNumber;
this.condition = breakpoint.condition();
this.enabled = breakpoint.enabled();
}






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


contentURL: function()
{
return null;
},


requestContent: function(callback)
{
var scripts = this._sortedScripts();
var sources = [];
function didRequestSource(content, contentEncoded, mimeType)
{
sources.push(content);
if (sources.length == scripts.length)
callback(this._concatenateScriptsContent(scripts, sources), false, this._mimeType);
}
for (var i = 0; i < scripts.length; ++i)
scripts[i].requestContent(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.CompilerSourceMappingContentProvider = function(sourceURL)
{
this._mimeType = "text/javascript";
this._sourceURL = sourceURL;
}

WebInspector.CompilerSourceMappingContentProvider.prototype = {

contentURL: function()
{
return this._sourceURL;
},


requestContent: function(callback)
{
var sourceCode = "";
try {

sourceCode = InspectorFrontendHost.loadResourceSynchronously(this._sourceURL);
} catch(e) {
console.error(e.message);
}
callback(sourceCode, false, this._mimeType);
},


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

contentURL: function()
{
return null;
},


requestContent: function(callback)
{
callback(this._content, false, this._mimeType);
},


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, request, 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._pendingRequest = request;

this._hasNewScripts = true;

if (this._pendingRequest)
this._pendingRequest.addEventListener(WebInspector.NetworkRequest.Events.FinishedLoading, this._finishedLoading, this);
else
this._updateSourceMapping();
}

WebInspector.RawSourceCode.Events = {
UISourceCodeChanged: "us-source-code-changed"
}

WebInspector.RawSourceCode.prototype = {

addScript: function(script)
{
this._scripts.push(script);
this._hasNewScripts = true;
},


rawLocationToUILocation: function(rawLocation)
{
if (this._sourceMapping)
return this._sourceMapping.rawLocationToUILocation(rawLocation);
return null;
},


uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
{
if (this._sourceMapping)
return this._sourceMapping.uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber);
return null;
},


uiSourceCode: function()
{
if (this._sourceMapping)
return this._sourceMapping.uiSourceCode();
return null;
},


setFormatted: function(formatted)
{
if (this._formatted === formatted)
return;
this._formatted = formatted;
this._updateSourceMapping();
},

_finishedLoading: function(event)
{
this._resource = WebInspector.resourceForURL(this._pendingRequest.url);
delete this._pendingRequest;
this._updateSourceMapping();
},


forceUpdateSourceMapping: function(script)
{
if (!this._pendingRequest || !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 && !this._updateNeeded)
this._saveSourceMapping(sourceMapping);
else
this._updateSourceMapping();
}
},

_createContentProvider: function()
{
if (this._resource)
return this._resource;
if (this._scripts.length === 1 && !this._scripts[0].lineOffset && !this._scripts[0].columnOffset)
return this._scripts[0];
return new WebInspector.ConcatenatedScriptsContentProvider(this._scripts);
},


_createSourceMapping: function(callback)
{
var originalContentProvider = this._createContentProvider();
if (!this._formatted) {
var uiSourceCode = this._createUISourceCode(this.url, this.url, originalContentProvider);
var sourceMapping = new WebInspector.RawSourceCode.PlainSourceMapping(this, uiSourceCode);
callback(sourceMapping);
return;
}


function didRequestContent(content, contentEncoded, mimeType)
{

function didFormatContent(formattedContent, mapping)
{
var contentProvider = new WebInspector.StaticContentProvider(mimeType, formattedContent)
var uiSourceCode = this._createUISourceCode("deobfuscated:" + this.url, this.url, 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));
},


_createUISourceCode: function(id, url, contentProvider)
{
var uiSourceCode = new WebInspector.JavaScriptSource(id, url, contentProvider);
uiSourceCode.isContentScript = this.isContentScript;
uiSourceCode.isEditable = this._scripts.length === 1 && !this._scripts[0].lineOffset && !this._scripts[0].columnOffset && !this._formatted;
return uiSourceCode;
},


_saveSourceMapping: function(sourceMapping)
{
var oldUISourceCode;
if (this._sourceMapping)
oldUISourceCode = this._sourceMapping.uiSourceCode();
this._sourceMapping = sourceMapping;
this.dispatchEventToListeners(WebInspector.RawSourceCode.Events.UISourceCodeChanged, { oldUISourceCode: oldUISourceCode });
}
}

WebInspector.RawSourceCode.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.RawSourceCode.SourceMapping = function()
{
}

WebInspector.RawSourceCode.SourceMapping.prototype = {

uiSourceCode: function() { }
}


WebInspector.RawSourceCode.PlainSourceMapping = function(rawSourceCode, uiSourceCode)
{
this._rawSourceCode = rawSourceCode;
this._uiSourceCode = uiSourceCode;
}

WebInspector.RawSourceCode.PlainSourceMapping.prototype = {

rawLocationToUILocation: function(rawLocation)
{
return new WebInspector.UILocation(this._uiSourceCode, rawLocation.lineNumber, rawLocation.columnNumber || 0);
},


uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
{
console.assert(uiSourceCode === this._uiSourceCode);
return WebInspector.debuggerModel.createRawLocation(this._rawSourceCode._scripts[0], lineNumber, columnNumber);
},


uiSourceCode: function()
{
return this._uiSourceCode;
}
}


WebInspector.RawSourceCode.FormattedSourceMapping = function(rawSourceCode, uiSourceCode, mapping)
{
this._rawSourceCode = rawSourceCode;
this._uiSourceCode = uiSourceCode;
this._mapping = mapping;
}

WebInspector.RawSourceCode.FormattedSourceMapping.prototype = {

rawLocationToUILocation: function(rawLocation)
{
var location = this._mapping.originalToFormatted(rawLocation.lineNumber, rawLocation.columnNumber || 0);
return new WebInspector.UILocation(this._uiSourceCode, location[0], location[1]);
},


uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
{
console.assert(uiSourceCode === this._uiSourceCode);
var location = this._mapping.formattedToOriginal(lineNumber, columnNumber);
return WebInspector.debuggerModel.createRawLocation(this._rawSourceCode._scripts[0], location[0], location[1]);
},


uiSourceCode: function()
{
return this._uiSourceCode;
}
}






WebInspector.ResourceScriptMapping = function()
{
this._rawSourceCodes = [];
this._rawSourceCodeForScriptId = {};
this._rawSourceCodeForURL = {};
this._rawSourceCodeForDocumentURL = {};
this._rawSourceCodeForUISourceCode = new Map();
this._formatter = new WebInspector.ScriptFormatter();
this._formatSource = false;
}

WebInspector.ResourceScriptMapping.prototype = {

rawLocationToUILocation: function(rawLocation)
{
var rawSourceCode = this._rawSourceCodeForScriptId[rawLocation.scriptId];
return rawSourceCode.rawLocationToUILocation(rawLocation);
},


uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
{
var rawSourceCode = this._rawSourceCodeForUISourceCode.get(uiSourceCode);
return rawSourceCode.uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber);
},


uiSourceCodeList: function()
{
var result = [];
for (var i = 0; i < this._rawSourceCodes.length; ++i) {
var uiSourceCode = this._rawSourceCodes[i].uiSourceCode();
if (uiSourceCode)
result.push(uiSourceCode);
}
return result;
},


addScript: function(script)
{
var resource = null;
var request = null;
var isInlineScript = false;
if (script.isInlineScript()) {

resource = WebInspector.resourceForURL(script.sourceURL);
if (resource && resource.type !== WebInspector.resourceTypes.Document)
resource = null;

if (resource && resource.request && !resource.request.finished)
resource = null;
if (!resource) {

request = WebInspector.networkManager.inflightRequestForURL(script.sourceURL);
if (request && request.type !== WebInspector.resourceTypes.Document)
request = null;
}

if (request || resource) {
isInlineScript = true;
var rawSourceCode = this._rawSourceCodeForDocumentURL[script.sourceURL];
if (rawSourceCode) {
rawSourceCode.addScript(script);
this._bindScriptToRawSourceCode(script, rawSourceCode);
return;
}
}
}

var rawSourceCode = new WebInspector.RawSourceCode(script.scriptId, script, resource, request, this._formatter, this._formatSource);
this._rawSourceCodes.push(rawSourceCode);
this._bindScriptToRawSourceCode(script, rawSourceCode);
if (isInlineScript)
this._rawSourceCodeForDocumentURL[script.sourceURL] = rawSourceCode;

if (rawSourceCode.uiSourceCode())
this._uiSourceCodeChanged(rawSourceCode, null, rawSourceCode.uiSourceCode());
rawSourceCode.addEventListener(WebInspector.RawSourceCode.Events.UISourceCodeChanged, this._handleUISourceCodeChanged, this);
},


_handleUISourceCodeChanged: function(event)
{
var rawSourceCode =   event.target;
var oldUISourceCode =   event.data.oldUISourceCode;
this._uiSourceCodeChanged(rawSourceCode, oldUISourceCode, rawSourceCode.uiSourceCode());
},


_uiSourceCodeChanged: function(rawSourceCode, removedItem, addedItem)
{
if (removedItem)
this._rawSourceCodeForUISourceCode.remove(removedItem);
if (addedItem)
this._rawSourceCodeForUISourceCode.put(addedItem, rawSourceCode);

var scriptIds = [];
for (var i = 0; i < rawSourceCode._scripts.length; ++i) {
scriptIds.push(rawSourceCode._scripts[i].scriptId);
rawSourceCode._scripts[i].setSourceMapping(this);
}
var removedItems = removedItem ? [removedItem] : [];
var addedItems = addedItem ? [addedItem] : [];

var data = { removedItems: removedItems, addedItems: addedItems };
this.dispatchEventToListeners(WebInspector.ScriptMapping.Events.UISourceCodeListChanged, data);
},


_bindScriptToRawSourceCode: function(script, rawSourceCode)
{
this._rawSourceCodeForScriptId[script.scriptId] = rawSourceCode;
this._rawSourceCodeForURL[script.sourceURL] = rawSourceCode;
script.setSourceMapping(this);
},


setFormatSource: function(formatSource)
{
if (this._formatSource === formatSource)
return;

this._formatSource = formatSource;
for (var i = 0; i < this._rawSourceCodes.length; ++i)
this._rawSourceCodes[i].setFormatted(this._formatSource);
},


forceUpdateSourceMapping: function(rawLocation)
{
var rawSourceCode = this._rawSourceCodeForScriptId[rawLocation.scriptId];
rawSourceCode.forceUpdateSourceMapping();
},

reset: function()
{
for (var i = 0; i < this._rawSourceCodes.length; ++i) {
var rawSourceCode = this._rawSourceCodes[i];
this._uiSourceCodeChanged(rawSourceCode, rawSourceCode.uiSourceCode(), null);
rawSourceCode.removeAllListeners();
}
this._rawSourceCodes = [];
this._rawSourceCodeForScriptId = {};
this._rawSourceCodeForURL = {};
this._rawSourceCodeForDocumentURL = {};
this._rawSourceCodeForUISourceCode.clear();
}
}

WebInspector.ResourceScriptMapping.prototype.__proto__ = WebInspector.ScriptMapping.prototype;






WebInspector.CompilerScriptMapping = function()
{
this._sourceMapByURL = {};
this._sourceMapForScriptId = {};
this._scriptForSourceMap = new Map();
this._sourceMapForUISourceCode = new Map();
this._uiSourceCodeByURL = {};
}

WebInspector.CompilerScriptMapping.prototype = {

rawLocationToUILocation: function(rawLocation)
{
var sourceMap = this._sourceMapForScriptId[rawLocation.scriptId];
var entry = sourceMap.findEntry(rawLocation.lineNumber, rawLocation.columnNumber || 0);
return new WebInspector.UILocation(this._uiSourceCodeByURL[entry[2]], entry[3], entry[4]);
},


uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
{
var sourceMap = this._sourceMapForUISourceCode.get(uiSourceCode);
var entry = sourceMap.findEntryReversed(uiSourceCode.url, lineNumber);
return WebInspector.debuggerModel.createRawLocation(this._scriptForSourceMap.get(sourceMap), entry[0], entry[1]);
},


uiSourceCodeList: function()
{
var result = []
for (var url in this._uiSourceCodeByURL)
result.push(this._uiSourceCodeByURL[url]);
return result;
},


_uiSourceCodesForSourceMap: function(sourceMap)
{
var result = []
var sourceURLs = sourceMap.sources();
for (var i = 0; i < sourceURLs.length; ++i)
result.push(this._uiSourceCodeByURL[sourceURLs[i]]);
return result;
},


addScript: function(script)
{
var sourceMap = this.loadSourceMapForScript(script);

if (this._scriptForSourceMap.get(sourceMap)) {
this._sourceMapForScriptId[script.scriptId] = sourceMap;
var uiSourceCodes = this._uiSourceCodesForSourceMap(sourceMap);
script.setSourceMapping(this);
return;
}

var uiSourceCodeList = [];
var sourceURLs = sourceMap.sources();
for (var i = 0; i < sourceURLs.length; ++i) {
var sourceURL = sourceURLs[i];
if (this._uiSourceCodeByURL[sourceURL])
continue;
var sourceContent = sourceMap.sourceContent(sourceURL);
var contentProvider;
if (sourceContent)
contentProvider = new WebInspector.StaticContentProvider("text/javascript", sourceContent);
else
contentProvider = new WebInspector.CompilerSourceMappingContentProvider(sourceURL);
var uiSourceCode = new WebInspector.JavaScriptSource(sourceURL, sourceURL, contentProvider);
uiSourceCode.isContentScript = script.isContentScript;
uiSourceCode.isEditable = false;
this._uiSourceCodeByURL[sourceURL] = uiSourceCode;
this._sourceMapForUISourceCode.put(uiSourceCode, sourceMap);
uiSourceCodeList.push(uiSourceCode);
}

this._sourceMapForScriptId[script.scriptId] = sourceMap;
this._scriptForSourceMap.put(sourceMap, script);
var data = { removedItems: [], addedItems: uiSourceCodeList };
this.dispatchEventToListeners(WebInspector.ScriptMapping.Events.UISourceCodeListChanged, data);
script.setSourceMapping(this);
},


loadSourceMapForScript: function(script)
{
var sourceMapURL = WebInspector.SourceMapParser.prototype._canonicalizeURL(script.sourceMapURL, script.sourceURL);
var sourceMap = this._sourceMapByURL[sourceMapURL];
if (sourceMap)
return sourceMap;

try {

var response = InspectorFrontendHost.loadResourceSynchronously(sourceMapURL);
if (response.slice(0, 3) === ")]}")
response = response.substring(response.indexOf('\n'));
var payload =   JSON.parse(response);
sourceMap = new WebInspector.SourceMapParser(sourceMapURL, payload);
} catch(e) {
console.error(e.message);
return null;
}
this._sourceMapByURL[sourceMapURL] = sourceMap;
return sourceMap;
},

reset: function()
{
var data = { removedItems: this.uiSourceCodeList(), addedItems: [] };
this.dispatchEventToListeners(WebInspector.ScriptMapping.Events.UISourceCodeListChanged, data);

this._sourceMapByURL = {};
this._sourceMapForScriptId = {};
this._scriptForSourceMap = new Map();
this._sourceMapForUISourceCode = new Map();
this._uiSourceCodeByURL = {};
}
}

WebInspector.CompilerScriptMapping.prototype.__proto__ = WebInspector.ScriptMapping.prototype;


WebInspector.SourceMapPayload = function()
{
this.sections = [];
this.mappings = "";
this.sourceRoot = "";
this.sources = [];
}


WebInspector.SourceMapParser = function(sourceMappingURL, payload)
{
if (!WebInspector.SourceMapParser.prototype._base64Map) {
const base64Digits = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
WebInspector.SourceMapParser.prototype._base64Map = {};
for (var i = 0; i < base64Digits.length; ++i)
WebInspector.SourceMapParser.prototype._base64Map[base64Digits.charAt(i)] = i;
}

this._sourceMappingURL = sourceMappingURL;
this._mappings = [];
this._reverseMappingsBySourceURL = {};
this._sourceContentByURL = {};
this._parseMappingPayload(payload);
}

WebInspector.SourceMapParser.prototype = {

sources: function()
{
var sources = [];
for (var sourceURL in this._reverseMappingsBySourceURL)
sources.push(sourceURL);
return sources;
},

sourceContent: function(sourceURL)
{
return this._sourceContentByURL[sourceURL];
},

findEntry: 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];
},

findEntryReversed: function(sourceURL, lineNumber)
{
var mappings = this._reverseMappingsBySourceURL[sourceURL];
for ( ; lineNumber < mappings.length; ++lineNumber) {
var mapping = mappings[lineNumber];
if (mapping)
return mapping;
}
return this._mappings[0];
},

_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, section.offset.column)
}
},

_parseMap: function(map, lineNumber, columnNumber)
{
var sourceIndex = 0;
var sourceLineNumber = 0;
var sourceColumnNumber = 0;
var nameIndex = 0;

var sources = [];
for (var i = 0; i < map.sources.length; ++i) {
var sourceURL = map.sources[i];
if (map.sourceRoot)
sourceURL = map.sourceRoot + "/" + sourceURL;
var url = this._canonicalizeURL(sourceURL, this._sourceMappingURL);
sources.push(url);
if (!this._reverseMappingsBySourceURL[url])
this._reverseMappingsBySourceURL[url] = [];
if (map.sourcesContent && map.sourcesContent[i])
this._sourceContentByURL[url] = map.sourcesContent[i];
}

var stringCharIterator = new WebInspector.SourceMapParser.StringCharIterator(map.mappings);
var sourceURL = 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 = 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(url, baseURL)
{
if (!url || !baseURL || url.asParsedURL() || url.substring(0, 5) === "data:")
return url;

var base = baseURL.asParsedURL();
if (!base)
return url;

var baseHost = base.scheme + "://" + base.host + (base.port ? ":" + base.port : "");
if (url[0] === "/")
return baseHost + url;
return baseHost + base.folderPathComponents + "/" + url;
},

_VLQ_BASE_SHIFT: 5,
_VLQ_BASE_MASK: (1 << 5) - 1,
_VLQ_CONTINUATION_MASK: 1 << 5
}


WebInspector.SourceMapParser.StringCharIterator = function(string)
{
this._string = string;
this._position = 0;
}

WebInspector.SourceMapParser.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 = new WebInspector.Linkifier(new WebInspector.ScriptsSearchResultsPane.LinkifierFormatter());
}

WebInspector.ScriptsSearchResultsPane.prototype = {

createAnchor: function(file, lineNumber, columnNumber)
{
var uiSourceCode =   file;
var rawLocation = WebInspector.debuggerPresentationModel.uiLocationToRawLocation(uiSourceCode, lineNumber, columnNumber);
var anchor = this._linkifier.linkifyRawLocation(rawLocation);
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 = {

formatLiveAnchor: function(anchor, uiLocation)
{

}
}

WebInspector.ScriptsSearchResultsPane.LinkifierFormatter.prototype.__proto__ = WebInspector.LinkifierFormatter.prototype;

WebInspector.settings.searchInContentScripts = WebInspector.settings.createSetting("searchInContentScripts", false);






WebInspector.DOMNode = function(domAgent, doc, isInShadowTree, payload) {
this._domAgent = domAgent;
this.ownerDocument = doc;
this._isInShadowTree = isInShadowTree;

this.id = payload.nodeId;
domAgent._idToDOMNode[this.id] = this;
this._nodeType = payload.nodeType;
this._nodeName = payload.nodeName;
this._localName = payload.localName;
this._nodeValue = payload.nodeValue;

this._shadowRoots = [];

this._attributes = [];
this._attributesMap = {};
if (payload.attributes)
this._setAttributesPayload(payload.attributes);

this._childNodeCount = payload.childNodeCount;
this.children = null;

this.nextSibling = null;
this.previousSibling = null;
this.firstChild = null;
this.lastChild = null;
this.parentNode = null;

if (payload.children)
this._setChildrenPayload(payload.children);

if (payload.contentDocument) {
this._contentDocument = new WebInspector.DOMDocument(domAgent, payload.contentDocument);
this.children = [this._contentDocument];
this._renumber();
}

if (payload.shadowRoots && WebInspector.experimentsSettings.showShadowDOM.isEnabled()) {
for (var i = 0; i < payload.shadowRoots.length; ++i) {
var root = payload.shadowRoots[i];
var node = new WebInspector.DOMNode(this._domAgent, this.ownerDocument, true, root);
this._shadowRoots.push(node);
}
}

if (this._nodeType === Node.ELEMENT_NODE) {

if (this.ownerDocument && !this.ownerDocument.documentElement && this._nodeName === "HTML")
this.ownerDocument.documentElement = this;
if (this.ownerDocument && !this.ownerDocument.body && this._nodeName === "BODY")
this.ownerDocument.body = this;
} 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.ATTRIBUTE_NODE) {
this.name = payload.name;
this.value = payload.value;
}
}


WebInspector.DOMNode.XPathStep = function(value, optimized)
{
this.value = value;
this.optimized = optimized;
}

WebInspector.DOMNode.XPathStep.prototype = {
toString: function()
{
return this.value;
}
}

WebInspector.DOMNode.prototype = {

hasAttributes: function()
{
return this._attributes.length > 0;
},


hasChildNodes: function()
{
return this._childNodeCount > 0 || !!this._shadowRoots.length;
},


nodeType: function()
{
return this._nodeType;
},


nodeName: function()
{
return this._nodeName;
},


isInShadowTree: function()
{
return this._isInShadowTree;
},


nodeNameInCorrectCase: function()
{
return this.isXMLNode() ? this.nodeName() : this.nodeName().toLowerCase();
},


setNodeName: function(name, callback)
{
DOMAgent.setNodeName(this.id, name, WebInspector.domAgent._markRevision(this, callback));
},


localName: function()
{
return this._localName;
},


nodeValue: function()
{
return this._nodeValue;
},


setNodeValue: function(value, callback)
{
DOMAgent.setNodeValue(this.id, value, WebInspector.domAgent._markRevision(this, 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, WebInspector.domAgent._markRevision(this, callback));
},


setAttributeValue: function(name, value, callback)
{
DOMAgent.setAttributeValue(this.id, name, value, WebInspector.domAgent._markRevision(this, callback));
},


attributes: function()
{
return this._attributes;
},


removeAttribute: function(name, callback)
{

function mycallback(error)
{
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;
}
}
}

WebInspector.domAgent._markRevision(this, callback)(error);
}
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, WebInspector.domAgent._markRevision(this, callback));
},


removeNode: function(callback)
{
DOMAgent.removeNode(this.id, WebInspector.domAgent._markRevision(this, callback));
},

copyNode: function()
{
function copy(error, text)
{
if (!error)
InspectorFrontendHost.copyText(text);
}
DOMAgent.getOuterHTML(this.id, copy);
},


copyXPath: function(optimized)
{
InspectorFrontendHost.copyText(this.xPath(optimized));
},


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.trim().replace(/\s+/g, ".");
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)
{
var attributesChanged = !this._attributes || attrs.length !== this._attributes.length * 2;
var oldAttributesMap = this._attributesMap || {};

this._attributes = [];
this._attributesMap = {};

for (var i = 0; i < attrs.length; i += 2) {
var name = attrs[i];
var value = attrs[i + 1];
this._addAttribute(name, value);

if (attributesChanged)
continue;

if (!oldAttributesMap[name] || oldAttributesMap[name].value !== value)
attributesChanged = true;
}
return attributesChanged;
},


_insertChild: function(prev, payload)
{
var node = new WebInspector.DOMNode(this._domAgent, this.ownerDocument, this._isInShadowTree, payload);
if (!prev) {
if (!this.children) {

this.children = this._shadowRoots.concat([ 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)
{

if (this._contentDocument)
return;

this.children = this._shadowRoots.slice();
for (var i = 0; i < payloads.length; ++i) {
var payload = payloads[i];
var node = new WebInspector.DOMNode(this._domAgent, this.ownerDocument, this._isInShadowTree, 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.previousSibling = 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];
}
},


moveTo: function(targetNode, anchorNode, callback)
{
DOMAgent.moveTo(this.id, targetNode.id, anchorNode ? anchorNode.id : undefined, WebInspector.domAgent._markRevision(this, callback));
},


isXMLNode: function()
{
return !!this.ownerDocument && !!this.ownerDocument.xmlVersion;
},


xPath: function(optimized)
{
if (this._nodeType === Node.DOCUMENT_NODE)
return "/";

var steps = [];
var contextNode = this;
while (contextNode) {
var step = contextNode._xPathValue(optimized);
if (!step)
break; 
steps.push(step);
if (step.optimized)
break;
contextNode = contextNode.parentNode;
}

steps.reverse();
return (steps.length && steps[0].optimized ? "" : "/") + steps.join("/");
},


_xPathValue: function(optimized)
{
var ownValue;
var ownIndex = this._xPathIndex();
if (ownIndex === -1)
return null; 

switch (this._nodeType) {
case Node.ELEMENT_NODE:
if (optimized && this.getAttribute("id"))
return new WebInspector.DOMNode.XPathStep("//*[@id=\"" + this.getAttribute("id") + "\"]", true);
ownValue = this._localName;
break;
case Node.ATTRIBUTE_NODE:
ownValue = "@" + this._nodeName;
break;
case Node.TEXT_NODE:
case Node.CDATA_SECTION_NODE:
ownValue = "text()";
break;
case Node.PROCESSING_INSTRUCTION_NODE:
ownValue = "processing-instruction()";
break;
case Node.COMMENT_NODE:
ownValue = "comment()";
break;
case Node.DOCUMENT_NODE:
ownValue = "";
break;
default:
ownValue = "";
break;
}

if (ownIndex > 0)
ownValue += "[" + ownIndex + "]";

return new WebInspector.DOMNode.XPathStep(ownValue, this._nodeType === Node.DOCUMENT_NODE);
},


_xPathIndex: function()
{

function areNodesSimilar(left, right)
{
if (left === right)
return true;

if (left._nodeType === Node.ELEMENT_NODE && right._nodeType === Node.ELEMENT_NODE)
return left._localName === right._localName;

if (left._nodeType === right._nodeType)
return true;


var leftType = left._nodeType === Node.CDATA_SECTION_NODE ? Node.TEXT_NODE : left._nodeType;
var rightType = right._nodeType === Node.CDATA_SECTION_NODE ? Node.TEXT_NODE : right._nodeType;
return leftType === rightType;
}

var siblings = this.parentNode ? this.parentNode.children : null;
if (!siblings)
return 0; 
var hasSameNamedElements;
for (var i = 0; i < siblings.length; ++i) {
if (areNodesSimilar(this, siblings[i]) && siblings[i] !== this) {
hasSameNamedElements = true;
break;
}
}
if (!hasSameNamedElements)
return 0;
var ownIndex = 1; 
for (var i = 0; i < siblings.length; ++i) {
if (areNodesSimilar(this, siblings[i])) {
if (siblings[i] === this)
return ownIndex;
++ownIndex;
}
}
return -1; 
}
}


WebInspector.DOMDocument = function(domAgent, payload)
{
WebInspector.DOMNode.call(this, domAgent, this, false, payload);
this.documentURL = payload.documentURL || "";
this.xmlVersion = payload.xmlVersion;
this._listeners = {};
}

WebInspector.DOMDocument.prototype.__proto__ = WebInspector.DOMNode.prototype;


WebInspector.DOMAgent = function() {

this._idToDOMNode = {};
this._document = null;
this._attributeLoadNodeIds = {};
InspectorBackend.registerDOMDispatcher(new WebInspector.DOMDispatcher(this));
if (WebInspector.settings.emulateTouchEvents.get())
this._emulateTouchEventsChanged();
WebInspector.settings.emulateTouchEvents.addChangeListener(this._emulateTouchEventsChanged, this);
}

WebInspector.DOMAgent.Events = {
AttrModified: "AttrModified",
AttrRemoved: "AttrRemoved",
CharacterDataModified: "CharacterDataModified",
NodeInserted: "NodeInserted",
NodeRemoved: "NodeRemoved",
DocumentUpdated: "DocumentUpdated",
ChildNodeCountUpdated: "ChildNodeCountUpdated",
InspectElementRequested: "InspectElementRequested",
StyleInvalidated: "StyleInvalidated",
UndoRedoRequested: "UndoRedoRequested",
UndoRedoCompleted: "UndoRedoCompleted"
}

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)
{
var callbackCast =   callback;
this._dispatchWhenDocumentAvailable(DOMAgent.requestNode.bind(DOMAgent, objectId), callbackCast);
},


pushNodeByPathToFrontend: function(path, callback)
{
var callbackCast =   callback;
this._dispatchWhenDocumentAvailable(DOMAgent.pushNodeByPathToFrontend.bind(DOMAgent, path), callbackCast);
},


_wrapClientCallback: function(callback)
{
if (!callback)
return;

return function(error, result)
{

callback(error ? null : result);
}
},


_dispatchWhenDocumentAvailable: function(func, callback)
{
var callbackWrapper =   this._wrapClientCallback(callback);

function onDocumentAvailable()
{
if (this._document)
func(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;
var issueStyleInvalidated = name === "style" && value !== node.getAttribute("style");

node._setAttribute(name, value);
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.AttrModified, { node: node, name: name });
if (issueStyleInvalidated)
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.StyleInvalidated, node)
},


_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, error, attributes)
{
if (error) {

return;
}
var node = this._idToDOMNode[nodeId];
if (node) {
if (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) {
var nodeIdAsNumber = parseInt(nodeId, 10);
DOMAgent.getAttributes(nodeIdAsNumber, callback.bind(this, nodeIdAsNumber));
}
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);
else
this._document = null;
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.DocumentUpdated, this._document);
},


_setDetachedRoot: function(payload)
{
if (payload.nodeName === "#document")
new WebInspector.DOMDocument(this, payload);
else
new WebInspector.DOMNode(this, null, false, payload);
},


_setChildNodes: function(parentId, payloads)
{
if (!parentId && payloads.length) {
this._setDetachedRoot(payloads[0]);
return;
}

var parent = this._idToDOMNode[parentId];
parent._setChildrenPayload(payloads);
},


_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._unbind(node);
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.NodeRemoved, {node:node, parent:parent});
},


_shadowRootPopped: function(rootId)
{
},


_unbind: function(node)
{
delete this._idToDOMNode[node.id];
for (var i = 0; node.children && i < node.children.length; ++i)
this._unbind(node.children[i]);
},


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)
{
var callbackCast =  callback;
DOMAgent.querySelector(nodeId, selectors, this._wrapClientCallback(callbackCast));
},


querySelectorAll: function(nodeId, selectors, callback)
{
var callbackCast =  callback;
DOMAgent.querySelectorAll(nodeId, selectors, this._wrapClientCallback(callbackCast));
},


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


_markRevision: function(node, callback)
{
function wrapperFunction(error)
{
if (!error)
this.markUndoableState();

if (callback)
callback.apply(this, arguments);
}
return wrapperFunction.bind(this);
},

_emulateTouchEventsChanged: function()
{
const injectedFunction = function() {
const touchEvents = ["ontouchstart", "ontouchend", "ontouchmove", "ontouchcancel"];
for (var i = 0; i < touchEvents.length; ++i) {
if (!(touchEvents[i] in window.__proto__))
Object.defineProperty(window.__proto__, touchEvents[i], { value: null, writable: true, configurable: true, enumerable: true });
if (!(touchEvents[i] in document.__proto__))
Object.defineProperty(document.__proto__, touchEvents[i], { value: null, writable: true, configurable: true, enumerable: true });
}
}

var emulationEnabled = WebInspector.settings.emulateTouchEvents.get();
if (emulationEnabled && !this._addTouchEventsScriptInjecting) {
this._addTouchEventsScriptInjecting = true;
PageAgent.addScriptToEvaluateOnLoad("(" + injectedFunction.toString() + ")", scriptAddedCallback.bind(this));
} else {
if (typeof this._addTouchEventsScriptId !== "undefined") {
PageAgent.removeScriptToEvaluateOnLoad(this._addTouchEventsScriptId);
delete this._addTouchEventsScriptId;
}
}

function scriptAddedCallback(error, scriptId)
{
delete this._addTouchEventsScriptInjecting;
if (error)
return;
this._addTouchEventsScriptId = scriptId;
}

DOMAgent.setTouchEmulationEnabled(emulationEnabled);
},

markUndoableState: function()
{
DOMAgent.markUndoableState();
},


undo: function(callback)
{
function mycallback(error)
{
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.UndoRedoCompleted);
callback(error);
}

this.dispatchEventToListeners(WebInspector.DOMAgent.Events.UndoRedoRequested);
DOMAgent.undo(callback);
},


redo: function(callback)
{
function mycallback(error)
{
this.dispatchEventToListeners(WebInspector.DOMAgent.Events.UndoRedoCompleted);
callback(error);
}

this.dispatchEventToListeners(WebInspector.DOMAgent.Events.UndoRedoRequested);
DOMAgent.redo(callback);
}
}

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


shadowRootPushed: function(hostId, root)
{
this._domAgent._childNodeInserted(hostId, 0, root);
},


shadowRootPopped: function(hostId, rootId)
{
this._domAgent._childNodeRemoved(hostId, rootId);
}
}


WebInspector.domAgent = null;






WebInspector.TimelinePresentationModel = function()
{
this._linkifier = new WebInspector.Linkifier();
this._glueRecords = false;
this._filters = [];
this.reset();
}

WebInspector.TimelinePresentationModel.shortRecordThreshold = 0.015;

WebInspector.TimelinePresentationModel.categories = function()
{
if (WebInspector.TimelinePresentationModel._categories)
return WebInspector.TimelinePresentationModel._categories;
WebInspector.TimelinePresentationModel._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 WebInspector.TimelinePresentationModel._categories;
};


WebInspector.TimelinePresentationModel.recordStyle = function(record) {
if (WebInspector.TimelinePresentationModel._recordStylesMap)
return WebInspector.TimelinePresentationModel._recordStylesMap[record.type];

var recordTypes = WebInspector.TimelineModel.RecordType;
var categories = WebInspector.TimelinePresentationModel.categories();

var recordStyles = {};
recordStyles[recordTypes.Root] = { title: "#root", category: categories["loading"] };
recordStyles[recordTypes.EventDispatch] = { title: WebInspector.UIString("Event"), category: categories["scripting"] };
recordStyles[recordTypes.Layout] = { title: WebInspector.UIString("Layout"), category: categories["rendering"] };
recordStyles[recordTypes.RecalculateStyles] = { title: WebInspector.UIString("Recalculate Style"), category: categories["rendering"] };
recordStyles[recordTypes.Paint] = { title: WebInspector.UIString("Paint"), category: categories["rendering"] };
recordStyles[recordTypes.BeginFrame] = { title: WebInspector.UIString("Frame Start"), category: categories["rendering"] };
recordStyles[recordTypes.ParseHTML] = { title: WebInspector.UIString("Parse"), category: categories["loading"] };
recordStyles[recordTypes.TimerInstall] = { title: WebInspector.UIString("Install Timer"), category: categories["scripting"] };
recordStyles[recordTypes.TimerRemove] = { title: WebInspector.UIString("Remove Timer"), category: categories["scripting"] };
recordStyles[recordTypes.TimerFire] = { title: WebInspector.UIString("Timer Fired"), category: categories["scripting"] };
recordStyles[recordTypes.XHRReadyStateChange] = { title: WebInspector.UIString("XHR Ready State Change"), category: categories["scripting"] };
recordStyles[recordTypes.XHRLoad] = { title: WebInspector.UIString("XHR Load"), category: categories["scripting"] };
recordStyles[recordTypes.EvaluateScript] = { title: WebInspector.UIString("Evaluate Script"), category: categories["scripting"] };
recordStyles[recordTypes.TimeStamp] = { title: WebInspector.UIString("Stamp"), category: categories["scripting"] };
recordStyles[recordTypes.ResourceSendRequest] = { title: WebInspector.UIString("Send Request"), category: categories["loading"] };
recordStyles[recordTypes.ResourceReceiveResponse] = { title: WebInspector.UIString("Receive Response"), category: categories["loading"] };
recordStyles[recordTypes.ResourceFinish] = { title: WebInspector.UIString("Finish Loading"), category: categories["loading"] };
recordStyles[recordTypes.FunctionCall] = { title: WebInspector.UIString("Function Call"), category: categories["scripting"] };
recordStyles[recordTypes.ResourceReceivedData] = { title: WebInspector.UIString("Receive Data"), category: categories["loading"] };
recordStyles[recordTypes.GCEvent] = { title: WebInspector.UIString("GC Event"), category: categories["scripting"] };
recordStyles[recordTypes.MarkDOMContent] = { title: WebInspector.UIString("DOMContent event"), category: categories["scripting"] };
recordStyles[recordTypes.MarkLoad] = { title: WebInspector.UIString("Load event"), category: categories["scripting"] };
recordStyles[recordTypes.ScheduleResourceRequest] = { title: WebInspector.UIString("Schedule Request"), category: categories["loading"] };
recordStyles[recordTypes.RequestAnimationFrame] = { title: WebInspector.UIString("Request Animation Frame"), category: categories["scripting"] };
recordStyles[recordTypes.CancelAnimationFrame] = { title: WebInspector.UIString("Cancel Animation Frame"), category: categories["scripting"] };
recordStyles[recordTypes.FireAnimationFrame] = { title: WebInspector.UIString("Animation Frame Fired"), category: categories["scripting"] };

WebInspector.TimelinePresentationModel._recordStylesMap = recordStyles;
return recordStyles[record.type];
}

WebInspector.TimelinePresentationModel.categoryForRecord = function(record)
{
return WebInspector.TimelinePresentationModel.recordStyle(record).category;
}

WebInspector.TimelinePresentationModel.isEventDivider = function(record)
{
var recordTypes = WebInspector.TimelineModel.RecordType;
return record.type === recordTypes.MarkDOMContent || record.type === recordTypes.MarkLoad || record.type === recordTypes.TimeStamp;
}

WebInspector.TimelinePresentationModel.forAllRecords = function(recordsArray, callback)
{
if (!recordsArray)
return;
var stack = [{array: recordsArray, index: 0}];
while (stack.length) {
var entry = stack[stack.length - 1];
var records = entry.array;
if (entry.index < records.length) {
var record = records[entry.index];
if (callback(record))
return;
if (record.children)
stack.push({array: record.children, index: 0});
++entry.index;
} else
stack.pop();
}
}


WebInspector.TimelinePresentationModel.createEventDivider = function(recordType, title)
{
var eventDivider = document.createElement("div");
eventDivider.className = "resources-event-divider";
var recordTypes = WebInspector.TimelineModel.RecordType;

var eventDividerPadding = document.createElement("div");
eventDividerPadding.className = "resources-event-divider-padding";

if (recordType === recordTypes.MarkDOMContent)
eventDivider.className += " resources-blue-divider";
else if (recordType === recordTypes.MarkLoad)
eventDivider.className += " resources-red-divider";
else if (recordType === recordTypes.TimeStamp)
eventDivider.className += " resources-orange-divider";
else if (recordType === recordTypes.BeginFrame)
eventDivider.className += " timeline-frame-divider";

if (title)
eventDividerPadding.title = title;

eventDividerPadding.appendChild(eventDivider);
return eventDividerPadding;
}

WebInspector.TimelinePresentationModel.prototype = {

addFilter: function(filter)
{
this._filters.push(filter);
},

rootRecord: function()
{
return this._rootRecord;
},

frames: function()
{
return this._frames;
},

reset: function()
{
this._linkifier.reset();
this._rootRecord = new WebInspector.TimelinePresentationModel.Record(this, { type: WebInspector.TimelineModel.RecordType.Root }, null, null);
this._sendRequestRecords = {};
this._scheduledResourceRequests = {};
this._timerRecords = {};
this._requestAnimationFrameRecords = {};
this._frames = [];
this._minimumRecordTime = -1;
},

addFrame: function(frame)
{
this._frames.push(frame);
},

addRecord: function(record, parentRecord)
{
var connectedToOldRecord = false;
var recordTypes = WebInspector.TimelineModel.RecordType;

if (this._minimumRecordTime === -1 || record.startTime < this._minimumRecordTime)
this._minimumRecordTime = WebInspector.TimelineModel.startTimeInSeconds(record);

if (record.type === recordTypes.MarkDOMContent || record.type === recordTypes.MarkLoad)
parentRecord = null; 
else {
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.FireAnimationFrame) && 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.TimelinePresentationModel.Record(this, record, parentRecord, scriptDetails);

if (record.type === recordTypes.MarkDOMContent || record.type === recordTypes.MarkLoad)
return formattedRecord;

formattedRecord.collapsed = (parentRecord === this._rootRecord);

var childrenCount = children ? children.length : 0;
for (var i = 0; i < childrenCount; ++i)
this.addRecord(children[i], formattedRecord);

formattedRecord.calculateAggregatedStats(WebInspector.TimelinePresentationModel.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;
}
return formattedRecord;
},

_findParentRecord: function(record)
{
if (!this._glueRecords)
return null;
var recordTypes = WebInspector.TimelineModel.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"]];
else if (record.type === recordTypes.FireAnimationFrame)
parentRecord = this._requestAnimationFrameRecords[record.data["id"]];
return parentRecord;
},

setGlueRecords: function(glue)
{
this._glueRecords = glue;
},

filteredRecords: function()
{
function filter(record)
{
for (var i = 0; i < this._filters.length; ++i) {
if (!this._filters[i].accept(record))
return false;
}
return true;
}
return this._filterRecords(filter.bind(this));
},

_filterRecords: function(filter)
{
var recordsInWindow = [];

var stack = [{children: this._rootRecord.children, index: 0, parentIsCollapsed: false}];
while (stack.length) {
var entry = stack[stack.length - 1];
var records = entry.children;
if (records && entry.index < records.length) {
var record = records[entry.index];
++entry.index;

if (filter(record)) {
++record.parent._invisibleChildrenCount;
if (!entry.parentIsCollapsed)
recordsInWindow.push(record);
}

record._invisibleChildrenCount = 0;

stack.push({children: record.children,
index: 0,
parentIsCollapsed: (entry.parentIsCollapsed || record.collapsed),
parentRecord: record,
windowLengthBeforeChildrenTraversal: recordsInWindow.length});
} else {
stack.pop();
if (entry.parentRecord)
entry.parentRecord._visibleChildrenCount = recordsInWindow.length - entry.windowLengthBeforeChildrenTraversal;
}
}

return recordsInWindow;
}
}

WebInspector.TimelinePresentationModel.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.TimelinePresentationModel.Record = function(presentationModel, record, parentRecord, scriptDetails)
{
this._presentationModel = presentationModel;
this._linkifier = this._presentationModel._linkifier;
this._aggregatedStats = [];
var recordTypes = WebInspector.TimelineModel.RecordType;
var style = WebInspector.TimelinePresentationModel.recordStyle(record);
this.parent = parentRecord;
if (parentRecord)
parentRecord.children.push(this);
this.category = style.category;
this.title = record.type === recordTypes.TimeStamp ? record.data["message"] : style.title;
this.startTime = WebInspector.TimelineModel.startTimeInSeconds(record);
this.data = record.data;
this.type = record.type;
this.endTime = WebInspector.TimelineModel.endTimeInSeconds(record);
this._selfTime = this.endTime - this.startTime;
this._lastChildEndTime = this.endTime;
this._initiatorOffset = (parentRecord && parentRecord !== presentationModel._rootRecord) ?
parentRecord._initiatorOffset + this.startTime - parentRecord.startTime : 0;
this._startTimeOffset = this.startTime - presentationModel._minimumRecordTime;

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) {
presentationModel._sendRequestRecords[record.data["requestId"]] = this;
} else if (record.type === recordTypes.ScheduleResourceRequest) {
presentationModel._scheduledResourceRequests[record.data["url"]] = this;
} else if (record.type === recordTypes.ResourceReceiveResponse) {
var sendRequestRecord = presentationModel._sendRequestRecords[record.data["requestId"]];
if (sendRequestRecord) { 
this.url = sendRequestRecord.url;

sendRequestRecord._refreshDetails();
if (sendRequestRecord.parent !== presentationModel._rootRecord && sendRequestRecord.parent.type === recordTypes.ScheduleResourceRequest)
sendRequestRecord.parent._refreshDetails();
}
} else if (record.type === recordTypes.ResourceReceivedData || record.type === recordTypes.ResourceFinish) {
var sendRequestRecord = presentationModel._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"];
presentationModel._timerRecords[record.data["timerId"]] = this;
} else if (record.type === recordTypes.TimerFire) {
var timerInstalledRecord = presentationModel._timerRecords[record.data["timerId"]];
if (timerInstalledRecord) {
this.callSiteStackTrace = timerInstalledRecord.stackTrace;
this.timeout = timerInstalledRecord.timeout;
this.singleShot = timerInstalledRecord.singleShot;
}
} else if (record.type === recordTypes.RequestAnimationFrame) {
presentationModel._requestAnimationFrameRecords[record.data["id"]] = this;
} else if (record.type === recordTypes.FireAnimationFrame) {
var requestAnimationRecord = presentationModel._requestAnimationFrameRecords[record.data["id"]];
if (requestAnimationRecord)
this.callSiteStackTrace = requestAnimationRecord.stackTrace;
}
this._refreshDetails();
}

WebInspector.TimelinePresentationModel.Record.prototype = {
get lastChildEndTime()
{
return this._lastChildEndTime;
},

set lastChildEndTime(time)
{
this._lastChildEndTime = time;
},

get selfTime()
{
return this._selfTime;
},

set selfTime(time)
{
this._selfTime = time;
},

get cpuTime()
{
return this._cpuTime;
},

isLong: function()
{
return (this._lastChildEndTime - this.startTime) > WebInspector.TimelinePresentationModel.shortRecordThreshold;
},

get children()
{
if (!this._children)
this._children = [];
return this._children;
},

get visibleChildrenCount()
{
return this._visibleChildrenCount || 0;
},

get invisibleChildrenCount()
{
return this._invisibleChildrenCount || 0;
},

containsTime: function(time)
{
return this.startTime <= time && time <= this.endTime;
},

generatePopupContent: function()
{
var contentHelper = new WebInspector.TimelinePresentationModel.PopupContentHelper(this.title);

if (this._children && this._children.length) {
contentHelper._appendTextRow(WebInspector.UIString("Self Time"), Number.secondsToString(this._selfTime, true));
contentHelper._appendElementRow(WebInspector.UIString("Aggregated Time"),
WebInspector.TimelinePresentationModel._generateAggregatedInfo(this._aggregatedStats));
}
var text = WebInspector.UIString("%s (at %s)", Number.secondsToString(this._lastChildEndTime - this.startTime, true),
Number.secondsToString(this._startTimeOffset));
contentHelper._appendTextRow(WebInspector.UIString("Duration"), text);

const recordTypes = WebInspector.TimelineModel.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.FireAnimationFrame:
contentHelper._appendTextRow(WebInspector.UIString("Callback ID"), this.data["id"]);
break;
case recordTypes.FunctionCall:
contentHelper._appendElementRow(WebInspector.UIString("Location"), this._linkifyScriptLocation());
break;
case recordTypes.ScheduleResourceRequest:
case recordTypes.ResourceSendRequest:
case recordTypes.ResourceReceiveResponse:
case recordTypes.ResourceReceivedData:
case recordTypes.ResourceFinish:
contentHelper._appendElementRow(WebInspector.UIString("Resource"), this._linkifyLocation(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._appendElementRow(WebInspector.UIString("Script"), this._linkifyLocation(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._appendElementRow(WebInspector.UIString("Function Call"), this._linkifyScriptLocation());

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, this._linkifyCallFrame.bind(this));

if (this.stackTrace)
contentHelper._appendStackTrace(WebInspector.UIString("Call Stack"), this.stackTrace, this._linkifyCallFrame.bind(this));

return contentHelper._contentTable;
},

_refreshDetails: function()
{
this.details = this._getRecordDetails();
},

_getRecordDetails: function()
{
switch (this.type) {
case WebInspector.TimelineModel.RecordType.GCEvent:
return WebInspector.UIString("%s collected", Number.bytesToString(this.data["usedHeapSizeDelta"]));
case WebInspector.TimelineModel.RecordType.TimerFire:
return this._linkifyScriptLocation(this.data["timerId"]);
case WebInspector.TimelineModel.RecordType.FunctionCall:
return this._linkifyScriptLocation();
case WebInspector.TimelineModel.RecordType.FireAnimationFrame:
return this._linkifyScriptLocation(this.data["id"]);
case WebInspector.TimelineModel.RecordType.EventDispatch:
return this.data ? this.data["type"] : null;
case WebInspector.TimelineModel.RecordType.Paint:
return this.data["width"] + "\u2009\u00d7\u2009" + this.data["height"];
case WebInspector.TimelineModel.RecordType.TimerInstall:
case WebInspector.TimelineModel.RecordType.TimerRemove:
return this._linkifyTopCallFrame(this.data["timerId"]);
case WebInspector.TimelineModel.RecordType.RequestAnimationFrame:
case WebInspector.TimelineModel.RecordType.CancelAnimationFrame:
return this._linkifyTopCallFrame(this.data["id"]);
case WebInspector.TimelineModel.RecordType.ParseHTML:
case WebInspector.TimelineModel.RecordType.RecalculateStyles:
return this._linkifyTopCallFrame();
case WebInspector.TimelineModel.RecordType.EvaluateScript:
return this.url ? this._linkifyLocation(this.url, this.data["lineNumber"], 0) : null;
case WebInspector.TimelineModel.RecordType.XHRReadyStateChange:
case WebInspector.TimelineModel.RecordType.XHRLoad:
case WebInspector.TimelineModel.RecordType.ScheduleResourceRequest:
case WebInspector.TimelineModel.RecordType.ResourceSendRequest:
case WebInspector.TimelineModel.RecordType.ResourceReceivedData:
case WebInspector.TimelineModel.RecordType.ResourceReceiveResponse:
case WebInspector.TimelineModel.RecordType.ResourceFinish:
return WebInspector.displayNameForURL(this.url);
case WebInspector.TimelineModel.RecordType.TimeStamp:
return this.data["message"];
default:
return null;
}
},


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


_linkifyTopCallFrame: function(defaultValue)
{
return this.stackTrace ? this._linkifyCallFrame(this.stackTrace[0]) : defaultValue;
},


_linkifyScriptLocation: function(defaultValue)
{
return this.scriptName ? this._linkifyLocation(this.scriptName, this.scriptLine, 0) : defaultValue;
},

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];
for (var category in categories)
this._aggregatedStats[category] += child._aggregatedStats[category];
}
for (var category in this._aggregatedStats)
this._cpuTime += this._aggregatedStats[category];
}
this._aggregatedStats[this.category.name] += this._selfTime;
},

get aggregatedStats()
{
return this._aggregatedStats;
}
}


WebInspector.TimelinePresentationModel._generateAggregatedInfo = function(aggregatedStats)
{
var cell = document.createElement("span");
cell.className = "timeline-aggregated-info";
for (var index in 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(aggregatedStats[index], true);
cell.appendChild(text);
}
return cell;
}


WebInspector.TimelinePresentationModel.PopupContentHelper = function(title)
{
this._contentTable = document.createElement("table");
var titleCell = this._createCell(WebInspector.UIString("%s - Details", title), "timeline-details-title");
titleCell.colSpan = 2;
var titleRow = document.createElement("tr");
titleRow.appendChild(titleCell);
this._contentTable.appendChild(titleRow);
}

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

_appendStackTrace: function(title, stackTrace, callFrameLinkifier)
{
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 = callFrameLinkifier(stackFrame);
linkCell.appendChild(urlElement);
row.appendChild(linkCell);
framesTable.appendChild(row);
}
this._appendElementRow(title, framesTable, "timeline-stacktrace-title");
}
}

WebInspector.TimelinePresentationModel.generatePopupContentForFrame = function(frame)
{
var contentHelper = new WebInspector.TimelinePresentationModel.PopupContentHelper(WebInspector.UIString("Frame"));
var durationInSeconds = frame.endTime - frame.startTime;
var durationText = WebInspector.UIString("%s (at %s)", Number.secondsToString(frame.endTime - frame.startTime, true),
Number.secondsToString(frame.startTimeOffset, true));
contentHelper._appendTextRow(WebInspector.UIString("Duration"), durationText);
contentHelper._appendTextRow(WebInspector.UIString("FPS"), Math.floor(1 / durationInSeconds));
contentHelper._appendTextRow(WebInspector.UIString("CPU time"), Number.secondsToString(frame.cpuTime, true));
contentHelper._appendElementRow(WebInspector.UIString("Aggregated Time"),
WebInspector.TimelinePresentationModel._generateAggregatedInfo(frame.timeByCategory));

return contentHelper._contentTable;
}


WebInspector.TimelinePresentationModel.Filter = function()
{
}

WebInspector.TimelinePresentationModel.Filter.prototype = {

accept: function(record) { return false; }
}


WebInspector.TimelineCategory = function(name, title, color)
{
this.name = name;
this.title = title;
this.color = color;
this.hidden = false;
}

WebInspector.TimelineCategory.Events = {
VisibilityChanged: "VisibilityChanged"
};

WebInspector.TimelineCategory.prototype = {

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

set hidden(hidden)
{
this._hidden = hidden;
this.dispatchEventToListeners(WebInspector.TimelineCategory.Events.VisibilityChanged, this);
}
}

WebInspector.TimelineCategory.prototype.__proto__ = WebInspector.Object.prototype;






WebInspector.TimelinePanel = function()
{
WebInspector.Panel.call(this, "timeline");
this.registerRequiredCSS("timelinePanel.css");

this._model = new WebInspector.TimelineModel();
this._presentationModel = new WebInspector.TimelinePresentationModel();

this._overviewPane = new WebInspector.TimelineOverviewPane(this._model);
this._overviewPane.addEventListener(WebInspector.TimelineOverviewPane.Events.WindowChanged, this._scheduleRefresh.bind(this, false));
this._overviewPane.addEventListener(WebInspector.TimelineOverviewPane.Events.ModeChanged, this._timelinesOverviewModeChanged, this);
this._overviewPane.show(this.element);

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

this._timelineMemorySplitter = this.element.createChild("div");
this._timelineMemorySplitter.id = "timeline-memory-splitter";
this._timelineMemorySplitter.addEventListener("mousedown", this._startSplitterDragging.bind(this), false);
this._timelineMemorySplitter.addStyleClass("hidden");
this._memoryStatistics = new WebInspector.MemoryStatistics(this, this.splitView.preferredSidebarWidth());
WebInspector.settings.memoryCounterGraphsHeight = WebInspector.settings.createSetting("memoryCounterGraphsHeight", 150);

var itemsTreeElement = new WebInspector.SidebarSectionTreeElement(WebInspector.UIString("RECORDS"), {}, 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._containerContentElement.appendChild(this._timelineGrid.element);
this._memoryStatistics.setMainTimelineGrid(this._timelineGrid);

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._calculator = new WebInspector.TimelineCalculator(this._model);
var shortRecordThresholdTitle = Number.secondsToString(WebInspector.TimelinePresentationModel.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._verticalOverview = false;
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._showShortEvents = this.toggleFilterButton.toggled;
this._overviewPane.setShowShortEvents(this._showShortEvents);

this._timeStampRecords = [];
this._expandOffset = 15;

this._createFileSelector();

this._model.addEventListener(WebInspector.TimelineModel.Events.RecordAdded, this._onTimelineEventRecorded, this);
this._model.addEventListener(WebInspector.TimelineModel.Events.RecordsCleared, this._onRecordsCleared, this);

this._registerShortcuts();

this._allRecordsCount = 0;

this._presentationModel.addFilter(this._overviewPane);
this._presentationModel.addFilter(new WebInspector.TimelineCategoryFilter()); 
this._presentationModel.addFilter(new WebInspector.TimelineIsLongFilter(this)); 
}


WebInspector.TimelinePanel.rowHeight = 18;

WebInspector.TimelinePanel.prototype = {

_startSplitterDragging: function(event)
{
this._dragOffset = this._timelineMemorySplitter.offsetTop + 2 - event.pageY;
WebInspector.elementDragStart(this._timelineMemorySplitter, this._splitterDragging.bind(this), this._endSplitterDragging.bind(this), event, "ns-resize");
},


_splitterDragging: function(event)
{
var top = event.pageY + this._dragOffset
this._setSplitterPosition(top);
event.preventDefault();
this._refresh();
},


_endSplitterDragging: function(event)
{
delete this._dragOffset;
WebInspector.elementDragEnd(event);
this._memoryStatistics.show();
WebInspector.settings.memoryCounterGraphsHeight.set(this.splitView.element.offsetHeight);
},

_setSplitterPosition: function(top)
{
const overviewHeight = 90;
const sectionMinHeight = 100;
top = Number.constrain(top, overviewHeight + sectionMinHeight, this.element.offsetHeight - sectionMinHeight);

this.splitView.element.style.height = (top - overviewHeight) + "px";
this._timelineMemorySplitter.style.top = (top - 2) + "px";
this._memoryStatistics.setTopPosition(top);
},

get calculator()
{
return this._calculator;
},

get toolbarItemLabel()
{
return WebInspector.UIString("Timeline");
},

get statusBarItems()
{
var statusBarItems = [ this.toggleFilterButton.element, this.toggleTimelineButton.element, this.clearButton.element, this.garbageCollectButton.element, this._glueParentButton.element, this.statusBarFilters ];

return statusBarItems;
},

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

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

this._glueParentButton = new WebInspector.StatusBarButton(WebInspector.UIString("Glue asynchronous events to causes"), "glue-async-status-bar-item");
this._glueParentButton.toggled = true;
this._presentationModel.setGlueRecords(true);
this._glueParentButton.addEventListener("click", this._glueParentButtonClicked, this);

this.statusBarFilters = document.createElement("div");
this.statusBarFilters.className = "status-bar-items";
var categories = WebInspector.TimelinePresentationModel.categories();
for (var categoryName in categories) {
var category = categories[categoryName];
this.statusBarFilters.appendChild(this._createTimelineCategoryStatusBarCheckbox(category, this._onCategoryCheckboxClicked.bind(this, category)));
}
},

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

_onCategoryCheckboxClicked: function(category, event)
{
category.hidden = !event.target.checked;
this._scheduleRefresh(true);
},

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

if (InspectorFrontendHost.canSave()) {
this._shortcuts[shortcut.makeKey("s", modifiers.CtrlOrMeta)] = this._saveToFile.bind(this);
section.addKey(shortcut.shortcutToString("s", modifiers.CtrlOrMeta), WebInspector.UIString("Save timeline data"));
}

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

_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();
if (InspectorFrontendHost.canSave())
contextMenu.appendItem(WebInspector.UIString("Save Timeline data\u2026"), this._saveToFile.bind(this));
contextMenu.appendItem(WebInspector.UIString("Load Timeline data\u2026"), this._fileSelectorElement.click.bind(this._fileSelectorElement));
contextMenu.show(event);
},

_saveToFile: function()
{
this._model.saveToFile();
},

_loadFromFile: function()
{
if (this.toggleTimelineButton.toggled) {
this.toggleTimelineButton.toggled = false;
this._model.stopRecord();
}
this._model.loadFromFile(this._fileSelectorElement.files[0]);
this._createFileSelector();
},

_rootRecord: function()
{
return this._presentationModel.rootRecord();
},

_updateRecordsCounter: function(recordsInWindowCount)
{
this.recordsCounter.textContent = WebInspector.UIString("%d of %d captured records are visible", recordsInWindowCount, this._allRecordsCount);
},

_updateEventDividers: function()
{
this._timelineGrid.removeEventDividers();
var clientWidth = this._graphRowsElement.offsetWidth;
var dividers = [];

for (var i = 0; i < this._timeStampRecords.length; ++i) {
var record = this._timeStampRecords[i];
var positions = this._calculator.computeBarGraphWindowPosition(record);
var dividerPosition = Math.round(positions.left);
if (dividerPosition < 0 || dividerPosition >= clientWidth || dividers[dividerPosition])
continue;
var divider = WebInspector.TimelinePresentationModel.createEventDivider(record.type, record.title);
divider.style.left = dividerPosition + "px";
dividers[dividerPosition] = divider;
}
this._timelineGrid.addEventDividers(dividers);
},

_shouldShowFrames: function()
{
return this._verticalOverview && this._presentationModel.frames().length > 0 && this.calculator.boundarySpan < 1.0;
},

_updateFrames: function()
{
var frames = this._presentationModel.frames();
var clientWidth = this._graphRowsElement.offsetWidth;
if (this._frameContainer)
this._frameContainer.removeChildren();
else {
this._frameContainer = document.createElement("div");
this._frameContainer.addStyleClass("fill");
this._frameContainer.addStyleClass("timeline-frame-container");
this._frameContainer.addEventListener("dblclick", this._onFrameDoubleClicked.bind(this), false);
}

var dividers = [ this._frameContainer ];

for (var i = 0; i < frames.length; ++i) {
var frame = frames[i];
var frameStart = this._calculator.computePosition(frame.startTime);
var frameEnd = this._calculator.computePosition(frame.endTime);
if (frameEnd <= 0 || frameStart >= clientWidth)
continue;

var frameStrip = document.createElement("div");
frameStrip.className = "timeline-frame-strip";
var actualStart = Math.max(frameStart, 0);
var width = frameEnd - actualStart;
frameStrip.style.left = actualStart + "px";
frameStrip.style.width = width + "px";
frameStrip._frame = frame;

const minWidthForFrameInfo = 60;
if (width > minWidthForFrameInfo)
frameStrip.textContent = Number.secondsToString(frame.endTime - frame.startTime, true);

this._frameContainer.appendChild(frameStrip);

if (actualStart > 0) {
var frameMarker = WebInspector.TimelinePresentationModel.createEventDivider(WebInspector.TimelineModel.RecordType.BeginFrame);
frameMarker.style.left = frameStart + "px";
dividers.push(frameMarker);
}
}
this._timelineGrid.addEventDividers(dividers);
},

_onFrameDoubleClicked: function(event)
{
var frameBar = event.target.enclosingNodeOrSelfWithClass("timeline-frame-strip");
if (!frameBar)
return;
this._overviewPane.zoomToFrame(frameBar._frame);
},

_timelinesOverviewModeChanged: function(event)
{
var shouldShowMemory = event.data === WebInspector.TimelineOverviewPane.Mode.Memory;
var verticalOverview = event.data === WebInspector.TimelineOverviewPane.Mode.EventsVertical;
if (verticalOverview !== this._verticalOverview) {
this._verticalOverview = verticalOverview;
this._glueParentButton.disabled = verticalOverview;
this._presentationModel.setGlueRecords(this._glueParentButton.toggled && !verticalOverview);
this._repopulateRecords();

if (verticalOverview) {
this.element.addStyleClass("timeline-vertical-overview");
this._frameController = new WebInspector.TimelineFrameController(this._model, this._overviewPane, this._presentationModel);
} else {
this._frameController.dispose();
this._frameController = null;
this.element.removeStyleClass("timeline-vertical-overview");
}
}
if (shouldShowMemory === this._memoryStatistics.visible())
return;
if (!shouldShowMemory) {
this._timelineMemorySplitter.addStyleClass("hidden");
this._memoryStatistics.hide();
this.splitView.element.style.height = "auto";
this.splitView.element.style.bottom = "0";
} else {
this._timelineMemorySplitter.removeStyleClass("hidden");
this._memoryStatistics.show();
this.splitView.element.style.bottom = "auto";
this._setSplitterPosition(WebInspector.settings.memoryCounterGraphsHeight.get());
}
this._refresh();
},

_toggleTimelineButtonClicked: function()
{
if (this.toggleTimelineButton.toggled)
this._model.stopRecord();
else {
this._model.startRecord();
WebInspector.userMetrics.TimelineStarted.record();
}
this.toggleTimelineButton.toggled = !this.toggleTimelineButton.toggled;
},

_toggleFilterButtonClicked: function()
{
this.toggleFilterButton.toggled = !this.toggleFilterButton.toggled;
this._showShortEvents = this.toggleFilterButton.toggled;
this._overviewPane.setShowShortEvents(this._showShortEvents);
this.toggleFilterButton.element.title = this._showShortEvents ? this._hideShortRecordsTitleText : this._showShortRecordsTitleText;
this._scheduleRefresh(true);
},

_garbageCollectButtonClicked: function()
{
ProfilerAgent.collectGarbage();
},

_glueParentButtonClicked: function()
{
this._glueParentButton.toggled = !this._glueParentButton.toggled;
this._presentationModel.setGlueRecords(this._glueParentButton.toggled);
this._repopulateRecords();
},

_repopulateRecords: function()
{
this._resetPanel();
var records = this._model.records;
for (var i = 0; i < records.length; ++i)
this._innerAddRecordToTimeline(records[i], this._rootRecord());
this._scheduleRefresh(false);
},

_onTimelineEventRecorded: function(event)
{
this._innerAddRecordToTimeline(event.data, this._rootRecord());
this._scheduleRefresh(false);

if (event.data["counters"])
this._memoryStatistics.addTimlineEvent(event);
},

_innerAddRecordToTimeline: function(record, parentRecord)
{
var formattedRecord = this._presentationModel.addRecord(record, parentRecord);
++this._allRecordsCount;
var recordTypes = WebInspector.TimelineModel.RecordType;
var timeStampRecords = this._timeStampRecords;
function addTimestampRecords(record)
{
if (WebInspector.TimelinePresentationModel.isEventDivider(record))
timeStampRecords.push(record);
}
WebInspector.TimelinePresentationModel.forAllRecords([ formattedRecord ], addTimestampRecords);
},

sidebarResized: function(event)
{
var width = event.data;
this._sidebarBackgroundElement.style.width = width + "px";
this._scheduleRefresh(false);
this._overviewPane.sidebarResized(width);

this.statusBarFilters.style.left = Math.max((this.statusBarItems.length + 2) * 31, width) + "px";
this._memoryStatistics.setSidebarWidth(width);
},

onResize: function()
{
this._closeRecordDetails();
this._scheduleRefresh(false);
},

_clearPanel: function()
{
this._model.reset();
},

_onRecordsCleared: function()
{
this._resetPanel();
this._refresh();
},

_resetPanel: function()
{
this._presentationModel.reset();
this._timeStampRecords = [];
this._boundariesAreValid = false;
this._adjustScrollPosition(0);
this._closeRecordDetails();
this._allRecordsCount = 0;
this._memoryStatistics.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);
},

_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._calculator.setWindow(this._overviewPane.windowStartTime(), this._overviewPane.windowEndTime());
this._calculator.setDisplayWindow(!this._overviewPane.windowLeft() ? this._expandOffset : 0, this._graphRowsElement.clientWidth);

var recordsInWindowCount = this._refreshRecords();
this._updateRecordsCounter(recordsInWindowCount);
if(!this._boundariesAreValid) {
this._updateEventDividers();
if (this._shouldShowFrames()) {
this._timelineGrid.removeDividers();
this._updateFrames();
} else {
this._timelineGrid.updateDividers(this._calculator);
}
}
if (this._memoryStatistics.visible())
this._memoryStatistics.refresh();
this._boundariesAreValid = true;
},

revealRecordAt: function(time)
{
if (this._verticalOverview)
return;
var recordsInWindow = this._presentationModel.filteredRecords();
var recordToReveal;
for (var i = 0; i < recordsInWindow.length; ++i) {
var record = recordsInWindow[i];
if (record.containsTime(time)) {
recordToReveal = record;
break;
}

if (!recordToReveal || record.endTime < time && recordToReveal.endTime < record.endTime)
recordToReveal = record;
}


if (!recordToReveal) {
this._containerElement.scrollTop = 0;
return;
}


for (var parent = recordToReveal.parent; parent !== this._rootRecord(); parent = parent.parent)
parent.collapsed = false;
var index = recordsInWindow.indexOf(recordToReveal);
this._containerElement.scrollTop = index * WebInspector.TimelinePanel.rowHeight;
},

_refreshRecords: function()
{
var recordsInWindow = this._presentationModel.filteredRecords();


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);
var positions = this._calculator.computeBarGraphWindowPosition(record);
expandElement._update(record, i, positions.left - this._expandOffset, positions.width);
}
} 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, visibleTop);
graphRowElement.row.update(record, isEven, this._calculator, 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";
this._adjustScrollPosition((recordsInWindow.length + 1) * rowHeight);

return recordsInWindow.length;
},

_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") ||
element.enclosingNodeOrSelfWithClass("timeline-frame-strip");
},

_mouseOut: function(e)
{
this._hideRectHighlight();
},

_mouseMove: function(e)
{
var anchor = this._getPopoverAnchor(e.target);

if (anchor && anchor.row && 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)
{
if (anchor.hasStyleClass("timeline-frame-strip")) {
var frame = anchor._frame;
popover.show(WebInspector.TimelinePresentationModel.generatePopupContentForFrame(frame), anchor);
} else {
var record = anchor.row._record;
popover.show(record.generatePopupContent(), anchor);
}
},

_closeRecordDetails: function()
{
this._popoverHelper.hidePopover();
}
}

WebInspector.TimelinePanel.prototype.__proto__ = WebInspector.Panel.prototype;


WebInspector.TimelineCalculator = function(model)
{
this._model = model;
}

WebInspector.TimelineCalculator._minWidth = 5;
WebInspector.TimelineCalculator._borderWidth = 4;

WebInspector.TimelineCalculator.prototype = {

computePosition: function(time)
{
return (time - this.minimumBoundary) / this.boundarySpan * this._workingArea + this.paddingLeft;
},

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)
{
var percentages = this.computeBarGraphPercentages(record);

var left = this.computePosition(record.startTime);
var width = (percentages.end - percentages.start) / 100 * this._workingArea + WebInspector.TimelineCalculator._minWidth;
var widthWithChildren =  (percentages.endWithChildren - percentages.start) / 100 * this._workingArea;
var cpuWidth = percentages.cpuWidth / 100 * this._workingArea + WebInspector.TimelineCalculator._minWidth;
if (percentages.endWithChildren > percentages.end)
widthWithChildren += WebInspector.TimelineCalculator._borderWidth + WebInspector.TimelineCalculator._minWidth;
return {left: left, width: width, widthWithChildren: widthWithChildren, cpuWidth: cpuWidth};
},

setWindow: function(minimumBoundary, maximumBoundary)
{
this.minimumBoundary = minimumBoundary;
this.maximumBoundary = maximumBoundary;
this.boundarySpan = this.maximumBoundary - this.minimumBoundary;
},


setDisplayWindow: function(paddingLeft, clientWidth)
{
this._workingArea = clientWidth - WebInspector.TimelineCalculator._minWidth - WebInspector.TimelineCalculator._borderWidth - paddingLeft;
this.paddingLeft = paddingLeft;
},

formatTime: function(value)
{
return Number.secondsToString(value + this.minimumBoundary - this._model.minimumRecordTime());
}
}


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, offset)
{
this._record = record;
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, expandOffset, index)
{
this._record = record;
this.element.className = "timeline-graph-side timeline-category-" + record.category.name + (isEven ? " even" : "");
var barPosition = calculator.computeBarGraphWindowPosition(record);
this._barWithChildrenElement.style.left = barPosition.left + "px";
this._barWithChildrenElement.style.width = barPosition.widthWithChildren + "px";
this._barElement.style.left = barPosition.left + "px";
this._barElement.style.width =  barPosition.width + "px";
this._barCpuElement.style.left = barPosition.left + "px";
this._barCpuElement.style.width = barPosition.cpuWidth + "px";
this._expandElement._update(record, index, barPosition.left - expandOffset, barPosition.width);
},

_onClick: function(event)
{
this._record.collapsed = !this._record.collapsed;
this._scheduleRefresh(false);
},

dispose: function()
{
this.element.parentElement.removeChild(this.element);
this._expandElement._dispose();
}
}


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, left, width)
{
const rowHeight = WebInspector.TimelinePanel.rowHeight;
if (record.visibleChildrenCount || record.invisibleChildrenCount) {
this._element.style.top = index * rowHeight + "px";
this._element.style.left = left + "px";
this._element.style.width = Math.max(12, 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.TimelineCategoryFilter = function()
{
}

WebInspector.TimelineCategoryFilter.prototype = {

accept: function(record)
{
return !record.category.hidden && record.type !== WebInspector.TimelineModel.RecordType.BeginFrame;
}
}


WebInspector.TimelineIsLongFilter = function(panel)
{
this._panel = panel;
}

WebInspector.TimelineIsLongFilter.prototype = {

accept: function(record)
{
return this._panel._showShortEvents || record.isLong();
}
}






WebInspector.TimelineOverviewPane = function(model)
{
WebInspector.View.call(this);
this.element.id = "timeline-overview-panel";

this._windowStartTime = 0;
this._windowEndTime = Infinity;
this._eventDividers = [];

this._model = model;

this._topPaneSidebarElement = document.createElement("div");
this._topPaneSidebarElement.id = "timeline-overview-sidebar";

if (WebInspector.experimentsSettings.timelineVerticalOverview.isEnabled()) {
this._overviewModeSelector = new WebInspector.TimelineOverviewModeSelector(this._onOverviewModeChanged.bind(this));
this._overviewModeSelector.addButton(WebInspector.UIString("Show each event category as a horizontal strip in overview"),
"timeline-mode-horizontal-bars", WebInspector.TimelineOverviewPane.Mode.EventsHorizontal);
this._overviewModeSelector.addButton(WebInspector.UIString("Show each event as a vertical bar in overview"),
"timeline-mode-vertical-bars", WebInspector.TimelineOverviewPane.Mode.EventsVertical);
}

var overviewTreeElement = document.createElement("ol");
overviewTreeElement.className = "sidebar-tree";
this._topPaneSidebarElement.appendChild(overviewTreeElement);
this.element.appendChild(this._topPaneSidebarElement);

var topPaneSidebarTree = new TreeOutline(overviewTreeElement);
this._timelinesOverviewItem = new WebInspector.SidebarTreeElement("resources-time-graph-sidebar-item", WebInspector.UIString("Timelines"));
if (this._overviewModeSelector)
this._timelinesOverviewItem.statusElement = this._overviewModeSelector.element;

topPaneSidebarTree.appendChild(this._timelinesOverviewItem);
this._timelinesOverviewItem.revealAndSelect(false);
this._timelinesOverviewItem.onselect = this._showTimelines.bind(this);

this._memoryOverviewItem = new WebInspector.SidebarTreeElement("resources-size-graph-sidebar-item", WebInspector.UIString("Memory"));
topPaneSidebarTree.appendChild(this._memoryOverviewItem);
this._memoryOverviewItem.onselect = this._showMemoryGraph.bind(this);

this._currentMode = WebInspector.TimelineOverviewPane.Mode.EventsHorizontal;

this._overviewContainer = this.element.createChild("div", "fill");
this._overviewContainer.id = "timeline-overview-container";

this._overviewGrid = new WebInspector.TimelineGrid();
this._overviewGrid.element.id = "timeline-overview-grid";
this._overviewGrid.itemsGraphsElement.id = "timeline-overview-timelines";

this._overviewContainer.appendChild(this._overviewGrid.element);

this._heapGraph = new WebInspector.HeapGraph(this._model);
this._heapGraph.element.id = "timeline-overview-memory";
this._overviewGrid.element.insertBefore(this._heapGraph.element, this._overviewGrid.itemsGraphsElement);

this._overviewWindow = new WebInspector.TimelineOverviewWindow(this._overviewContainer);
this._overviewWindow.addEventListener(WebInspector.TimelineOverviewWindow.Events.WindowChanged, this._onWindowChanged, this);

this._overviewContainer.appendChild(this._overviewGrid.element);

var separatorElement = document.createElement("div");
separatorElement.id = "timeline-overview-separator";
this.element.appendChild(separatorElement);

this._categoryGraphs = {};
var i = 0;
var categories = WebInspector.TimelinePresentationModel.categories();
for (var category in categories) {
var categoryGraph = new WebInspector.TimelineCategoryGraph(categories[category], i++ % 2);
this._categoryGraphs[category] = categoryGraph;
this._overviewGrid.itemsGraphsElement.appendChild(categoryGraph.graphElement);
categories[category].addEventListener(WebInspector.TimelineCategory.Events.VisibilityChanged, this._onCategoryVisibilityChanged, this);
}

this._overviewGrid.setScrollAndDividerTop(0, 0);
this._overviewCalculator = new WebInspector.TimelineOverviewCalculator();

model.addEventListener(WebInspector.TimelineModel.Events.RecordAdded, this._onRecordAdded, this);
model.addEventListener(WebInspector.TimelineModel.Events.RecordsCleared, this._reset, this);
}

WebInspector.TimelineOverviewPane.MinSelectableSize = 12;

WebInspector.TimelineOverviewPane.WindowScrollSpeedFactor = .3;

WebInspector.TimelineOverviewPane.ResizerOffset = 3.5; 

WebInspector.TimelineOverviewPane.Mode = {
EventsVertical: "EventsVertical",
EventsHorizontal: "EventsHorizontal",
Memory: "Memory"
};

WebInspector.TimelineOverviewPane.Events = {
ModeChanged: "ModeChanged",
WindowChanged: "WindowChanged"
};

WebInspector.TimelineOverviewPane.prototype = {
wasShown: function()
{
this._update();
},

_showTimelines: function()
{
var newMode = this._overviewModeSelector ? this._overviewModeSelector.value : WebInspector.TimelineOverviewPane.Mode.EventsHorizontal;
if (this._currentMode === newMode)
return;
this._currentMode = newMode;
this._timelinesOverviewItem.revealAndSelect(false);
this._heapGraph.hide();
this._setVerticalOverview(this._currentMode === WebInspector.TimelineOverviewPane.Mode.EventsVertical);
this._overviewGrid.itemsGraphsElement.removeStyleClass("hidden");
this.dispatchEventToListeners(WebInspector.TimelineOverviewPane.Events.ModeChanged, this._currentMode);
},

_showMemoryGraph: function()
{
this._currentMode = WebInspector.TimelineOverviewPane.Mode.Memory;
this._setVerticalOverview(false);
this._memoryOverviewItem.revealAndSelect(false);
this._heapGraph.show();
this._heapGraph.update();
this._overviewGrid.itemsGraphsElement.addStyleClass("hidden");
this.dispatchEventToListeners(WebInspector.TimelineOverviewPane.Events.ModeChanged, this._currentMode);
},

_setVerticalOverview: function(enabled)
{
if (!enabled === !this._verticalOverview)
return;
if (enabled) {
this._verticalOverview = new WebInspector.TimelineVerticalOverview(this._model);
this._verticalOverview.show(this._overviewContainer);
} else {
this._verticalOverview.detach();
this._verticalOverview = null;
this._overviewGrid.itemsGraphsElement.removeStyleClass("hidden");
this._updateCategoryStrips();
}
},

_onOverviewModeChanged: function()
{

if (this._currentMode === WebInspector.TimelineOverviewPane.Mode.Memory)
return;
this._showTimelines();
},

_onCategoryVisibilityChanged: function(event)
{
var category = event.data;
this._categoryGraphs[category.name].dimmed = category.hidden;
this._update();
},

_update: function()
{
delete this._refreshTimeout;

this._overviewCalculator.setWindow(this._model.minimumRecordTime(), this._model.maximumRecordTime());
this._overviewCalculator.setDisplayWindow(0, this._overviewContainer.clientWidth);

if (this._heapGraph.visible)
this._heapGraph.update();
else if (this._verticalOverview)
this._verticalOverview.update();
else
this._updateCategoryStrips();

this._overviewGrid.updateDividers(this._overviewCalculator);
this._updateEventDividers();
},

_updateCategoryStrips: function()
{

var timelines = {};
var categories = WebInspector.TimelinePresentationModel.categories();
for (var category in categories) {
timelines[category] = [];
this._categoryGraphs[category].clearChunks();
}


function markPercentagesForRecord(record)
{
var isLong = WebInspector.TimelineModel.durationInSeconds(record) > WebInspector.TimelinePresentationModel.shortRecordThreshold;
if (!(this._showShortEvents || isLong))
return;
var percentages = this._overviewCalculator.computeBarGraphPercentages(record);

var end = Math.round(percentages.end);
var categoryName = WebInspector.TimelinePresentationModel.categoryForRecord(record).name;
for (var j = Math.round(percentages.start); j <= end; ++j)
timelines[categoryName][j] = true;
}
var records = this._model.records;
WebInspector.TimelinePresentationModel.forAllRecords(records, markPercentagesForRecord.bind(this));


for (var category in 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;
}
}
},

_updateEventDividers: function()
{
var records = this._eventDividers;
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 = WebInspector.TimelinePresentationModel.createEventDivider(record.type);
divider.style.left = positions.start + "%";
dividers[dividerPosition] = divider;
}
this._overviewGrid.addEventDividers(dividers);
},

sidebarResized: function(width)
{
this._overviewContainer.style.left = width + "px";
this._topPaneSidebarElement.style.width = width + "px";
},


addFrame: function(frame)
{
this._verticalOverview.addFrame(frame);
this._scheduleRefresh();
},


zoomToFrame: function(frame)
{
var window = this._verticalOverview.framePosition(frame);
if (!window)
return;

this._overviewWindow._setWindowPosition(window.start, window.end);
},

_onRecordAdded: function(event)
{
var record = event.data;
var eventDividers = this._eventDividers;
function addEventDividers(record)
{
if (WebInspector.TimelinePresentationModel.isEventDivider(record))
eventDividers.push(record);
}
WebInspector.TimelinePresentationModel.forAllRecords([record], addEventDividers);
this._scheduleRefresh();
},

_reset: function()
{
this._windowStartTime = 0;
this._windowEndTime = Infinity;
this._overviewWindow.reset();
this._overviewCalculator.reset();
this._eventDividers = [];
this._overviewGrid.updateDividers(this._overviewCalculator);
if (this._verticalOverview)
this._verticalOverview.reset();
this._update();
},


accept: function(record)
{
return record.endTime >= this._windowStartTime && record.startTime <= this._windowEndTime;
},

windowStartTime: function()
{
return this._windowStartTime || this._model.minimumRecordTime();
},

windowEndTime: function()
{
return this._windowEndTime < Infinity ? this._windowEndTime : this._model.maximumRecordTime();
},

windowLeft: function()
{
return this._overviewWindow.windowLeft;
},

windowRight: function()
{
return this._overviewWindow.windowRight;
},

_onWindowChanged: function()
{
if (this._verticalOverview) {
var times = this._verticalOverview.getWindowTimes(this.windowLeft(), this.windowRight());
this._windowStartTime = times.startTime;
this._windowEndTime = times.endTime;
} else {
var absoluteMin = this._model.minimumRecordTime();
var absoluteMax = this._model.maximumRecordTime();
this._windowStartTime = absoluteMin + (absoluteMax - absoluteMin) * this.windowLeft();
this._windowEndTime = absoluteMin + (absoluteMax - absoluteMin) * this.windowRight();
}
this.dispatchEventToListeners(WebInspector.TimelineOverviewPane.Events.WindowChanged);
},

setShowShortEvents: function(value)
{
this._showShortEvents = value;
this._update();
},

_scheduleRefresh: function()
{
if (this._refreshTimeout)
return;
if (!this.isShowing())
return;
this._refreshTimeout = setTimeout(this._update.bind(this), 100);
}
}

WebInspector.TimelineOverviewPane.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.TimelineOverviewWindow = function(parentElement)
{
this._parentElement = parentElement;

this.windowLeft = 0.0;
this.windowRight = 1.0;

this._parentElement.addEventListener("mousedown", this._dragWindow.bind(this), true);
this._parentElement.addEventListener("mousewheel", this._onMouseWheel.bind(this), true);
this._parentElement.addEventListener("dblclick", this._resizeWindowMaximum.bind(this), true);

this._overviewWindowElement = document.createElement("div");
this._overviewWindowElement.className = "timeline-overview-window";
parentElement.appendChild(this._overviewWindowElement);

this._overviewWindowBordersElement = document.createElement("div");
this._overviewWindowBordersElement.className = "timeline-overview-window-rulers";
parentElement.appendChild(this._overviewWindowBordersElement);

var overviewDividersBackground = document.createElement("div");
overviewDividersBackground.className = "timeline-overview-dividers-background";
parentElement.appendChild(overviewDividersBackground);

this._leftResizeElement = document.createElement("div");
this._leftResizeElement.className = "timeline-window-resizer";
this._leftResizeElement.style.left = 0;
parentElement.appendChild(this._leftResizeElement);

this._rightResizeElement = document.createElement("div");
this._rightResizeElement.className = "timeline-window-resizer timeline-window-resizer-right";
this._rightResizeElement.style.right = 0;
parentElement.appendChild(this._rightResizeElement);
}

WebInspector.TimelineOverviewWindow.Events = {
WindowChanged: "WindowChanged"
}

WebInspector.TimelineOverviewWindow.prototype = {
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%";
},

_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._parentElement.offsetLeft);
else
this._resizeWindowRight(event.pageX - this._parentElement.offsetLeft);
event.preventDefault();
},

_dragWindow: function(event)
{

if (event.button)
return;
var node = event.target;
while (node) {
if (node.hasStyleClass("resources-dividers-label-bar")) {
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._parentElement) {
var position = event.pageX - this._parentElement.offsetLeft;
this._overviewWindowSelector = new WebInspector.TimelineOverviewPane.WindowSelector(this._parentElement, position);
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._parentElement.offsetLeft);
event.preventDefault();
},

_endWindowSelectorDragging: function(event)
{
WebInspector.elementDragEnd(event);
var window = this._overviewWindowSelector._close(event.pageX - this._parentElement.offsetLeft);
delete this._overviewWindowSelector;
if (window.end === window.start) { 
var middle = window.end;
window.start = Math.max(0, middle - WebInspector.TimelineOverviewPane.MinSelectableSize / 2);
window.end = Math.min(this._parentElement.clientWidth, middle + WebInspector.TimelineOverviewPane.MinSelectableSize / 2);
} else if (window.end - window.start < WebInspector.TimelineOverviewPane.MinSelectableSize) {
if (this._parentElement.clientWidth - 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._parentElement.clientWidth) {
end = this._parentElement.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._parentElement.clientWidth - 10)
end = this._parentElement.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._parentElement.clientWidth);
},

_setWindowPosition: function(start, end)
{
var clientWidth = this._parentElement.clientWidth;
const rulerAdjustment = 1 / clientWidth;
if (typeof start === "number") {
this.windowLeft = start / 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 / 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(WebInspector.TimelineOverviewWindow.Events.WindowChanged);
},

_endWindowDragging: function(event)
{
WebInspector.elementDragEnd(event);
},

_onMouseWheel: function(event)
{
const zoomFactor = 1.1;
const mouseWheelZoomSpeed = 1 / 120;

if (typeof event.wheelDeltaY === "number" && event.wheelDeltaY) {
var referencePoint = event.pageX - this._parentElement.offsetLeft;
this._zoom(Math.pow(zoomFactor, -event.wheelDeltaY * mouseWheelZoomSpeed), referencePoint);
}
if (typeof event.wheelDeltaX === "number" && event.wheelDeltaX) {
this._windowDragging(event.pageX + Math.round(event.wheelDeltaX * WebInspector.TimelineOverviewPane.WindowScrollSpeedFactor),
this._leftResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.ResizerOffset,
this._rightResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.ResizerOffset,
event);
}
},


_zoom: function(factor, referencePoint)
{
var left = this._leftResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.ResizerOffset;
var right = this._rightResizeElement.offsetLeft + WebInspector.TimelineOverviewPane.ResizerOffset;

if (factor < 1 && factor * (right - left) < WebInspector.TimelineOverviewPane.MinSelectableSize)
return;
left = Math.max(0, referencePoint + (left - referencePoint) * factor);
right = Math.min(this._parentElement.clientWidth, referencePoint + (right - referencePoint) * factor);
this._setWindowPosition(left, right);
}
}

WebInspector.TimelineOverviewWindow.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.TimelineOverviewCalculator = function()
{
}

WebInspector.TimelineOverviewCalculator.prototype = {

computePosition: function(time)
{
return (time - this.minimumBoundary) / this.boundarySpan * this._workingArea + this.paddingLeft;
},

computeBarGraphPercentages: function(record)
{
var start = (WebInspector.TimelineModel.startTimeInSeconds(record) - this.minimumBoundary) / this.boundarySpan * 100;
var end = (WebInspector.TimelineModel.endTimeInSeconds(record) - this.minimumBoundary) / this.boundarySpan * 100;
return {start: start, end: end};
},


setWindow: function(minimum, maximum)
{
this.minimumBoundary = minimum >= 0 ? minimum : undefined;
this.maximumBoundary = maximum >= 0 ? maximum : undefined;
this.boundarySpan = this.maximumBoundary - this.minimumBoundary;
},


setDisplayWindow: function(paddingLeft, clientWidth)
{
this._workingArea = clientWidth - paddingLeft;
this.paddingLeft = paddingLeft;
},

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

formatTime: 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.TimelineOverviewPane.WindowSelector = function(parent, position)
{
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.TimelineOverviewPane.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(model) {
this._canvas = document.createElement("canvas");
this._model = model;

this._maxHeapSizeLabel = document.createElement("div");
this._maxHeapSizeLabel.addStyleClass("max");
this._maxHeapSizeLabel.addStyleClass("memory-graph-label");
this._minHeapSizeLabel = document.createElement("div");
this._minHeapSizeLabel.addStyleClass("min");
this._minHeapSizeLabel.addStyleClass("memory-graph-label");

this._element = document.createElement("div");
this._element.addStyleClass("hidden");
this._element.appendChild(this._canvas);
this._element.appendChild(this._maxHeapSizeLabel);
this._element.appendChild(this._minHeapSizeLabel);
}

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

update: function()
{
var records = this._model.records;
if (!records.length)
return;

const yPadding = 5;
this._canvas.width = this.element.clientWidth;
this._canvas.height = this.element.clientHeight - yPadding;

const lowerOffset = 3;
var maxUsedHeapSize = 0;
var minUsedHeapSize = 100000000000;
var minTime = this._model.minimumRecordTime();
var maxTime = this._model.maximumRecordTime();;
WebInspector.TimelinePresentationModel.forAllRecords(records, function(r) {
maxUsedHeapSize = Math.max(maxUsedHeapSize, r.usedHeapSize || maxUsedHeapSize);
minUsedHeapSize = Math.min(minUsedHeapSize, r.usedHeapSize || minUsedHeapSize);
});
minUsedHeapSize = Math.min(minUsedHeapSize, maxUsedHeapSize);

var width = this._canvas.width;
var height = this._canvas.height - lowerOffset;
var xFactor = width / (maxTime - minTime);
var yFactor = height / (maxUsedHeapSize - minUsedHeapSize);

var histogram = new Array(width);
WebInspector.TimelinePresentationModel.forAllRecords(records, function(r) {
if (!r.usedHeapSize)
return;
var x = Math.round((WebInspector.TimelineModel.endTimeInSeconds(r) - minTime) * xFactor);
var y = Math.round((r.usedHeapSize - minUsedHeapSize) * 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(maxUsedHeapSize);
this._minHeapSizeLabel.textContent = Number.bytesToString(minUsedHeapSize);
},

_clear: function(ctx) {
ctx.fillStyle = "rgba(255,255,255,0.8)";
ctx.fillRect(0, 0, this._canvas.width, this._canvas.height);
},
}


WebInspector.TimelineVerticalOverview = function(model) {
WebInspector.View.call(this);
this.element = document.createElement("canvas");
this.element.className = "timeline-vertical-overview-bars fill";
this._model = model;
this.reset();

this._outerPadding = 4;
this._maxInnerBarWidth = 10;


this._actualPadding = 5;
this._actualOuterBarWidth = this._maxInnerBarWidth + this._actualPadding;

this._context = this.element.getContext("2d");
this._fillStyles = {};
this._fillStyles.loading = this._context.createLinearGradient(0, 0, this._maxInnerBarWidth, 0);
this._fillStyles.loading.addColorStop(0, "rgb(201, 220, 245)");
this._fillStyles.loading.addColorStop(1, "rgb(109, 157, 222)");
this._fillStyles.scripting = this._context.createLinearGradient(0, 0, this._maxInnerBarWidth, 0);
this._fillStyles.scripting.addColorStop(0, "rgb(251, 222, 168)");
this._fillStyles.scripting.addColorStop(1, "rgb(234, 182, 77)");
this._fillStyles.rendering = this._context.createLinearGradient(0, 0, this._maxInnerBarWidth, 0);
this._fillStyles.rendering.addColorStop(0, "rgb(213, 185, 236)");
this._fillStyles.rendering.addColorStop(1, "rgb(137, 62, 200)");

this._borderStyles = {};
this._borderStyles.loading = "rgb(106, 152, 213)";
this._borderStyles.scripting = "rgb(223, 175, 77)";
this._borderStyles.rendering = "rgb(130, 59, 190)";
this._borderStyles._frameLength = "rgb(90, 90, 90)";
}

WebInspector.TimelineVerticalOverview.prototype = {
reset: function()
{
this._recordsPerBar = 1;
this._barTimes = [];
this._frames = [];
},

update: function()
{
const minBarWidth = 4;
this._framesPerBar = Math.max(1, this._frames.length * minBarWidth / this.element.clientWidth);
this._barTimes = [];
var visibleFrames = this._aggregateFrames(this._framesPerBar);

const paddingTop = 4;
var scale = (this.element.clientHeight - paddingTop) / this._normalBarLength;

this._renderBars(visibleFrames, scale);
},


addFrame: function(frame)
{
this._frames.push(frame);
},

framePosition: function(frame)
{
var frameNumber = this._frames.indexOf(frame);
if (frameNumber < 0)
return;
var barNumber = Math.floor(frameNumber / this._framesPerBar);
var firstBar = this._framesPerBar > 1 ? barNumber : Math.max(barNumber - 1, 0);
var lastBar = this._framesPerBar > 1 ? barNumber : Math.min(barNumber + 1, this._barTimes.length - 1);
return {
start: Math.ceil(this._barNumberToScreenPosition(firstBar) - this._actualPadding / 2),
end: Math.floor(this._barNumberToScreenPosition(lastBar + 1) - this._actualPadding / 2)
}
},


_aggregateFrames: function(framesPerBar)
{
var visibleFrames = [];
var durations = [];
var longestFrameTime = 0;

for (var barNumber = 0, currentFrame = 0; currentFrame < this._frames.length; ++barNumber) {
var barStartTime = this._frames[currentFrame].startTime;
var longestFrame = null;

for (var lastFrame = Math.min(Math.floor((barNumber + 1) * framesPerBar), this._frames.length);
currentFrame < lastFrame; ++currentFrame) {
if (!longestFrame || longestFrame.duration < this._frames[currentFrame].duration)
longestFrame = this._frames[currentFrame];
}
var barEndTime = this._frames[currentFrame - 1].endTime;
if (longestFrame) {
longestFrameTime = Math.max(longestFrameTime, longestFrame.duration);
visibleFrames.push(longestFrame);
this._barTimes.push({ startTime: barStartTime, endTime: barEndTime });
durations.push(longestFrame.duration);
}
}

this._normalBarLength = Math.min(longestFrameTime, 3 * durations.qselect(Math.floor(durations.length / 2)));
return visibleFrames;
},

_renderBars: function(frames, scale)
{

this.element.width = this.element.clientWidth;
this.element.height = this.element.clientHeight;

const maxPadding = 5;
this._actualOuterBarWidth = Math.min((this.element.width - 2 * this._outerPadding) / frames.length, this._maxInnerBarWidth + maxPadding);
this._actualPadding = Math.min(Math.floor(this._actualOuterBarWidth / 3), maxPadding);

for (var i = 0; i < frames.length; ++i) {
var width = this._actualOuterBarWidth - this._actualPadding;
this._renderBar(this._barNumberToScreenPosition(i), width, frames[i], scale);
}
},

_barNumberToScreenPosition: function(n)
{
return this._outerPadding + this._actualOuterBarWidth * n;
},

_renderBar: function(left, width, frame, scale)
{
var categories = Object.keys(frame.timeByCategory);
if (!categories.length)
return;
var x = Math.floor(left) + 0.5;
width = Math.floor(width);

for (var i = 0, bottomOffset = this.element.height; i < categories.length; ++i) {
var category = categories[i];
var duration = frame.timeByCategory[category];

if (!duration)
continue;
var height = duration * scale;
var y = Math.floor(bottomOffset - height) + 0.5;

this._context.save();
this._context.translate(x, 0);
this._context.scale(width / this._maxInnerBarWidth, 1);
this._context.fillStyle = this._fillStyles[category];
this._context.fillRect(0, y, this._maxInnerBarWidth, Math.floor(height));
this._context.restore();

this._context.strokeStyle = this._borderStyles[category];
this._context.strokeRect(x, y, width, Math.floor(height));
bottomOffset -= height - 1;
}

var nonCPUTime = frame.duration - frame.cpuTime;
var y0 = Math.floor(bottomOffset - nonCPUTime * scale) + 0.5;
var y1 = Math.floor(bottomOffset) + 0.5;

this._context.strokeStyle = this._borderStyles._frameLength;
this._context.beginPath();
this._context.moveTo(x, y1);
this._context.lineTo(x, y0);
this._context.lineTo(x + width, y0);
this._context.lineTo(x + width, y1);
this._context.stroke();
},

getWindowTimes: function(windowLeft, windowRight)
{
var windowSpan = this.element.clientWidth;
var leftOffset = windowLeft * windowSpan - this._outerPadding + this._actualPadding;
var rightOffset = windowRight * windowSpan - this._outerPadding;
var bars = this.element.children;
var firstBar = Math.floor(Math.max(leftOffset, 0) / this._actualOuterBarWidth);
var lastBar = Math.min(Math.floor(rightOffset / this._actualOuterBarWidth), this._barTimes.length - 1);
const snapToRightTolerancePixels = 3;
return {
startTime: firstBar >= this._barTimes.length ? Infinity : this._barTimes[firstBar].startTime,
endTime: rightOffset + snapToRightTolerancePixels > windowSpan ? Infinity : this._barTimes[lastBar].endTime
}
}
}

WebInspector.TimelineVerticalOverview.prototype.__proto__ = WebInspector.View.prototype;


WebInspector.TimelineOverviewModeSelector = function(selectCallback)
{
this.element = document.createElement("div");
this.element.className = "timeline-overview-mode-selector";
this._selectCallback = selectCallback;

this._buttons = [];
this.element.addEventListener("click", this._onClick.bind(this), false);
}

WebInspector.TimelineOverviewModeSelector.prototype = {
addButton: function(tooltip, className, value)
{
var button = this._createButton(tooltip, className, value);
this.element.appendChild(button);
this._buttons.push(button);
if (this._buttons.length === 1)
this._select(button, true);
},

get value()
{
return this._value;
},

_createButton: function(tooltip, className, value)
{
var button = document.createElement("button");
button.createChild("div", "glyph");
button.createChild("div", "glyph shadow");
button.className = className;
button.title = tooltip;
button.value = value;
return button;
},

_select: function(button, selected)
{
if (selected) {
button.addStyleClass("toggled");
this._value = button.value;
} else
button.removeStyleClass("toggled");
},

_onClick: function(event)
{
var button = event.target.enclosingNodeOrSelfWithNodeName("button");
if (!button)
return;
for (var i = 0; i < this._buttons.length; ++i)
this._select(this._buttons[i], this._buttons[i] === button);
this._selectCallback(button.value);
}
}






WebInspector.TimelineFrameController = function(model, overviewPane, presentationModel)
{
this._lastFrame = null;
this._model = model;
this._overviewPane = overviewPane;
this._presentationModel = presentationModel;
this._model.addEventListener(WebInspector.TimelineModel.Events.RecordAdded, this._onRecordAdded, this);
this._model.addEventListener(WebInspector.TimelineModel.Events.RecordsCleared, this._onRecordsCleared, this);

var records = model.records;
for (var i = 0; i < records.length; ++i)
this._addRecord(records[i]);
}

WebInspector.TimelineFrameController.prototype = {
_onRecordAdded: function(event)
{
this._addRecord(event.data);
},

_onRecordsCleared: function()
{
this._lastFrame = null;
},

_addRecord: function(record)
{
if (record.type === WebInspector.TimelineModel.RecordType.BeginFrame)
this._flushFrame(record);
else if (this._lastFrame) {
WebInspector.TimelineModel.aggregateTimeForRecord(this._lastFrame.timeByCategory, record);
this._lastFrame.cpuTime += WebInspector.TimelineModel.durationInSeconds(record);
} else {


this._overviewPane.addFrame(this._createSyntheticFrame(record));
}
},

_flushFrame: function(record)
{
var frameBeginTime = WebInspector.TimelineModel.startTimeInSeconds(record);
if (this._lastFrame) {
this._lastFrame.endTime = frameBeginTime;
this._lastFrame.duration = this._lastFrame.endTime - this._lastFrame.startTime;
this._overviewPane.addFrame(this._lastFrame);
this._presentationModel.addFrame(this._lastFrame);
}
this._lastFrame = new WebInspector.TimelineFrame();
this._lastFrame.startTime = frameBeginTime;
this._lastFrame.startTimeOffset = this._model.recordOffsetInSeconds(record);
},

_createSyntheticFrame: function(record)
{
var frame = new WebInspector.TimelineFrame();
frame.startTime = WebInspector.TimelineModel.startTimeInSeconds(record);
frame.startTimeOffset = this._model.recordOffsetInSeconds(record);
frame.endTime = WebInspector.TimelineModel.endTimeInSeconds(record);
frame.duration = WebInspector.TimelineModel.durationInSeconds(record);
frame.cpuTime = frame.duration;
return frame;
},

dispose: function()
{
this._model.removeEventListener(WebInspector.TimelineModel.Events.RecordAdded, this._onRecordAdded, this);
this._model.removeEventListener(WebInspector.TimelineModel.Events.RecordsCleared, this._onRecordsCleared, this);
}
}


WebInspector.TimelineFrame = function()
{
this.timeByCategory = {};
this.cpuTime = 0;
}






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

_onBlur: function(event)
{

if (this._isShown && !this._element.isSelfOrAncestor(event.target))
WebInspector.setCurrentFocusElement(this._element);
}
}






WebInspector.Dialog = function(relativeToElement, delegate)
{
this._delegate = delegate;
this._relativeToElement = relativeToElement;


this._glassPaneElement = document.body.createChild("div");
this._glassPaneElement.className = "dialog-glass-pane";
this._glassPaneElement.tabIndex = 0;
this._glassPaneElement.addEventListener("focus", this._onGlassPaneFocus.bind(this), false);

this._element = this._glassPaneElement.createChild("div");
this._element.tabIndex = 0;
this._element.addEventListener("focus", this._onFocus.bind(this), false);
this._element.addEventListener("keydown", this._onKeyDown.bind(this), false);
this._closeKeys = [
WebInspector.KeyboardShortcut.Keys.Enter.code,
WebInspector.KeyboardShortcut.Keys.Esc.code,
];

delegate.show(this._element);

this._position();
this._windowResizeHandler = this._position.bind(this);
window.addEventListener("resize", this._windowResizeHandler, true);

this._previousFocusElement = WebInspector.currentFocusElement();
this._delegate.focus();
}


WebInspector.Dialog.currentInstance = function()
{
return WebInspector.Dialog._instance;
}


WebInspector.Dialog.show = function(relativeToElement, delegate)
{
if (WebInspector.Dialog._instance)
return;
WebInspector.Dialog._instance = new WebInspector.Dialog(relativeToElement, delegate);
}

WebInspector.Dialog.hide = function()
{
if (!WebInspector.Dialog._instance)
return;
WebInspector.Dialog._instance._hide();
}

WebInspector.Dialog.prototype = {
_hide: function()
{
if (this._isHiding)
return;
this._isHiding = true;

this._delegate.willHide();

if (this._element.isSelfOrAncestor(document.activeElement))
WebInspector.setCurrentFocusElement(this._previousFocusElement);
delete WebInspector.Dialog._instance;
document.body.removeChild(this._glassPaneElement);
window.removeEventListener("resize", this._windowResizeHandler, true);
},

_onGlassPaneFocus: function(event)
{
this._hide();
},

_onFocus: function(event)
{
this._delegate.focus();
},

_position: function()
{
this._delegate.position(this._element, this._relativeToElement);
},

_onKeyDown: function(event)
{
if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Tab.code) {
event.preventDefault();
return;
}

if (event.keyCode === WebInspector.KeyboardShortcut.Keys.Enter.code)
this._delegate.onEnter();

if (this._closeKeys.indexOf(event.keyCode) >= 0) {
this._hide();
event.consume(true);
}
}
};


WebInspector.DialogDelegate = function()
{
}

WebInspector.DialogDelegate.prototype = {

show: function(element)
{
element.appendChild(this.element);
this.element.addStyleClass("dialog-contents");
element.addStyleClass("dialog");    
},


position: function(element, relativeToElement)
{
var offset = relativeToElement.offsetRelativeToWindow(window);

var positionX = offset.x + (relativeToElement.offsetWidth - element.offsetWidth) / 2;
positionX = Number.constrain(positionX, 0, window.innerWidth - element.offsetWidth);

var positionY = offset.y + (relativeToElement.offsetHeight - element.offsetHeight) / 2;
positionY = Number.constrain(positionY, 0, window.innerHeight - element.offsetHeight);

element.style.left = positionX + "px";
element.style.top = positionY + "px";
},

focus: function() { },

onEnter: function() { },

willHide: function() { }
};

WebInspector.DialogDelegate.prototype.__proto__ = WebInspector.Object.prototype;






WebInspector.GoToLineDialog = function(view)
{
WebInspector.DialogDelegate.call(this);

this.element = document.createElement("div");
this.element.className = "go-to-line-dialog";

this.element.createChild("label").textContent = WebInspector.UIString("Go to line: ");

this._input = this.element.createChild("input");
this._input.setAttribute("type", "text");
this._input.setAttribute("size", 6);

this._goButton = this.element.createChild("button");
this._goButton.textContent = WebInspector.UIString("Go");
this._goButton.addEventListener("click", this._onGoClick.bind(this), false);

this._view = view;
}


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;
WebInspector.Dialog.show(sourceView.element, 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 = {
focus: function()
{
WebInspector.setCurrentFocusElement(this._input);
this._input.select();
},

_onGoClick: function()
{
this._applyLineNumber();
WebInspector.Dialog.hide();
},

_applyLineNumber: function()
{
var value = this._input.value;
var lineNumber = parseInt(value, 10) - 1;
if (!isNaN(lineNumber) && lineNumber >= 0)
this._view.highlightLine(lineNumber);
},

onEnter: function()
{
this._applyLineNumber();
}
}

WebInspector.GoToLineDialog.prototype.__proto__ = WebInspector.DialogDelegate.prototype;






WebInspector.FilteredItemSelectionDialog = function(delegate)
{
WebInspector.DialogDelegate.call(this);

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

this.element = document.createElement("div");
this.element.className = "js-outline-dialog";
this.element.addEventListener("keydown", this._onKeyDown.bind(this), false);
this.element.addEventListener("mousemove", this._onMouseMove.bind(this), false);
this.element.addEventListener("click", this._onClick.bind(this), false);
var styleElement = this.element.createChild("style");
styleElement.type = "text/css";
styleElement.textContent = xhr.responseText;

this._previousInputLength = 0;
this._itemElements = [];
this._elementIndexes = new Map();
this._elementHighlightChanges = new Map();

this._promptElement = this.element.createChild("input", "monospace");
this._promptElement.type = "text";
this._promptElement.setAttribute("spellcheck", "false");

this._progressElement = this.element.createChild("div", "progress");

this._itemElementsContainer = document.createElement("div");
this._itemElementsContainer.className = "container monospace";
this._itemElementsContainer.addEventListener("scroll", this._onScroll.bind(this), false);
this.element.appendChild(this._itemElementsContainer);

this._delegate = delegate;

this._delegate.requestItems(this._itemsLoaded.bind(this));
}

WebInspector.FilteredItemSelectionDialog.prototype = {

position: function(element, relativeToElement)
{
const minWidth = 500;
const minHeight = 204;
var width = Math.max(relativeToElement.offsetWidth * 2 / 3, minWidth);
var height = Math.max(relativeToElement.offsetHeight * 2 / 3, minHeight);

this.element.style.width = width + "px";
this.element.style.height = height + "px";

const shadowPadding = 20; 
element.positionAt(
relativeToElement.totalOffsetLeft() + Math.max((relativeToElement.offsetWidth - width - 2 * shadowPadding) / 2, shadowPadding),
relativeToElement.totalOffsetTop() + Math.max((relativeToElement.offsetHeight - height - 2 * shadowPadding) / 2, shadowPadding));
},

focus: function()
{
WebInspector.setCurrentFocusElement(this._promptElement);
},

willHide: function()
{
if (this._isHiding)
return;
this._isHiding = true;
if (this._filterTimer)
clearTimeout(this._filterTimer);
},

onEnter: function()
{
if (!this._selectedElement)
return;
this._delegate.selectItem(this._elementIndexes.get(this._selectedElement));
},


_itemsLoaded: function(index, chunkLength, chunkIndex, chunkCount)
{
var fragment = document.createDocumentFragment();
var candidateItem = this._selectedElement;
for (var i = index; i < index + chunkLength; ++i) {
var itemElement = this._createItemElement(i, this._delegate.itemTitleAt(i));
if (this._checkItemAt(i, this._promptElement.value)) {
if (!candidateItem)
candidateItem = itemElement;
} else
this._hideItemElement(itemElement);
fragment.appendChild(itemElement);
}
this._itemElementsContainer.appendChild(fragment);
this._updateSelection(candidateItem);

if (chunkIndex === chunkCount)
this._progressElement.style.backgroundImage = "";
else {
const color = "rgb(66, 129, 235)";
const percent = ((chunkIndex / chunkCount) * 100) + "%";
this._progressElement.style.backgroundImage = "-webkit-linear-gradient(left, " + color + ", " + color + " " + percent + ",  transparent " + percent + ")";
}
},


_createItemElement: function(index, title)
{
if (this._itemElements[index])
return this._itemElements[index];

var itemElement = document.createElement("div");
itemElement.className = "item";
itemElement.textContent = title;
this._elementIndexes.put(itemElement, index);
this._itemElements.push(itemElement);

return itemElement;
},


_hideItemElement: function(itemElement)
{
itemElement.style.display = "none";
},


_itemElementVisible: function(itemElement)
{
return itemElement.style.display !== "none";
},


_showItemElement: function(itemElement)
{
itemElement.style.display = "";
},


_checkItemAt: function(index, query)
{
if (!query)
return true;
var regExp = this._createSearchRegExp(query);
var key = this._delegate.itemKeyAt(index);
return regExp.test(key);
},


_createSearchRegExp: function(query, isGlobal)
{
var trimmedQuery = query.trim();
var regExpString = trimmedQuery.escapeForRegExp().replace(/\\\*/g, ".*").replace(/(?!^)([A-Z])/g, "[^A-Z]*$1");
var isSuffix = (query.charAt(query.length - 1) === " ");
if (isSuffix)
regExpString += "$";
return new RegExp(regExpString, (trimmedQuery === trimmedQuery.toLowerCase() ? "i" : "") + (isGlobal ? "g" : ""));
},

_filterItems: function()
{
delete this._filterTimer;

var query = this._promptElement.value;
var charsAdded = this._previousInputLength < query.length;
this._previousInputLength = query.length;
query = query.trim();

var firstElement;
for (var i = 0; i < this._itemElements.length; ++i) {
var itemElement = this._itemElements[i];

if (this._itemElementVisible(itemElement)) { 
if (!this._checkItemAt(i, query))
this._hideItemElement(itemElement);
} else if (!charsAdded && this._checkItemAt(i, query))
this._showItemElement(itemElement);

if (!firstElement && this._itemElementVisible(itemElement))
firstElement = itemElement;
}

this._updateSelection(firstElement);
if (query) {
this._highlightItems(query);
this._query = query;
} else {
this._clearHighlight();
delete this._query;
}
},

_onKeyDown: function(event)
{
function nextItem(itemElement, isPageScroll, forward)
{
var scrollItemsLeft = isPageScroll && this._rowsPerViewport ? this._rowsPerViewport : 1;
var candidate = itemElement;
var lastVisibleCandidate = candidate;
do {
candidate = forward ? candidate.nextSibling : candidate.previousSibling;
if (!candidate) {
if (isPageScroll)
return lastVisibleCandidate;
else
candidate = forward ? this._itemElementsContainer.firstChild : this._itemElementsContainer.lastChild;
}
if (!this._itemElementVisible(candidate))
continue;
lastVisibleCandidate = candidate;
--scrollItemsLeft;
} while (scrollItemsLeft && candidate !== this._selectedElement);

return candidate;
}

var isPageScroll = false;

if (this._selectedElement) {
var candidate;
switch (event.keyCode) {
case WebInspector.KeyboardShortcut.Keys.Down.code:
candidate = nextItem.call(this, this._selectedElement, false, true);
break;
case WebInspector.KeyboardShortcut.Keys.Up.code:
candidate = nextItem.call(this, this._selectedElement, false, false);
break;
case WebInspector.KeyboardShortcut.Keys.PageDown.code:
candidate = nextItem.call(this, this._selectedElement, true, true);
break;
case WebInspector.KeyboardShortcut.Keys.PageUp.code:
candidate = nextItem.call(this, this._selectedElement, true, false);
break;
}

if (candidate) {
this._updateSelection(candidate);
event.preventDefault();
return;
}
}

if (event.keyIdentifier !== "Shift" && event.keyIdentifier !== "Ctrl" && event.keyIdentifier !== "Meta" && event.keyIdentifier !== "Left" && event.keyIdentifier !== "Right")
this._scheduleFilter();
},

_scheduleFilter: function()
{
if (this._filterTimer)
return;
this._filterTimer = setTimeout(this._filterItems.bind(this), 0);
},


_updateSelection: function(newSelectedElement)
{
if (this._selectedElement === newSelectedElement)
return;
if (this._selectedElement)
this._selectedElement.removeStyleClass("selected");

this._selectedElement = newSelectedElement;
if (newSelectedElement) {
newSelectedElement.addStyleClass("selected");
newSelectedElement.scrollIntoViewIfNeeded(false);
if (!this._itemHeight) {
this._itemHeight = newSelectedElement.offsetHeight;
this._rowsPerViewport = Math.floor(this._itemElementsContainer.offsetHeight / this._itemHeight);
}
}
},

_onClick: function(event)
{
var itemElement = event.target.enclosingNodeOrSelfWithClass("item");
if (!itemElement)
return;
this._updateSelection(itemElement);
this._delegate.selectItem(this._elementIndexes.get(this._selectedElement));
WebInspector.Dialog.hide();
},

_onMouseMove: function(event)
{
var itemElement = event.target.enclosingNodeOrSelfWithClass("item");
if (!itemElement)
return;
this._updateSelection(itemElement);
},

_onScroll: function()
{
if (this._query)
this._highlightItems(this._query);
else
this._clearHighlight();
},


_highlightItems: function(query)
{
var regex = this._createSearchRegExp(query, true);
for (var i = 0; i < this._delegate.itemsCount(); ++i) {
var itemElement = this._itemElements[i];
if (this._itemElementVisible(itemElement) && this._itemElementInViewport(itemElement))
this._highlightItem(itemElement, regex);
}
},

_clearHighlight: function()
{
for (var i = 0; i < this._delegate.itemsCount(); ++i)
this._clearElementHighlight(this._itemElements[i]);
},


_clearElementHighlight: function(itemElement)
{
var changes = this._elementHighlightChanges.get(itemElement)
if (changes) {
WebInspector.revertDomChanges(changes);
this._elementHighlightChanges.remove(itemElement);
}
},


_highlightItem: function(itemElement, regex)
{
this._clearElementHighlight(itemElement);

var key = this._delegate.itemKeyAt(this._elementIndexes.get(itemElement));
var ranges = [];

var match;
while ((match = regex.exec(key)) !== null) {
ranges.push({ offset: match.index, length: regex.lastIndex - match.index });
}

var changes = [];
WebInspector.highlightRangesWithStyleClass(itemElement, ranges, "highlight", changes);

if (changes.length)
this._elementHighlightChanges.put(itemElement, changes);
},


_itemElementInViewport: function(itemElement)
{
if (itemElement.offsetTop + this._itemHeight < this._itemElementsContainer.scrollTop)
return false;
if (itemElement.offsetTop > this._itemElementsContainer.scrollTop + this._itemHeight * (this._rowsPerViewport + 1))
return false;
return true;
}
}

WebInspector.FilteredItemSelectionDialog.prototype.__proto__ = WebInspector.DialogDelegate.prototype;


WebInspector.SelectionDialogContentProvider = function()
{
}

WebInspector.SelectionDialogContentProvider.prototype = {

itemTitleAt: function(itemIndex) { },


itemKeyAt: function(itemIndex) { },


itemsCount: function() { },


requestItems: function(callback) { },


selectItem: function(itemIndex) { }
};


WebInspector.JavaScriptOutlineDialog = function(panel, view)
{
WebInspector.SelectionDialogContentProvider.call(this);

this._functionItems = [];

this._panel = panel;
this._view = view;
}


WebInspector.JavaScriptOutlineDialog.didAddChunk = function(data)
{
var instance = WebInspector.JavaScriptOutlineDialog._instance;
if (!instance)
return;

if (data.id !== instance._view.uiSourceCode.id)
return;

instance._appendItemElements(data.chunk, data.index, data.total);
},

WebInspector.JavaScriptOutlineDialog.install = function(panel, viewGetter)
{
function showJavaScriptOutlineDialog()
{
var view = viewGetter();
if (view)
WebInspector.JavaScriptOutlineDialog._show(panel, view);
}

var javaScriptOutlineShortcut = WebInspector.JavaScriptOutlineDialog.createShortcut();
panel.registerShortcut(javaScriptOutlineShortcut.key, showJavaScriptOutlineDialog);
}

WebInspector.JavaScriptOutlineDialog._show = function(panel, sourceView)
{
if (WebInspector.Dialog.currentInstance())
return;
if (!sourceView || !sourceView.canHighlightLine())
return;
WebInspector.JavaScriptOutlineDialog._instance = new WebInspector.JavaScriptOutlineDialog(panel, sourceView);

var filteredItemSelectionDialog = new WebInspector.FilteredItemSelectionDialog(WebInspector.JavaScriptOutlineDialog._instance);
WebInspector.Dialog.show(sourceView.element, filteredItemSelectionDialog);
}

WebInspector.JavaScriptOutlineDialog.createShortcut = function()
{
return WebInspector.KeyboardShortcut.makeDescriptor("o", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta | WebInspector.KeyboardShortcut.Modifiers.Shift);
}

WebInspector.JavaScriptOutlineDialog.prototype = {

itemTitleAt: function(itemIndex)
{
var functionItem = this._functionItems[itemIndex];
return functionItem.name + (functionItem.arguments ? functionItem.arguments : "");
},


itemKeyAt: function(itemIndex)
{
return this._functionItems[itemIndex].name;
},


itemsCount: function()
{
return this._functionItems.length;
},


requestItems: function(callback)
{
this._itemsAddedCallback = callback;
this._panel.requestVisibleScriptOutline();
},


selectItem: function(itemIndex)
{
var lineNumber = this._functionItems[itemIndex].line;
if (!isNaN(lineNumber) && lineNumber >= 0)
this._view.highlightLine(lineNumber);
this._view.focus();
delete WebInspector.JavaScriptOutlineDialog._instance;
},


_appendItemElements: function(chunk, chunkIndex, chunkCount)
{
var index = this._functionItems.length;
for (var i = 0; i < chunk.length; ++i) {
this._functionItems.push(chunk[i]);
}
this._itemsAddedCallback(index, chunk.length, chunkIndex, chunkCount);
}
}

WebInspector.JavaScriptOutlineDialog.prototype.__proto__ = WebInspector.SelectionDialogContentProvider.prototype;


WebInspector.OpenResourceDialog = function(resources)
{

WebInspector.SelectionDialogContentProvider.call(this);

this.resources = resources;

function filterOutEmptyURLs(resource)
{
return !!resource.parsedURL.lastPathComponent;
}
this.resources = this.resources.filter(filterOutEmptyURLs);

function compareFunction(resource1, resource2)
{
return resource1.parsedURL.lastPathComponent.localeCompare(resource2.parsedURL.lastPathComponent);
}
this.resources.sort(compareFunction);
}

WebInspector.OpenResourceDialog.createShortcut = function()
{
return WebInspector.KeyboardShortcut.makeDescriptor("o", WebInspector.KeyboardShortcut.Modifiers.CtrlOrMeta);
}

WebInspector.OpenResourceDialog.prototype = {

itemTitleAt: function(itemIndex)
{
return this.resources[itemIndex].parsedURL.lastPathComponent;
},


itemKeyAt: function(itemIndex)
{
return this.resources[itemIndex].parsedURL.lastPathComponent;
},


itemsCount: function()
{
return this.resources.length;
},


requestItems: function(callback)
{
callback(0, this.resources.length, 1, 1);
},


selectItem: function(itemIndex)
{

}
}

WebInspector.OpenResourceDialog.prototype.__proto__ = WebInspector.SelectionDialogContentProvider.prototype;


WebInspector.OpenScriptDialog = function(panel, presentationModel)
{
WebInspector.OpenResourceDialog.call(this, presentationModel.uiSourceCodes());
this._panel = panel;
}


WebInspector.OpenScriptDialog.install = function(panel, presentationModel, relativeToElement)
{
function showOpenResourceDialog()
{
WebInspector.OpenScriptDialog._show(panel, presentationModel, relativeToElement);
}

var openResourceShortcut = WebInspector.OpenResourceDialog.createShortcut();
panel.registerShortcut(openResourceShortcut.key, showOpenResourceDialog);
}


WebInspector.OpenScriptDialog._show = function(panel, presentationModel, relativeToElement)
{
if (WebInspector.Dialog.currentInstance())
return;

var filteredItemSelectionDialog = new WebInspector.FilteredItemSelectionDialog(new WebInspector.OpenScriptDialog(panel, presentationModel));
WebInspector.Dialog.show(relativeToElement, filteredItemSelectionDialog);
}

WebInspector.OpenScriptDialog.prototype = {

selectItem: function(itemIndex)
{
this._panel.showUISourceCode(this.resources[itemIndex]);
}
}

WebInspector.OpenScriptDialog.prototype.__proto__ = WebInspector.OpenResourceDialog.prototype;






WebInspector.SidebarOverlay = function(view, widthSettingName, minimalWidth)
{
WebInspector.Object.call(this);

this.element = document.createElement("div");
this.element.className = "sidebar-overlay";

this._view = view;
this._widthSettingName = widthSettingName;
this._minimalWidth = minimalWidth;
this._savedWidth = minimalWidth || 300;

if (this._widthSettingName)
WebInspector.settings[this._widthSettingName] = WebInspector.settings.createSetting(this._widthSettingName, undefined);

this._resizerElement = document.createElement("div");
this._resizerElement.className = "sidebar-overlay-resizer";
this._installResizer(this._resizerElement);
}

WebInspector.SidebarOverlay.EventTypes = {
WasShown: "WasShown",
WillHide: "WillHide"
}

WebInspector.SidebarOverlay.prototype = {

show: function(relativeToElement)
{
relativeToElement.appendChild(this.element);
relativeToElement.addStyleClass("sidebar-overlay-shown");
this._view.show(this.element);
this.element.appendChild(this._resizerElement);
if (this._resizerWidgetElement)
this.element.appendChild(this._resizerWidgetElement);
this.position(relativeToElement);
this._boundContainingElementFocused = this._containingElementFocused.bind(this);
relativeToElement.addEventListener("mousedown", this._boundContainingElementFocused, false);

this.dispatchEventToListeners(WebInspector.SidebarOverlay.EventTypes.WasShown, null);
},

_containingElementFocused: function(event)
{
if (!event.target.isSelfOrDescendant(this.element))
this.hide();
},


position: function(relativeToElement)
{
this._totalWidth = relativeToElement.offsetWidth;
this._setWidth(this._preferredWidth());
},

focus: function()
{
WebInspector.setCurrentFocusElement(this._view.element);
},

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

this.dispatchEventToListeners(WebInspector.SidebarOverlay.EventTypes.WillHide, null);

this._view.detach();
element.removeChild(this.element);
element.removeStyleClass("sidebar-overlay-shown");
this.element.removeChild(this._resizerElement);
if (this._resizerWidgetElement)
this.element.removeChild(this._resizerWidgetElement);
element.removeEventListener("mousedown", this._boundContainingElementFocused, false);
},


_setWidth: function(newWidth)
{
var width = Number.constrain(newWidth, this._minimalWidth, this._totalWidth);

if (this._width === width)
return;

this.element.style.width = width + "px";
this._resizerElement.style.left = (width - 3) + "px";
this._width = width;
this._view.doResize();
this._saveWidth();
},


_preferredWidth: function()
{
if (!this._widthSettingName)
return this._savedWidth;

return WebInspector.settings[this._widthSettingName].get() || this._savedWidth;
},

_saveWidth: function()
{
this._savedWidth = this._width;
if (!this._widthSettingName)
return;

WebInspector.settings[this._widthSettingName].set(this._width);
},


_startResizerDragging: function(event)
{
var width = this._width;
this._dragOffset = width - event.pageX;
WebInspector.elementDragStart(this._resizerElement, this._resizerDragging.bind(this), this._endResizerDragging.bind(this), event, "ew-resize");
},


_resizerDragging: function(event)
{
var width = event.pageX + this._dragOffset;
this._setWidth(width);
event.preventDefault();
},


_endResizerDragging: function(event)
{
delete this._dragOffset;
WebInspector.elementDragEnd(event);
},


_installResizer: function(resizerElement)
{
resizerElement.addEventListener("mousedown", this._startResizerDragging.bind(this), false);
},


set resizerWidgetElement(resizerWidgetElement)
{
this._resizerWidgetElement = resizerWidgetElement;
this._installResizer(resizerWidgetElement);
}
}

WebInspector.SidebarOverlay.prototype.__proto__ = WebInspector.Object.prototype;






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("General"));
if (Preferences.showDockToRight)
p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Dock to right"), WebInspector.settings.dockToRight));
if (Preferences.exposeDisableCache)
p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Disable cache"), WebInspector.settings.cacheDisabled));
var disableJSElement = this._createCheckboxSetting(WebInspector.UIString("Disable JavaScript"), WebInspector.settings.javaScriptDisabled);
p.appendChild(disableJSElement);
WebInspector.settings.javaScriptDisabled.addChangeListener(this._javaScriptDisabledChanged, this);
this._disableJSCheckbox = disableJSElement.getElementsByTagName("input")[0];
this._updateScriptDisabledCheckbox();

p = this._appendSection(WebInspector.UIString("Rendering"));
p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show paint rectangles"), WebInspector.settings.showPaintRects));
WebInspector.settings.showPaintRects.addChangeListener(this._showPaintRectsChanged, this);

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("User Agent"), true);
p.appendChild(this._createUserAgentControl());
if (Capabilities.canOverrideDeviceMetrics)
p.appendChild(this._createDeviceMetricsControl());
p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Emulate touch events"), WebInspector.settings.emulateTouchEvents));

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.appendChild(this._createCheckboxSetting(WebInspector.UIString("Enable source maps"), WebInspector.settings.sourceMapsEnabled));

p = this._appendSection(WebInspector.UIString("Profiler"), true);
p.appendChild(this._createCheckboxSetting(WebInspector.UIString("Show objects' hidden properties"), WebInspector.settings.showHeapSnapshotObjectsHiddenProperties));

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 experiments = WebInspector.experimentsSettings.experiments;
if (WebInspector.experimentsSettings.experimentsEnabled && experiments.length) {
var experimentsSection = this._appendSection(WebInspector.UIString("Experiments"), true);
experimentsSection.appendChild(this._createExperimentsWarningSubsection());
for (var i = 0; i < experiments.length; ++i)
experimentsSection.appendChild(this._createExperimentCheckbox(experiments[i]));
}

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


_createExperimentsWarningSubsection: function()
{
var subsection = document.createElement("div");
var warning = subsection.createChild("span", "settings-experiments-warning-subsection-warning");
warning.textContent = WebInspector.UIString("WARNING:");
subsection.appendChild(document.createTextNode(" "));
var message = subsection.createChild("span", "settings-experiments-warning-subsection-message");
message.textContent = WebInspector.UIString("These experiments could be dangerous and may require restart.");
return subsection;
},

_columnElement: function(right)
{
return right ? this._rightColumnElement : this._leftColumnElement;
},


_createCheckboxSetting: function(name, setting, omitParagraphElement)
{
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 label = document.createElement("label");
label.appendChild(input);
label.appendChild(document.createTextNode(name));
if (omitParagraphElement)
return label;

var p = document.createElement("p");
p.appendChild(label);
return p;
},

_createExperimentCheckbox: function(experiment)
{
var input = document.createElement("input");
input.type = "checkbox";
input.name = experiment.name;
input.checked = experiment.isEnabled();
function listener()
{
experiment.setEnabled(input.checked);
}
input.addEventListener("click", listener, false);

var p = document.createElement("p");
var label = document.createElement("label");
label.appendChild(input);
label.appendChild(document.createTextNode(WebInspector.UIString(experiment.title)));
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;
},

_createUserAgentControl: 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", "640x960x1"],
["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", "640x960x1"],
["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", "1024x768x1"],
["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", "1024x768x1"],

["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", "480x800x1.1"],
["Android 4.0.2 \u2014 Galaxy Nexus", "Mozilla/5.0 (Linux; U; Android 4.0.2; en-us; Galaxy Nexus Build/ICL53F) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30", "720x1280x1.1"],

["BlackBerry \u2014 PlayBook 1.0","Mozilla/5.0 (PlayBook; U; RIM Tablet OS 1.0.0; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.1.0.7 Safari/534.11+", "1024x600x1"],
["BlackBerry \u2014 PlayBook 2.0", "Mozilla/5.0 (PlayBook; U; RIM Tablet OS 2.0.0; en-US) AppleWebKit/535.8+ (KHTML, like Gecko) Version/7.2.0.0 Safari/535.8+", "1024x600x1"],
["BlackBerry \u2014 9900", "Mozilla/5.0 (BlackBerry; U; BlackBerry 9900; en-US) AppleWebKit/534.11+ (KHTML, like Gecko) Version/7.0.0.187 Mobile Safari/534.11+", "640x480x1"],

["MeeGo \u2014 Nokia N9", "Mozilla/5.0 (MeeGo; NokiaN9) AppleWebKit/534.13 (KHTML, like Gecko) NokiaBrowser/8.5.0 Mobile Safari/534.13", "480x854x1"],

[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];
var option = new Option(agent[0], agent[1]);
option._metrics = agent[2] ? agent[2] : "";
selectElement.add(option);
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, true), false);


function selectionChanged(isUserGesture)
{
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();
}

if (isUserGesture && Capabilities.canOverrideDeviceMetrics) {
var metrics = selectElement.options[selectElement.selectedIndex]._metrics;
this._setDeviceMetricsOverride(WebInspector.UserAgentSupport.DeviceMetrics.parseSetting(metrics), false, true);
}
}

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

_showPaintRectsChanged: function()
{
PageAgent.setShowPaintRects(WebInspector.settings.showPaintRects.get());
},

_updateScriptDisabledCheckbox: function()
{
function executionStatusCallback(error, status)
{
if (error || !status)
return;

switch (status) {
case "forbidden":
this._disableJSCheckbox.checked = true;
this._disableJSCheckbox.disabled = true;
break;
case "disabled":
this._disableJSCheckbox.checked = true;
break;
default:
this._disableJSCheckbox.checked = false;
break;
}
}

PageAgent.getScriptExecutionStatus(executionStatusCallback.bind(this));
},

_javaScriptDisabledChanged: function()
{

PageAgent.setScriptExecutionDisabled(WebInspector.settings.javaScriptDisabled.get(), this._updateScriptDisabledCheckbox.bind(this));
},

_createDeviceMetricsControl: function()
{
const metricsSetting = WebInspector.settings.deviceMetrics.get();
var metrics = WebInspector.UserAgentSupport.DeviceMetrics.parseSetting(metricsSetting);

const p = document.createElement("p");
const labelElement = p.createChild("label");
const checkboxElement = labelElement.createChild("input");
checkboxElement.id = "metrics-override-checkbox";
checkboxElement.type = "checkbox";
checkboxElement.checked = !metrics || (metrics.width && metrics.height && metrics.fontScaleFactor);
checkboxElement.addEventListener("click", this._onMetricsCheckboxClicked.bind(this), false);
this._metricsCheckboxElement = checkboxElement;
labelElement.appendChild(document.createTextNode(WebInspector.UIString("Override device metrics")));

const metricsSectionElement = this._createDeviceMetricsElement(metrics);
p.appendChild(metricsSectionElement);
this._metricsSectionElement = metricsSectionElement;

this._setDeviceMetricsOverride(metrics, false, true);

return p;
},

_onMetricsCheckboxClicked: function()
{
if (this._metricsCheckboxElement.checked) {
this._metricsSectionElement.removeStyleClass("hidden");
var metrics = WebInspector.UserAgentSupport.DeviceMetrics.parseUserInput(this._widthOverrideElement.value, this._heightOverrideElement.value, this._fontScaleFactorOverrideElement.value);
if (metrics && metrics.isValid() && metrics.width && metrics.height)
this._setDeviceMetricsOverride(metrics, false, false);
if (!this._widthOverrideElement.value)
this._widthOverrideElement.focus();
} else {
this._metricsSectionElement.addStyleClass("hidden");
if (WebInspector.settings.deviceMetrics.get())
WebInspector.settings.deviceMetrics.set("");
}
},

_applyDeviceMetricsUserInput: function()
{
this._setDeviceMetricsOverride(WebInspector.UserAgentSupport.DeviceMetrics.parseUserInput(this._widthOverrideElement.value.trim(), this._heightOverrideElement.value.trim(), this._fontScaleFactorOverrideElement.value.trim()), true, false);
},


_setDeviceMetricsOverride: function(metrics, userInputModified, updateCheckbox)
{
function setValid(condition, element)
{
if (condition)
element.removeStyleClass("error-input");
else
element.addStyleClass("error-input");
}

setValid(metrics && metrics.isWidthValid(), this._widthOverrideElement);
setValid(metrics && metrics.isHeightValid(), this._heightOverrideElement);
setValid(metrics && metrics.isFontScaleFactorValid(), this._fontScaleFactorOverrideElement);

if (!metrics)
return;

if (!userInputModified) {
this._widthOverrideElement.value = metrics.widthToInput();
this._heightOverrideElement.value = metrics.heightToInput();
this._fontScaleFactorOverrideElement.value = metrics.fontScaleFactorToInput();
}

if (metrics.isValid()) {
var value = metrics.toSetting();
if (value !== WebInspector.settings.deviceMetrics.get())
WebInspector.settings.deviceMetrics.set(value);
}

if (this._metricsCheckboxElement && updateCheckbox) {
this._metricsCheckboxElement.checked = !!metrics.toSetting();
this._onMetricsCheckboxClicked();
}
},


_createDeviceMetricsElement: function(metrics)
{
var fieldsetElement = document.createElement("fieldset");
fieldsetElement.id = "metrics-override-section";

function createInput(parentElement, id, defaultText)
{
var element = parentElement.createChild("input");
element.id = id;
element.maxLength = 6;
element.style.width = "48px";
element.value = defaultText;
element.addEventListener("blur", this._applyDeviceMetricsUserInput.bind(this), false);
return element;
}

function swapDimensionsClicked(event)
{
var widthValue = this._widthOverrideElement.value;
this._widthOverrideElement.value = this._heightOverrideElement.value;
this._heightOverrideElement.value = widthValue;
this._applyDeviceMetricsUserInput();
}

var tableElement = fieldsetElement.createChild("table");

var rowElement = tableElement.createChild("tr");
var cellElement = rowElement.createChild("td");
cellElement.appendChild(document.createTextNode(WebInspector.UIString("Screen resolution:")));
cellElement = rowElement.createChild("td");
this._widthOverrideElement = createInput.call(this, cellElement, "metrics-override-width", String(metrics.width || screen.width));
cellElement.appendChild(document.createTextNode(" \u00D7 ")); 
this._heightOverrideElement = createInput.call(this, cellElement, "metrics-override-height", String(metrics.height || screen.height));
cellElement.appendChild(document.createTextNode(" \u2014 ")); 
var swapDimensionsElement = cellElement.createChild("button");
swapDimensionsElement.appendChild(document.createTextNode(" \u21C4 ")); 
swapDimensionsElement.title = WebInspector.UIString("Swap dimensions");
swapDimensionsElement.addEventListener("click", swapDimensionsClicked.bind(this), false);

rowElement = tableElement.createChild("tr");
cellElement = rowElement.createChild("td");
cellElement.appendChild(document.createTextNode(WebInspector.UIString("Font scale factor:")));
cellElement = rowElement.createChild("td");
this._fontScaleFactorOverrideElement = createInput.call(this, cellElement, "metrics-override-font-scale", String(metrics.fontScaleFactor || 1));

rowElement = tableElement.createChild("tr");
cellElement = rowElement.createChild("td");
cellElement.colspan = 2;
cellElement.appendChild(this._createCheckboxSetting(WebInspector.UIString("Fit window"), WebInspector.settings.deviceFitWindow, true));

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);
WebInspector.HelpScreen.prototype.show.call(this, onHide);
},


_buildTable: function(parent)
{
if (this._tableReady)
return;
this._tableReady = true;

var totalHeight = 0;
var orderedSections = [];
for (var section in this._sections) {
totalHeight += this._sections[section]._height;
orderedSections.push(this._sections[section])
}
function compareSections(a, b)
{
return a.order - b.order;
}
orderedSections.sort(compareSections);


var minMax = totalHeight;
var minMaxIndex = -1;
var sum = 0;
for (var sectionIndex = 0; sectionIndex < orderedSections.length; ++sectionIndex) {
sum += orderedSections[sectionIndex]._height;
var max = Math.max(sum, totalHeight - sum);
if (minMax > max) {
minMax = max;
minMaxIndex = sectionIndex;
}
}

var table = document.createElement("table");
table.className = "help-table";
var row = table.createChild("tr");

var stopIndices = [0, minMaxIndex + 1, orderedSections.length];

for (var columnIndex = 1; columnIndex < stopIndices.length; ++columnIndex) {
var td = row.createChild("td");
td.style.width = "50%";
var column = td.createChild("table");
column.className = "help-column-table";
for (var i = stopIndices[columnIndex - 1]; i < stopIndices[columnIndex]; ++i)
orderedSections[i].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(this._createSpan("help-key-delimiter", ":"));
tr.createChild("td").textContent = this._lines[line].text;
}
},

_renderHeader: function(parent)
{
var trHead = parent.createChild("tr");
var thTitle;

trHead.createChild("th");

thTitle = trHead.createChild("th");
thTitle.className = "help-section-title";
thTitle.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(request)
{
this._request = request;
}

WebInspector.HAREntry.prototype = {

build: function()
{
var entry =  {
startedDateTime: new Date(this._request.startTime * 1000),
time: WebInspector.HAREntry._toMilliseconds(this._request.duration),
request: this._buildRequest(),
response: this._buildResponse(),
cache: { }, 
timings: this._buildTimings()
};
var page = WebInspector.networkLog.pageLoadForRequest(this._request);
if (page)
entry.pageref = "page_" + page.id;
return entry;
},


_buildRequest: function()
{
var res = {
method: this._request.requestMethod,
url: this._buildRequestURL(this._request.url),
httpVersion: this._request.requestHttpVersion,
headers: this._buildHeaders(this._request.requestHeaders),
queryString: this._buildParameters(this._request.queryParameters || []),
cookies: this._buildCookies(this._request.requestCookies || []),
headersSize: this._request.requestHeadersSize,
bodySize: this.requestBodySize
};
if (this._request.requestFormData)
res.postData = this._buildPostData();

return res;
},


_buildResponse: function()
{
return {
status: this._request.statusCode,
statusText: this._request.statusText,
httpVersion: this._request.responseHttpVersion,
headers: this._buildHeaders(this._request.responseHeaders),
cookies: this._buildCookies(this._request.responseCookies || []),
content: this._buildContent(),
redirectURL: this._request.responseHeaderValue("Location") || "",
headersSize: this._request.responseHeadersSize,
bodySize: this.responseBodySize
};
},


_buildContent: function()
{
var content = {
size: this._request.resourceSize,
mimeType: this._request.mimeType,

};
var compression = this.responseCompression;
if (typeof compression === "number")
content.compression = compression;
return content;
},


_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._request.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._request.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._request.requestHeaderValue("Content-Type"),
text: this._request.requestFormData
};
if (this._request.formParameters)
res.params = this._buildParameters(this._request.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._request.startTime * 1000)),
httpOnly: cookie.httpOnly,
secure: cookie.secure
};
},


_interval: function(start, end)
{
var timing = this._request.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._request.requestFormData ? 0 : this._request.requestFormData.length;
},


get responseBodySize()
{
if (this._request.cached || this._request.statusCode === 304)
return 0;
return this._request.transferSize - this._request.responseHeadersSize
},


get responseCompression()
{
if (this._request.cached || this._request.statusCode === 304)
return;
return this._request.resourceSize - (this._request.transferSize - this._request.responseHeadersSize);
}
}


WebInspector.HAREntry._toMilliseconds = function(time)
{
return time === -1 ? -1 : Math.round(time * 1000);
}


WebInspector.HARLog = function(requests)
{
this._requests = requests;
}

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._requests.map(this._convertResource.bind(this))
}
},


_buildPages: function()
{
var seenIdentifiers = {};
var pages = [];
for (var i = 0; i < this._requests.length; ++i) {
var page = WebInspector.networkLog.pageLoadForRequest(this._requests[i]);
if (!page || seenIdentifiers[page.id])
continue;
seenIdentifiers[page.id] = true;
pages.push(this._convertPage(page));
}
return pages;
},


_convertPage: function(page)
{
return {
startedDateTime: new Date(page.startTime * 1000),
id: "page_" + page.id,
title: page.url, 
pageTimings: {
onContentLoad: this._pageEventTime(page, page.contentLoadTime),
onLoad: this._pageEventTime(page, page.loadTime)
}
}
},


_convertResource: function(request)
{
return (new WebInspector.HAREntry(request)).build();
},


_pageEventTime: function(page, time)
{
var startTime = page.startTime;
if (time === -1 || startTime === -1)
return -1;
return WebInspector.HAREntry._toMilliseconds(time - startTime);
}
}













WebInspector.CookieParser = function()
{
}


WebInspector.CookieParser.KeyValue = function(key, value, position)
{
this.key = key;
this.value = value;
this.position = position;
}

WebInspector.CookieParser.prototype = {

get cookies()
{
return this._cookies;
},


parseCookie: function(cookieHeader)
{
if (!this._initialize(cookieHeader))
return null;

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 null;
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 = new WebInspector.CookieParser.KeyValue(keyValueMatch[1], keyValueMatch[2] && keyValueMatch[2].trim(), this._originalInputLength - this._input.length);
        this._input = this._input.slice(keyValueMatch[0].length);
        return result;
    },

    /**
* @return {boolean}
*/
_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 compact(compact)
{
if (compact)
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.isCompactMode() && 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.isCompactMode() ? "row-resize" : "default"));
},

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

delete this.element.lastScreenX;
delete this.element.lastScreenY;
},

_toolbarDrag: function(event)
{
if (WebInspector.isCompactMode()) {
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.consume();
this.hide();
}
}


WebInspector.toolbar = null;






WebInspector.SearchController = function()
{
this.element = document.getElementById("search");
this._matchesElement = document.getElementById("search-results-matches");
this._searchItemElement = document.getElementById("toolbar-search-item");
this._searchControlBoxElement = document.getElementById("toolbar-search-navigation-control");

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

this._populateSearchNavigationButtons();
}

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);
this.element.setAttribute("placeholder", 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();
}
},

_updateSearchNavigationButtonState: function(visible)
{
if (visible)
this._searchItemElement.addStyleClass("with-navigation-buttons");
else
this._searchItemElement.removeStyleClass("with-navigation-buttons");
},


_updateSearchMatchesCountAndCurrentMatchIndex: function(matches, currentMatchIndex)
{
if (matches == null) {
this._matchesElement.addStyleClass("hidden");

this._updateSearchNavigationButtonState(false); 
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);

this._updateSearchNavigationButtonState(true);
}
} else {
var matchesString = WebInspector.UIString("Not Found");

this._updateSearchNavigationButtonState(false);
}

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

event.consume(true);

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

_onNextButtonSearch: function(event)
{

this._performSearch(this.element.value, true, false, false);
},

_onPrevButtonSearch: function(event)
{

this._performSearch(this.element.value, true, true, 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);
},


_createSearchNavigationButton: function(direction) 
{
var searchNavigationControlElement = document.createElement("div");
var searchNavigationIconElement = document.createElement("div");

searchNavigationControlElement.className = "toolbar-search-navigation-label";

switch (direction) {
case "prev":
var searchTitle = WebInspector.UIString("Search Previous");
searchNavigationIconElement.className = "toolbar-search-navigation-icon-prev";
this._searchNavigationPrev = searchNavigationControlElement;
this._searchNavigationPrev.addEventListener("mousedown", this._onPrevButtonSearch.bind(this), false);
break;

case "next":
var searchTitle = WebInspector.UIString("Search Next");
searchNavigationIconElement.className = "toolbar-search-navigation-icon-next";
this._searchNavigationNext = searchNavigationControlElement;
this._searchNavigationNext.addEventListener("mousedown", this._onNextButtonSearch.bind(this), false); 
break;
}

searchNavigationControlElement.setAttribute("title" , searchTitle);
searchNavigationControlElement.appendChild(searchNavigationIconElement);  
this._searchControlBoxElement.appendChild(searchNavigationControlElement);
},

_populateSearchNavigationButtons: function() 
{

this._createSearchNavigationButton("prev");
this._createSearchNavigationButton("next");
}
}


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, doNotPauseOnExceptionsAndMuteConsole: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 (event.target.location.href === "about:blank")
return;
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 = new WebInspector.ParsedURL(this._frame.url).displayName;
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;
}
}






WebInspector.MemoryStatistics = function(timelinePanel, sidebarWidth)
{
this._timelinePanel = timelinePanel;
this._counters = [];

this._containerAnchor = timelinePanel.element.lastChild;
this._memorySplitView = new WebInspector.SplitView(WebInspector.SplitView.SidebarPosition.Left, undefined, sidebarWidth);
this._memorySplitView.sidebarElement.addStyleClass("sidebar");
this._memorySplitView.element.id = "memory-graphs-container";

this._memorySplitView.addEventListener(WebInspector.SplitView.EventTypes.Resized, this._sidebarResized.bind(this));

this._canvasContainer = this._memorySplitView.mainElement;
this._canvasContainer.id = "memory-graphs-canvas-container";
this._currentValuesBar = this._canvasContainer.createChild("div");
this._currentValuesBar.id = "counter-values-bar";
this._canvas = this._canvasContainer.createChild("canvas");
this._canvas.id = "memory-counters-graph";
this._lastMarkerXPosition = 0;

this._canvas.addEventListener("mouseover", this._onMouseOver.bind(this), true);
this._canvas.addEventListener("mousemove", this._onMouseMove.bind(this), true);
this._canvas.addEventListener("mouseout", this._onMouseOut.bind(this), true);
this._canvas.addEventListener("click", this._onClick.bind(this), true);

this._timelineGrid = new WebInspector.TimelineGrid();
this._canvasContainer.appendChild(this._timelineGrid.dividersElement);


this._memorySplitView.sidebarElement.createChild("div", "sidebar-tree sidebar-tree-section").textContent = WebInspector.UIString("COUNTERS");
function getDocumentCount(entry)
{
return entry.documentCount;
}
function getNodeCount(entry)
{
return entry.nodeCount;
}
function getListenerCount(entry)
{
return entry.listenerCount;
}
this._counterUI = [
new WebInspector.CounterUI(this, "Document Count", "Documents: %d", [100,0,0], getDocumentCount),
new WebInspector.CounterUI(this, "DOM Node Count", "Nodes: %d", [0,100,0], getNodeCount),
new WebInspector.CounterUI(this, "Event Listener Count", "Listeners: %d", [0,0,100], getListenerCount)
];

TimelineAgent.setIncludeMemoryDetails(true);
}


WebInspector.SwatchCheckbox = function(title, color)
{
this.element = document.createElement("div");
this._swatch = this.element.createChild("div", "swatch");
this.element.createChild("span", "title").textContent = title;
this._color = color;
this.checked = true;

this.element.addEventListener("click", this._toggleCheckbox.bind(this), true);
}

WebInspector.SwatchCheckbox.Events = {
Changed: "Changed"
}

WebInspector.SwatchCheckbox.prototype = {
get checked()
{
return this._checked;
},

set checked(v)
{
this._checked = v;
if (this._checked)
this._swatch.style.backgroundColor = this._color;
else
this._swatch.style.backgroundColor = "";
},

_toggleCheckbox: function(event)
{
this.checked = !this.checked;
this.dispatchEventToListeners(WebInspector.SwatchCheckbox.Events.Changed);
}
}

WebInspector.SwatchCheckbox.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.CounterUI = function(memoryCountersPane, title, currentValueLabel, rgb, valueGetter)
{
this._memoryCountersPane = memoryCountersPane;
this.valueGetter = valueGetter;
var container = memoryCountersPane._memorySplitView.sidebarElement.createChild("div", "memory-counter-sidebar-info");
var swatchColor = "rgb(" + rgb.join(",") + ")";
this._swatch = new WebInspector.SwatchCheckbox(WebInspector.UIString(title), swatchColor);
this._swatch.addEventListener(WebInspector.SwatchCheckbox.Events.Changed, this._toggleCounterGraph.bind(this));
container.appendChild(this._swatch.element);
this._range = this._swatch.element.createChild("span");

this._value = memoryCountersPane._currentValuesBar.createChild("span", "memory-counter-value");
this._value.style.color = swatchColor;
this._currentValueLabel = currentValueLabel;

this.graphColor = "rgba(" + rgb.join(",") + ",0.8)";
this.graphYValues = [];
}

WebInspector.CounterUI.prototype = {
_toggleCounterGraph: function(event)
{
if (this._swatch.checked)
this._value.removeStyleClass("hidden");
else
this._value.addStyleClass("hidden");
this._memoryCountersPane.refresh();
},

setRange: function(minValue, maxValue)
{
this._range.textContent = WebInspector.UIString("[ %d - %d ]", minValue, maxValue);
},

updateCurrentValue: function(countersEntry)
{
this._value.textContent =  WebInspector.UIString(this._currentValueLabel, this.valueGetter(countersEntry));
},

clearCurrentValueAndMarker: function(ctx)
{
this._value.textContent = "";
this.restoreImageUnderMarker(ctx);
},

get visible()
{
return this._swatch.checked;
},

saveImageUnderMarker: function(ctx, x, y, radius)
{
const w = radius + 1;
var imageData = ctx.getImageData(x - w, y - w, 2 * w, 2 * w);
this._imageUnderMarker = {
x: x - w,
y: y - w,
imageData: imageData };
},

restoreImageUnderMarker: function(ctx)
{
if (!this.visible)
return;
if (this._imageUnderMarker)
ctx.putImageData(this._imageUnderMarker.imageData, this._imageUnderMarker.x, this._imageUnderMarker.y);
this.discardImageUnderMarker();
},

discardImageUnderMarker: function()
{
delete this._imageUnderMarker;
}
}


WebInspector.MemoryStatistics.prototype = {
reset: function()
{
this._counters = [];
},

setMainTimelineGrid: function(timelineGrid)
{
this._mainTimelineGrid = timelineGrid;
},

setTopPosition: function(top)
{
this._memorySplitView.element.style.top = top + "px";
this._updateSize();
},

setSidebarWidth: function(width)
{
if (this._ignoreSidebarResize)
return;
this._ignoreSidebarResize = true;
this._memorySplitView.setSidebarWidth(width);
this._ignoreSidebarResize = false;
},

_sidebarResized: function(event)
{
if (this._ignoreSidebarResize)
return;
this._ignoreSidebarResize = true;
this._timelinePanel.splitView.setSidebarWidth(event.data);
this._ignoreSidebarResize = false;
},

_updateSize: function()
{
var width = this._mainTimelineGrid.dividersElement.offsetWidth + 1;
this._canvasContainer.style.width = width + "px";

var height = this._canvasContainer.offsetHeight - this._currentValuesBar.offsetHeight;
this._canvas.width = width;
this._canvas.height = height;
},

addTimlineEvent: function(event)
{
var counters = event.data["counters"];
this._counters.push({
time: event.data.endTime || event.data.startTime,
documentCount: counters["documents"],
nodeCount: counters["nodes"],
listenerCount: counters["jsEventListeners"]
});
},

_draw: function()
{
this._calculateVisibleIndexes();
this._calculateXValues();
this._clear();

this._setVerticalClip(10, this._canvas.height - 20);
for (var i = 0; i < this._counterUI.length; i++)
this._drawGraph(this._counterUI[i]);
},

_calculateVisibleIndexes: function()
{
var calculator = this._timelinePanel.calculator;
var start = calculator.minimumBoundary * 1000;
var end = calculator.maximumBoundary * 1000;
var firstIndex = 0;
var lastIndex = this._counters.length - 1;
for (var i = 0; i < this._counters.length; i++) {
var time = this._counters[i].time;
if (time <= start) {
firstIndex = i;
} else {
if (end < time)
break;
lastIndex = i;
}
}

this._minimumIndex = firstIndex;


this._maximumIndex = lastIndex;


this._minTime = start;
this._maxTime = end;
},

_onClick: function(event)
{
var x = event.x - event.target.offsetParent.offsetLeft
var i = this._recordIndexAt(x);
var counter = this._counters[i];
this._timelinePanel.revealRecordAt(counter.time / 1000);
},

_onMouseOut: function(event)
{
delete this._markerXPosition;

var ctx = this._canvas.getContext("2d");
for (var i = 0; i < this._counterUI.length; i++)
this._counterUI[i].clearCurrentValueAndMarker(ctx);
},

_onMouseOver: function(event)
{
this._onMouseMove(event);
},

_onMouseMove: function(event)
{
var x = event.x - event.target.offsetParent.offsetLeft
this._markerXPosition = x;
this._refreshCurrentValues();
},

_refreshCurrentValues: function()
{
if (!this._counters.length)
return;
if (this._markerXPosition === undefined)
return;
var i = this._recordIndexAt(this._markerXPosition);

for (var j = 0; j < this._counterUI.length; j++)
this._counterUI[j].updateCurrentValue(this._counters[i]);

this._highlightCurrentPositionOnGraphs(this._markerXPosition, i);
},

_recordIndexAt: function(x)
{
var i;
for (i = this._minimumIndex + 1; i <= this._maximumIndex; i++) {
var statX = this._counters[i].x;
if (x < statX)
break;
}
i--;
return i;
},

_highlightCurrentPositionOnGraphs: function(x, index)
{
var ctx = this._canvas.getContext("2d");
for (var i = 0; i < this._counterUI.length; i++) {
var counterUI = this._counterUI[i];
if (!counterUI.visible)
continue;
counterUI.restoreImageUnderMarker(ctx);
}

const radius = 2;
for (var i = 0; i < this._counterUI.length; i++) {
var counterUI = this._counterUI[i];
if (!counterUI.visible)
continue;
var y = counterUI.graphYValues[index];
counterUI.saveImageUnderMarker(ctx, x, y, radius);
}

for (var i = 0; i < this._counterUI.length; i++) {
var counterUI = this._counterUI[i];
if (!counterUI.visible)
continue;
var y = counterUI.graphYValues[index];
ctx.beginPath();
ctx.arc(x, y, radius, 0, Math.PI*2, true);
ctx.lineWidth = 1;
ctx.fillStyle = counterUI.graphColor;
ctx.strokeStyle = counterUI.graphColor;
ctx.fill();
ctx.stroke();
ctx.closePath();
}
},

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

show: function()
{
var anchor =   this._containerAnchor.nextSibling;
this._memorySplitView.show(this._timelinePanel.element, anchor);
this._updateSize();
this._refreshDividers();
setTimeout(this._draw.bind(this), 0);
},

refresh: function()
{
this._updateSize();
this._refreshDividers();
this._draw();
this._refreshCurrentValues();
},

hide: function()
{
this._memorySplitView.detach();
},

_refreshDividers: function()
{
this._timelineGrid.updateDividers(this._timelinePanel.calculator);
},

_setVerticalClip: function(originY, height)
{
this._originY = originY;
this._clippedHeight = height;
},

_calculateXValues: function()
{
if (!this._counters.length)
return;

var width = this._canvas.width;
var xFactor = width / (this._maxTime - this._minTime);

this._counters[this._minimumIndex].x = 0;
for (var i = this._minimumIndex + 1; i < this._maximumIndex; i++)
this._counters[i].x = xFactor * (this._counters[i].time - this._minTime);
this._counters[this._maximumIndex].x = width;
},

_drawGraph: function(counterUI)
{
var canvas = this._canvas;
var ctx = canvas.getContext("2d");
var width = canvas.width;
var height = this._clippedHeight;
var originY = this._originY;
var valueGetter = counterUI.valueGetter;

if (!this._counters.length)
return;

var maxValue;
var minValue;
for (var i = this._minimumIndex; i <= this._maximumIndex; i++) {
var value = valueGetter(this._counters[i]);
if (minValue === undefined || value < minValue)
minValue = value;
if (maxValue === undefined || value > maxValue)
maxValue = value;
}

counterUI.setRange(minValue, maxValue);

if (!counterUI.visible)
return;

var yValues = counterUI.graphYValues;
yValues.length = this._counters.length;

var maxYRange = maxValue - minValue;
var yFactor = maxYRange ? height / (maxYRange) : 1;

ctx.beginPath();
var currentY = originY + (height - (valueGetter(this._counters[this._minimumIndex])- minValue) * yFactor);
ctx.moveTo(0, currentY);
for (var i = this._minimumIndex; i <= this._maximumIndex; i++) {
var x = this._counters[i].x;
ctx.lineTo(x, currentY);
currentY = originY + (height - (valueGetter(this._counters[i])- minValue) * yFactor);
ctx.lineTo(x, currentY);

yValues[i] = currentY;
}
ctx.lineTo(width, currentY);
ctx.lineWidth = 1;
ctx.strokeStyle = counterUI.graphColor;
ctx.stroke();
ctx.closePath();
},

_clear: function() {
var ctx = this._canvas.getContext("2d");
ctx.clearRect(0, 0, ctx.canvas.width, ctx.canvas.height);
for (var i = 0; i < this._counterUI.length; i++)
this._counterUI[i].discardImageUnderMarker();
}
}







WebInspector.SnippetsModel = function()
{
this._snippets = {};

this._lastSnippetIdentifierSetting = WebInspector.settings.createSetting("lastSnippetIdentifier", 0);
this._snippetsSetting = WebInspector.settings.createSetting("snippets", []);
this._lastSnippetEvaluationIndexSetting = WebInspector.settings.createSetting("lastSnippetEvaluationIndex", 0);

this._loadSettings();
}

WebInspector.SnippetsModel.snippetsSourceURLPrefix = "snippets://";

WebInspector.SnippetsModel.EventTypes = {
SnippetAdded: "SnippetAdded",
SnippetWillBeEvaluated: "SnippetWillBeEvaluated",
SnippetRenamed: "SnippetRenamed",
SnippetRemoved: "SnippetRemoved",
}

WebInspector.SnippetsModel.prototype = {
_saveSettings: function()
{
var savedSnippets = [];
for (var id in this._snippets)
savedSnippets.push(this._snippets[id].serializeToObject());
this._snippetsSetting.set(savedSnippets);
},


get snippets()
{
var result = [];
for (var id in this._snippets)
result.push(this._snippets[id]);
return result;
},

_loadSettings: function()
{
var savedSnippets = this._snippetsSetting.get();
for (var i = 0; i < savedSnippets.length; ++i)
this._snippetAdded(WebInspector.Snippet.fromObject(savedSnippets[i]));
},


deleteSnippet: function(snippet)
{
delete this._snippets[snippet.id];
this._saveSettings();
this.dispatchEventToListeners(WebInspector.SnippetsModel.EventTypes.SnippetRemoved, snippet);
},


createSnippet: function()
{
var nextId = this._lastSnippetIdentifierSetting.get() + 1;
var snippetId = String(nextId);
this._lastSnippetIdentifierSetting.set(nextId);
var snippet = new WebInspector.Snippet(this, snippetId);
this._snippetAdded(snippet);
this._saveSettings();

return snippet;
},


_snippetAdded: function(snippet)
{
this._snippets[snippet.id] = snippet;
this.dispatchEventToListeners(WebInspector.SnippetsModel.EventTypes.SnippetAdded, snippet);
},


_snippetContentUpdated: function(snippetId)
{
this._saveSettings();
},


_snippetRenamed: function(snippet)
{
this._saveSettings();
this.dispatchEventToListeners(WebInspector.SnippetsModel.EventTypes.SnippetRenamed, snippet);
},


_evaluateSnippet: function(snippet)
{
this.dispatchEventToListeners(WebInspector.SnippetsModel.EventTypes.SnippetWillBeEvaluated, snippet);
var evaluationIndex = this._lastSnippetEvaluationIndexSetting.get() + 1;
this._lastSnippetEvaluationIndexSetting.set(evaluationIndex);

var sourceURL = this._sourceURLForSnippet(snippet, evaluationIndex);
snippet._lastEvaluationSourceURL = sourceURL;
var expression = "\n//@ sourceURL=" + sourceURL + "\n" + snippet.content;
WebInspector.evaluateInConsole(expression, true);
},


_sourceURLForSnippet: function(snippet, evaluationIndex)
{
var snippetsPrefix = WebInspector.SnippetsModel.snippetsSourceURLPrefix;
var evaluationSuffix = evaluationIndex ? "_" + evaluationIndex : "";
return snippetsPrefix + snippet.id + evaluationSuffix;
},


snippetIdForSourceURL: function(sourceURL)
{
var snippetsPrefix = WebInspector.SnippetsModel.snippetsSourceURLPrefix;
if (!sourceURL.startsWith(snippetsPrefix))
return null;
var splittedURL = sourceURL.substring(snippetsPrefix.length).split("_");
var snippetId = splittedURL[0];
return snippetId;
},


snippetForSourceURL: function(sourceURL)
{
var snippetId = this.snippetIdForSourceURL(sourceURL);
if (!snippetId)
return null;
var snippet = this._snippets[snippetId];
if (!snippet || snippet._lastEvaluationSourceURL !== sourceURL)
return null;
return snippet;
}
}

WebInspector.SnippetsModel.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.Snippet = function(model, id, name, content)
{
this._model = model;
this._id = id;
this._name = name || "Snippet #" + id;
this._content = content || "";
}

WebInspector.Snippet.evaluatedSnippetExtraLinesCount = 2;


WebInspector.Snippet.fromObject = function(serializedSnippet)
{
return new WebInspector.Snippet(this, serializedSnippet.id, serializedSnippet.name, serializedSnippet.content);
}

WebInspector.Snippet.prototype = {

get id()
{
return this._id;
},


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

set name(name)
{
if (this._name === name)
return;

this._name = name;
this._model._snippetRenamed(this);
},


get content()
{
return this._content;
},

set content(content)
{
if (this._content === content)
return;

this._content = content;
this._model._snippetContentUpdated(this._id);
},

evaluate: function()
{
this._model._evaluateSnippet(this);
},


serializeToObject: function()
{
var serializedSnippet = {};
serializedSnippet.id = this.id;
serializedSnippet.name = this.name;
serializedSnippet.content = this.content;
return serializedSnippet;
}
}

WebInspector.Snippet.prototype.__proto__ = WebInspector.Object.prototype;


WebInspector.SnippetsScriptMapping = function()
{
this._snippetForScriptId = {};
this._uiSourceCodeForScriptId = {};
this._scriptForUISourceCode = new Map();
this._uiSourceCodeForSnippet = new Map();

WebInspector.snippetsModel.addEventListener(WebInspector.SnippetsModel.EventTypes.SnippetAdded, this._handleSnippetAdded.bind(this));
WebInspector.snippetsModel.addEventListener(WebInspector.SnippetsModel.EventTypes.SnippetWillBeEvaluated, this._snippetWillBeEvaluated.bind(this));
WebInspector.snippetsModel.addEventListener(WebInspector.SnippetsModel.EventTypes.SnippetRemoved, this._snippetRemoved.bind(this));
for (var i = 0; i < WebInspector.snippetsModel.snippets.length; ++i)
this._snippetAdded(WebInspector.snippetsModel.snippets[i]);
}

WebInspector.SnippetsScriptMapping.prototype = {

rawLocationToUILocation: function(rawLocation)
{
var uiSourceCode = this._uiSourceCodeForScriptId[rawLocation.scriptId];

var snippet = this._snippetForScriptId[rawLocation.scriptId];
if (snippet) {
var uiLineNumber = rawLocation.lineNumber - WebInspector.Snippet.evaluatedSnippetExtraLinesCount;
return new WebInspector.UILocation(uiSourceCode, uiLineNumber, rawLocation.columnNumber || 0);
}

return new WebInspector.UILocation(uiSourceCode, rawLocation.lineNumber, rawLocation.columnNumber || 0);
},


uiLocationToRawLocation: function(uiSourceCode, lineNumber, columnNumber)
{
var script = this._scriptForUISourceCode.get(uiSourceCode);
if (!script)
return null;

if (uiSourceCode.isSnippet) {
var rawLineNumber = lineNumber + WebInspector.Snippet.evaluatedSnippetExtraLinesCount;
return WebInspector.debuggerModel.createRawLocation(script, rawLineNumber, columnNumber);
}

return WebInspector.debuggerModel.createRawLocation(script, lineNumber, columnNumber);
},


uiSourceCodeList: function()
{
var result = this._uiSourceCodeForSnippet.values();
result = result.concat(this._releasedUISourceCodes());
return result;
},


_releasedUISourceCodes: function()
{
var result = [];
for (var scriptId in this._uiSourceCodeForScriptId) {
var uiSourceCode = this._uiSourceCodeForScriptId[scriptId];
if (uiSourceCode.isSnippet)
continue;
result.push(uiSourceCode);
}
return result;
},


addScript: function(script)
{
var snippet = WebInspector.snippetsModel.snippetForSourceURL(script.sourceURL);
if (!snippet) {
this._createUISourceCodeForScript(script);
return;
}
var uiSourceCode = this._uiSourceCodeForSnippet.get(snippet);
console.assert(!this._scriptForUISourceCode.get(uiSourceCode));

this._uiSourceCodeForScriptId[script.scriptId] = uiSourceCode;
this._snippetForScriptId[script.scriptId] = snippet;
this._scriptForUISourceCode.put(uiSourceCode, script);
script.setSourceMapping(this);
},


_handleSnippetAdded: function(event)
{
var snippet =   event.data;
this._snippetAdded(snippet);
},


_snippetAdded: function(snippet)
{
var uiSourceCodeId = ""; 
var uiSourceCodeURL = ""; 
var uiSourceCode = new WebInspector.JavaScriptSource(uiSourceCodeId, uiSourceCodeURL, new WebInspector.SnippetContentProvider(snippet));
uiSourceCode.isSnippet = true;
uiSourceCode.isEditable = true;
this._uiSourceCodeForSnippet.put(snippet, uiSourceCode);
uiSourceCode.snippet = snippet;
var data = { removedItems: [], addedItems: [uiSourceCode] };
this.dispatchEventToListeners(WebInspector.ScriptMapping.Events.UISourceCodeListChanged, data);
},


_snippetWillBeEvaluated: function(event)
{
var snippet =   event.data;
this._releaseSnippetScript(snippet);
},


_createUISourceCodeForScript: function(script)
{
var uiSourceCode = new WebInspector.JavaScriptSource(script.sourceURL, script.sourceURL, script);
uiSourceCode.isSnippetEvaluation = true;
var oldUISourceCode = this._uiSourceCodeForScriptId[script.scriptId];
this._uiSourceCodeForScriptId[script.scriptId] = uiSourceCode;
this._scriptForUISourceCode.put(uiSourceCode, script);
var data = { removedItems: [], addedItems: [uiSourceCode] };
this.dispatchEventToListeners(WebInspector.ScriptMapping.Events.UISourceCodeListChanged, data);
script.setSourceMapping(this);
},


_releaseSnippetScript: function(snippet)
{
var uiSourceCode = this._uiSourceCodeForSnippet.get(snippet);
var script = this._scriptForUISourceCode.get(uiSourceCode);
if (!script)
return;

delete this._uiSourceCodeForScriptId[script.scriptId];
delete this._snippetForScriptId[script.scriptId];
this._scriptForUISourceCode.remove(uiSourceCode);

this._createUISourceCodeForScript(script);
},


_snippetRemoved: function(event)
{
var snippet =   event.data;
var uiSourceCode = this._uiSourceCodeForSnippet.get(snippet);
this._releaseSnippetScript(snippet);
this._uiSourceCodeForSnippet.remove(snippet);
var data = { removedItems: [uiSourceCode], addedItems: [] };
this.dispatchEventToListeners(WebInspector.ScriptMapping.Events.UISourceCodeListChanged, data);
},

reset: function()
{
var removedUISourceCodes = this._releasedUISourceCodes();
this._snippetForScriptId = {};
this._uiSourceCodeForScriptId = {};
this._scriptForUISourceCode = new Map();
var data = { removedItems: removedUISourceCodes, addedItems: [] };
this.dispatchEventToListeners(WebInspector.ScriptMapping.Events.UISourceCodeListChanged, data);
}
}

WebInspector.SnippetsScriptMapping.prototype.__proto__ = WebInspector.ScriptMapping.prototype;


WebInspector.SnippetContentProvider = function(snippet)
{
WebInspector.StaticContentProvider.call(this, "text/javascript", snippet.content);
}

WebInspector.SnippetContentProvider.prototype.__proto__ = WebInspector.StaticContentProvider.prototype;


WebInspector.snippetsModel = null;






WebInspector.StylesPanel = function()
{
WebInspector.Panel.call(this, "styles");
this.registerRequiredCSS("scriptsPanel.css");

const initialNavigatorWidth = 225;
const minimalViewsContainerWidthPercent = 50;

this._mainView = new WebInspector.SplitView(WebInspector.SplitView.SidebarPosition.Left, "stylesPanelNavigatorSidebarWidth", initialNavigatorWidth);
this._mainView.element.id = "styles-main-view";
this._mainView.element.tabIndex = 0;

this._mainView.minimalSidebarWidth = Preferences.minScriptsSidebarWidth;
this._mainView.minimalMainWidthPercent = minimalViewsContainerWidthPercent;

this._navigatorView = new WebInspector.NavigatorView();
this._navigatorView.addEventListener(WebInspector.NavigatorView.Events.ItemSelected, this._itemSelected, this);

this._tabbedPane = new WebInspector.TabbedPane();
this._tabbedPane.element.addStyleClass("navigator-tabbed-pane");
this._tabbedPane.shrinkableTabs = true;
this._tabbedPane.appendTab(WebInspector.ScriptsNavigator.ScriptsTab, WebInspector.UIString("Stylesheets"), this._navigatorView);
this._tabbedPane.show(this._mainView.sidebarElement);

this._editorContainer = new WebInspector.TabbedEditorContainer(this, "previouslyViewedCSSFiles");
this._editorContainer.show(this._mainView.mainElement);

this._mainView.show(this.element);

this._navigatorController = new WebInspector.NavigatorOverlayController(this, this._mainView, this._tabbedPane, this._editorContainer.view);

WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.CachedResourcesLoaded, this._cachedResourcesLoaded, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.WillLoadCachedResources, this._reset, this);
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._reset, this);

this._sourceFramesForResource = new Map();
this._urlToResource = {};

var openResourceShortcut = WebInspector.OpenResourceDialog.createShortcut();
this.registerShortcut(openResourceShortcut.key, this._showOpenStylesheetDialog.bind(this));
}

WebInspector.StylesPanel.prototype = {
wasShown: function()
{
WebInspector.Panel.prototype.wasShown.call(this);
this._navigatorController.wasShown();
this._initialize();
},

_initialize: function()
{
if (!this._initialized && this.isShowing() && this._cachedResourcesWereLoaded) {
this._populateResourceTree();
this._initialized = true;
}
},

_populateResourceTree: function()
{
WebInspector.resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.ResourceAdded, this._resourceAdded, this);

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

_resourceAdded: function(event)
{
var resource = event.data;
if (resource.type !== WebInspector.resourceTypes.Stylesheet)
return;
this._urlToResource[resource.url] = resource;
this._navigatorView.addUISourceCode(resource);
this._editorContainer.uiSourceCodeAdded(resource);
},

_reset: function()
{
this._navigatorView.reset();
this._editorContainer.reset();
this._urlToResource = {};
this._sourceFramesForResource = new Map();
},

_cachedResourcesLoaded: function()
{
this._cachedResourcesWereLoaded = true;
this._initialize();
},

get toolbarItemLabel()
{
return WebInspector.UIString("Styles");
},


viewForFile: function(uiSourceCode)
{
var sourceFrame = this._sourceFramesForResource.get(uiSourceCode);
if (!sourceFrame) {
sourceFrame = new WebInspector.EditableResourceSourceFrame(uiSourceCode);
sourceFrame.addEventListener(WebInspector.EditableResourceSourceFrame.Events.TextEdited, this._textEdited, this);
this._sourceFramesForResource.put(uiSourceCode, sourceFrame);
}
return sourceFrame;
},

_textEdited: function(event)
{
var sourceFrame =   event.data;
this._editorContainer.setFileIsDirty(sourceFrame.resource, sourceFrame.isDirty());
},

_itemSelected: function(event)
{
var uiSourceCode =   event.data.uiSourceCode;
this._showFile(uiSourceCode);
this._navigatorController.hideNavigatorOverlay();
if (event.data.focusSource)
this._editorContainer.view.focus();
},

_showFile: function(uiSourceCode)
{
this._navigatorView.revealUISourceCode(uiSourceCode);
this._editorContainer.showFile(uiSourceCode);
},

canShowAnchorLocation: function(anchor)
{
var resource = WebInspector.resourceForURL(anchor.href);
return !!resource && resource.type === WebInspector.resourceTypes.Stylesheet;
},

showAnchorLocation: function(anchor)
{
var resource = this._urlToResource[anchor.href];
if (!resource)
return;

this._showFile(resource);
var sourceFrame = this._sourceFramesForResource.get(resource);
if (typeof anchor.lineNumber === "number")
sourceFrame.highlightLine(anchor.lineNumber);
this._editorContainer.view.focus();
},

_showOpenStylesheetDialog: function()
{
if (WebInspector.Dialog.currentInstance())
return;

var dialog = new WebInspector.FilteredItemSelectionDialog(new WebInspector.OpenStylesheetDialog(this));
WebInspector.Dialog.show(this.element, dialog);
}
}

WebInspector.StylesPanel.prototype.__proto__ = WebInspector.Panel.prototype;


WebInspector.OpenStylesheetDialog = function(panel)
{
var resources = [];
for (var url in panel._urlToResource)
resources.push(panel._urlToResource[url]);
WebInspector.OpenResourceDialog.call(this, resources);

this._panel = panel;
}

WebInspector.OpenStylesheetDialog.prototype = {

selectItem: function(itemIndex)
{
this._panel._showFile(this.resources[itemIndex]);
}
}

WebInspector.OpenStylesheetDialog.prototype.__proto__ = WebInspector.OpenResourceDialog.prototype;







{(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;
Preferences.showDockToRight = true;
})();}

function buildPlatformExtensionAPI(extensionInfo)
{
return "var extensionInfo = " + JSON.stringify(extensionInfo) + ";" +
"var tabId = " + WebInspector._inspectedTabId + ";" +
platformExtensionAPI.toString();
}

WebInspector.setInspectedTabId = function(tabId)
{
WebInspector._inspectedTabId = tabId;
}





function platformExtensionAPI(coreAPI)
{
function getTabId()
{
return tabId;
}
chrome = window.chrome || {};



var devtools_descriptor = Object.getOwnPropertyDescriptor(chrome, "devtools");
if (!devtools_descriptor || devtools_descriptor.get)
Object.defineProperty(chrome, "devtools", { value: {}, enumerable: true });

chrome.devtools.inspectedWindow = {};
chrome.devtools.inspectedWindow.__defineGetter__("tabId", getTabId);
chrome.devtools.inspectedWindow.__proto__ = coreAPI.inspectedWindow;
chrome.devtools.network = coreAPI.network;
chrome.devtools.panels = coreAPI.panels;


if (extensionInfo.exposeExperimentalAPIs !== false) {
chrome.experimental = chrome.experimental || {};
chrome.experimental.devtools = chrome.experimental.devtools || {};

var properties = Object.getOwnPropertyNames(coreAPI);
for (var i = 0; i < properties.length; ++i) {
var descriptor = Object.getOwnPropertyDescriptor(coreAPI, properties[i]);
Object.defineProperty(chrome.experimental.devtools, properties[i], descriptor);
}
chrome.experimental.devtools.inspectedWindow = chrome.devtools.inspectedWindow;
}
if (extensionInfo.exposeWebInspectorNamespace)
window.webInspector = coreAPI;
}








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(test._scriptsAreParsed(["debugger_test_page.html"]), "Some scripts are missing.");
checkNoDuplicates();
test.releaseControl();
}

function checkNoDuplicates() {
var uiSourceCodes = test.nonAnonymousUISourceCodes_();
for (var i = 0; i < uiSourceCodes.length; i++) {
var scriptName = uiSourceCodes[i].fileName;
for (var j = i + 1; j < uiSourceCodes.length; j++)
test.assertTrue(scriptName !== uiSourceCodes[j].fileName, "Found script duplicates: " + test.uiSourceCodesToString_(uiSourceCodes));
}
}

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, "_finishNetworkRequest", 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, "_finishNetworkRequest", 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, "_finishNetworkRequest", 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, "_finishNetworkRequest", 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.waitForTestResultsInConsole = function()
{
var messages = WebInspector.console.messages;
for (var i = 0; i < messages.length; ++i) {
var text = messages[i].text;
if (text === "PASS")
return;
else if (/^FAIL/.test(text))
this.fail(text); 
}

function onConsoleMessage(event)
{
var text = event.data.text;
if (text === "PASS")
this.releaseControl();
else if (/^FAIL/.test(text))
this.fail(text);
}

WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, onConsoleMessage, this);
this.takeControl();
};

TestSuite.prototype.checkLogAndErrorMessages = function()
{
var messages = WebInspector.console.messages;

var matchesCount = 0;
function validMessage(message)
{
if (message.text === "log" && message.level === WebInspector.ConsoleMessage.MessageLevel.Log) {
++matchesCount;
return true;
}

if (message.text === "error" && message.level === WebInspector.ConsoleMessage.MessageLevel.Error) {
++matchesCount;
return true;
}
return false;
}

for (var i = 0; i < messages.length; ++i) {
if (validMessage(messages[i]))
continue;
this.fail(messages[i].text + ":" + messages[i].level); 
}

if (matchesCount === 2)
return;


function onConsoleMessage(event)
{
var message = event.data;
if (validMessage(message)) {
if (matchesCount === 2) {
this.releaseControl();
return;
}
} else
this.fail(message.text + ":" + messages[i].level);
}

WebInspector.console.addEventListener(WebInspector.ConsoleModel.Events.MessageAdded, onConsoleMessage, this);
this.takeControl();
};


TestSuite.prototype.uiSourceCodesToString_ = function(uiSourceCodes)
{
var names = [];
for (var i = 0; i < uiSourceCodes.length; i++)
names.push('"' + uiSourceCodes[i].fileName + '"');
return names.join(",");
};



TestSuite.prototype.nonAnonymousUISourceCodes_ = function()
{
function filterOutAnonymous(uiSourceCode)
{
return !!uiSourceCode.url;
}

var uiSourceCodes = WebInspector.panels.scripts._presentationModel.uiSourceCodes();
return uiSourceCodes.filter(filterOutAnonymous);
};



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 uiSourceCodes = this.nonAnonymousUISourceCodes_();

var missing = expected.slice(0);
for (var i = 0; i < uiSourceCodes.length; ++i) {
for (var j = 0; j < missing.length; ++j) {
if (uiSourceCodes[i].parsedURL.lastPathComponent.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, "_addUISourceCode", 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();
}

})();

}

