diff --git a/Inspector-1.1.json b/Inspector-1.1.json
index 42541d4f5e..2977d00655 100644
--- a/Inspector-1.1.json
+++ b/Inspector-1.1.json
@@ -2787,62 +2787,6 @@
}
]
},
- {
- "domain": "Timeline",
- "description": "Timeline provides its clients with instrumentation records that are generated during the page runtime. Timeline instrumentation can be started and stopped using corresponding commands. While timeline is started, it is generating timeline event records.",
- "types": [
- {
- "id": "DOMCounters",
- "type": "object",
- "properties": [
- { "name": "documents", "type": "integer" },
- { "name": "nodes", "type": "integer" },
- { "name": "jsEventListeners", "type": "integer" }
- ],
- "description": "Current values of DOM counters.",
- "hidden": true
- },
- {
- "id": "TimelineEvent",
- "type": "object",
- "properties": [
- { "name": "type", "type": "string", "description": "Event type." },
- { "name": "thread", "type": "string", "optional": true, "description": "If present, identifies the thread that produced the event.", "hidden": true },
- { "name": "data", "type": "object", "description": "Event data." },
- { "name": "children", "type": "array", "optional": true, "items": { "$ref": "TimelineEvent" }, "description": "Nested records." },
- { "name": "counters", "$ref": "DOMCounters", "optional": true, "hidden": true, "description": "Current values of DOM counters." },
- { "name": "usedHeapSize", "type": "integer", "optional": true, "hidden": true, "description": "Current size of JS heap." },
- { "name": "nativeHeapStatistics", "type": "object", "optional": true, "hidden": true, "description": "Native heap statistics." }
- ],
- "description": "Timeline record contains information about the recorded activity."
- }
- ],
- "commands": [
- {
- "name": "start",
- "parameters": [
- { "name": "maxCallStackDepth", "optional": true, "type": "integer", "description": "Samples JavaScript stack traces up to maxCallStackDepth
, defaults to 5." },
- { "name": "includeDomCounters", "optional": true, "type": "boolean", "hidden": true, "description": "Whether DOM counters data should be included into timeline events." },
- { "name": "includeNativeMemoryStatistics", "optional": true, "type": "boolean", "hidden": true, "description": "Whether native memory usage statistics should be reported as part of timeline events." }
-
- ],
- "description": "Starts capturing instrumentation events."
- },
- {
- "name": "stop",
- "description": "Stops capturing instrumentation events."
- }
- ],
- "events": [
- {
- "name": "eventRecorded",
- "parameters": [
- { "name": "record", "$ref": "TimelineEvent", "description": "Timeline event record data." }
- ],
- "description": "Fired for every instrumentation event while timeline is started."
- }
- ]
- },
{
"domain": "Debugger",
"description": "Debugger domain exposes JavaScript debugging capabilities. It allows setting and removing breakpoints, stepping through execution, exploring stack traces, etc.",
diff --git a/devtools.gypi b/devtools.gypi
index 38c0061515..c96d70d700 100644
--- a/devtools.gypi
+++ b/devtools.gypi
@@ -202,7 +202,9 @@
'front_end/emulation/mediaQueryInspector.css',
'front_end/emulation/sensors.css',
'front_end/emulation/DeviceModeModel.js',
+ 'front_end/emulation/DeviceModeToolbar.js',
'front_end/emulation/DeviceModeView.js',
+ 'front_end/emulation/DeviceModeWrapper.js',
'front_end/emulation/DeviceOrientation.js',
'front_end/emulation/DevicesSettingsTab.js',
'front_end/emulation/EmulatedDevices.js',
@@ -354,6 +356,7 @@
'front_end/accessibility/accessibilityNode.css',
'front_end/accessibility/AccessibilityModel.js',
'front_end/accessibility/AccessibilitySidebarView.js',
+ 'front_end/accessibility/AccessibilityNodeView.js',
'front_end/accessibility/AccessibilityStrings.js',
],
'devtools_animation_js_files': [
@@ -681,6 +684,7 @@
'front_end/timeline/TimelineEventOverview.js',
'front_end/timeline/TimelineFlameChart.js',
'front_end/timeline/TimelineFrameModel.js',
+ 'front_end/timeline/TimelineIRModel.js',
'front_end/timeline/TimelineJSProfile.js',
'front_end/timeline/TimelineLayersView.js',
'front_end/timeline/TimelineModel.js',
diff --git a/front_end/accessibility/AccessibilityNodeView.js b/front_end/accessibility/AccessibilityNodeView.js
new file mode 100644
index 0000000000..ba02da296b
--- /dev/null
+++ b/front_end/accessibility/AccessibilityNodeView.js
@@ -0,0 +1,667 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @constructor
+ * @extends {WebInspector.AccessibilitySubPane}
+ */
+WebInspector.AXNodeSubPane = function()
+{
+ WebInspector.AccessibilitySubPane.call(this, WebInspector.UIString("Accessibility Node"));
+
+ this._noNodeInfo = this.createInfo(WebInspector.UIString("No accessibility node"));
+ this._ignoredInfo = this.createInfo(WebInspector.UIString("Accessibility node not exposed"), "ax-ignored-info hidden");
+
+ this._treeOutline = this.createTreeOutline();
+ this._ignoredReasonsTree = this.createTreeOutline();
+};
+
+
+WebInspector.AXNodeSubPane.prototype = {
+ /**
+ * @param {?AccessibilityAgent.AXNode} axNode
+ * @override
+ */
+ setAXNode: function(axNode)
+ {
+ if (this._axNode === axNode)
+ return;
+ this._axNode = axNode;
+
+ var treeOutline = this._treeOutline;
+ treeOutline.removeChildren();
+ var ignoredReasons = this._ignoredReasonsTree;
+ ignoredReasons.removeChildren();
+ var target = this.node().target();
+
+ if (!axNode) {
+ treeOutline.element.classList.add("hidden");
+ this._ignoredInfo.classList.add("hidden");
+ ignoredReasons.element.classList.add("hidden");
+
+ this._noNodeInfo.classList.remove("hidden");
+ this.element.classList.add("ax-ignored-node-pane");
+
+ return;
+ } else if (axNode.ignored) {
+ this._noNodeInfo.classList.add("hidden");
+ treeOutline.element.classList.add("hidden");
+ this.element.classList.add("ax-ignored-node-pane");
+
+ this._ignoredInfo.classList.remove("hidden");
+ ignoredReasons.element.classList.remove("hidden");
+ /**
+ * @param {!AccessibilityAgent.AXProperty} property
+ */
+ function addIgnoredReason(property)
+ {
+ ignoredReasons.appendChild(new WebInspector.AXNodeIgnoredReasonTreeElement(property, axNode, target));
+ }
+ var ignoredReasonsArray = /** @type {!Array.} */(axNode.ignoredReasons);
+ for (var reason of ignoredReasonsArray)
+ addIgnoredReason(reason);
+ if (!ignoredReasons.firstChild())
+ ignoredReasons.element.classList.add("hidden");
+ return;
+ }
+ this.element.classList.remove("ax-ignored-node-pane");
+
+ this._ignoredInfo.classList.add("hidden");
+ ignoredReasons.element.classList.add("hidden");
+ this._noNodeInfo.classList.add("hidden");
+
+ treeOutline.element.classList.remove("hidden");
+
+ /**
+ * @param {!AccessibilityAgent.AXProperty} property
+ */
+ function addProperty(property)
+ {
+ treeOutline.appendChild(new WebInspector.AXNodePropertyTreePropertyElement(property, target));
+ }
+
+ for (var propertyName of ["name", "description", "help", "value"]) {
+ if (propertyName in axNode) {
+ var defaultProperty = /** @type {!AccessibilityAgent.AXProperty} */ ({name: propertyName, value: axNode[propertyName]});
+ addProperty(defaultProperty);
+ }
+ }
+
+ var roleProperty = /** @type {!AccessibilityAgent.AXProperty} */ ({name: "role", value: axNode.role});
+ addProperty(roleProperty);
+
+ var propertyMap = {};
+ var propertiesArray = /** @type {!Array.} */ (axNode.properties);
+ for (var property of propertiesArray)
+ propertyMap[property.name] = property;
+
+ for (var propertySet of [AccessibilityAgent.AXWidgetAttributes, AccessibilityAgent.AXWidgetStates, AccessibilityAgent.AXGlobalStates, AccessibilityAgent.AXLiveRegionAttributes, AccessibilityAgent.AXRelationshipAttributes]) {
+ for (var propertyKey in propertySet) {
+ var property = propertySet[propertyKey];
+ if (property in propertyMap)
+ addProperty(propertyMap[property]);
+ }
+ }
+ },
+
+ __proto__: WebInspector.AccessibilitySubPane.prototype
+};
+
+/**
+ * @constructor
+ * @extends {TreeElement}
+ * @param {!WebInspector.Target} target
+ */
+WebInspector.AXNodePropertyTreeElement = function(target)
+{
+ this._target = target;
+
+ // Pass an empty title, the title gets made later in onattach.
+ TreeElement.call(this, "");
+};
+
+/**
+ * @param {?AccessibilityAgent.AXValueType} type
+ * @param {string} value
+ * @return {!Element}
+ */
+WebInspector.AXNodePropertyTreeElement.createSimpleValueElement = function(type, value)
+{
+ var valueElement;
+ var AXValueType = AccessibilityAgent.AXValueType;
+ if (!type || type === AXValueType.ValueUndefined || type === AXValueType.ComputedString)
+ valueElement = createElement("span");
+ else
+ valueElement = createElementWithClass("span", "monospace");
+ var valueText;
+ if (type === AXValueType.String || type === AXValueType.ComputedString || type === AXValueType.IdrefList || type === AXValueType.Idref) {
+ // Render \n as a nice unicode cr symbol.
+ valueText = value.replace(/\n/g, "\u21B5");
+ valueElement._originalTextContent = value;
+ } else {
+ valueText = String(value);
+ }
+
+ if (type && type in WebInspector.AXNodePropertyTreeElement.TypeStyles)
+ valueElement.classList.add(WebInspector.AXNodePropertyTreeElement.TypeStyles[type]);
+
+ valueElement.setTextContentTruncatedIfNeeded(valueText || "");
+
+ valueElement.title = String(value) || "";
+
+ return valueElement;
+};
+
+/**
+ * @param {string} tooltip
+ * @return {!Element}
+ */
+WebInspector.AXNodePropertyTreeElement.createExclamationMark = function(tooltip)
+{
+ var exclamationElement = createElement("label", "dt-icon-label");
+ exclamationElement.type = "warning-icon";
+ exclamationElement.title = tooltip;
+ return exclamationElement;
+};
+
+/** @type {!Object} */
+WebInspector.AXNodePropertyTreeElement.TypeStyles = {
+ attribute: "ax-value-string",
+ boolean: "object-value-boolean",
+ booleanOrUndefined: "object-value-boolean",
+ computedString: "ax-readable-string",
+ idref: "ax-value-string",
+ idrefList: "ax-value-string",
+ integer: "object-value-number",
+ internalRole: "ax-internal-role",
+ number: "ax-value-number",
+ role: "ax-role",
+ string: "ax-value-string",
+ tristate: "object-value-boolean",
+ valueUndefined: "ax-value-undefined"
+};
+
+/** @type {!Set.} */
+WebInspector.AXNodePropertyTreeElement.StringProperties = new Set([
+ AccessibilityAgent.AXValueType.String,
+ AccessibilityAgent.AXValueType.ComputedString,
+ AccessibilityAgent.AXValueType.IdrefList,
+ AccessibilityAgent.AXValueType.Idref
+]);
+
+WebInspector.AXNodePropertyTreeElement.prototype = {
+ /**
+ * @param {string} name
+ */
+ appendNameElement: function(name)
+ {
+ var nameElement = createElement("span");
+ var AXAttributes = WebInspector.AccessibilityStrings.AXAttributes;
+ if (name in AXAttributes) {
+ nameElement.textContent = WebInspector.UIString(AXAttributes[name].name);
+ nameElement.title = AXAttributes[name].description;
+ nameElement.classList.add("ax-readable-name");
+ } else {
+ nameElement.textContent = name;
+ nameElement.classList.add("ax-name");
+ nameElement.classList.add("monospace");
+ }
+ this.listItemElement.appendChild(nameElement);
+ },
+
+ /**
+ * @param {!AccessibilityAgent.AXValue} value
+ */
+ appendValueElement: function(value)
+ {
+ var AXValueType = AccessibilityAgent.AXValueType;
+ if (value.type === AXValueType.Idref || value.type === AXValueType.Node ||
+ value.type === AXValueType.IdrefList || value.type === AXValueType.NodeList) {
+ this.appendRelatedNodeListValueElement(value);
+ return;
+ } else if (value.sources) {
+ var sources = value.sources;
+ for (var i = 0; i < sources.length; i++) {
+ var source = sources[i];
+ var child = new WebInspector.AXValueSourceTreeElement(source, this._target);
+ this.appendChild(child);
+ }
+ this.expand();
+ }
+ var isStringProperty = WebInspector.AXNodePropertyTreeElement.StringProperties.has(value.type);
+ if (isStringProperty)
+ this.listItemElement.createTextChild("\"");
+ this.listItemElement.appendChild(WebInspector.AXNodePropertyTreeElement.createSimpleValueElement(value.type, String(value.value)));
+ if (isStringProperty)
+ this.listItemElement.createTextChild("\"");
+ },
+
+ /**
+ * @param {!AccessibilityAgent.AXRelatedNode} relatedNode
+ * @param {number} index
+ */
+ appendRelatedNode: function(relatedNode, index)
+ {
+ if (index > 0)
+ this.listItemElement.createTextChild(",\u00a0");
+
+ var deferredNode = new WebInspector.DeferredDOMNode(this._target, relatedNode.backendNodeId);
+ var linkedNode = new WebInspector.AXRelatedNodeElement({ deferredNode: deferredNode }, relatedNode);
+ this.listItemElement.appendChild(linkedNode.render());
+ },
+
+ /**
+ * @param {!AccessibilityAgent.AXValue} value
+ */
+ appendRelatedNodeListValueElement: function(value)
+ {
+ value.relatedNodes.forEach(this.appendRelatedNode, this);
+ },
+
+ __proto__: TreeElement.prototype
+};
+
+/**
+ * @constructor
+ * @extends {WebInspector.AXNodePropertyTreeElement}
+ * @param {!AccessibilityAgent.AXProperty} property
+ * @param {!WebInspector.Target} target
+ */
+WebInspector.AXNodePropertyTreePropertyElement = function(property, target)
+{
+ this._property = property;
+ this.toggleOnClick = true;
+ this.selectable = false;
+
+ WebInspector.AXNodePropertyTreeElement.call(this, target);
+ this.listItemElement.classList.add("property");
+}
+
+WebInspector.AXNodePropertyTreePropertyElement.prototype = {
+ /**
+ * @override
+ */
+ onattach: function()
+ {
+ this._update();
+ },
+
+ _update: function()
+ {
+ this.listItemElement.removeChildren();
+
+ this.appendNameElement(this._property.name);
+
+ this.listItemElement.createChild("span", "separator").textContent = ":\u00A0";
+
+ this.appendValueElement(this._property.value);
+ },
+
+ __proto__: WebInspector.AXNodePropertyTreeElement.prototype
+};
+
+/**
+ * @constructor
+ * @extends {WebInspector.AXNodePropertyTreeElement}
+ * @param {!AccessibilityAgent.AXValueSource} source
+ * @param {!WebInspector.Target} target
+ */
+WebInspector.AXValueSourceTreeElement = function(source, target)
+{
+ this._source = source;
+ WebInspector.AXNodePropertyTreeElement.call(this, target);
+ this.selectable = false;
+}
+
+WebInspector.AXValueSourceTreeElement.prototype = {
+ /**
+ * @override
+ */
+ onattach: function()
+ {
+ this._update();
+ },
+
+ /**
+ * @param {!AccessibilityAgent.AXRelatedNode} relatedNode
+ * @param {number} index
+ * @override
+ */
+ appendRelatedNode: function(relatedNode, index)
+ {
+ var deferredNode = new WebInspector.DeferredDOMNode(this._target, relatedNode.backendNodeId);
+ var nodeTreeElement = new WebInspector.AXRelatedNodeSourceTreeElement({ deferredNode: deferredNode }, relatedNode);
+ this.appendChild(nodeTreeElement);
+ },
+
+ /**
+ * @param {!AccessibilityAgent.AXRelatedNode} relatedNode
+ * @param {number} index
+ * @param {string} idref
+ */
+ appendRelatedNodeWithIdref: function(relatedNode, index, idref)
+ {
+ var deferredNode = new WebInspector.DeferredDOMNode(this._target, relatedNode.backendNodeId);
+ var nodeTreeElement = new WebInspector.AXRelatedNodeSourceTreeElement({ deferredNode: deferredNode, idref: idref }, relatedNode);
+ this.appendChild(nodeTreeElement);
+ },
+
+ /**
+ * @param {!AccessibilityAgent.AXValue} value
+ */
+ appendIDRefValueElement: function(value)
+ {
+ var relatedNodes = value.relatedNodes;
+ var numNodes = relatedNodes.length;
+ var valueElement;
+
+ var idrefs = value.value.trim().split(/\s+/);
+ if (idrefs.length === 1) {
+ var idref = idrefs[0];
+ var matchingNode = relatedNodes.find(node => node.idref === idref);
+ if (matchingNode) {
+ this.appendRelatedNodeWithIdref(matchingNode, 0, idref);
+ } else {
+ this.listItemElement.appendChild(new WebInspector.AXRelatedNodeElement({ idref: idref }).render());
+ }
+ } else {
+ // TODO(aboxhall): exclamation mark if not idreflist type
+ for (var i = 0; i < idrefs.length; ++i) {
+ var idref = idrefs[i];
+ var matchingNode = relatedNodes.find(node => node.idref === idref);
+ if (matchingNode) {
+ this.appendRelatedNodeWithIdref(matchingNode, i, idref);
+ } else {
+ this.appendChild(new WebInspector.AXRelatedNodeSourceTreeElement({ idref: idref }));
+ }
+ }
+ }
+ },
+
+ /**
+ * @param {!AccessibilityAgent.AXValue} value
+ * @override
+ */
+ appendRelatedNodeListValueElement: function(value)
+ {
+ var relatedNodes = value.relatedNodes;
+ var numNodes = relatedNodes.length;
+
+ if (value.type === AccessibilityAgent.AXValueType.IdrefList ||
+ value.type === AccessibilityAgent.AXValueType.Idref) {
+ this.appendIDRefValueElement(value);
+ } else {
+ WebInspector.AXNodePropertyTreeElement.prototype.appendRelatedNodeListValueElement.call(this, value);
+ }
+
+ if (numNodes <= 3)
+ this.expand();
+ else
+ this.collapse();
+ },
+
+ /**
+ * @param {!AccessibilityAgent.AXValueSource} source
+ */
+ appendSourceNameElement: function(source)
+ {
+ var nameElement = createElement("span");
+ var AXValueSourceType = AccessibilityAgent.AXValueSourceType;
+ var type = source.type;
+ var name;
+ switch (type) {
+ case AXValueSourceType.Attribute:
+ case AXValueSourceType.Placeholder:
+ case AXValueSourceType.RelatedElement:
+ if (source.nativeSource) {
+ var AXNativeSourceTypes = WebInspector.AccessibilityStrings.AXNativeSourceTypes;
+ var nativeSource = source.nativeSource;
+ nameElement.textContent = WebInspector.UIString(AXNativeSourceTypes[nativeSource].name);
+ nameElement.title = WebInspector.UIString(AXNativeSourceTypes[nativeSource].description);
+ nameElement.classList.add("ax-readable-name");
+ break;
+ }
+ nameElement.textContent = source.attribute;
+ nameElement.classList.add("ax-name");
+ nameElement.classList.add("monospace");
+ break;
+ default:
+ var AXSourceTypes = WebInspector.AccessibilityStrings.AXSourceTypes;
+ if (type in AXSourceTypes) {
+ nameElement.textContent = WebInspector.UIString(AXSourceTypes[type].name);
+ nameElement.title = WebInspector.UIString(AXSourceTypes[type].description);
+ nameElement.classList.add("ax-readable-name");
+ } else {
+ console.warn(type, "not in AXSourceTypes");
+ nameElement.textContent = WebInspector.UIString(type);
+ }
+ }
+ this.listItemElement.appendChild(nameElement);
+ },
+
+ _update: function()
+ {
+ this.listItemElement.removeChildren();
+
+ if (this._source.invalid) {
+ var exclamationMark = WebInspector.AXNodePropertyTreeElement.createExclamationMark(WebInspector.UIString("Invalid source."));
+ this.listItemElement.appendChild(exclamationMark);
+ this.listItemElement.classList.add("ax-value-source-invalid");
+ } else if (this._source.superseded) {
+ this.listItemElement.classList.add("ax-value-source-unused");
+ }
+
+ this.appendSourceNameElement(this._source);
+
+ this.listItemElement.createChild("span", "separator").textContent = ":\u00a0";
+
+ if (this._source.attributeValue) {
+ this.appendValueElement(this._source.attributeValue);
+ this.listItemElement.createTextChild("\u00a0");
+ } else if (this._source.nativeSourceValue) {
+ this.appendValueElement(this._source.nativeSourceValue);
+ this.listItemElement.createTextChild("\u00a0");
+ }
+
+ if (this._source.value) {
+ this.appendValueElement(this._source.value);
+ if (this._source.superseded)
+ this.listItemElement.classList.add("ax-value-source-superseded");
+ } else {
+ var valueElement = WebInspector.AXNodePropertyTreeElement.createSimpleValueElement(AccessibilityAgent.AXValueType.ValueUndefined, WebInspector.UIString("Not specified"));
+ this.listItemElement.appendChild(valueElement);
+ this.listItemElement.classList.add("ax-value-source-unused");
+ }
+ },
+
+ __proto__: WebInspector.AXNodePropertyTreeElement.prototype
+};
+
+/**
+ * @constructor
+ * @param {{deferredNode: (!WebInspector.DeferredDOMNode|undefined), idref: (string|undefined)}} node
+ * @param {!AccessibilityAgent.AXRelatedNode=} value
+ * @extends {TreeElement}
+ */
+WebInspector.AXRelatedNodeSourceTreeElement = function(node, value)
+{
+ this._value = value;
+ this._axRelatedNodeElement = new WebInspector.AXRelatedNodeElement(node, value);
+
+ TreeElement.call(this, "");
+
+ this.selectable = false;
+};
+
+WebInspector.AXRelatedNodeSourceTreeElement.prototype = {
+ /**
+ * @override
+ */
+ onattach: function()
+ {
+ this.listItemElement.appendChild(this._axRelatedNodeElement.render());
+ if (!this._value)
+ return;
+
+ this.listItemElement.createTextChild("\u00a0\"");
+ if (this._value.text)
+ this.listItemElement.appendChild(WebInspector.AXNodePropertyTreeElement.createSimpleValueElement(AccessibilityAgent.AXValueType.ComputedString, this._value.text));
+ this.listItemElement.createTextChild("\"");
+ },
+
+ __proto__: TreeElement.prototype
+};
+
+
+/**
+ * @constructor
+ * @param {{deferredNode: (!WebInspector.DeferredDOMNode|undefined), idref: (string|undefined)}} node
+ * @param {!AccessibilityAgent.AXRelatedNode=} value
+ */
+WebInspector.AXRelatedNodeElement = function(node, value)
+{
+ this._deferredNode = node.deferredNode;
+ this._idref = node.idref;
+ this._value = value;
+};
+
+WebInspector.AXRelatedNodeElement.prototype = {
+ /**
+ * @return {!Element}
+ */
+ render: function()
+ {
+ var element = createElement("span");
+ var valueElement;
+
+ /**
+ * @param {?WebInspector.DOMNode} node
+ * @this {!WebInspector.AXRelatedNodeElement}
+ */
+ function onNodeResolved(node)
+ {
+ valueElement.appendChild(WebInspector.DOMPresentationUtils.linkifyNodeReference(node, this._idref));
+ }
+
+ if (this._deferredNode) {
+ valueElement = createElement("span");
+ element.appendChild(valueElement);
+ this._deferredNode.resolve(onNodeResolved.bind(this));
+ } else if (this._idref) {
+ element.classList.add("invalid");
+ valueElement = WebInspector.AXNodePropertyTreeElement.createExclamationMark(WebInspector.UIString("No node with this ID."));
+ valueElement.createTextChild(this._idref);
+ element.appendChild(valueElement);
+ }
+
+ return element;
+ }
+};
+
+/**
+ * @constructor
+ * @extends {WebInspector.AXNodePropertyTreeElement}
+ * @param {!AccessibilityAgent.AXProperty} property
+ * @param {?AccessibilityAgent.AXNode} axNode
+ * @param {!WebInspector.Target} target
+ */
+WebInspector.AXNodeIgnoredReasonTreeElement = function(property, axNode, target)
+{
+ this._property = property;
+ this._axNode = axNode;
+
+ WebInspector.AXNodePropertyTreeElement.call(this, target);
+ this.toggleOnClick = true;
+ this.selectable = false;
+}
+
+WebInspector.AXNodeIgnoredReasonTreeElement.prototype = {
+ /**
+ * @override
+ */
+ onattach: function()
+ {
+ this.listItemElement.removeChildren();
+
+ this._reasonElement = WebInspector.AXNodeIgnoredReasonTreeElement.createReasonElement(this._property.name, this._axNode);
+ this.listItemElement.appendChild(this._reasonElement);
+
+ var value = this._property.value;
+ if (value.type === AccessibilityAgent.AXValueType.Idref)
+ this.appendRelatedNodeListValueElement(value);
+ },
+
+ __proto__: WebInspector.AXNodePropertyTreeElement.prototype
+};
+
+/**
+ * @param {?string} reason
+ * @param {?AccessibilityAgent.AXNode} axNode
+ * @return {?Element}
+ */
+WebInspector.AXNodeIgnoredReasonTreeElement.createReasonElement = function(reason, axNode)
+{
+ var reasonElement = null;
+ switch(reason) {
+ case "activeModalDialog":
+ reasonElement = WebInspector.formatLocalized("Element is hidden by active modal dialog:\u00a0", []);
+ break;
+ case "ancestorDisallowsChild":
+ reasonElement = WebInspector.formatLocalized("Element is not permitted as child of ", []);
+ break;
+ // http://www.w3.org/TR/wai-aria/roles#childrenArePresentational
+ case "ancestorIsLeafNode":
+ reasonElement = WebInspector.formatLocalized("Ancestor's children are all presentational:\u00a0", []);
+ break;
+ case "ariaHidden":
+ var ariaHiddenSpan = createElement("span", "source-code").textContent = "aria-hidden";
+ reasonElement = WebInspector.formatLocalized("Element is %s.", [ ariaHiddenSpan ]);
+ break;
+ case "ariaHiddenRoot":
+ var ariaHiddenSpan = createElement("span", "source-code").textContent = "aria-hidden";
+ var trueSpan = createElement("span", "source-code").textContent = "true";
+ reasonElement = WebInspector.formatLocalized("%s is %s on ancestor:\u00a0", [ ariaHiddenSpan, trueSpan ]);
+ break;
+ case "emptyAlt":
+ reasonElement = WebInspector.formatLocalized("Element has empty alt text.", []);
+ break;
+ case "emptyText":
+ reasonElement = WebInspector.formatLocalized("No text content.", []);
+ break;
+ case "inert":
+ reasonElement = WebInspector.formatLocalized("Element is inert.", []);
+ break;
+ case "inheritsPresentation":
+ reasonElement = WebInspector.formatLocalized("Element inherits presentational role from\u00a0", []);
+ break;
+ case "labelContainer":
+ reasonElement = WebInspector.formatLocalized("Part of label element:\u00a0", []);
+ break;
+ case "labelFor":
+ reasonElement = WebInspector.formatLocalized("Label for\u00a0", []);
+ break;
+ case "notRendered":
+ reasonElement = WebInspector.formatLocalized("Element is not rendered.", []);
+ break;
+ case "notVisible":
+ reasonElement = WebInspector.formatLocalized("Element is not visible.", []);
+ break;
+ case "presentationalRole":
+ var rolePresentationSpan = createElement("span", "source-code").textContent = "role=" + axNode.role.value;
+ reasonElement = WebInspector.formatLocalized("Element has %s.", [ rolePresentationSpan ]);
+ break;
+ case "probablyPresentational":
+ reasonElement = WebInspector.formatLocalized("Element is presentational.", []);
+ break;
+ case "staticTextUsedAsNameFor":
+ reasonElement = WebInspector.formatLocalized("Static text node is used as name for\u00a0", []);
+ break;
+ case "uninteresting":
+ reasonElement = WebInspector.formatLocalized("Element not interesting for accessibility.", []);
+ break;
+ }
+ if (reasonElement)
+ reasonElement.classList.add("ax-reason");
+ return reasonElement;
+};
diff --git a/front_end/accessibility/AccessibilitySidebarView.js b/front_end/accessibility/AccessibilitySidebarView.js
index a871c06b0b..1d6e2d9e72 100644
--- a/front_end/accessibility/AccessibilitySidebarView.js
+++ b/front_end/accessibility/AccessibilitySidebarView.js
@@ -131,18 +131,6 @@ WebInspector.AccessibilitySidebarView.prototype = {
__proto__: WebInspector.ThrottledWidget.prototype
};
-/**
- * @param {string} tooltip
- * @return {!Element}
- */
-WebInspector.AccessibilitySidebarView.createExclamationMark = function(tooltip)
-{
- var exclamationElement = createElement("label", "dt-icon-label");
- exclamationElement.type = "warning-icon";
- exclamationElement.title = tooltip;
- return exclamationElement;
-};
-
/**
* @constructor
* @extends {WebInspector.SidebarPane}
@@ -282,602 +270,3 @@ WebInspector.AXComputedTextSubPane.prototype = {
__proto__: WebInspector.AccessibilitySubPane.prototype
};
-
-/**
- * @constructor
- * @extends {WebInspector.AccessibilitySubPane}
- */
-WebInspector.AXNodeSubPane = function()
-{
- WebInspector.AccessibilitySubPane.call(this, WebInspector.UIString("Accessibility Node"));
-
- this._noNodeInfo = this.createInfo(WebInspector.UIString("No accessibility node"));
- this._ignoredInfo = this.createInfo(WebInspector.UIString("Accessibility node not exposed"), "ax-ignored-info hidden");
-
- this._treeOutline = this.createTreeOutline();
- this._ignoredReasonsTree = this.createTreeOutline();
-};
-
-
-WebInspector.AXNodeSubPane.prototype = {
- /**
- * @param {?AccessibilityAgent.AXNode} axNode
- * @override
- */
- setAXNode: function(axNode)
- {
- if (this._axNode === axNode)
- return;
- this._axNode = axNode;
-
- var treeOutline = this._treeOutline;
- treeOutline.removeChildren();
- var ignoredReasons = this._ignoredReasonsTree;
- ignoredReasons.removeChildren();
- var target = this.node().target();
-
- if (!axNode) {
- treeOutline.element.classList.add("hidden");
- this._ignoredInfo.classList.add("hidden");
- ignoredReasons.element.classList.add("hidden");
-
- this._noNodeInfo.classList.remove("hidden");
- this.element.classList.add("ax-ignored-node-pane");
-
- return;
- } else if (axNode.ignored) {
- this._noNodeInfo.classList.add("hidden");
- treeOutline.element.classList.add("hidden");
- this.element.classList.add("ax-ignored-node-pane");
-
- this._ignoredInfo.classList.remove("hidden");
- ignoredReasons.element.classList.remove("hidden");
- /**
- * @param {!AccessibilityAgent.AXProperty} property
- */
- function addIgnoredReason(property)
- {
- ignoredReasons.appendChild(new WebInspector.AXNodeIgnoredReasonTreeElement(property, axNode, target));
- }
- var ignoredReasonsArray = /** @type {!Array.} */(axNode.ignoredReasons);
- for (var reason of ignoredReasonsArray)
- addIgnoredReason(reason);
- if (!ignoredReasons.firstChild())
- ignoredReasons.element.classList.add("hidden");
- return;
- }
- this.element.classList.remove("ax-ignored-node-pane");
-
- this._ignoredInfo.classList.add("hidden");
- ignoredReasons.element.classList.add("hidden");
- this._noNodeInfo.classList.add("hidden");
-
- treeOutline.element.classList.remove("hidden");
-
- /**
- * @param {!AccessibilityAgent.AXProperty} property
- */
- function addProperty(property)
- {
- treeOutline.appendChild(new WebInspector.AXNodePropertyTreePropertyElement(property, target));
- }
-
- for (var propertyName of ["name", "description", "help", "value"]) {
- if (propertyName in axNode) {
- var defaultProperty = /** @type {!AccessibilityAgent.AXProperty} */ ({name: propertyName, value: axNode[propertyName]});
- addProperty(defaultProperty);
- }
- }
-
- var roleProperty = /** @type {!AccessibilityAgent.AXProperty} */ ({name: "role", value: axNode.role});
- addProperty(roleProperty);
-
- var propertyMap = {};
- var propertiesArray = /** @type {!Array.} */ (axNode.properties);
- for (var property of propertiesArray)
- propertyMap[property.name] = property;
-
- for (var propertySet of [AccessibilityAgent.AXWidgetAttributes, AccessibilityAgent.AXWidgetStates, AccessibilityAgent.AXGlobalStates, AccessibilityAgent.AXLiveRegionAttributes, AccessibilityAgent.AXRelationshipAttributes]) {
- for (var propertyKey in propertySet) {
- var property = propertySet[propertyKey];
- if (property in propertyMap)
- addProperty(propertyMap[property]);
- }
- }
- },
-
- __proto__: WebInspector.AccessibilitySubPane.prototype
-};
-
-/**
- * @param {?AccessibilityAgent.AXValueType} type
- * @param {string} value
- * @return {!Element}
- */
-WebInspector.AccessibilitySidebarView.createSimpleValueElement = function(type, value)
-{
- var valueElement;
- var AXValueType = AccessibilityAgent.AXValueType;
- if (!type || type === AXValueType.ValueUndefined || type === AXValueType.ComputedString)
- valueElement = createElement("span");
- else
- valueElement = createElementWithClass("span", "monospace");
- var valueText;
- if (type === AXValueType.String || type === AXValueType.ComputedString || type === AXValueType.IdrefList || type === AXValueType.Idref) {
- // Render \n as a nice unicode cr symbol.
- valueText = value.replace(/\n/g, "\u21B5");
- valueElement._originalTextContent = value;
- } else {
- valueText = String(value);
- }
-
- if (type && type in WebInspector.AXNodePropertyTreeElement.TypeStyles)
- valueElement.classList.add(WebInspector.AXNodePropertyTreeElement.TypeStyles[type]);
-
- valueElement.setTextContentTruncatedIfNeeded(valueText || "");
-
- valueElement.title = String(value) || "";
-
- return valueElement;
-}
-
-/**
- * @constructor
- * @extends {TreeElement}
- * @param {!WebInspector.Target} target
- */
-WebInspector.AXNodePropertyTreeElement = function(target)
-{
- this._target = target;
-
- // Pass an empty title, the title gets made later in onattach.
- TreeElement.call(this, "");
- this.selectable = false;
-}
-
-WebInspector.AXNodePropertyTreeElement.prototype = {
- /**
- * @param {string} name
- */
- appendNameElement: function(name)
- {
- var nameElement = createElement("span");
- var AXAttributes = WebInspector.AccessibilityStrings.AXAttributes;
- if (name in AXAttributes) {
- nameElement.textContent = WebInspector.UIString(AXAttributes[name].name);
- nameElement.title = AXAttributes[name].description;
- nameElement.classList.add("ax-readable-name");
- } else {
- nameElement.textContent = name;
- nameElement.classList.add("ax-name");
- nameElement.classList.add("monospace");
- }
- this.listItemElement.appendChild(nameElement);
- },
-
- /**
- * @param {!AccessibilityAgent.AXValue} value
- */
- appendValueElement: function(value)
- {
- var AXValueType = AccessibilityAgent.AXValueType;
- if (value.type === AXValueType.Idref || value.type === AXValueType.Node) {
- this.appendRelationshipValueElement(value);
- return;
- }
- if (value.type === AXValueType.IdrefList || value.type === AXValueType.NodeList) {
- this.appendRelatedNodeListValueElement(value);
- return;
- }
- if (value.sources) {
- var sources = value.sources;
- for (var i = 0; i < sources.length; i++) {
- var source = sources[i];
- var child = new WebInspector.AXValueSourceTreeElement(source, this._target);
- this.appendChild(child);
- }
- }
- var isStringProperty = WebInspector.AXNodePropertyTreeElement.StringProperties.has(value.type);
- if (isStringProperty)
- this.listItemElement.createTextChild("\"");
- this.listItemElement.appendChild(WebInspector.AccessibilitySidebarView.createSimpleValueElement(value.type, String(value.value)));
- if (isStringProperty)
- this.listItemElement.createTextChild("\"");
- },
-
- /**
- * @param {!AccessibilityAgent.AXValue} value
- */
- appendRelationshipValueElement: function(value)
- {
- var relatedNode = value.relatedNodes[0];
- var deferredNode = new WebInspector.DeferredDOMNode(this._target, relatedNode.backendNodeId);
- var valueElement = createElement("span");
-
- /**
- * @param {?WebInspector.DOMNode} node
- */
- function onNodeResolved(node)
- {
- valueElement.appendChild(WebInspector.DOMPresentationUtils.linkifyNodeReference(node));
- if (relatedNode.text) {
- valueElement.createTextChild("\"");
- valueElement.appendChild(WebInspector.AccessibilitySidebarView.createSimpleValueElement(AccessibilityAgent.AXValueType.ComputedString, relatedNode.text));
- valueElement.createTextChild("\"");
- }
- }
- deferredNode.resolve(onNodeResolved);
-
- this.listItemElement.appendChild(valueElement);
- },
-
- /**
- * @param {!AccessibilityAgent.AXValue} value
- */
- appendRelatedNodeListValueElement: function(value)
- {
- var relatedNodes = value.relatedNodes;
- var numNodes = relatedNodes.length;
- var valueElement;
- if (value.type === AccessibilityAgent.AXValueType.IdrefList) {
- var idrefs = value.value.split(/\s/);
- for (var idref of idrefs) {
- var matchingNode = null;
- /**
- * @param {!AccessibilityAgent.AXRelatedNode} relatedNode
- * @return {boolean}
- */
- function matchesIDRef(relatedNode)
- {
- if (relatedNode.idref !== idref)
- return false;
- matchingNode = relatedNode;
- return true;
- }
- relatedNodes.some(matchesIDRef);
- if (matchingNode) {
- var relatedNode = /** @type {!AccessibilityAgent.AXRelatedNode} */ (matchingNode);
- var backendNodeId = matchingNode.backendNodeId;
- var deferredNode = new WebInspector.DeferredDOMNode(this._target, backendNodeId);
- var child = new WebInspector.AXRelatedNodeTreeElement({ deferredNode: deferredNode, idref: idref }, relatedNode);
- this.appendChild(child);
- } else {
- this.appendChild(new WebInspector.AXRelatedNodeTreeElement({ idref: idref }));
- }
- }
- this.listItemElement.createTextChild("\"");
- this.listItemElement.appendChild(WebInspector.AccessibilitySidebarView.createSimpleValueElement(value.type, String(value.value)));
- this.listItemElement.createTextChild("\"");
- } else {
- for (var i = 0; i < numNodes; i++) {
- var relatedNode = relatedNodes[i];
- var deferredNode = new WebInspector.DeferredDOMNode(this._target, relatedNode.backendNodeId);
- var child = new WebInspector.AXRelatedNodeTreeElement({ deferredNode: deferredNode }, relatedNode);
- this.appendChild(child);
- }
- var numNodesString = "(" + numNodes + (numNodes === 1 ? " node" : " nodes") + ")";
- this.listItemElement.appendChild(WebInspector.AccessibilitySidebarView.createSimpleValueElement(null, numNodesString));
- }
- if (relatedNodes.length <= 3)
- this.expand();
- else
- this.collapse();
- },
-
- __proto__: TreeElement.prototype
-}
-
-/**
- * @constructor
- * @extends {WebInspector.AXNodePropertyTreeElement}
- * @param {!AccessibilityAgent.AXProperty} property
- * @param {!WebInspector.Target} target
- */
-WebInspector.AXNodePropertyTreePropertyElement = function(property, target)
-{
- this._property = property;
- this.toggleOnClick = true;
- this.selectable = false;
-
- WebInspector.AXNodePropertyTreeElement.call(this, target);
- this.listItemElement.classList.add("property");
-}
-
-WebInspector.AXNodePropertyTreePropertyElement.prototype = {
- /**
- * @override
- */
- onattach: function()
- {
- this._update();
- },
-
- _update: function()
- {
- this.listItemElement.removeChildren();
-
- this.appendNameElement(this._property.name);
-
- this.listItemElement.createChild("span", "separator").textContent = ":\u00A0";
-
- this.appendValueElement(this._property.value);
- },
-
- __proto__: WebInspector.AXNodePropertyTreeElement.prototype
-}
-
-/**
- * @constructor
- * @extends {WebInspector.AXNodePropertyTreeElement}
- * @param {!AccessibilityAgent.AXValueSource} source
- * @param {!WebInspector.Target} target
- */
-WebInspector.AXValueSourceTreeElement = function(source, target)
-{
- this._source = source;
- WebInspector.AXNodePropertyTreeElement.call(this, target);
- this.selectable = false;
-}
-
-WebInspector.AXValueSourceTreeElement.prototype = {
- /**
- * @override
- */
- onattach: function()
- {
- this._update();
- },
-
- /**
- * @param {!AccessibilityAgent.AXValueSource} source
- */
- appendSourceNameElement: function(source)
- {
- var nameElement = createElement("span");
- var AXValueSourceType = AccessibilityAgent.AXValueSourceType;
- var type = source.type;
- var name;
- switch (type) {
- case AXValueSourceType.Attribute:
- case AXValueSourceType.Placeholder:
- case AXValueSourceType.RelatedElement:
- if (source.nativeSource) {
- var AXNativeSourceTypes = WebInspector.AccessibilityStrings.AXNativeSourceTypes;
- var nativeSource = source.nativeSource;
- nameElement.textContent = WebInspector.UIString(AXNativeSourceTypes[nativeSource].name);
- nameElement.title = WebInspector.UIString(AXNativeSourceTypes[nativeSource].description);
- nameElement.classList.add("ax-readable-name");
- break;
- }
- nameElement.textContent = source.attribute;
- nameElement.classList.add("ax-name");
- nameElement.classList.add("monospace");
- break;
- default:
- var AXSourceTypes = WebInspector.AccessibilityStrings.AXSourceTypes;
- if (type in AXSourceTypes) {
- nameElement.textContent = WebInspector.UIString(AXSourceTypes[type].name);
- nameElement.title = WebInspector.UIString(AXSourceTypes[type].description);
- nameElement.classList.add("ax-readable-name");
- } else {
- console.warn(type, "not in AXSourceTypes");
- nameElement.textContent = WebInspector.UIString(type);
- }
- }
- this.listItemElement.appendChild(nameElement);
- },
-
- _update: function() {
- this.listItemElement.removeChildren();
-
- if (this._source.invalid) {
- var exclamationMark = WebInspector.AccessibilitySidebarView.createExclamationMark(WebInspector.UIString("Invalid source."));
- this.listItemElement.appendChild(exclamationMark);
- this.listItemElement.classList.add("ax-value-source-invalid");
- } else if (this._source.superseded) {
- this.listItemElement.classList.add("ax-value-source-unused");
- }
-
- this.appendSourceNameElement(this._source);
-
- this.listItemElement.createChild("span", "separator").innerHTML = ": ";
-
- if (this._source.value) {
- this.appendValueElement(this._source.value);
- if (this._source.superseded)
- this.listItemElement.classList.add("ax-value-source-superseded");
- } else {
- var valueElement = WebInspector.AccessibilitySidebarView.createSimpleValueElement(AccessibilityAgent.AXValueType.ValueUndefined, WebInspector.UIString("Not specified"));
- this.listItemElement.appendChild(valueElement);
- this.listItemElement.classList.add("ax-value-source-unused");
- }
- },
-
- __proto__: WebInspector.AXNodePropertyTreeElement.prototype
-}
-
-/**
- * @constructor
- * @extends {TreeElement}
- * @param {{deferredNode: (!WebInspector.DeferredDOMNode|undefined), idref: (string|undefined)}} node
- * @param {!AccessibilityAgent.AXRelatedNode=} value
- */
-WebInspector.AXRelatedNodeTreeElement = function(node, value)
-{
- this._deferredNode = node.deferredNode;
- this._idref = node.idref;
- this._value = value;
-
- TreeElement.call(this, "");
- this.selectable = false;
-};
-
-WebInspector.AXRelatedNodeTreeElement.prototype = {
- onattach: function()
- {
- this._update();
- },
-
- _update: function()
- {
- var valueElement;
-
- /**
- * @param {?WebInspector.DOMNode} node
- */
- function onNodeResolved(node)
- {
- valueElement.appendChild(WebInspector.DOMPresentationUtils.linkifyNodeReference(node));
- }
- if (this._deferredNode) {
- valueElement = createElement("span");
- this.listItemElement.appendChild(valueElement);
- this._deferredNode.resolve(onNodeResolved);
- } else if (this._idref) {
- this.listItemElement.classList.add("invalid");
- valueElement = WebInspector.AccessibilitySidebarView.createExclamationMark(WebInspector.UIString("No node with this ID."));
- valueElement.createTextChild(this._idref);
- }
- this.listItemElement.appendChild(valueElement);
- if (this._value && this._value.text) {
- var textElement = WebInspector.AccessibilitySidebarView.createSimpleValueElement(AccessibilityAgent.AXValueType.ComputedString, this._value.text);
- this.listItemElement.createTextChild("\u00A0\"");
- this.listItemElement.appendChild(textElement);
- this.listItemElement.createTextChild("\"");
- }
- },
-
- __proto__: TreeElement.prototype
-};
-
-/** @type {!Object} */
-WebInspector.AXNodePropertyTreeElement.TypeStyles = {
- attribute: "ax-value-string",
- boolean: "object-value-boolean",
- booleanOrUndefined: "object-value-boolean",
- computedString: "ax-readable-string",
- idref: "ax-value-string",
- idrefList: "ax-value-string",
- integer: "object-value-number",
- internalRole: "ax-internal-role",
- number: "ax-value-number",
- role: "ax-role",
- string: "ax-value-string",
- tristate: "object-value-boolean",
- valueUndefined: "ax-value-undefined"
-};
-
-/** @type {!Set.} */
-WebInspector.AXNodePropertyTreeElement.StringProperties = new Set([
- AccessibilityAgent.AXValueType.String,
- AccessibilityAgent.AXValueType.ComputedString,
- AccessibilityAgent.AXValueType.IdrefList,
- AccessibilityAgent.AXValueType.Idref
-]);
-
-/**
- * @constructor
- * @extends {WebInspector.AXNodePropertyTreeElement}
- * @param {!AccessibilityAgent.AXProperty} property
- * @param {?AccessibilityAgent.AXNode} axNode
- * @param {!WebInspector.Target} target
- */
-WebInspector.AXNodeIgnoredReasonTreeElement = function(property, axNode, target)
-{
- this._property = property;
- this._axNode = axNode;
-
- WebInspector.AXNodePropertyTreeElement.call(this, target);
- this.toggleOnClick = true;
- this.selectable = false;
-}
-
-WebInspector.AXNodeIgnoredReasonTreeElement.prototype = {
- /**
- * @override
- */
- onattach: function()
- {
- this.listItemElement.removeChildren();
-
- this._reasonElement = WebInspector.AXNodeIgnoredReasonTreeElement.createReasonElement(this._property.name, this._axNode);
- this.listItemElement.appendChild(this._reasonElement);
-
- var value = this._property.value;
- if (value.type === AccessibilityAgent.AXValueType.Idref)
- this.appendRelationshipValueElement(value);
- },
-
- __proto__: WebInspector.AXNodePropertyTreeElement.prototype
-};
-
-/**
- * @param {?string} reason
- * @param {?AccessibilityAgent.AXNode} axNode
- * @return {?Element}
- */
-WebInspector.AXNodeIgnoredReasonTreeElement.createReasonElement = function(reason, axNode)
-{
- var reasonElement = null;
- switch(reason) {
- case "activeModalDialog":
- reasonElement = WebInspector.formatLocalized("Element is hidden by active modal dialog: ", []);
- break;
- case "ancestorDisallowsChild":
- reasonElement = WebInspector.formatLocalized("Element is not permitted as child of ", []);
- break;
- // http://www.w3.org/TR/wai-aria/roles#childrenArePresentational
- case "ancestorIsLeafNode":
- reasonElement = WebInspector.formatLocalized("Ancestor's children are all presentational: ", []);
- break;
- case "ariaHidden":
- var ariaHiddenSpan = createElement("span", "source-code").textContent = "aria-hidden";
- reasonElement = WebInspector.formatLocalized("Element is %s.", [ ariaHiddenSpan ]);
- break;
- case "ariaHiddenRoot":
- var ariaHiddenSpan = createElement("span", "source-code").textContent = "aria-hidden";
- var trueSpan = createElement("span", "source-code").textContent = "true";
- reasonElement = WebInspector.formatLocalized("%s is %s on ancestor: ", [ ariaHiddenSpan, trueSpan ]);
- break;
- case "emptyAlt":
- reasonElement = WebInspector.formatLocalized("Element has empty alt text.", []);
- break;
- case "emptyText":
- reasonElement = WebInspector.formatLocalized("No text content.", []);
- break;
- case "inert":
- reasonElement = WebInspector.formatLocalized("Element is inert.", []);
- break;
- case "inheritsPresentation":
- reasonElement = WebInspector.formatLocalized("Element inherits presentational role from ", []);
- break;
- case "labelContainer":
- reasonElement = WebInspector.formatLocalized("Part of label element: ", []);
- break;
- case "labelFor":
- reasonElement = WebInspector.formatLocalized("Label for ", []);
- break;
- case "notRendered":
- reasonElement = WebInspector.formatLocalized("Element is not rendered.", []);
- break;
- case "notVisible":
- reasonElement = WebInspector.formatLocalized("Element is not visible.", []);
- break;
- case "presentationalRole":
- var rolePresentationSpan = createElement("span", "source-code").textContent = "role=" + axNode.role.value;
- reasonElement = WebInspector.formatLocalized("Element has %s.", [ rolePresentationSpan ]);
- break;
- case "probablyPresentational":
- reasonElement = WebInspector.formatLocalized("Element is presentational.", []);
- break;
- case "staticTextUsedAsNameFor":
- reasonElement = WebInspector.formatLocalized("Static text node is used as name for ", []);
- break;
- case "uninteresting":
- reasonElement = WebInspector.formatLocalized("Element not interesting for accessibility.", [])
- break;
- }
- if (reasonElement)
- reasonElement.classList.add("ax-reason");
- return reasonElement;
-}
diff --git a/front_end/accessibility/accessibilityNode.css b/front_end/accessibility/accessibilityNode.css
index f9a74e964d..5ee0919271 100644
--- a/front_end/accessibility/accessibilityNode.css
+++ b/front_end/accessibility/accessibilityNode.css
@@ -71,6 +71,9 @@ span.ax-internal-role {
.tree-outline li.invalid {
position: relative;
left: -2px;
+}
+
+.invalid {
text-decoration: line-through;
}
diff --git a/front_end/accessibility/module.json b/front_end/accessibility/module.json
index 868f32eb40..4b11f008f2 100644
--- a/front_end/accessibility/module.json
+++ b/front_end/accessibility/module.json
@@ -12,6 +12,7 @@
"scripts": [
"AccessibilityModel.js",
"AccessibilitySidebarView.js",
+ "AccessibilityNodeView.js",
"AccessibilityStrings.js"
],
"resources": [
diff --git a/front_end/bindings/BlackboxSupport.js b/front_end/bindings/BlackboxSupport.js
index 0d0c0cf1ae..e868560637 100644
--- a/front_end/bindings/BlackboxSupport.js
+++ b/front_end/bindings/BlackboxSupport.js
@@ -2,6 +2,46 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+/**
+ * @constructor
+ */
+WebInspector.BlackboxManager = function()
+{
+ WebInspector.targetManager.addModelListener(WebInspector.DebuggerModel, WebInspector.DebuggerModel.Events.ParsedScriptSource, this._parsedScriptSource, this);
+ WebInspector.moduleSetting("skipStackFramesPattern").addChangeListener(this._patternChanged.bind(this));
+ WebInspector.moduleSetting("skipContentScripts").addChangeListener(this._patternChanged.bind(this));
+}
+
+WebInspector.BlackboxManager.prototype = {
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _parsedScriptSource: function(event)
+ {
+ var script = /** @type {!WebInspector.Script} */ (event.data);
+ this._blackboxScriptIfNeeded(script);
+ },
+
+ _patternChanged: function()
+ {
+ for (var debuggerModel of WebInspector.DebuggerModel.instances()) {
+ for (var scriptId in debuggerModel.scripts)
+ this._blackboxScriptIfNeeded(debuggerModel.scripts[scriptId]);
+ }
+ },
+
+ /**
+ * @param {!WebInspector.Script} script
+ */
+ _blackboxScriptIfNeeded: function(script)
+ {
+ if (WebInspector.BlackboxSupport.isBlackboxed(script.sourceURL, script.isContentScript()))
+ script.setBlackboxedRanges([ { line: 0, column: 0 } ]);
+ else
+ script.setBlackboxedRanges([]);
+ }
+}
+
WebInspector.BlackboxSupport = {}
/**
diff --git a/front_end/bindings/DefaultScriptMapping.js b/front_end/bindings/DefaultScriptMapping.js
index a004fd5f03..e24e191909 100644
--- a/front_end/bindings/DefaultScriptMapping.js
+++ b/front_end/bindings/DefaultScriptMapping.js
@@ -46,6 +46,17 @@ WebInspector.DefaultScriptMapping = function(debuggerModel, workspace, debuggerW
this._debuggerReset();
}
+WebInspector.DefaultScriptMapping._scriptSymbol = Symbol("symbol");
+
+/**
+ * @param {!WebInspector.UISourceCode} uiSourceCode
+ * @return {?WebInspector.Script}
+ */
+WebInspector.DefaultScriptMapping.scriptForUISourceCode = function(uiSourceCode)
+{
+ return uiSourceCode[WebInspector.DefaultScriptMapping._scriptSymbol] || null;
+}
+
WebInspector.DefaultScriptMapping.prototype = {
/**
* @override
@@ -91,6 +102,7 @@ WebInspector.DefaultScriptMapping.prototype = {
url = "debugger:///VM" + script.scriptId + (url ? " " + url: "");
var uiSourceCode = this._project.createUISourceCode(url, WebInspector.resourceTypes.Script);
+ uiSourceCode[WebInspector.DefaultScriptMapping._scriptSymbol] = script;
this._uiSourceCodeForScriptId.set(script.scriptId, uiSourceCode);
this._scriptIdForUISourceCode.set(uiSourceCode, script.scriptId);
this._project.addUISourceCodeWithProvider(uiSourceCode, script);
diff --git a/front_end/bindings/PresentationConsoleMessageHelper.js b/front_end/bindings/PresentationConsoleMessageHelper.js
index 6b3773600b..0f66b56b22 100644
--- a/front_end/bindings/PresentationConsoleMessageHelper.js
+++ b/front_end/bindings/PresentationConsoleMessageHelper.js
@@ -84,11 +84,12 @@ WebInspector.PresentationConsoleMessageHelper.prototype = {
var debuggerModel = WebInspector.DebuggerModel.fromTarget(message.target());
if (!debuggerModel)
return null;
+ var callFrame = message.stackTrace && message.stackTrace.callFrames ? message.stackTrace.callFrames[0] : null;
// FIXME(62725): stack trace line/column numbers are one-based.
- var lineNumber = message.stackTrace ? message.stackTrace[0].lineNumber - 1 : message.line - 1;
+ var lineNumber = callFrame ? callFrame.lineNumber - 1 : message.line - 1;
var columnNumber = message.column ? message.column - 1 : 0;
- if (message.stackTrace && message.stackTrace[0].columnNumber)
- columnNumber = message.stackTrace[0].columnNumber - 1;
+ if (callFrame && callFrame.columnNumber)
+ columnNumber = callFrame.columnNumber - 1;
if (message.scriptId)
return debuggerModel.createRawLocationByScriptId(message.scriptId, lineNumber, columnNumber);
return debuggerModel.createRawLocationByURL(message.url || "", lineNumber, columnNumber);
diff --git a/front_end/bindings/StylesSourceMapping.js b/front_end/bindings/StylesSourceMapping.js
index 0f1b608ae9..9aeaee651d 100644
--- a/front_end/bindings/StylesSourceMapping.js
+++ b/front_end/bindings/StylesSourceMapping.js
@@ -47,8 +47,8 @@ WebInspector.StylesSourceMapping = function(cssModel, workspace, networkMapping)
cssModel.target().resourceTreeModel.addEventListener(WebInspector.ResourceTreeModel.EventTypes.MainFrameNavigated, this._unbindAllUISourceCodes, this);
this._cssModel.addEventListener(WebInspector.CSSStyleModel.Events.StyleSheetChanged, this._styleSheetChanged, this);
- /** @type {!Object.>>} */
- this._urlToHeadersByFrameId = {};
+ /** @type {!Map>>} */
+ this._urlToHeadersByFrameId = new Map();
/** @type {!Map.} */
this._styleFiles = new Map();
}
@@ -126,10 +126,10 @@ WebInspector.StylesSourceMapping.prototype = {
return;
WebInspector.cssWorkspaceBinding.pushSourceMapping(header, this);
- var map = this._urlToHeadersByFrameId[url];
+ var map = this._urlToHeadersByFrameId.get(url);
if (!map) {
map = /** @type {!Map.>} */ (new Map());
- this._urlToHeadersByFrameId[url] = map;
+ this._urlToHeadersByFrameId.set(url, map);
}
var headersById = map.get(header.frameId);
if (!headersById) {
@@ -151,16 +151,16 @@ WebInspector.StylesSourceMapping.prototype = {
if (!url)
return;
- var map = this._urlToHeadersByFrameId[url];
+ var map = this._urlToHeadersByFrameId.get(url);
console.assert(map);
var headersById = map.get(header.frameId);
console.assert(headersById);
- headersById.remove(header.id);
+ headersById.delete(header.id);
if (!headersById.size) {
- map.remove(header.frameId);
+ map.delete(header.frameId);
if (!map.size) {
- delete this._urlToHeadersByFrameId[url];
+ this._urlToHeadersByFrameId.delete(url);
var uiSourceCode = this._networkMapping.uiSourceCodeForStyleURL(url, header);
if (uiSourceCode)
this._unbindUISourceCode(uiSourceCode);
@@ -177,7 +177,7 @@ WebInspector.StylesSourceMapping.prototype = {
if (!styleFile)
return;
styleFile.dispose();
- this._styleFiles.remove(uiSourceCode);
+ this._styleFiles.delete(uiSourceCode);
},
_unbindAllUISourceCodes: function()
@@ -185,7 +185,7 @@ WebInspector.StylesSourceMapping.prototype = {
for (var styleFile of this._styleFiles.keys())
styleFile.dispose();
this._styleFiles.clear();
- this._urlToHeadersByFrameId = {};
+ this._urlToHeadersByFrameId = new Map();
},
/**
@@ -195,9 +195,9 @@ WebInspector.StylesSourceMapping.prototype = {
{
var uiSourceCode = /** @type {!WebInspector.UISourceCode} */ (event.data);
var networkURL = this._networkMapping.networkURL(uiSourceCode);
- if (!networkURL || !this._urlToHeadersByFrameId[networkURL])
+ if (!networkURL || !this._urlToHeadersByFrameId.has(networkURL))
return;
- this._bindUISourceCode(uiSourceCode, this._urlToHeadersByFrameId[networkURL].valuesArray()[0].valuesArray()[0]);
+ this._bindUISourceCode(uiSourceCode, this._urlToHeadersByFrameId.get(networkURL).valuesArray()[0].valuesArray()[0]);
},
/**
diff --git a/front_end/common/Settings.js b/front_end/common/Settings.js
index 6944a294f6..7869c34aa7 100644
--- a/front_end/common/Settings.js
+++ b/front_end/common/Settings.js
@@ -266,7 +266,7 @@ WebInspector.Setting.prototype = {
try {
this._value = JSON.parse(this._storage.get(this._name));
} catch(e) {
- this.remove();
+ this._storage.remove(this._name);
}
}
return this._value;
diff --git a/front_end/components/DOMPresentationUtils.js b/front_end/components/DOMPresentationUtils.js
index af4a7d8068..103d218f14 100644
--- a/front_end/components/DOMPresentationUtils.js
+++ b/front_end/components/DOMPresentationUtils.js
@@ -102,9 +102,10 @@ WebInspector.DOMPresentationUtils.createSpansForNodeTitle = function(container,
/**
* @param {?WebInspector.DOMNode} node
+ * @param {string=} idref
* @return {!Node}
*/
-WebInspector.DOMPresentationUtils.linkifyNodeReference = function(node)
+WebInspector.DOMPresentationUtils.linkifyNodeReference = function(node, idref)
{
if (!node)
return createTextNode(WebInspector.UIString(""));
@@ -113,7 +114,10 @@ WebInspector.DOMPresentationUtils.linkifyNodeReference = function(node)
var shadowRoot = WebInspector.createShadowRootWithCoreStyles(root, "components/domUtils.css");
var link = shadowRoot.createChild("div", "node-link");
- WebInspector.DOMPresentationUtils.decorateNodeLabel(node, link);
+ if (idref)
+ link.createChild("span", "node-label-id").createTextChild("#" + idref);
+ else
+ WebInspector.DOMPresentationUtils.decorateNodeLabel(node, link);
link.addEventListener("click", WebInspector.Revealer.reveal.bind(WebInspector.Revealer, node, undefined), false);
link.addEventListener("mouseover", node.highlight.bind(node, undefined, undefined), false);
@@ -214,11 +218,10 @@ WebInspector.DOMPresentationUtils.buildImagePreviewContents = function(target, o
/**
* @param {!WebInspector.Target} target
* @param {!WebInspector.Linkifier} linkifier
- * @param {!Array.=} stackTrace
- * @param {!ConsoleAgent.AsyncStackTrace=} asyncStackTrace
+ * @param {!RuntimeAgent.StackTrace=} stackTrace
* @return {!Element}
*/
-WebInspector.DOMPresentationUtils.buildStackTracePreviewContents = function(target, linkifier, stackTrace, asyncStackTrace)
+WebInspector.DOMPresentationUtils.buildStackTracePreviewContents = function(target, linkifier, stackTrace)
{
var element = createElement("span");
element.style.display = "inline-block";
@@ -226,11 +229,11 @@ WebInspector.DOMPresentationUtils.buildStackTracePreviewContents = function(targ
var contentElement = shadowRoot.createChild("table", "stack-preview-container");
/**
- * @param {!Array.} stackTrace
+ * @param {!RuntimeAgent.StackTrace} stackTrace
*/
function appendStackTrace(stackTrace)
{
- for (var stackFrame of stackTrace) {
+ for (var stackFrame of stackTrace.callFrames) {
var row = createElement("tr");
row.createChild("td", "function-name").textContent = WebInspector.beautifyFunctionName(stackFrame.functionName);
row.createChild("td").textContent = " @ ";
@@ -239,19 +242,23 @@ WebInspector.DOMPresentationUtils.buildStackTracePreviewContents = function(targ
}
}
- if (stackTrace)
- appendStackTrace(stackTrace);
+ if (!stackTrace)
+ return element;
+ appendStackTrace(stackTrace);
+
+ var asyncStackTrace = stackTrace.parent;
while (asyncStackTrace) {
- var callFrames = asyncStackTrace.callFrames;
- if (!callFrames || !callFrames.length)
- break;
+ if (!asyncStackTrace.callFrames.length) {
+ asyncStackTrace = asyncStackTrace.parent;
+ continue;
+ }
var row = contentElement.createChild("tr");
row.createChild("td", "stack-preview-async-description").textContent = WebInspector.asyncStackTraceLabel(asyncStackTrace.description);
row.createChild("td");
row.createChild("td");
- appendStackTrace(callFrames);
- asyncStackTrace = asyncStackTrace.asyncStackTrace;
+ appendStackTrace(asyncStackTrace);
+ asyncStackTrace = asyncStackTrace.parent;
}
return element;
diff --git a/front_end/components/DebuggerPresentationUtils.js b/front_end/components/DebuggerPresentationUtils.js
index b5719fc399..b40b21f3a0 100644
--- a/front_end/components/DebuggerPresentationUtils.js
+++ b/front_end/components/DebuggerPresentationUtils.js
@@ -6,44 +6,39 @@ WebInspector.DebuggerPresentationUtils = {}
/**
* @param {?WebInspector.DebuggerModel} debuggerModel
- * @param {!Array.=} stackTrace
- * @param {!ConsoleAgent.AsyncStackTrace=} asyncStackTrace
+ * @param {!RuntimeAgent.StackTrace=} stackTrace
* @param {boolean=} showBlackboxed
- * @return {?ConsoleAgent.CallFrame}
+ * @return {?RuntimeAgent.CallFrame}
*/
-WebInspector.DebuggerPresentationUtils.callFrameAnchorFromStackTrace = function(debuggerModel, stackTrace, asyncStackTrace, showBlackboxed)
+WebInspector.DebuggerPresentationUtils.callFrameAnchorFromStackTrace = function(debuggerModel, stackTrace, showBlackboxed)
{
/**
- * @param {?Array.=} stackTrace
- * @return {?ConsoleAgent.CallFrame}
+ * @param {!Array.} callFrames
+ * @return {?RuntimeAgent.CallFrame}
*/
- function innerCallFrameAnchorFromStackTrace(stackTrace)
+ function innerCallFrameAnchorFromStackTrace(callFrames)
{
- if (!stackTrace || !stackTrace.length)
+ if (!callFrames.length)
return null;
if (showBlackboxed)
- return stackTrace[0];
- for (var i = 0; i < stackTrace.length; ++i) {
- var script = debuggerModel && debuggerModel.scriptForId(stackTrace[i].scriptId);
+ return callFrames[0];
+ for (var i = 0; i < callFrames.length; ++i) {
+ var script = debuggerModel && debuggerModel.scriptForId(callFrames[i].scriptId);
var blackboxed = script ?
WebInspector.BlackboxSupport.isBlackboxed(script.sourceURL, script.isContentScript()) :
- WebInspector.BlackboxSupport.isBlackboxedURL(stackTrace[i].url);
+ WebInspector.BlackboxSupport.isBlackboxedURL(callFrames[i].url);
if (!blackboxed)
- return stackTrace[i];
+ return callFrames[i];
}
return null;
}
- var callFrame = innerCallFrameAnchorFromStackTrace(stackTrace);
- if (callFrame)
- return callFrame;
-
+ var asyncStackTrace = stackTrace;
while (asyncStackTrace) {
- callFrame = innerCallFrameAnchorFromStackTrace(asyncStackTrace.callFrames);
+ var callFrame = innerCallFrameAnchorFromStackTrace(asyncStackTrace.callFrames);
if (callFrame)
return callFrame;
- asyncStackTrace = asyncStackTrace.asyncStackTrace;
+ asyncStackTrace = asyncStackTrace.parent;
}
-
- return stackTrace ? stackTrace[0] : null;
+ return stackTrace && stackTrace.callFrames.length ? stackTrace.callFrames[0] : null;
}
diff --git a/front_end/components/Drawer.js b/front_end/components/Drawer.js
index 6058785e5d..7d6fad36ac 100644
--- a/front_end/components/Drawer.js
+++ b/front_end/components/Drawer.js
@@ -68,7 +68,6 @@ WebInspector.Drawer.prototype = {
showView: function(id, immediate)
{
this._innerShow(immediate);
- WebInspector.userMetrics.drawerShown(id);
return this._extensibleTabbedPaneController.showTab(id);
},
diff --git a/front_end/components/Linkifier.js b/front_end/components/Linkifier.js
index d791afddd5..a49b44c6be 100644
--- a/front_end/components/Linkifier.js
+++ b/front_end/components/Linkifier.js
@@ -193,7 +193,7 @@ WebInspector.Linkifier.prototype = {
/**
* @param {?WebInspector.Target} target
- * @param {!ConsoleAgent.CallFrame} callFrame
+ * @param {!RuntimeAgent.CallFrame} callFrame
* @param {string=} classes
* @return {!Element}
*/
diff --git a/front_end/components_lazy/CookiesTable.js b/front_end/components_lazy/CookiesTable.js
index 3619ffa050..60d5a6c311 100644
--- a/front_end/components_lazy/CookiesTable.js
+++ b/front_end/components_lazy/CookiesTable.js
@@ -51,7 +51,7 @@ WebInspector.CookiesTable = function(expandable, refreshCallback, selectedCallba
{id: "size", title: WebInspector.UIString("Size"), sortable: true, align: WebInspector.DataGrid.Align.Right, weight: 7},
{id: "httpOnly", title: WebInspector.UIString("HTTP"), sortable: true, align: WebInspector.DataGrid.Align.Center, weight: 7},
{id: "secure", title: WebInspector.UIString("Secure"), sortable: true, align: WebInspector.DataGrid.Align.Center, weight: 7},
- {id: "firstPartyOnly", title: WebInspector.UIString("First-Party"), sortable: true, align: WebInspector.DataGrid.Align.Center, weight: 7}
+ {id: "sameSite", title: WebInspector.UIString("Same-Site"), sortable: true, align: WebInspector.DataGrid.Align.Center, weight: 7}
];
if (readOnly)
@@ -144,7 +144,7 @@ WebInspector.CookiesTable.prototype = {
for (var i = 0; i < this._data.length; ++i) {
var item = this._data[i];
if (item.folderName) {
- var groupData = {name: item.folderName, value: "", domain: "", path: "", expires: "", size: this._totalSize(item.cookies), httpOnly: "", secure: "", firstPartyOnly: ""};
+ var groupData = {name: item.folderName, value: "", domain: "", path: "", expires: "", size: this._totalSize(item.cookies), httpOnly: "", secure: "", sameSite: ""};
var groupNode = new WebInspector.DataGridNode(groupData);
groupNode.selectable = true;
this._dataGrid.rootNode().appendChild(groupNode);
@@ -227,7 +227,7 @@ WebInspector.CookiesTable.prototype = {
case "size": comparator = numberCompare.bind(null, WebInspector.Cookie.prototype.size); break;
case "httpOnly": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.httpOnly); break;
case "secure": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.secure); break;
- case "firstPartyOnly": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.firstPartyOnly); break;
+ case "sameSite": comparator = compareTo.bind(null, WebInspector.Cookie.prototype.sameSite); break;
default: compareTo.bind(null, WebInspector.Cookie.prototype.name);
}
@@ -261,7 +261,7 @@ WebInspector.CookiesTable.prototype = {
const checkmark = "\u2713";
data.httpOnly = (cookie.httpOnly() ? checkmark : "");
data.secure = (cookie.secure() ? checkmark : "");
- data.firstPartyOnly = (cookie.firstPartyOnly() ? checkmark : "");
+ data.sameSite = (cookie.sameSite() ? checkmark : "");
var node = new WebInspector.DataGridNode(data);
node.cookie = cookie;
diff --git a/front_end/console/ConsoleView.js b/front_end/console/ConsoleView.js
index 22d74a1d48..cef8e5226b 100644
--- a/front_end/console/ConsoleView.js
+++ b/front_end/console/ConsoleView.js
@@ -776,7 +776,7 @@ WebInspector.ConsoleView.prototype = {
* @param {?WebInspector.RemoteObject} result
* @param {boolean} wasThrown
* @param {!WebInspector.ConsoleMessage} originatingConsoleMessage
- * @param {?DebuggerAgent.ExceptionDetails=} exceptionDetails
+ * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails
*/
_printResult: function(result, wasThrown, originatingConsoleMessage, exceptionDetails)
{
@@ -788,7 +788,7 @@ WebInspector.ConsoleView.prototype = {
if (!wasThrown)
message = new WebInspector.ConsoleMessage(result.target(), WebInspector.ConsoleMessage.MessageSource.JS, level, "", WebInspector.ConsoleMessage.MessageType.Result, undefined, undefined, undefined, undefined, [result]);
else
- message = new WebInspector.ConsoleMessage(result.target(), WebInspector.ConsoleMessage.MessageSource.JS, level, exceptionDetails.text, WebInspector.ConsoleMessage.MessageType.Result, exceptionDetails.url, exceptionDetails.line, exceptionDetails.column, undefined, [WebInspector.UIString("Uncaught"), result], exceptionDetails.stackTrace, undefined, undefined, undefined, exceptionDetails.scriptId);
+ message = new WebInspector.ConsoleMessage(result.target(), WebInspector.ConsoleMessage.MessageSource.JS, level, exceptionDetails.text, WebInspector.ConsoleMessage.MessageType.Result, exceptionDetails.url, exceptionDetails.line, exceptionDetails.column, undefined, [WebInspector.UIString("Uncaught"), result], exceptionDetails.stack, undefined, undefined, exceptionDetails.scriptId);
message.setOriginatingMessage(originatingConsoleMessage);
result.target().consoleModel.addMessage(message);
},
diff --git a/front_end/console/ConsoleViewMessage.js b/front_end/console/ConsoleViewMessage.js
index 937afd0662..0de41e3f99 100644
--- a/front_end/console/ConsoleViewMessage.js
+++ b/front_end/console/ConsoleViewMessage.js
@@ -215,7 +215,7 @@ WebInspector.ConsoleViewMessage.prototype = {
} else {
var showBlackboxed = (consoleMessage.source !== WebInspector.ConsoleMessage.MessageSource.ConsoleAPI);
var debuggerModel = WebInspector.DebuggerModel.fromTarget(this._target());
- var callFrame = WebInspector.DebuggerPresentationUtils.callFrameAnchorFromStackTrace(debuggerModel, consoleMessage.stackTrace, consoleMessage.asyncStackTrace, showBlackboxed);
+ var callFrame = WebInspector.DebuggerPresentationUtils.callFrameAnchorFromStackTrace(debuggerModel, consoleMessage.stackTrace, showBlackboxed);
if (callFrame && callFrame.scriptId)
this._anchorElement = this._linkifyCallFrame(callFrame);
else if (consoleMessage.url && consoleMessage.url !== "undefined")
@@ -230,7 +230,7 @@ WebInspector.ConsoleViewMessage.prototype = {
this._formattedMessage.insertBefore(this._anchorElement, this._formattedMessage.firstChild);
}
- var dumpStackTrace = (!!consoleMessage.stackTrace || !!consoleMessage.asyncStackTrace) && (consoleMessage.source === WebInspector.ConsoleMessage.MessageSource.Network || consoleMessage.level === WebInspector.ConsoleMessage.MessageLevel.Error || consoleMessage.level === WebInspector.ConsoleMessage.MessageLevel.RevokedError || consoleMessage.type === WebInspector.ConsoleMessage.MessageType.Trace);
+ var dumpStackTrace = !!consoleMessage.stackTrace && (consoleMessage.source === WebInspector.ConsoleMessage.MessageSource.Network || consoleMessage.level === WebInspector.ConsoleMessage.MessageLevel.Error || consoleMessage.level === WebInspector.ConsoleMessage.MessageLevel.RevokedError || consoleMessage.type === WebInspector.ConsoleMessage.MessageType.Trace);
if (dumpStackTrace) {
var treeOutline = new TreeOutline();
treeOutline.element.classList.add("outline-disclosure", "outline-disclosure-no-padding");
@@ -276,7 +276,7 @@ WebInspector.ConsoleViewMessage.prototype = {
},
/**
- * @param {!ConsoleAgent.CallFrame} callFrame
+ * @param {!RuntimeAgent.CallFrame} callFrame
* @return {?Element}
*/
_linkifyCallFrame: function(callFrame)
@@ -1013,8 +1013,7 @@ WebInspector.ConsoleViewMessage.prototype = {
var target = this._target();
if (!target)
return;
- var content = WebInspector.DOMPresentationUtils.buildStackTracePreviewContents(target,
- this._linkifier, this._message.stackTrace, this._message.asyncStackTrace);
+ var content = WebInspector.DOMPresentationUtils.buildStackTracePreviewContents(target, this._linkifier, this._message.stackTrace);
var treeElement = new TreeElement(content);
treeElement.selectable = false;
parentTreeElement.appendChild(treeElement);
diff --git a/front_end/devtools.js b/front_end/devtools.js
index 05c2b25a38..643f939599 100644
--- a/front_end/devtools.js
+++ b/front_end/devtools.js
@@ -867,6 +867,105 @@ window.InspectorFrontendHost = new InspectorFrontendHostImpl();
// DevToolsApp ---------------------------------------------------------------
+function installObjectObserve()
+{
+ var properties = [
+ "advancedSearchConfig", "auditsPanelSplitViewState", "auditsSidebarWidth", "blockedURLs", "breakpoints", "cacheDisabled", "colorFormat", "consoleHistory",
+ "consoleTimestampsEnabled", "cpuProfilerView", "cssSourceMapsEnabled", "currentDockState", "customColorPalette", "customDevicePresets", "customEmulatedDeviceList",
+ "customFormatters", "customUserAgent", "databaseTableViewVisibleColumns", "dataGrid-cookiesTable", "dataGrid-DOMStorageItemsView", "debuggerSidebarHidden", "disableDataSaverInfobar",
+ "disablePausedStateOverlay", "domBreakpoints", "domWordWrap", "elementsPanelSplitViewState", "elementsSidebarWidth", "emulation.deviceHeight", "emulation.deviceModeValue",
+ "emulation.deviceOrientationOverride", "emulation.deviceScale", "emulation.deviceScaleFactor", "emulation.deviceUA", "emulation.deviceWidth", "emulation.geolocationOverride",
+ "emulation.showDeviceMode", "emulation.showRulers", "enableAsyncStackTraces", "eventListenerBreakpoints", "fileMappingEntries", "fileSystemMapping", "FileSystemViewSidebarWidth",
+ "fileSystemViewSplitViewState", "filterBar-consoleView", "filterBar-networkPanel", "filterBar-promisePane", "filterBar-timelinePanel", "frameViewerHideChromeWindow",
+ "heapSnapshotRetainersViewSize", "heapSnapshotSplitViewState", "hideCollectedPromises", "hideNetworkMessages", "highlightNodeOnHoverInOverlay", "highResolutionCpuProfiling",
+ "inlineVariableValues", "Inspector.drawerSplitView", "Inspector.drawerSplitViewState", "InspectorView.panelOrder", "InspectorView.screencastSplitView",
+ "InspectorView.screencastSplitViewState", "InspectorView.splitView", "InspectorView.splitViewState", "javaScriptDisabled", "jsSourceMapsEnabled", "lastActivePanel", "lastDockState",
+ "lastSelectedSourcesSidebarPaneTab", "lastSnippetEvaluationIndex", "layerDetailsSplitView", "layerDetailsSplitViewState", "layersPanelSplitViewState", "layersShowInternalLayers",
+ "layersSidebarWidth", "messageLevelFilters", "messageURLFilters", "monitoringXHREnabled", "navigatorGroupByFolder", "navigatorHidden", "networkColorCodeResourceTypes",
+ "networkConditions", "networkConditionsCustomProfiles", "networkHideDataURL", "networkLogColumnsVisibility", "networkLogLargeRows", "networkLogShowOverview",
+ "networkPanelSplitViewState", "networkRecordFilmStripSetting", "networkResourceTypeFilters", "networkShowPrimaryLoadWaterfall", "networkSidebarWidth", "openLinkHandler",
+ "pauseOnCaughtException", "pauseOnExceptionEnabled", "preserveConsoleLog", "prettyPrintInfobarDisabled", "previouslyViewedFiles", "profilesPanelSplitViewState",
+ "profilesSidebarWidth", "promiseStatusFilters", "recordAllocationStacks", "requestHeaderFilterSetting", "request-info-formData-category-expanded",
+ "request-info-general-category-expanded", "request-info-queryString-category-expanded", "request-info-requestHeaders-category-expanded",
+ "request-info-requestPayload-category-expanded", "request-info-responseHeaders-category-expanded", "resources", "resourcesLastSelectedItem", "resourcesPanelSplitViewState",
+ "resourcesSidebarWidth", "resourceViewTab", "savedURLs", "screencastEnabled", "scriptsPanelNavigatorSidebarWidth", "searchInContentScripts", "selectedAuditCategories",
+ "selectedColorPalette", "selectedProfileType", "shortcutPanelSwitch", "showAdvancedHeapSnapshotProperties", "showEventListenersForAncestors", "showFrameowkrListeners",
+ "showHeaSnapshotObjectsHiddenProperties", "showInheritedComputedStyleProperties", "showMediaQueryInspector", "showNativeFunctionsInJSProfile", "showUAShadowDOM",
+ "showWhitespacesInEditor", "sidebarPosition", "skipContentScripts", "skipStackFramesPattern", "sourceMapInfobarDisabled", "sourcesPanelDebuggerSidebarSplitViewState",
+ "sourcesPanelNavigatorSplitViewState", "sourcesPanelSplitSidebarRatio", "sourcesPanelSplitViewState", "sourcesSidebarWidth", "standardEmulatedDeviceList",
+ "StylesPaneSplitRatio", "stylesPaneSplitViewState", "textEditorAutocompletion", "textEditorAutoDetectIndent", "textEditorBracketMatching", "textEditorIndent",
+ "timelineCaptureFilmStrip", "timelineCaptureLayersAndPictures", "timelineCaptureMemory", "timelineCaptureNetwork", "timeline-details", "timelineEnableJSSampling",
+ "timelineOverviewMode", "timelinePanelDetailsSplitViewState", "timelinePanelRecorsSplitViewState", "timelinePanelTimelineStackSplitViewState", "timelinePerspective",
+ "timeline-split", "timelineTreeGroupBy", "timeline-view", "timelineViewMode", "uiTheme", "watchExpressions", "WebInspector.Drawer.lastSelectedView", "WebInspector.Drawer.showOnLoad",
+ "workspaceExcludedFolders", "workspaceFolderExcludePattern", "workspaceInfobarDisabled", "workspaceMappingInfobarDisabled", "xhrBreakpoints"];
+
+ /**
+ * @this {!{_storage: Object, _name: string}}
+ */
+ function settingRemove()
+ {
+ this._storage[this._name] = undefined;
+ }
+
+ function objectObserve(object, observer)
+ {
+ if (window["WebInspector"]) {
+ var settingPrototype = window["WebInspector"]["Setting"]["prototype"];
+ if (typeof settingPrototype["remove"] === "function")
+ settingPrototype["remove"] = settingRemove;
+ }
+
+ var changedProperties = new Set();
+ var scheduled = false;
+
+ function scheduleObserver()
+ {
+ if (!scheduled) {
+ scheduled = true;
+ setImmediate(callObserver);
+ }
+ }
+
+ function callObserver()
+ {
+ scheduled = false;
+ var changes = [];
+ changedProperties.forEach(function(name) { changes.push({name: name}); });
+ changedProperties.clear();
+ observer.call(null, changes);
+ }
+
+ var storage = new Map();
+
+ function defineProperty(property)
+ {
+ if (property in object) {
+ storage.set(property, object[property]);
+ delete object[property];
+ }
+
+ Object.defineProperty(object, property, {
+ get: function()
+ {
+ return storage.get(property);
+ },
+
+ set: function(value)
+ {
+ storage.set(property, value);
+ changedProperties.add(property);
+ scheduleObserver();
+ }
+ });
+ }
+
+ for (var i = 0; i < properties.length; ++i)
+ defineProperty(properties[i]);
+ }
+
+ window.Object.observe = objectObserve;
+}
+
/**
* @suppressGlobalPropertiesCheck
*/
@@ -875,6 +974,9 @@ function installBackwardsCompatibility()
if (window.location.search.indexOf("remoteFrontend") === -1)
return;
+ // Support for legacy (}
+ */
+ _setHeaderText: function(rule, newContent)
+ {
/**
* @param {!WebInspector.CSSRule} rule
* @param {!WebInspector.TextRange} oldSelectorRange
* @param {boolean} success
+ * @return {boolean}
* @this {WebInspector.StylePropertiesSection}
*/
- function finishCallback(rule, oldSelectorRange, success)
+ function updateSourceRanges(rule, oldSelectorRange, success)
{
if (success) {
var doesAffectSelectedNode = rule.matchingSelectors.length > 0;
@@ -1512,16 +1562,16 @@ WebInspector.StylePropertiesSection.prototype = {
this._parentPane._styleSheetRuleEdited(rule, oldSelectorRange, newSelectorRange);
this._parentPane._refreshUpdate(this);
}
-
- delete this._parentPane._userOperation;
- this._moveEditorFromSelector(moveDirection);
- this._editingSelectorCommittedForTest();
+ return true;
}
- // This gets deleted in finishOperationAndMoveEditor(), which is called both on success and failure.
- this._parentPane._userOperation = true;
+ if (!(rule instanceof WebInspector.CSSStyleRule))
+ return Promise.resolve(false);
+ var oldSelectorRange = rule.selectorRange();
+ if (!oldSelectorRange)
+ return Promise.resolve(false);
var selectedNode = this._parentPane.node();
- rule.setSelectorText(selectedNode ? selectedNode.id : 0, newContent, finishCallback.bind(this, rule, oldSelectorRange));
+ return rule.setSelectorText(selectedNode ? selectedNode.id : 0, newContent).then(updateSourceRanges.bind(this, rule, oldSelectorRange));
},
_editingSelectorCommittedForTest: function() { },
@@ -1559,7 +1609,11 @@ WebInspector.StylePropertiesSection.createRuleOriginNode = function(cssModel, li
return createTextNode("");
var firstMatchingIndex = rule.matchingSelectors && rule.matchingSelectors.length ? rule.matchingSelectors[0] : 0;
- var ruleLocation = rule.selectors[firstMatchingIndex].range;
+ var ruleLocation;
+ if (rule instanceof WebInspector.CSSStyleRule)
+ ruleLocation = rule.selectors[firstMatchingIndex].range;
+ else if (rule instanceof WebInspector.CSSKeyframeRule)
+ ruleLocation = rule.key().range;
var header = rule.styleSheetId ? cssModel.styleSheetHeaderForId(rule.styleSheetId) : null;
if (ruleLocation && rule.styleSheetId && header && header.resourceURL())
@@ -1732,6 +1786,109 @@ WebInspector.BlankStylePropertiesSection.prototype = {
__proto__: WebInspector.StylePropertiesSection.prototype
}
+/**
+ * @constructor
+ * @extends {WebInspector.StylePropertiesSection}
+ * @param {!WebInspector.StylesSidebarPane} stylesPane
+ * @param {!WebInspector.CSSStyleModel.MatchedStyleResult} matchedStyles
+ * @param {!WebInspector.CSSStyleDeclaration} style
+ */
+WebInspector.KeyframePropertiesSection = function(stylesPane, matchedStyles, style)
+{
+ WebInspector.StylePropertiesSection.call(this, stylesPane, matchedStyles, style);
+ this._selectorElement.className = "keyframe-key";
+}
+
+WebInspector.KeyframePropertiesSection.prototype = {
+ /**
+ * @override
+ * @return {string}
+ */
+ _headerText: function()
+ {
+ return this._style.parentRule.key().text;
+ },
+
+ /**
+ * @override
+ * @param {!WebInspector.CSSRule} rule
+ * @param {string} newContent
+ * @return {!Promise.}
+ */
+ _setHeaderText: function(rule, newContent)
+ {
+ /**
+ * @param {!WebInspector.CSSRule} rule
+ * @param {!WebInspector.TextRange} oldRange
+ * @param {boolean} success
+ * @return {boolean}
+ * @this {WebInspector.KeyframePropertiesSection}
+ */
+ function updateSourceRanges(rule, oldRange, success)
+ {
+ if (success) {
+ var newRange = /** @type {!WebInspector.TextRange} */(rule.key().range);
+ rule.style.sourceStyleSheetEdited(/** @type {string} */(rule.styleSheetId), oldRange, newRange);
+ this._parentPane._styleSheetRuleEdited(rule, oldRange, newRange);
+ this._parentPane._refreshUpdate(this);
+ }
+ return true;
+ }
+
+ if (!(rule instanceof WebInspector.CSSKeyframeRule))
+ return Promise.resolve(false);
+ var oldRange = rule.key().range;
+ if (!oldRange)
+ return Promise.resolve(false);
+ var selectedNode = this._parentPane.node();
+ return rule.setKeyText(newContent).then(updateSourceRanges.bind(this, rule, oldRange));
+ },
+
+ /**
+ * @override
+ * @param {string} propertyName
+ * @return {boolean}
+ */
+ isPropertyInherited: function(propertyName)
+ {
+ return false;
+ },
+
+ /**
+ * @override
+ * @param {!WebInspector.CSSProperty} property
+ * @return {boolean}
+ */
+ _isPropertyOverloaded: function(property)
+ {
+ return false;
+ },
+
+ /**
+ * @override
+ */
+ _markSelectorHighlights: function()
+ {
+ },
+
+ /**
+ * @override
+ */
+ _markSelectorMatches: function()
+ {
+ this._selectorElement.textContent = this._style.parentRule.key().text;
+ },
+
+ /**
+ * @override
+ */
+ _highlight: function()
+ {
+ },
+
+ __proto__: WebInspector.StylePropertiesSection.prototype
+}
+
/**
* @constructor
* @extends {TreeElement}
@@ -2274,7 +2431,7 @@ WebInspector.StylePropertyTreeElement.prototype = {
if (!isEditingName && this._parentPane._mouseDownTreeElementIsName)
moveDirection = "backward";
}
- this.editingCommitted(event.target.textContent, context, moveDirection);
+ this.editingCommitted((context.isEditingName ? this.name : this.value) || event.target.textContent, context, moveDirection);
}
this._originalPropertyText = this.property.propertyText;
diff --git a/front_end/elements/elementsPanel.css b/front_end/elements/elementsPanel.css
index ca1ca3d77d..c7347bf0ca 100644
--- a/front_end/elements/elementsPanel.css
+++ b/front_end/elements/elementsPanel.css
@@ -260,7 +260,7 @@
color: #888;
}
-.styles-section .simple-selector.selector-matches {
+.styles-section .simple-selector.selector-matches, .styles-section.keyframe-key {
color: #222;
}
diff --git a/front_end/elements/elementsTreeOutline.css b/front_end/elements/elementsTreeOutline.css
index 908698b9bc..7f6252be03 100644
--- a/front_end/elements/elementsTreeOutline.css
+++ b/front_end/elements/elementsTreeOutline.css
@@ -28,7 +28,8 @@
.elements-disclosure li.selected:after {
font-style: italic;
content: " == $0";
- color: #555;
+ color: black;
+ opacity: 0.6;
}
.elements-disclosure ol:focus li.selected:after {
diff --git a/front_end/emulation/DeviceModeModel.js b/front_end/emulation/DeviceModeModel.js
index 3ab03939ba..6ff51ae000 100644
--- a/front_end/emulation/DeviceModeModel.js
+++ b/front_end/emulation/DeviceModeModel.js
@@ -18,7 +18,6 @@ WebInspector.DeviceModeModel = function(updateCallback)
this._deviceMetricsThrottler = new WebInspector.Throttler(0);
this._appliedDeviceSize = new Size(1, 1);
this._currentDeviceScaleFactor = window.devicePixelRatio;
- this._appliedDeviceScaleFactor = 0;
this._scaleSetting = WebInspector.settings.createSetting("emulation.deviceScale", 1);
// We've used to allow zero before.
@@ -86,24 +85,24 @@ WebInspector.DeviceModeModel.MaxDeviceSize = 9999;
/**
* @param {string} value
- * @return {string}
+ * @return {boolean}
*/
WebInspector.DeviceModeModel.deviceSizeValidator = function(value)
{
if (/^[\d]+$/.test(value) && value >= WebInspector.DeviceModeModel.MinDeviceSize && value <= WebInspector.DeviceModeModel.MaxDeviceSize)
- return "";
- return WebInspector.UIString("Value must be positive integer");
+ return true;
+ return false;
}
/**
* @param {string} value
- * @return {string}
+ * @return {boolean}
*/
WebInspector.DeviceModeModel.deviceScaleFactorValidator = function(value)
{
if (!value || (/^[\d]+(\.\d+)?|\.\d+$/.test(value) && value >= 0 && value <= 10))
- return "";
- return WebInspector.UIString("Value must be non-negative float");
+ return true;
+ return false;
}
WebInspector.DeviceModeModel._touchEventsScriptIdSymbol = Symbol("DeviceModeModel.touchEventsScriptIdSymbol");
@@ -283,14 +282,6 @@ WebInspector.DeviceModeModel.prototype = {
return !this._heightSetting.get();
},
- /**
- * @return {number}
- */
- appliedDeviceScaleFactor: function()
- {
- return this._appliedDeviceScaleFactor;
- },
-
/**
* @return {!WebInspector.Setting}
*/
@@ -384,11 +375,6 @@ WebInspector.DeviceModeModel.prototype = {
this._target = null;
},
- requestAppBanner: function()
- {
- this._target.pageAgent().requestAppBanner();
- },
-
_scaleSettingChanged: function()
{
this._calculateAndEmulate(true);
@@ -528,7 +514,6 @@ WebInspector.DeviceModeModel.prototype = {
Math.min(pageWidth * scale, this._availableSize.width - this._screenRect.left - positionX * scale),
Math.min(pageHeight * scale, this._availableSize.height - this._screenRect.top - positionY * scale));
this._scale = scale;
- this._appliedDeviceScaleFactor = deviceScaleFactor;
if (scale === 1 && this._availableSize.width >= screenSize.width && this._availableSize.height >= screenSize.height) {
// When we have enough space, no page size override is required. This will speed things up and remove lag.
@@ -553,12 +538,13 @@ WebInspector.DeviceModeModel.prototype = {
return Promise.resolve();
var clear = !pageWidth && !pageHeight && !mobile && !deviceScaleFactor && scale === 1;
+ var allPromises = [];
+ if (resetPageScaleFactor)
+ allPromises.push(this._target.emulationAgent().resetPageScaleFactor());
var setDevicePromise = clear ?
this._target.emulationAgent().clearDeviceMetricsOverride(this._deviceMetricsOverrideAppliedForTest.bind(this)) :
this._target.emulationAgent().setDeviceMetricsOverride(pageWidth, pageHeight, deviceScaleFactor, mobile, false, scale, 0, 0, screenSize.width, screenSize.height, positionX, positionY, this._deviceMetricsOverrideAppliedForTest.bind(this));
- var allPromises = [ setDevicePromise ];
- if (resetPageScaleFactor)
- allPromises.push(this._target.emulationAgent().resetPageScaleFactor());
+ allPromises.push(setDevicePromise);
return Promise.all(allPromises);
}
},
diff --git a/front_end/emulation/DeviceModeToolbar.js b/front_end/emulation/DeviceModeToolbar.js
new file mode 100644
index 0000000000..cfce4c79d1
--- /dev/null
+++ b/front_end/emulation/DeviceModeToolbar.js
@@ -0,0 +1,518 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @param {!WebInspector.DeviceModeModel} model
+ * @param {!WebInspector.Setting} showMediaInspectorSetting
+ * @param {!WebInspector.Setting} showRulersSetting
+ * @constructor
+ */
+WebInspector.DeviceModeToolbar = function(model, showMediaInspectorSetting, showRulersSetting)
+{
+ this._model = model;
+ this._showMediaInspectorSetting = showMediaInspectorSetting;
+ this._showRulersSetting = showRulersSetting;
+ /** @type {!Map} */
+ this._lastMode = new Map();
+
+ this._element = createElementWithClass("div", "device-mode-toolbar");
+
+ var leftContainer = this._element.createChild("div", "device-mode-toolbar-spacer");
+ leftContainer.createChild("div", "device-mode-toolbar-spacer");
+ var leftToolbar = new WebInspector.Toolbar("", leftContainer);
+ leftToolbar.makeWrappable();
+ this._fillLeftToolbar(leftToolbar);
+
+ var mainToolbar = new WebInspector.Toolbar("", this._element);
+ mainToolbar.makeWrappable();
+ this._fillMainToolbar(mainToolbar);
+
+ var rightContainer = this._element.createChild("div", "device-mode-toolbar-spacer");
+ var rightToolbar = new WebInspector.Toolbar("device-mode-toolbar-fixed-size", rightContainer);
+ rightToolbar.makeWrappable();
+ this._fillRightToolbar(rightToolbar);
+ var modeToolbar = new WebInspector.Toolbar("device-mode-toolbar-fixed-size", rightContainer);
+ modeToolbar.makeWrappable();
+ this._fillModeToolbar(modeToolbar);
+ rightContainer.createChild("div", "device-mode-toolbar-spacer");
+ var optionsToolbar = new WebInspector.Toolbar("", rightContainer);
+ optionsToolbar.makeWrappable(true);
+ this._fillOptionsToolbar(optionsToolbar);
+
+ WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.CustomDevicesUpdated, this._deviceListChanged, this);
+ WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.StandardDevicesUpdated, this._deviceListChanged, this);
+
+ this._persistenceSetting = WebInspector.settings.createSetting("emulation.deviceModeValue", {device: "", orientation: "", mode: ""});
+}
+
+WebInspector.DeviceModeToolbar.prototype = {
+ /**
+ * @param {!WebInspector.Toolbar} toolbar
+ */
+ _fillLeftToolbar: function(toolbar)
+ {
+ toolbar.appendToolbarItem(this._wrapToolbarItem(createElementWithClass("div", "device-mode-empty-toolbar-element")));
+ this._deviceSelectItem = new WebInspector.ToolbarMenuButton(this._appendDeviceMenuItems.bind(this));
+ this._deviceSelectItem.setGlyph("");
+ this._deviceSelectItem.turnIntoSelect(95);
+ toolbar.appendToolbarItem(this._deviceSelectItem);
+ },
+
+ /**
+ * @param {!WebInspector.Toolbar} toolbar
+ */
+ _fillMainToolbar: function(toolbar)
+ {
+ var widthInput = createElementWithClass("input", "device-mode-size-input");
+ widthInput.maxLength = 4;
+ widthInput.type = "text";
+ widthInput.title = WebInspector.UIString("Width");
+ this._updateWidthInput = WebInspector.bindInput(widthInput, applyWidth.bind(this), WebInspector.DeviceModeModel.deviceSizeValidator, true);
+ this._widthInput = widthInput;
+ this._widthItem = this._wrapToolbarItem(widthInput);
+ toolbar.appendToolbarItem(this._widthItem);
+
+ var xElement = createElementWithClass("div", "device-mode-x");
+ xElement.textContent = "\u00D7";
+ this._xItem = this._wrapToolbarItem(xElement);
+ toolbar.appendToolbarItem(this._xItem);
+
+ var heightInput = createElementWithClass("input", "device-mode-size-input");
+ heightInput.maxLength = 4;
+ heightInput.type = "text";
+ heightInput.title = WebInspector.UIString("Height (leave empty for full)");
+ this._updateHeightInput = WebInspector.bindInput(heightInput, applyHeight.bind(this), validateHeight, true);
+ this._heightInput = heightInput;
+ this._heightItem = this._wrapToolbarItem(heightInput);
+ toolbar.appendToolbarItem(this._heightItem);
+
+ /**
+ * @param {string} value
+ * @return {boolean}
+ */
+ function validateHeight(value)
+ {
+ return !value || WebInspector.DeviceModeModel.deviceSizeValidator(value);
+ }
+
+ /**
+ * @param {string} value
+ * @this {WebInspector.DeviceModeToolbar}
+ */
+ function applyWidth(value)
+ {
+ var width = value ? Number(value) : 0;
+ this._model.setWidthAndScaleToFit(width);
+ }
+
+ /**
+ * @param {string} value
+ * @this {WebInspector.DeviceModeToolbar}
+ */
+ function applyHeight(value)
+ {
+ var height = value ? Number(value) : 0;
+ this._model.setHeightAndScaleToFit(height);
+ }
+ },
+
+ /**
+ * @param {!WebInspector.Toolbar} toolbar
+ */
+ _fillRightToolbar: function(toolbar)
+ {
+ toolbar.appendToolbarItem(this._wrapToolbarItem(createElementWithClass("div", "device-mode-empty-toolbar-element")));
+ this._scaleItem = new WebInspector.ToolbarMenuButton(this._appendScaleMenuItems.bind(this));
+ this._scaleItem.setTitle(WebInspector.UIString("Zoom"));
+ this._scaleItem.setGlyph("");
+ this._scaleItem.turnIntoSelect();
+ toolbar.appendToolbarItem(this._scaleItem);
+ },
+
+ /**
+ * @param {!WebInspector.Toolbar} toolbar
+ */
+ _fillModeToolbar: function(toolbar)
+ {
+ toolbar.appendToolbarItem(this._wrapToolbarItem(createElementWithClass("div", "device-mode-empty-toolbar-element")));
+ this._modeButton = new WebInspector.ToolbarButton("", "rotate-screen-toolbar-item");
+ this._modeButton.addEventListener("click", this._modeMenuClicked, this);
+ toolbar.appendToolbarItem(this._modeButton);
+ },
+
+ /**
+ * @param {!WebInspector.Toolbar} toolbar
+ */
+ _fillOptionsToolbar: function(toolbar)
+ {
+ this._uaItem = new WebInspector.ToolbarText();
+ this._uaItem.setVisible(false);
+ this._uaItem.setTitle(WebInspector.UIString("User agent type"));
+ this._uaItem.element.style.opacity = "0.5";
+ toolbar.appendToolbarItem(this._uaItem);
+
+ this._deviceScaleItem = new WebInspector.ToolbarText();
+ this._deviceScaleItem.setVisible(false);
+ this._deviceScaleItem.setTitle(WebInspector.UIString("Device pixel ratio"));
+ this._deviceScaleItem.element.style.opacity = "0.5";
+ toolbar.appendToolbarItem(this._deviceScaleItem);
+
+ var moreOptionsButton = new WebInspector.ToolbarMenuButton(this._appendOptionsMenuItems.bind(this));
+ moreOptionsButton.setTitle(WebInspector.UIString("More options"));
+ toolbar.appendToolbarItem(moreOptionsButton);
+
+ toolbar.appendToolbarItem(this._wrapToolbarItem(createElementWithClass("div", "device-mode-empty-toolbar-element")));
+ },
+
+
+ /**
+ * @param {!WebInspector.ContextMenu} contextMenu
+ */
+ _appendScaleMenuItems: function(contextMenu)
+ {
+ var scaleSetting = this._model.scaleSetting();
+ if (this._model.type() === WebInspector.DeviceModeModel.Type.Device) {
+ contextMenu.appendItem(WebInspector.UIString("Fit to window (%.0f%%)", this._model.fitScale() * 100), scaleSetting.set.bind(scaleSetting, this._model.fitScale()), false);
+ contextMenu.appendSeparator();
+ }
+ appendScaleItem(WebInspector.UIString("50%"), 0.5);
+ appendScaleItem(WebInspector.UIString("75%"), 0.75);
+ appendScaleItem(WebInspector.UIString("100%"), 1);
+ appendScaleItem(WebInspector.UIString("125%"), 1.25);
+ appendScaleItem(WebInspector.UIString("150%"), 1.5);
+
+ /**
+ * @param {string} title
+ * @param {number} value
+ */
+ function appendScaleItem(title, value)
+ {
+ contextMenu.appendCheckboxItem(title, scaleSetting.set.bind(scaleSetting, value), scaleSetting.get() === value, false);
+ }
+ },
+
+ /**
+ * @param {!WebInspector.ContextMenu} contextMenu
+ */
+ _appendOptionsMenuItems: function(contextMenu)
+ {
+ var uaDisabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive;
+ var uaSetting = this._model.uaSetting();
+ var uaSubmenu = contextMenu.appendSubMenuItem(WebInspector.UIString("User agent type"), false);
+ var uaValue = this._model.uaSetting().get();
+ if (this._model.type() === WebInspector.DeviceModeModel.Type.None)
+ uaValue = WebInspector.DeviceModeModel.UA.Desktop;
+ if (this._model.type() === WebInspector.DeviceModeModel.Type.Device)
+ uaValue = this._model.device().mobile() ? WebInspector.DeviceModeModel.UA.Mobile : this._model.device().touch() ? WebInspector.DeviceModeModel.UA.DesktopTouch : WebInspector.DeviceModeModel.UA.Desktop;
+ appendUAItem(WebInspector.UIString("Mobile (default)"), WebInspector.DeviceModeModel.UA.Mobile);
+ appendUAItem(WebInspector.UIString("Desktop"), WebInspector.DeviceModeModel.UA.Desktop);
+ appendUAItem(WebInspector.UIString("Desktop with touch"), WebInspector.DeviceModeModel.UA.DesktopTouch);
+
+ /**
+ * @param {string} title
+ * @param {!WebInspector.DeviceModeModel.UA} value
+ */
+ function appendUAItem(title, value)
+ {
+ uaSubmenu.appendCheckboxItem(title, uaSetting.set.bind(uaSetting, value), uaValue === value, uaDisabled);
+ }
+
+ var deviceScaleFactorDisabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive;
+ var deviceScaleFactorSubmenu = contextMenu.appendSubMenuItem(WebInspector.UIString("Device pixel ratio"), false);
+ var deviceScaleFactorSetting = this._model.deviceScaleFactorSetting();
+ var deviceScaleFactorValue = deviceScaleFactorDisabled ? 0 : deviceScaleFactorSetting.get();
+ appendDeviceScaleFactorItem(WebInspector.UIString("Default: %f", this._model.defaultDeviceScaleFactor()), 0);
+ deviceScaleFactorSubmenu.appendSeparator();
+ appendDeviceScaleFactorItem(WebInspector.UIString("1"), 1);
+ appendDeviceScaleFactorItem(WebInspector.UIString("2"), 2);
+ appendDeviceScaleFactorItem(WebInspector.UIString("3"), 3);
+
+ /**
+ * @param {string} title
+ * @param {number} value
+ */
+ function appendDeviceScaleFactorItem(title, value)
+ {
+ deviceScaleFactorSubmenu.appendCheckboxItem(title, deviceScaleFactorSetting.set.bind(deviceScaleFactorSetting, value), deviceScaleFactorValue === value, deviceScaleFactorDisabled);
+ }
+
+ contextMenu.appendItem(WebInspector.UIString("Reset to defaults"), this._model.reset.bind(this._model), this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive);
+ contextMenu.appendSeparator();
+
+ contextMenu.appendCheckboxItem(WebInspector.UIString("Show media queries"), this._toggleMediaInspector.bind(this), this._showMediaInspectorSetting.get(), this._model.type() === WebInspector.DeviceModeModel.Type.None);
+ contextMenu.appendCheckboxItem(WebInspector.UIString("Show rulers"), this._toggleRulers.bind(this), this._showRulersSetting.get(), this._model.type() === WebInspector.DeviceModeModel.Type.None);
+ contextMenu.appendItem(WebInspector.UIString("Configure network\u2026"), this._openNetworkConfig.bind(this), false);
+ contextMenu.appendItemsAtLocation("deviceModeMenu");
+ },
+
+ _toggleMediaInspector: function()
+ {
+ this._showMediaInspectorSetting.set(!this._showMediaInspectorSetting.get());
+ },
+
+ _toggleRulers: function()
+ {
+ this._showRulersSetting.set(!this._showRulersSetting.get());
+ },
+
+ _openNetworkConfig: function()
+ {
+ InspectorFrontendHost.bringToFront();
+ // TODO(dgozman): make it explicit.
+ WebInspector.actionRegistry.action("network.show-config").execute();
+ },
+
+ /**
+ * @param {!Element} element
+ * @return {!WebInspector.ToolbarItem}
+ */
+ _wrapToolbarItem: function(element)
+ {
+ var container = createElement("div");
+ var shadowRoot = WebInspector.createShadowRootWithCoreStyles(container, "emulation/deviceModeToolbar.css");
+ shadowRoot.appendChild(element);
+ return new WebInspector.ToolbarItem(container);
+ },
+
+ /**
+ * @param {!WebInspector.EmulatedDevice} device
+ */
+ _emulateDevice: function(device)
+ {
+ this._model.emulate(WebInspector.DeviceModeModel.Type.Device, device, this._lastMode.get(device) || device.modes[0]);
+ },
+
+ _switchToResponsive: function()
+ {
+ this._model.emulate(WebInspector.DeviceModeModel.Type.Responsive, null, null);
+ },
+
+ /**
+ * @param {!Array} devices
+ * @return {!Array}
+ */
+ _filterDevices: function(devices)
+ {
+ devices = devices.filter(function(d) { return d.show(); });
+ devices.sort(WebInspector.EmulatedDevice.deviceComparator);
+ return devices;
+ },
+
+ /**
+ * @return {!Array}
+ */
+ _standardDevices: function()
+ {
+ return this._filterDevices(WebInspector.emulatedDevicesList.standard());
+ },
+
+ /**
+ * @return {!Array}
+ */
+ _customDevices: function()
+ {
+ return this._filterDevices(WebInspector.emulatedDevicesList.custom());
+ },
+
+ /**
+ * @return {!Array}
+ */
+ _allDevices: function()
+ {
+ return this._standardDevices().concat(this._customDevices());
+ },
+
+ /**
+ * @param {!WebInspector.ContextMenu} contextMenu
+ */
+ _appendDeviceMenuItems: function(contextMenu)
+ {
+ contextMenu.appendCheckboxItem(WebInspector.UIString("Responsive"), this._switchToResponsive.bind(this), this._model.type() === WebInspector.DeviceModeModel.Type.Responsive, false);
+ appendGroup.call(this, this._standardDevices());
+ appendGroup.call(this, this._customDevices());
+ contextMenu.appendSeparator();
+ contextMenu.appendItem(WebInspector.UIString("Edit\u2026"), WebInspector.emulatedDevicesList.revealCustomSetting.bind(WebInspector.emulatedDevicesList), false);
+
+ /**
+ * @param {!Array} devices
+ * @this {WebInspector.DeviceModeToolbar}
+ */
+ function appendGroup(devices)
+ {
+ if (!devices.length)
+ return;
+ contextMenu.appendSeparator();
+ for (var device of devices)
+ contextMenu.appendCheckboxItem(device.title, this._emulateDevice.bind(this, device), this._model.device() === device, false);
+ }
+ },
+
+ /**
+ * @this {WebInspector.DeviceModeToolbar}
+ */
+ _deviceListChanged: function()
+ {
+ if (!this._model.device())
+ return;
+
+ var devices = this._allDevices();
+ if (devices.indexOf(this._model.device()) === -1) {
+ if (devices.length)
+ this._emulateDevice(devices[0]);
+ else
+ this._model.emulate(WebInspector.DeviceModeModel.Type.Responsive, null, null);
+ }
+ },
+
+ /**
+ * @param {!WebInspector.Event} event
+ */
+ _modeMenuClicked: function(event)
+ {
+ var device = this._model.device();
+ var model = this._model;
+
+ if (device.modes.length === 2 && device.modes[0].orientation !== device.modes[1].orientation) {
+ model.emulate(model.type(), model.device(), model.mode() === device.modes[0] ? device.modes[1] : device.modes[0]);
+ return;
+ }
+
+ var contextMenu = new WebInspector.ContextMenu(/** @type {!Event} */ (event.data),
+ false,
+ event.target.element.totalOffsetLeft(),
+ event.target.element.totalOffsetTop() + event.target.element.offsetHeight);
+ addOrientation(WebInspector.EmulatedDevice.Vertical, WebInspector.UIString("Portrait"));
+ addOrientation(WebInspector.EmulatedDevice.Horizontal, WebInspector.UIString("Landscape"));
+ contextMenu.show();
+
+ /**
+ * @param {string} orientation
+ * @param {string} title
+ */
+ function addOrientation(orientation, title)
+ {
+ var modes = device.modesForOrientation(orientation);
+ if (!modes.length)
+ return;
+ if (modes.length === 1) {
+ addMode(modes[0], title);
+ } else {
+ for (var index = 0; index < modes.length; index++)
+ addMode(modes[index], title + " \u2013 " + modes[index].title);
+ }
+ }
+
+ /**
+ * @param {!WebInspector.EmulatedDevice.Mode} mode
+ * @param {string} title
+ */
+ function addMode(mode, title)
+ {
+ contextMenu.appendCheckboxItem(title, applyMode.bind(null, mode), model.mode() === mode, false);
+ }
+
+ /**
+ * @param {!WebInspector.EmulatedDevice.Mode} mode
+ */
+ function applyMode(mode)
+ {
+ model.emulate(model.type(), model.device(), mode);
+ }
+ },
+
+ /**
+ * @return {!Element}
+ */
+ element: function()
+ {
+ return this._element;
+ },
+
+ update: function()
+ {
+ if (this._model.type() !== this._cachedModelType) {
+ this._cachedModelType = this._model.type();
+ this._widthInput.disabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive;
+ this._heightInput.disabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive;
+ }
+
+ var size = this._model.appliedDeviceSize();
+ this._updateHeightInput(this._model.type() === WebInspector.DeviceModeModel.Type.Responsive && this._model.isFullHeight() ? "" : String(size.height));
+ this._updateWidthInput(String(size.width));
+ this._heightInput.placeholder = size.height;
+
+ if (this._model.scale() !== this._cachedScale) {
+ this._scaleItem.setText(WebInspector.UIString("%.0f%%", this._model.scale() * 100));
+ this._scaleItem.setState(this._model.scale() === 1 ? "off" : "on");
+ this._cachedScale = this._model.scale();
+ }
+
+ var deviceScale = this._model.deviceScaleFactorSetting().get();
+ this._deviceScaleItem.setVisible(this._model.type() === WebInspector.DeviceModeModel.Type.Responsive && !!deviceScale);
+ if (deviceScale !== this._cachedDeviceScale) {
+ this._deviceScaleItem.setText(WebInspector.UIString("DPR: %.1f", deviceScale));
+ this._cachedDeviceScale = deviceScale;
+ }
+
+ var uaType = this._model.type() === WebInspector.DeviceModeModel.Type.Responsive ? this._model.uaSetting().get() : WebInspector.DeviceModeModel.UA.Mobile;
+ this._uaItem.setVisible(this._model.type() === WebInspector.DeviceModeModel.Type.Responsive && uaType !== WebInspector.DeviceModeModel.UA.Mobile);
+ if (uaType !== this._cachedUaType) {
+ this._uaItem.setText(uaType === WebInspector.DeviceModeModel.UA.Desktop ? WebInspector.UIString("Desktop") : WebInspector.UIString("Touch"));
+ this._cachedUaType = uaType;
+ }
+
+ var deviceItemTitle = WebInspector.UIString("None");
+ if (this._model.type() === WebInspector.DeviceModeModel.Type.Responsive)
+ deviceItemTitle = WebInspector.UIString("Responsive");
+ if (this._model.type() === WebInspector.DeviceModeModel.Type.Device)
+ deviceItemTitle = this._model.device().title;
+ this._deviceSelectItem.setText(deviceItemTitle);
+
+ if (this._model.device() !== this._cachedModelDevice) {
+ var device = this._model.device();
+ this._modeButton.setVisible(!!device);
+ if (device) {
+ var modeCount = device ? device.modes.length : 0;
+ this._modeButton.setEnabled(modeCount >= 2);
+ this._modeButton.setTitle(modeCount === 2 ? WebInspector.UIString("Rotate") : WebInspector.UIString("Screen options"));
+ }
+ this._cachedModelDevice = device;
+ }
+
+ if (this._model.type() === WebInspector.DeviceModeModel.Type.Device)
+ this._lastMode.set(/** @type {!WebInspector.EmulatedDevice} */ (this._model.device()), /** @type {!WebInspector.EmulatedDevice.Mode} */ (this._model.mode()));
+
+ if (this._model.mode() !== this._cachedModelMode && this._model.type() !== WebInspector.DeviceModeModel.Type.None) {
+ this._cachedModelMode = this._model.mode();
+ var value = this._persistenceSetting.get();
+ if (this._model.device()) {
+ value.device = this._model.device().title;
+ value.orientation = this._model.mode() ? this._model.mode().orientation : "";
+ value.mode = this._model.mode() ? this._model.mode().title : "";
+ } else {
+ value.device = "";
+ value.orientation = "";
+ value.mode = "";
+ }
+ this._persistenceSetting.set(value);
+ }
+ },
+
+ restore: function()
+ {
+ for (var device of this._allDevices()) {
+ if (device.title === this._persistenceSetting.get().device) {
+ for (var mode of device.modes) {
+ if (mode.orientation === this._persistenceSetting.get().orientation && mode.title === this._persistenceSetting.get().mode) {
+ this._lastMode.set(device, mode);
+ this._emulateDevice(device);
+ return;
+ }
+ }
+ }
+ }
+
+ this._model.emulate(WebInspector.DeviceModeModel.Type.Responsive, null, null);
+ }
+}
diff --git a/front_end/emulation/DeviceModeView.js b/front_end/emulation/DeviceModeView.js
index da378087ea..bea33bc619 100644
--- a/front_end/emulation/DeviceModeView.js
+++ b/front_end/emulation/DeviceModeView.js
@@ -33,7 +33,7 @@ WebInspector.DeviceModeView = function()
WebInspector.DeviceModeView.prototype = {
_createUI: function()
{
- this._toolbar = new WebInspector.DeviceModeView.Toolbar(this._model, this._showMediaInspectorSetting, this._showRulersSetting);
+ this._toolbar = new WebInspector.DeviceModeToolbar(this._model, this._showMediaInspectorSetting, this._showRulersSetting);
this.contentElement.appendChild(this._toolbar.element());
this._contentClip = this.contentElement.createChild("div", "device-mode-content-clip vbox");
@@ -47,19 +47,27 @@ WebInspector.DeviceModeView.prototype = {
this._screenImage.addEventListener("load", this._onScreenImageLoaded.bind(this, true), false);
this._screenImage.addEventListener("error", this._onScreenImageLoaded.bind(this, false), false);
- this._cornerResizerElement = this._screenArea.createChild("div", "device-mode-resizer device-mode-corner-resizer");
- this._cornerResizerElement.createChild("div", "");
- this._createResizer(this._cornerResizerElement, true, true);
+ this._bottomRightResizerElement = this._screenArea.createChild("div", "device-mode-resizer device-mode-bottom-right-resizer");
+ this._bottomRightResizerElement.createChild("div", "");
+ this._createResizer(this._bottomRightResizerElement, 2, 1);
- this._widthResizerElement = this._screenArea.createChild("div", "device-mode-resizer device-mode-width-resizer");
- this._widthResizerElement.createChild("div", "");
- this._createResizer(this._widthResizerElement, true, false);
+ this._bottomLeftResizerElement = this._screenArea.createChild("div", "device-mode-resizer device-mode-bottom-left-resizer");
+ this._bottomLeftResizerElement.createChild("div", "");
+ this._createResizer(this._bottomLeftResizerElement, -2, 1);
- this._heightResizerElement = this._screenArea.createChild("div", "device-mode-resizer device-mode-height-resizer");
- this._heightResizerElement.createChild("div", "");
- this._createResizer(this._heightResizerElement, false, true);
- this._heightResizerElement.addEventListener("dblclick", this._model.setHeight.bind(this._model, 0), false);
- this._heightResizerElement.title = WebInspector.UIString("Double-click for full height");
+ this._rightResizerElement = this._screenArea.createChild("div", "device-mode-resizer device-mode-right-resizer");
+ this._rightResizerElement.createChild("div", "");
+ this._createResizer(this._rightResizerElement, 2, 0);
+
+ this._leftResizerElement = this._screenArea.createChild("div", "device-mode-resizer device-mode-left-resizer");
+ this._leftResizerElement.createChild("div", "");
+ this._createResizer(this._leftResizerElement, -2, 0);
+
+ this._bottomResizerElement = this._screenArea.createChild("div", "device-mode-resizer device-mode-bottom-resizer");
+ this._bottomResizerElement.createChild("div", "");
+ this._createResizer(this._bottomResizerElement, 0, 1);
+ this._bottomResizerElement.addEventListener("dblclick", this._model.setHeight.bind(this._model, 0), false);
+ this._bottomResizerElement.title = WebInspector.UIString("Double-click for full height");
this._pageArea = this._screenArea.createChild("div", "device-mode-page-area");
this._pageArea.createChild("content");
@@ -106,17 +114,22 @@ WebInspector.DeviceModeView.prototype = {
/**
* @param {!Element} element
- * @param {boolean} width
- * @param {boolean} height
+ * @param {number} widthFactor
+ * @param {number} heightFactor
* @return {!WebInspector.ResizerWidget}
*/
- _createResizer: function(element, width, height)
+ _createResizer: function(element, widthFactor, heightFactor)
{
var resizer = new WebInspector.ResizerWidget();
resizer.addElement(element);
- resizer.setCursor(width && height ? "nwse-resize" : (width ? "ew-resize" : "ns-resize"));
+ var cursor = widthFactor ? "ew-resize" : "ns-resize";
+ if (widthFactor * heightFactor > 0)
+ cursor = "nwse-resize";
+ if (widthFactor * heightFactor < 0)
+ cursor = "nesw-resize";
+ resizer.setCursor(cursor);
resizer.addEventListener(WebInspector.ResizerWidget.Events.ResizeStart, this._onResizeStart, this);
- resizer.addEventListener(WebInspector.ResizerWidget.Events.ResizeUpdate, this._onResizeUpdate.bind(this, width, height));
+ resizer.addEventListener(WebInspector.ResizerWidget.Events.ResizeUpdate, this._onResizeUpdate.bind(this, widthFactor, heightFactor));
resizer.addEventListener(WebInspector.ResizerWidget.Events.ResizeEnd, this._onResizeEnd, this);
return resizer;
},
@@ -132,11 +145,11 @@ WebInspector.DeviceModeView.prototype = {
},
/**
- * @param {boolean} width
- * @param {boolean} height
+ * @param {number} widthFactor
+ * @param {number} heightFactor
* @param {!WebInspector.Event} event
*/
- _onResizeUpdate: function(width, height, event)
+ _onResizeUpdate: function(widthFactor, heightFactor, event)
{
if (event.data.shiftKey !== !!this._slowPositionStart)
this._slowPositionStart = event.data.shiftKey ? {x: event.data.currentX, y: event.data.currentY} : null;
@@ -148,17 +161,17 @@ WebInspector.DeviceModeView.prototype = {
cssOffsetY = (event.data.currentY - this._slowPositionStart.y) / 10 + this._slowPositionStart.y - event.data.startY;
}
- if (width) {
+ if (widthFactor) {
var dipOffsetX = cssOffsetX * WebInspector.zoomManager.zoomFactor();
- var newWidth = this._resizeStart.width + dipOffsetX * 2;
+ var newWidth = this._resizeStart.width + dipOffsetX * widthFactor;
newWidth = Math.round(newWidth / this._model.scale());
if (newWidth >= WebInspector.DeviceModeModel.MinDeviceSize && newWidth <= WebInspector.DeviceModeModel.MaxDeviceSize)
this._model.setWidth(newWidth);
}
- if (height) {
+ if (heightFactor) {
var dipOffsetY = cssOffsetY * WebInspector.zoomManager.zoomFactor();
- var newHeight = this._resizeStart.height + dipOffsetY;
+ var newHeight = this._resizeStart.height + dipOffsetY * heightFactor;
newHeight = Math.round(newHeight / this._model.scale());
if (newHeight >= WebInspector.DeviceModeModel.MinDeviceSize && newHeight <= WebInspector.DeviceModeModel.MaxDeviceSize)
this._model.setHeight(newHeight);
@@ -209,9 +222,11 @@ WebInspector.DeviceModeView.prototype = {
var resizable = this._model.type() === WebInspector.DeviceModeModel.Type.Responsive;
if (resizable !== this._cachedResizable) {
- this._widthResizerElement.classList.toggle("hidden", !resizable);
- this._heightResizerElement.classList.toggle("hidden", !resizable);
- this._cornerResizerElement.classList.toggle("hidden", !resizable);
+ this._rightResizerElement.classList.toggle("hidden", !resizable);
+ this._leftResizerElement.classList.toggle("hidden", !resizable);
+ this._bottomResizerElement.classList.toggle("hidden", !resizable);
+ this._bottomRightResizerElement.classList.toggle("hidden", !resizable);
+ this._bottomLeftResizerElement.classList.toggle("hidden", !resizable);
this._cachedResizable = resizable;
}
@@ -292,13 +307,13 @@ WebInspector.DeviceModeView.prototype = {
_measureHandles: function()
{
- var hidden = this._widthResizerElement.classList.contains("hidden");
- this._widthResizerElement.classList.toggle("hidden", false);
- this._heightResizerElement.classList.toggle("hidden", false);
- this._handleWidth = this._widthResizerElement.offsetWidth;
- this._handleHeight = this._heightResizerElement.offsetHeight;
- this._widthResizerElement.classList.toggle("hidden", hidden);
- this._heightResizerElement.classList.toggle("hidden", hidden);
+ var hidden = this._rightResizerElement.classList.contains("hidden");
+ this._rightResizerElement.classList.toggle("hidden", false);
+ this._bottomResizerElement.classList.toggle("hidden", false);
+ this._handleWidth = this._rightResizerElement.offsetWidth;
+ this._handleHeight = this._bottomResizerElement.offsetHeight;
+ this._rightResizerElement.classList.toggle("hidden", hidden);
+ this._bottomResizerElement.classList.toggle("hidden", hidden);
},
_zoomChanged: function()
@@ -326,7 +341,6 @@ WebInspector.DeviceModeView.prototype = {
wasShown: function()
{
this._measureHandles();
- this._mediaInspector.setEnabled(true);
this._toolbar.restore();
},
@@ -336,575 +350,11 @@ WebInspector.DeviceModeView.prototype = {
willHide: function()
{
this._model.emulate(WebInspector.DeviceModeModel.Type.None, null, null);
- this._mediaInspector.setEnabled(false);
},
__proto__: WebInspector.VBox.prototype
}
-/**
- * @param {!WebInspector.DeviceModeModel} model
- * @param {!WebInspector.Setting} showMediaInspectorSetting
- * @param {!WebInspector.Setting} showRulersSetting
- * @constructor
- */
-WebInspector.DeviceModeView.Toolbar = function(model, showMediaInspectorSetting, showRulersSetting)
-{
- this._model = model;
- this._showMediaInspectorSetting = showMediaInspectorSetting;
- this._showRulersSetting = showRulersSetting;
- /** @type {!Map} */
- this._lastMode = new Map();
-
- this._element = createElementWithClass("div", "device-mode-toolbar");
-
- var leftContainer = this._element.createChild("div", "device-mode-toolbar-spacer");
- leftContainer.createChild("div", "device-mode-toolbar-spacer");
- var leftToolbar = new WebInspector.Toolbar("", leftContainer);
- leftToolbar.makeWrappable();
- this._fillLeftToolbar(leftToolbar);
-
- var mainToolbar = new WebInspector.Toolbar("", this._element);
- mainToolbar.makeWrappable();
- this._fillMainToolbar(mainToolbar);
-
- var rightContainer = this._element.createChild("div", "device-mode-toolbar-spacer");
- var rightToolbar = new WebInspector.Toolbar("device-mode-toolbar-fixed-size", rightContainer);
- rightToolbar.makeWrappable();
- this._fillRightToolbar(rightToolbar);
- var modeToolbar = new WebInspector.Toolbar("device-mode-toolbar-fixed-size", rightContainer);
- modeToolbar.makeWrappable();
- this._fillModeToolbar(modeToolbar);
- rightContainer.createChild("div", "device-mode-toolbar-spacer");
- var optionsToolbar = new WebInspector.Toolbar("", rightContainer);
- optionsToolbar.makeWrappable(true);
- this._fillOptionsToolbar(optionsToolbar);
-
- WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.CustomDevicesUpdated, this._deviceListChanged, this);
- WebInspector.emulatedDevicesList.addEventListener(WebInspector.EmulatedDevicesList.Events.StandardDevicesUpdated, this._deviceListChanged, this);
-
- this._persistenceSetting = WebInspector.settings.createSetting("emulation.deviceModeValue", {device: "", orientation: "", mode: ""});
-}
-
-WebInspector.DeviceModeView.Toolbar.prototype = {
- /**
- * @param {!WebInspector.Toolbar} toolbar
- */
- _fillLeftToolbar: function(toolbar)
- {
- toolbar.appendToolbarItem(this._wrapToolbarItem(createElementWithClass("div", "device-mode-empty-toolbar-element")));
- this._deviceSelectItem = new WebInspector.ToolbarMenuButton(this._appendDeviceMenuItems.bind(this));
- this._deviceSelectItem.setGlyph("");
- this._deviceSelectItem.turnIntoSelect(95);
- toolbar.appendToolbarItem(this._deviceSelectItem);
- },
-
- /**
- * @param {!WebInspector.Toolbar} toolbar
- */
- _fillMainToolbar: function(toolbar)
- {
- var widthInput = createElementWithClass("input", "device-mode-size-input");
- widthInput.maxLength = 4;
- widthInput.type = "text";
- widthInput.title = WebInspector.UIString("Width");
- this._updateWidthInput = this._bindInput(widthInput, this._model.setWidthAndScaleToFit.bind(this._model), WebInspector.DeviceModeModel.deviceSizeValidator);
- this._widthInput = widthInput;
- this._widthItem = this._wrapToolbarItem(widthInput);
- toolbar.appendToolbarItem(this._widthItem);
-
- var xElement = createElementWithClass("div", "device-mode-x");
- xElement.textContent = "\u00D7";
- this._xItem = this._wrapToolbarItem(xElement);
- toolbar.appendToolbarItem(this._xItem);
-
- var heightInput = createElementWithClass("input", "device-mode-size-input");
- heightInput.maxLength = 4;
- heightInput.type = "text";
- heightInput.title = WebInspector.UIString("Height (leave empty for full)");
- this._updateHeightInput = this._bindInput(heightInput, this._model.setHeightAndScaleToFit.bind(this._model), validateHeight);
- this._heightInput = heightInput;
- this._heightItem = this._wrapToolbarItem(heightInput);
- toolbar.appendToolbarItem(this._heightItem);
-
- /**
- * @param {string} value
- * @return {string}
- */
- function validateHeight(value)
- {
- return !value ? "" : WebInspector.DeviceModeModel.deviceSizeValidator(value);
- }
- },
-
- /**
- * @param {!WebInspector.Toolbar} toolbar
- */
- _fillRightToolbar: function(toolbar)
- {
- toolbar.appendToolbarItem(this._wrapToolbarItem(createElementWithClass("div", "device-mode-empty-toolbar-element")));
- this._scaleItem = new WebInspector.ToolbarMenuButton(this._appendScaleMenuItems.bind(this));
- this._scaleItem.setTitle(WebInspector.UIString("Zoom"));
- this._scaleItem.setGlyph("");
- this._scaleItem.turnIntoSelect();
- toolbar.appendToolbarItem(this._scaleItem);
- },
-
- /**
- * @param {!WebInspector.Toolbar} toolbar
- */
- _fillModeToolbar: function(toolbar)
- {
- toolbar.appendToolbarItem(this._wrapToolbarItem(createElementWithClass("div", "device-mode-empty-toolbar-element")));
- this._modeButton = new WebInspector.ToolbarButton("", "rotate-screen-toolbar-item");
- this._modeButton.addEventListener("click", this._modeMenuClicked, this);
- toolbar.appendToolbarItem(this._modeButton);
- },
-
- /**
- * @param {!WebInspector.Toolbar} toolbar
- */
- _fillOptionsToolbar: function(toolbar)
- {
- this._uaItem = new WebInspector.ToolbarText();
- this._uaItem.setVisible(false);
- this._uaItem.setTitle(WebInspector.UIString("User agent type"));
- toolbar.appendToolbarItem(this._uaItem);
-
- this._deviceScaleItem = new WebInspector.ToolbarText();
- this._deviceScaleItem.setVisible(false);
- this._deviceScaleItem.setTitle(WebInspector.UIString("Device pixel ratio"));
- toolbar.appendToolbarItem(this._deviceScaleItem);
-
- var moreOptionsButton = new WebInspector.ToolbarMenuButton(this._appendOptionsMenuItems.bind(this));
- moreOptionsButton.setTitle(WebInspector.UIString("More options"));
- toolbar.appendToolbarItem(moreOptionsButton);
-
- toolbar.appendToolbarItem(this._wrapToolbarItem(createElementWithClass("div", "device-mode-empty-toolbar-element")));
- },
-
-
- /**
- * @param {!Element} input
- * @param {function(number)} apply
- * @param {function(string):?string} validate
- * @return {function(number)}
- */
- _bindInput: function(input, apply, validate)
- {
- input.addEventListener("change", onChange, false);
- input.addEventListener("input", onInput, false);
- input.addEventListener("keydown", onKeyDown, false);
- input.addEventListener("focus", input.select.bind(input), false);
-
- function onInput()
- {
- input.classList.toggle("error-input", !!validate(input.value));
- }
-
- function onChange()
- {
- var valid = !validate(input.value);
- input.classList.toggle("error-input", !valid);
- if (valid)
- apply(input.value ? Number(input.value) : 0);
- }
-
- /**
- * @param {!Event} event
- */
- function onKeyDown(event)
- {
- if (isEnterKey(event)) {
- if (!validate(input.value))
- apply(input.value ? Number(input.value) : 0);
- return;
- }
-
- var increment = event.keyIdentifier === "Up" ? 1 : event.keyIdentifier === "Down" ? -1 : 0;
- if (!increment)
- return;
- if (event.shiftKey)
- increment *= 10;
-
- var value = input.value;
- if (validate(value) || !value)
- return;
-
- value = (value ? Number(value) : 0) + increment;
- var stringValue = value ? String(value) : "";
- if (validate(stringValue) || !value)
- return;
-
- input.value = stringValue;
- apply(input.value ? Number(input.value) : 0);
- event.preventDefault();
- }
-
- /**
- * @param {number} value
- */
- function setValue(value)
- {
- var stringValue = value ? String(value) : "";
- if (stringValue === input.value)
- return;
- var valid = !validate(stringValue);
- input.classList.toggle("error-input", !valid);
- input.value = stringValue;
- input.setSelectionRange(stringValue.length, stringValue.length);
- }
-
- return setValue;
- },
-
- /**
- * @param {!WebInspector.ContextMenu} contextMenu
- */
- _appendScaleMenuItems: function(contextMenu)
- {
- var scaleSetting = this._model.scaleSetting();
- if (this._model.type() === WebInspector.DeviceModeModel.Type.Device) {
- contextMenu.appendItem(WebInspector.UIString("Fit to window (%.0f%%)", this._model.fitScale() * 100), scaleSetting.set.bind(scaleSetting, this._model.fitScale()), false);
- contextMenu.appendSeparator();
- }
- appendScaleItem(WebInspector.UIString("50%"), 0.5);
- appendScaleItem(WebInspector.UIString("75%"), 0.75);
- appendScaleItem(WebInspector.UIString("100%"), 1);
- appendScaleItem(WebInspector.UIString("125%"), 1.25);
- appendScaleItem(WebInspector.UIString("150%"), 1.5);
-
- /**
- * @param {string} title
- * @param {number} value
- */
- function appendScaleItem(title, value)
- {
- contextMenu.appendCheckboxItem(title, scaleSetting.set.bind(scaleSetting, value), scaleSetting.get() === value, false);
- }
- },
-
- /**
- * @param {!WebInspector.ContextMenu} contextMenu
- */
- _appendOptionsMenuItems: function(contextMenu)
- {
- var uaDisabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive;
- var uaSetting = this._model.uaSetting();
- var uaSubmenu = contextMenu.appendSubMenuItem(WebInspector.UIString("User agent type"), false);
- var uaValue = this._model.uaSetting().get();
- if (this._model.type() === WebInspector.DeviceModeModel.Type.None)
- uaValue = WebInspector.DeviceModeModel.UA.Desktop;
- if (this._model.type() === WebInspector.DeviceModeModel.Type.Device)
- uaValue = this._model.device().mobile() ? WebInspector.DeviceModeModel.UA.Mobile : this._model.device().touch() ? WebInspector.DeviceModeModel.UA.DesktopTouch : WebInspector.DeviceModeModel.UA.Desktop;
- appendUAItem(WebInspector.UIString("Mobile (default)"), WebInspector.DeviceModeModel.UA.Mobile);
- appendUAItem(WebInspector.UIString("Desktop"), WebInspector.DeviceModeModel.UA.Desktop);
- appendUAItem(WebInspector.UIString("Desktop with touch"), WebInspector.DeviceModeModel.UA.DesktopTouch);
-
- /**
- * @param {string} title
- * @param {!WebInspector.DeviceModeModel.UA} value
- */
- function appendUAItem(title, value)
- {
- uaSubmenu.appendCheckboxItem(title, uaSetting.set.bind(uaSetting, value), uaValue === value, uaDisabled);
- }
-
- var deviceScaleFactorDisabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive;
- var deviceScaleFactorSubmenu = contextMenu.appendSubMenuItem(WebInspector.UIString("Device pixel ratio"), false);
- var deviceScaleFactorSetting = this._model.deviceScaleFactorSetting();
- var deviceScaleFactorValue = deviceScaleFactorDisabled ? 0 : deviceScaleFactorSetting.get();
- appendDeviceScaleFactorItem(WebInspector.UIString("Default: %f", this._model.defaultDeviceScaleFactor()), 0);
- deviceScaleFactorSubmenu.appendSeparator();
- appendDeviceScaleFactorItem(WebInspector.UIString("1"), 1);
- appendDeviceScaleFactorItem(WebInspector.UIString("2"), 2);
- appendDeviceScaleFactorItem(WebInspector.UIString("3"), 3);
-
- /**
- * @param {string} title
- * @param {number} value
- */
- function appendDeviceScaleFactorItem(title, value)
- {
- deviceScaleFactorSubmenu.appendCheckboxItem(title, deviceScaleFactorSetting.set.bind(deviceScaleFactorSetting, value), deviceScaleFactorValue === value, deviceScaleFactorDisabled);
- }
-
- contextMenu.appendItem(WebInspector.UIString("Reset to defaults"), this._model.reset.bind(this._model), this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive);
- contextMenu.appendSeparator();
-
- contextMenu.appendCheckboxItem(WebInspector.UIString("Show media queries"), this._toggleMediaInspector.bind(this), this._showMediaInspectorSetting.get(), this._model.type() === WebInspector.DeviceModeModel.Type.None);
- contextMenu.appendCheckboxItem(WebInspector.UIString("Show rulers"), this._toggleRulers.bind(this), this._showRulersSetting.get(), this._model.type() === WebInspector.DeviceModeModel.Type.None);
- contextMenu.appendItem(WebInspector.UIString("Configure network\u2026"), this._openNetworkConfig.bind(this), false);
- contextMenu.appendItemsAtLocation("deviceModeMenu");
- },
-
- _toggleMediaInspector: function()
- {
- this._showMediaInspectorSetting.set(!this._showMediaInspectorSetting.get());
- },
-
- _toggleRulers: function()
- {
- this._showRulersSetting.set(!this._showRulersSetting.get());
- },
-
- _openNetworkConfig: function()
- {
- InspectorFrontendHost.bringToFront();
- // TODO(dgozman): make it explicit.
- WebInspector.actionRegistry.action("network.show-config").execute();
- },
-
- /**
- * @param {!Element} element
- * @return {!WebInspector.ToolbarItem}
- */
- _wrapToolbarItem: function(element)
- {
- var container = createElement("div");
- var shadowRoot = WebInspector.createShadowRootWithCoreStyles(container, "emulation/deviceModeToolbar.css");
- shadowRoot.appendChild(element);
- return new WebInspector.ToolbarItem(container);
- },
-
- /**
- * @param {!WebInspector.EmulatedDevice} device
- */
- _emulateDevice: function(device)
- {
- this._model.emulate(WebInspector.DeviceModeModel.Type.Device, device, this._lastMode.get(device) || device.modes[0]);
- },
-
- _switchToResponsive: function()
- {
- this._model.emulate(WebInspector.DeviceModeModel.Type.Responsive, null, null);
- },
-
- /**
- * @param {!Array} devices
- * @return {!Array}
- */
- _filterDevices: function(devices)
- {
- devices = devices.filter(function(d) { return d.show(); });
- devices.sort(WebInspector.EmulatedDevice.deviceComparator);
- return devices;
- },
-
- /**
- * @return {!Array}
- */
- _standardDevices: function()
- {
- return this._filterDevices(WebInspector.emulatedDevicesList.standard());
- },
-
- /**
- * @return {!Array}
- */
- _customDevices: function()
- {
- return this._filterDevices(WebInspector.emulatedDevicesList.custom());
- },
-
- /**
- * @return {!Array}
- */
- _allDevices: function()
- {
- return this._standardDevices().concat(this._customDevices());
- },
-
- /**
- * @param {!WebInspector.ContextMenu} contextMenu
- */
- _appendDeviceMenuItems: function(contextMenu)
- {
- contextMenu.appendCheckboxItem(WebInspector.UIString("Responsive"), this._switchToResponsive.bind(this), this._model.type() === WebInspector.DeviceModeModel.Type.Responsive, false);
- appendGroup.call(this, this._standardDevices());
- appendGroup.call(this, this._customDevices());
- contextMenu.appendSeparator();
- contextMenu.appendItem(WebInspector.UIString("Edit\u2026"), WebInspector.emulatedDevicesList.revealCustomSetting.bind(WebInspector.emulatedDevicesList), false);
-
- /**
- * @param {!Array} devices
- * @this {WebInspector.DeviceModeView.Toolbar}
- */
- function appendGroup(devices)
- {
- if (!devices.length)
- return;
- contextMenu.appendSeparator();
- for (var device of devices)
- contextMenu.appendCheckboxItem(device.title, this._emulateDevice.bind(this, device), this._model.device() === device, false);
- }
- },
-
- /**
- * @this {WebInspector.DeviceModeView.Toolbar}
- */
- _deviceListChanged: function()
- {
- if (!this._model.device())
- return;
-
- var devices = this._allDevices();
- if (devices.indexOf(this._model.device()) === -1)
- this._emulateDevice(devices[0] || WebInspector.emulatedDevicesList.standard()[0]);
- },
-
- /**
- * @param {!WebInspector.Event} event
- */
- _modeMenuClicked: function(event)
- {
- var device = this._model.device();
- var model = this._model;
-
- if (device.modes.length === 2 && device.modes[0].orientation !== device.modes[1].orientation) {
- model.emulate(model.type(), model.device(), model.mode() === device.modes[0] ? device.modes[1] : device.modes[0]);
- return;
- }
-
- var contextMenu = new WebInspector.ContextMenu(/** @type {!Event} */ (event.data),
- false,
- event.target.element.totalOffsetLeft(),
- event.target.element.totalOffsetTop() + event.target.element.offsetHeight);
- addOrientation(WebInspector.EmulatedDevice.Vertical, WebInspector.UIString("Portrait"));
- addOrientation(WebInspector.EmulatedDevice.Horizontal, WebInspector.UIString("Landscape"));
- contextMenu.show();
-
- /**
- * @param {string} orientation
- * @param {string} title
- */
- function addOrientation(orientation, title)
- {
- var modes = device.modesForOrientation(orientation);
- if (!modes.length)
- return;
- if (modes.length === 1) {
- addMode(modes[0], title);
- } else {
- for (var index = 0; index < modes.length; index++)
- addMode(modes[index], title + " \u2013 " + modes[index].title);
- }
- }
-
- /**
- * @param {!WebInspector.EmulatedDevice.Mode} mode
- * @param {string} title
- */
- function addMode(mode, title)
- {
- contextMenu.appendCheckboxItem(title, applyMode.bind(null, mode), model.mode() === mode, false);
- }
-
- /**
- * @param {!WebInspector.EmulatedDevice.Mode} mode
- */
- function applyMode(mode)
- {
- model.emulate(model.type(), model.device(), mode);
- }
- },
-
- /**
- * @return {!Element}
- */
- element: function()
- {
- return this._element;
- },
-
- update: function()
- {
- if (this._model.type() !== this._cachedModelType) {
- this._cachedModelType = this._model.type();
- this._widthInput.disabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive;
- this._heightInput.disabled = this._model.type() !== WebInspector.DeviceModeModel.Type.Responsive;
- }
-
- var size = this._model.appliedDeviceSize();
- this._updateHeightInput(this._model.type() === WebInspector.DeviceModeModel.Type.Responsive && this._model.isFullHeight() ? 0 : size.height);
- this._updateWidthInput(size.width);
- this._heightInput.placeholder = size.height;
-
- if (this._model.scale() !== this._cachedScale) {
- this._scaleItem.setText(WebInspector.UIString("%.0f%%", this._model.scale() * 100));
- this._scaleItem.setState(this._model.scale() === 1 ? "off" : "on");
- this._cachedScale = this._model.scale();
- }
-
- var deviceScale = this._model.deviceScaleFactorSetting().get();
- this._deviceScaleItem.setVisible(this._model.type() === WebInspector.DeviceModeModel.Type.Responsive && !!deviceScale);
- if (deviceScale !== this._cachedDeviceScale) {
- this._deviceScaleItem.setText(WebInspector.UIString("DPR: %.1f", deviceScale));
- this._cachedDeviceScale = deviceScale;
- }
-
- var uaType = this._model.type() === WebInspector.DeviceModeModel.Type.Responsive ? this._model.uaSetting().get() : WebInspector.DeviceModeModel.UA.Mobile;
- this._uaItem.setVisible(this._model.type() === WebInspector.DeviceModeModel.Type.Responsive && uaType !== WebInspector.DeviceModeModel.UA.Mobile);
- if (uaType !== this._cachedUaType) {
- this._uaItem.setText(uaType === WebInspector.DeviceModeModel.UA.Desktop ? WebInspector.UIString("Desktop") : WebInspector.UIString("Touch"));
- this._cachedUaType = uaType;
- }
-
- var deviceItemTitle = WebInspector.UIString("None");
- if (this._model.type() === WebInspector.DeviceModeModel.Type.Responsive)
- deviceItemTitle = WebInspector.UIString("Responsive");
- if (this._model.type() === WebInspector.DeviceModeModel.Type.Device)
- deviceItemTitle = this._model.device().title;
- this._deviceSelectItem.setText(deviceItemTitle);
-
- if (this._model.device() !== this._cachedModelDevice) {
- var device = this._model.device();
- this._modeButton.setVisible(!!device);
- if (device) {
- var modeCount = device ? device.modes.length : 0;
- this._modeButton.setEnabled(modeCount >= 2);
- this._modeButton.setTitle(modeCount === 2 ? WebInspector.UIString("Rotate") : WebInspector.UIString("Screen options"));
- }
- this._cachedModelDevice = device;
- }
-
- if (this._model.type() === WebInspector.DeviceModeModel.Type.Device)
- this._lastMode.set(/** @type {!WebInspector.EmulatedDevice} */ (this._model.device()), /** @type {!WebInspector.EmulatedDevice.Mode} */ (this._model.mode()));
-
- if (this._model.mode() !== this._cachedModelMode && this._model.type() !== WebInspector.DeviceModeModel.Type.None) {
- this._cachedModelMode = this._model.mode();
- var value = this._persistenceSetting.get();
- if (this._model.device()) {
- value.device = this._model.device().title;
- value.orientation = this._model.mode() ? this._model.mode().orientation : "";
- value.mode = this._model.mode() ? this._model.mode().title : "";
- } else {
- value.device = "";
- value.orientation = "";
- value.mode = "";
- }
- this._persistenceSetting.set(value);
- }
- },
-
- restore: function()
- {
- for (var device of this._allDevices()) {
- if (device.title === this._persistenceSetting.get().device) {
- for (var mode of device.modes) {
- if (mode.orientation === this._persistenceSetting.get().orientation && mode.title === this._persistenceSetting.get().mode) {
- this._lastMode.set(device, mode);
- this._emulateDevice(device);
- return;
- }
- }
- }
- }
-
- this._model.emulate(WebInspector.DeviceModeModel.Type.Responsive, null, null);
- }
-}
-
/**
* @constructor
* @extends {WebInspector.VBox}
@@ -1012,97 +462,3 @@ WebInspector.DeviceModeView.Ruler.prototype = {
__proto__: WebInspector.VBox.prototype
}
-
-
-/**
- * @constructor
- * @implements {WebInspector.ActionDelegate}
- */
-WebInspector.DeviceModeView.ActionDelegate = function()
-{
-}
-
-WebInspector.DeviceModeView.ActionDelegate.prototype = {
- /**
- * @override
- * @param {!WebInspector.Context} context
- * @param {string} actionId
- * @return {boolean}
- */
- handleAction: function(context, actionId)
- {
- if (WebInspector.DeviceModeView._wrapperInstance) {
- if (actionId === "emulation.toggle-device-mode") {
- WebInspector.DeviceModeView._wrapperInstance._toggleDeviceMode();
- return true;
- }
- if (actionId === "emulation.request-app-banner") {
- WebInspector.DeviceModeView._wrapperInstance._requestAppBanner();
- return true;
- }
- }
- return false;
- }
-}
-
-
-/**
- * @extends {WebInspector.VBox}
- * @param {!WebInspector.InspectedPagePlaceholder} inspectedPagePlaceholder
- * @constructor
- */
-WebInspector.DeviceModeView.Wrapper = function(inspectedPagePlaceholder)
-{
- WebInspector.VBox.call(this);
- WebInspector.DeviceModeView._wrapperInstance = this;
- this._inspectedPagePlaceholder = inspectedPagePlaceholder;
- /** @type {?WebInspector.DeviceModeView} */
- this._deviceModeView = null;
- this._toggleDeviceModeAction = WebInspector.actionRegistry.action("emulation.toggle-device-mode");
- this._showDeviceModeSetting = WebInspector.settings.createSetting("emulation.showDeviceMode", false);
- this._showDeviceModeSetting.addChangeListener(this._update.bind(this, false));
- this._update(true);
-}
-
-/** @type {!WebInspector.DeviceModeView.Wrapper} */
-WebInspector.DeviceModeView._wrapperInstance;
-
-WebInspector.DeviceModeView.Wrapper.prototype = {
- _toggleDeviceMode: function()
- {
- this._showDeviceModeSetting.set(!this._showDeviceModeSetting.get());
- },
-
- /**
- * @param {boolean} force
- */
- _update: function(force)
- {
- this._toggleDeviceModeAction.setToggled(this._showDeviceModeSetting.get());
- if (!force) {
- var showing = this._deviceModeView && this._deviceModeView.isShowing();
- if (this._showDeviceModeSetting.get() === showing)
- return;
- }
-
- if (this._showDeviceModeSetting.get()) {
- if (!this._deviceModeView)
- this._deviceModeView = new WebInspector.DeviceModeView();
- this._deviceModeView.show(this.element);
- this._inspectedPagePlaceholder.clearMinimumSizeAndMargins();
- this._inspectedPagePlaceholder.show(this._deviceModeView.element);
- } else {
- if (this._deviceModeView)
- this._deviceModeView.detach();
- this._inspectedPagePlaceholder.restoreMinimumSizeAndMargins();
- this._inspectedPagePlaceholder.show(this.element);
- }
- },
-
- _requestAppBanner: function()
- {
- this._deviceModeView._model.requestAppBanner();
- },
-
- __proto__: WebInspector.VBox.prototype
-}
diff --git a/front_end/emulation/DeviceModeWrapper.js b/front_end/emulation/DeviceModeWrapper.js
new file mode 100644
index 0000000000..51515ccc47
--- /dev/null
+++ b/front_end/emulation/DeviceModeWrapper.js
@@ -0,0 +1,92 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @extends {WebInspector.VBox}
+ * @param {!WebInspector.InspectedPagePlaceholder} inspectedPagePlaceholder
+ * @constructor
+ */
+WebInspector.DeviceModeWrapper = function(inspectedPagePlaceholder)
+{
+ WebInspector.VBox.call(this);
+ WebInspector.DeviceModeView._wrapperInstance = this;
+ this._inspectedPagePlaceholder = inspectedPagePlaceholder;
+ /** @type {?WebInspector.DeviceModeView} */
+ this._deviceModeView = null;
+ this._toggleDeviceModeAction = WebInspector.actionRegistry.action("emulation.toggle-device-mode");
+ this._showDeviceModeSetting = WebInspector.settings.createSetting("emulation.showDeviceMode", false);
+ this._showDeviceModeSetting.addChangeListener(this._update.bind(this, false));
+ this._update(true);
+}
+
+/** @type {!WebInspector.DeviceModeWrapper} */
+WebInspector.DeviceModeView._wrapperInstance;
+
+WebInspector.DeviceModeWrapper.prototype = {
+ _toggleDeviceMode: function()
+ {
+ this._showDeviceModeSetting.set(!this._showDeviceModeSetting.get());
+ },
+
+ /**
+ * @param {boolean} force
+ */
+ _update: function(force)
+ {
+ this._toggleDeviceModeAction.setToggled(this._showDeviceModeSetting.get());
+ if (!force) {
+ var showing = this._deviceModeView && this._deviceModeView.isShowing();
+ if (this._showDeviceModeSetting.get() === showing)
+ return;
+ }
+
+ if (this._showDeviceModeSetting.get()) {
+ if (!this._deviceModeView)
+ this._deviceModeView = new WebInspector.DeviceModeView();
+ this._deviceModeView.show(this.element);
+ this._inspectedPagePlaceholder.clearMinimumSizeAndMargins();
+ this._inspectedPagePlaceholder.show(this._deviceModeView.element);
+ } else {
+ if (this._deviceModeView)
+ this._deviceModeView.detach();
+ this._inspectedPagePlaceholder.restoreMinimumSizeAndMargins();
+ this._inspectedPagePlaceholder.show(this.element);
+ }
+ },
+
+ __proto__: WebInspector.VBox.prototype
+}
+
+/**
+ * @constructor
+ * @implements {WebInspector.ActionDelegate}
+ */
+WebInspector.DeviceModeWrapper.ActionDelegate = function()
+{
+}
+
+WebInspector.DeviceModeWrapper.ActionDelegate.prototype = {
+ /**
+ * @override
+ * @param {!WebInspector.Context} context
+ * @param {string} actionId
+ * @return {boolean}
+ */
+ handleAction: function(context, actionId)
+ {
+ if (WebInspector.DeviceModeView._wrapperInstance) {
+ if (actionId === "emulation.toggle-device-mode") {
+ WebInspector.DeviceModeView._wrapperInstance._toggleDeviceMode();
+ return true;
+ }
+ if (actionId === "emulation.request-app-banner") {
+ var target = WebInspector.targetManager.mainTarget();
+ if (target && target.isPage())
+ target.pageAgent().requestAppBanner();
+ return true;
+ }
+ }
+ return false;
+ }
+}
diff --git a/front_end/emulation/DevicesSettingsTab.js b/front_end/emulation/DevicesSettingsTab.js
index 6e5bcd3d22..c126eaae99 100644
--- a/front_end/emulation/DevicesSettingsTab.js
+++ b/front_end/emulation/DevicesSettingsTab.js
@@ -77,6 +77,10 @@ WebInspector.DevicesSettingsTab.prototype = {
{
var device = new WebInspector.EmulatedDevice();
device.deviceScaleFactor = 0;
+ device.horizontal.width = 700;
+ device.horizontal.height = 400;
+ device.vertical.width = 400;
+ device.vertical.height = 700;
this._list.addNewItem(WebInspector.emulatedDevicesList.custom().length, device);
},
@@ -221,7 +225,7 @@ WebInspector.DevicesSettingsTab.prototype = {
*/
function sizeValidator(item, index, input)
{
- return !WebInspector.DeviceModeModel.deviceSizeValidator(input.value);
+ return WebInspector.DeviceModeModel.deviceSizeValidator(input.value);
}
/**
@@ -232,7 +236,7 @@ WebInspector.DevicesSettingsTab.prototype = {
*/
function scaleValidator(item, index, input)
{
- return !WebInspector.DeviceModeModel.deviceScaleFactorValidator(input.value);
+ return WebInspector.DeviceModeModel.deviceScaleFactorValidator(input.value);
}
/**
diff --git a/front_end/emulation/EmulatedDevices.js b/front_end/emulation/EmulatedDevices.js
index 70d8a0e116..a204b33b37 100644
--- a/front_end/emulation/EmulatedDevices.js
+++ b/front_end/emulation/EmulatedDevices.js
@@ -184,7 +184,6 @@ WebInspector.EmulatedDevice.fromJSONV1 = function(json)
return result;
} catch (e) {
- WebInspector.console.error("Failed to update emulated device list. " + String(e));
return null;
}
}
@@ -371,13 +370,16 @@ WebInspector.EmulatedDevicesList = function()
/** @type {!WebInspector.Setting} */
this._standardSetting = WebInspector.settings.createSetting("standardEmulatedDeviceList", []);
/** @type {!Array.} */
- this._standard = this._listFromJSONV1(this._standardSetting.get());
+ this._standard = [];
+ this._listFromJSONV1(this._standardSetting.get(), this._standard);
this._updateStandardDevices();
/** @type {!WebInspector.Setting} */
this._customSetting = WebInspector.settings.createSetting("customEmulatedDeviceList", []);
/** @type {!Array.} */
- this._custom = this._listFromJSONV1(this._customSetting.get());
+ this._custom = [];
+ if (!this._listFromJSONV1(this._customSetting.get(), this._custom))
+ this.saveCustomDevices();
}
WebInspector.EmulatedDevicesList.Events = {
@@ -402,13 +404,14 @@ WebInspector.EmulatedDevicesList.prototype = {
/**
* @param {!Array.<*>} jsonArray
- * @return {!Array.}
+ * @param {!Array.} result
+ * @return {boolean}
*/
- _listFromJSONV1: function(jsonArray)
+ _listFromJSONV1: function(jsonArray, result)
{
- var result = [];
if (!Array.isArray(jsonArray))
- return result;
+ return false;
+ var success = true;
for (var i = 0; i < jsonArray.length; ++i) {
var device = WebInspector.EmulatedDevice.fromJSONV1(jsonArray[i]);
if (device) {
@@ -417,9 +420,11 @@ WebInspector.EmulatedDevicesList.prototype = {
device.modes.push({title: "", orientation: WebInspector.EmulatedDevice.Horizontal, insets: new Insets(0, 0, 0, 0), image: null});
device.modes.push({title: "", orientation: WebInspector.EmulatedDevice.Vertical, insets: new Insets(0, 0, 0, 0), image: null});
}
+ } else {
+ success = false;
}
}
- return result;
+ return success;
},
/**
diff --git a/front_end/emulation/MediaQueryInspector.js b/front_end/emulation/MediaQueryInspector.js
index ad59526596..198b67ba7c 100644
--- a/front_end/emulation/MediaQueryInspector.js
+++ b/front_end/emulation/MediaQueryInspector.js
@@ -13,7 +13,7 @@ WebInspector.MediaQueryInspector = function(getWidthCallback, setWidthCallback)
{
WebInspector.Widget.call(this, true);
this.registerRequiredCSS("emulation/mediaQueryInspector.css");
- this.contentElement.classList.add("media-inspector-view", "media-inspector-view-empty");
+ this.contentElement.classList.add("media-inspector-view");
this.contentElement.addEventListener("click", this._onMediaQueryClicked.bind(this), false);
this.contentElement.addEventListener("contextmenu", this._onContextMenu.bind(this), false);
this._mediaThrottler = new WebInspector.Throttler(0);
@@ -22,10 +22,8 @@ WebInspector.MediaQueryInspector = function(getWidthCallback, setWidthCallback)
this._setWidthCallback = setWidthCallback;
this._offset = 0;
this._scale = 1;
- this._lastReportedCount = 0;
WebInspector.targetManager.observeTargets(this);
-
WebInspector.zoomManager.addEventListener(WebInspector.ZoomManager.Events.ZoomChanged, this._renderMediaQueries.bind(this), this);
}
@@ -38,10 +36,6 @@ WebInspector.MediaQueryInspector.Section = {
Min: 2
}
-WebInspector.MediaQueryInspector.Events = {
- CountUpdated: "CountUpdated"
-}
-
WebInspector.MediaQueryInspector.prototype = {
/**
* @override
@@ -89,15 +83,6 @@ WebInspector.MediaQueryInspector.prototype = {
this._renderMediaQueries();
},
- /**
- * @param {boolean} enabled
- */
- setEnabled: function(enabled)
- {
- this._enabled = enabled;
- this._scheduleMediaQueriesUpdate();
- },
-
/**
* @param {!Event} event
*/
@@ -165,14 +150,14 @@ WebInspector.MediaQueryInspector.prototype = {
_scheduleMediaQueriesUpdate: function()
{
- if (!this._enabled)
+ if (!this.isShowing())
return;
this._mediaThrottler.schedule(this._refetchMediaQueries.bind(this));
},
_refetchMediaQueries: function()
{
- if (!this._enabled || !this._cssModel)
+ if (!this.isShowing() || !this._cssModel)
return Promise.resolve();
return this._cssModel.mediaQueriesPromise()
@@ -235,7 +220,7 @@ WebInspector.MediaQueryInspector.prototype = {
_renderMediaQueries: function()
{
- if (!this._cachedQueryModels)
+ if (!this._cachedQueryModels || !this.isShowing())
return;
var markers = [];
@@ -255,15 +240,6 @@ WebInspector.MediaQueryInspector.prototype = {
}
}
- if (markers.length !== this._lastReportedCount) {
- this._lastReportedCount = markers.length;
- this.dispatchEventToListeners(WebInspector.MediaQueryInspector.Events.CountUpdated, markers.length);
- }
-
- if (!this.isShowing())
- return;
-
- var oldChildrenCount = this.contentElement.children.length;
this.contentElement.removeChildren();
var container = null;
@@ -289,7 +265,7 @@ WebInspector.MediaQueryInspector.prototype = {
wasShown: function()
{
- this._renderMediaQueries();
+ this._scheduleMediaQueriesUpdate();
},
/**
diff --git a/front_end/emulation/deviceModeToolbar.css b/front_end/emulation/deviceModeToolbar.css
index 03556bb33f..292d36fc84 100644
--- a/front_end/emulation/deviceModeToolbar.css
+++ b/front_end/emulation/deviceModeToolbar.css
@@ -14,16 +14,13 @@
box-shadow: 0px 0px 1px 0px hsla(0, 0%, 0%, 0.13);
border-radius: 1px;
height: 18px;
+ color: hsl(210, 16%, 22%);
}
.device-mode-size-input:focus::-webkit-input-placeholder {
color: transparent;
}
-.device-mode-size-input.error-input {
- outline: auto 2px red !important;
-}
-
.device-mode-size-input:disabled {
background: transparent;
box-shadow: none;
diff --git a/front_end/emulation/deviceModeView.css b/front_end/emulation/deviceModeView.css
index cf00646e1d..7351960afb 100644
--- a/front_end/emulation/deviceModeView.css
+++ b/front_end/emulation/deviceModeView.css
@@ -122,7 +122,7 @@
width: 0;
height: 0;
background-color: #171717;
- box-shadow: hsl(0, 0%, 88%) 1px 1px 0 1px, hsla(0, 0%, 80%, 0.6) 0 0 16px;
+ box-shadow: hsl(240, 3%, 84%) 0 0 0 0.5px, hsla(0, 0%, 80%, 0.4) 0 0 20px;
}
.device-mode-screen-image {
@@ -139,32 +139,41 @@
align-items: center;
justify-content: center;
overflow: hidden;
- transition: background-color 0.1s ease;
+ transition: background-color 0.1s ease, opacity 0.1s ease;
}
.device-mode-resizer:hover {
background-color: hsla(0, 0%, 0%, 0.1);
+ opacity: 1;
}
.device-mode-resizer > div {
pointer-events: none;
}
-.device-mode-width-resizer {
+.device-mode-right-resizer {
top: 0;
- bottom: -2px;
+ bottom: -1px;
right: -20px;
width: 20px;
}
-.device-mode-height-resizer {
+.device-mode-left-resizer {
+ top: 0;
+ bottom: -1px;
+ left: -20px;
+ width: 20px;
+ opacity: 0;
+}
+
+.device-mode-bottom-resizer {
left: 0;
- right: -2px;
+ right: -1px;
bottom: -20px;
height: 20px;
}
-.device-mode-corner-resizer {
+.device-mode-bottom-right-resizer {
left: 0;
top: 0;
right: -20px;
@@ -172,20 +181,34 @@
background-color: hsla(0, 0%, 0%, 0.02);
}
-.device-mode-width-resizer > div {
+.device-mode-bottom-left-resizer {
+ left: -20px;
+ top: 0;
+ right: 0;
+ bottom: -20px;
+ opacity: 0;
+}
+
+.device-mode-right-resizer > div {
+ content: url(Images/resizeHorizontal.png);
+ width: 6px;
+ height: 26px;
+}
+
+.device-mode-left-resizer > div {
content: url(Images/resizeHorizontal.png);
width: 6px;
height: 26px;
}
-.device-mode-height-resizer > div {
+.device-mode-bottom-resizer > div {
content: url(Images/resizeVertical.png);
margin-bottom: -2px;
width: 26px;
height: 6px;
}
-.device-mode-corner-resizer > div {
+.device-mode-bottom-right-resizer > div {
position: absolute;
bottom: 3px;
right: 3px;
@@ -194,16 +217,34 @@
content: url(Images/resizeDiagonal.png);
}
+.device-mode-bottom-left-resizer > div {
+ position: absolute;
+ bottom: 3px;
+ left: 3px;
+ width: 13px;
+ height: 13px;
+ content: url(Images/resizeDiagonal.png);
+ transform: rotate(90deg);
+}
+
@media (-webkit-min-device-pixel-ratio: 1.5) {
- .device-mode-width-resizer > div {
+ .device-mode-right-resizer > div {
+ content: url(Images/resizeHorizontal_2x.png);
+ }
+
+ .device-mode-left-resizer > div {
content: url(Images/resizeHorizontal_2x.png);
}
- .device-mode-height-resizer > div {
+ .device-mode-bottom-resizer > div {
content: url(Images/resizeVertical_2x.png);
}
- .device-mode-corner-resizer > div {
+ .device-mode-bottom-right-resizer > div {
+ content: url(Images/resizeDiagonal_2x.png);
+ }
+
+ .device-mode-bottom-left-resizer > div {
content: url(Images/resizeDiagonal_2x.png);
}
} /* media */
diff --git a/front_end/emulation/module.json b/front_end/emulation/module.json
index 8e958ad36a..2962b8a2eb 100644
--- a/front_end/emulation/module.json
+++ b/front_end/emulation/module.json
@@ -3,7 +3,7 @@
{
"type": "@WebInspector.ActionDelegate",
"actionId": "emulation.toggle-device-mode",
- "className": "WebInspector.DeviceModeView.ActionDelegate",
+ "className": "WebInspector.DeviceModeWrapper.ActionDelegate",
"condition": "can_dock",
"title": "Toggle device mode",
"iconClass": "phone-toolbar-item",
@@ -59,12 +59,13 @@
{
"type": "@WebInspector.ActionDelegate",
"actionId": "emulation.request-app-banner",
- "className": "WebInspector.DeviceModeView.ActionDelegate",
- "title": "Request app banner"
+ "className": "WebInspector.DeviceModeWrapper.ActionDelegate",
+ "title": "Request app banner\u2026"
},
{
"type": "context-menu-item",
"location": "deviceModeMenu/tools",
+ "experiment": "appBanner",
"order": 10,
"actionId": "emulation.request-app-banner"
}
@@ -84,7 +85,9 @@
"MediaQueryInspector.js",
"SensorsView.js",
"DeviceModeModel.js",
- "DeviceModeView.js"
+ "DeviceModeToolbar.js",
+ "DeviceModeView.js",
+ "DeviceModeWrapper.js"
],
"resources": [
"devicesSettingsTab.css",
diff --git a/front_end/es6.js b/front_end/es6.js
index 34a94495dd..875ed2ab9e 100644
--- a/front_end/es6.js
+++ b/front_end/es6.js
@@ -986,6 +986,25 @@ Promise.prototype.then = function(opt_onFulfilled, opt_onRejected) {};
Promise.prototype.catch = function(onRejected) {};
+/**
+ * @param {T} value
+ * @param {number=} start
+ * @param {number=} end
+ * @this {!Array}
+ * @template T
+ */
+Array.prototype.fill = function(value, start, end) {}
+
+
+/**
+ * @param {function(this:S,T,number,!Array)} callback
+ * @param {?S=} thisArg
+ * @this {!Array}
+ * @template T,S
+ */
+Array.prototype.find = function(callback, thisArg) {}
+
+
/** @return {!Array} */
Array.prototype.keys;
@@ -995,7 +1014,6 @@ Array.prototype.keys;
*/
Array.prototype.entries;
-
/** @return {!Array} */
Object.getOwnPropertySymbols;
diff --git a/front_end/externs.js b/front_end/externs.js
index 93211c5129..773a9fde6e 100644
--- a/front_end/externs.js
+++ b/front_end/externs.js
@@ -171,15 +171,6 @@ Array.prototype.intersectOrdered = function(array, comparator) {}
*/
Array.prototype.mergeOrdered = function(array, comparator) {}
-/**
- * @param {T} value
- * @param {number} start
- * @param {number=} end
- * @this {!Array.}
- * @template T
- */
-Array.prototype.fill = function(value, start, end) {}
-
// File System API
/**
* @constructor
diff --git a/front_end/host/UserMetrics.js b/front_end/host/UserMetrics.js
index 093bac74e6..a8a545f0c9 100644
--- a/front_end/host/UserMetrics.js
+++ b/front_end/host/UserMetrics.js
@@ -72,15 +72,6 @@ WebInspector.UserMetrics._PanelCodes = {
layers: 9
}
-WebInspector.UserMetrics._DrawerCodes = {
- "console": 1,
- "animations": 2,
- "network.config": 3,
- "rendering": 4,
- "sensors": 5,
- "sources.search": 6
-}
-
WebInspector.UserMetrics.prototype = {
/**
* @param {string} panelName
@@ -92,16 +83,6 @@ WebInspector.UserMetrics.prototype = {
InspectorFrontendHost.recordEnumeratedHistogram("DevTools.PanelShown", code, size);
},
- /**
- * @param {string} viewId
- */
- drawerShown: function(viewId)
- {
- var code = WebInspector.UserMetrics._DrawerCodes[viewId] || 0;
- var size = Object.keys(WebInspector.UserMetrics._DrawerCodes).length + 1;
- InspectorFrontendHost.recordEnumeratedHistogram("DevTools.DrawerShown", code, size);
- },
-
/**
* @param {!WebInspector.UserMetrics.Action} action
*/
diff --git a/front_end/main/AdvancedApp.js b/front_end/main/AdvancedApp.js
index 0d834162ca..58e9b540cc 100644
--- a/front_end/main/AdvancedApp.js
+++ b/front_end/main/AdvancedApp.js
@@ -28,7 +28,7 @@ WebInspector.AdvancedApp.prototype = {
this._inspectedPagePlaceholder = new WebInspector.InspectedPagePlaceholder();
this._inspectedPagePlaceholder.addEventListener(WebInspector.InspectedPagePlaceholder.Events.Update, this._onSetInspectedPageBounds.bind(this), this);
- this._deviceModeView = new WebInspector.DeviceModeView.Wrapper(this._inspectedPagePlaceholder);
+ this._deviceModeView = new WebInspector.DeviceModeWrapper(this._inspectedPagePlaceholder);
WebInspector.dockController.addEventListener(WebInspector.DockController.Events.BeforeDockSideChanged, this._onBeforeDockSideChange, this);
WebInspector.dockController.addEventListener(WebInspector.DockController.Events.DockSideChanged, this._onDockSideChange, this);
diff --git a/front_end/main/Main.js b/front_end/main/Main.js
index ce3ec7c898..334ec50cb5 100644
--- a/front_end/main/Main.js
+++ b/front_end/main/Main.js
@@ -104,6 +104,7 @@ WebInspector.Main.prototype = {
{
Runtime.experiments.register("accessibilityInspection", "Accessibility Inspection");
Runtime.experiments.register("applyCustomStylesheet", "Allow custom UI themes");
+ Runtime.experiments.register("appBanner", "App banner support", true);
Runtime.experiments.register("blackboxJSFramesOnTimeline", "Blackbox JavaScript frames on Timeline", true);
Runtime.experiments.register("colorContrastRatio", "Contrast ratio line in color picker", true);
Runtime.experiments.register("cpuThrottling", "CPU throttling", true);
@@ -113,7 +114,7 @@ WebInspector.Main.prototype = {
Runtime.experiments.register("inputEventsOnTimelineOverview", "Input events on Timeline overview", true);
Runtime.experiments.register("layersPanel", "Layers panel");
Runtime.experiments.register("layoutEditor", "Layout editor", true);
- Runtime.experiments.register("materialDesign", "Material design");
+ Runtime.experiments.register("inspectTooltip", "Dark inspect element tooltip");
Runtime.experiments.register("multipleTimelineViews", "Multiple main views on Timeline", true);
Runtime.experiments.register("networkRequestHeadersFilterInDetailsView", "Network request headers filter in details view", true);
Runtime.experiments.register("networkRequestsOnTimeline", "Network requests on Timeline", true);
@@ -146,6 +147,7 @@ WebInspector.Main.prototype = {
}
Runtime.experiments.setDefaultExperiments([
+ "inspectTooltip",
"securityPanel"
]);
},
@@ -202,6 +204,7 @@ WebInspector.Main.prototype = {
new WebInspector.OverlayController();
new WebInspector.ExecutionContextSelector(WebInspector.targetManager, WebInspector.context);
+ new WebInspector.BlackboxManager();
var autoselectPanel = WebInspector.UIString("auto");
var openAnchorLocationSetting = WebInspector.settings.createSetting("openLinkHandler", autoselectPanel);
@@ -213,6 +216,7 @@ WebInspector.Main.prototype = {
new WebInspector.Main.InspectedNodeRevealer();
new WebInspector.NetworkPanelIndicator();
new WebInspector.SourcesPanelIndicator();
+ new WebInspector.AutoAttachToCreatedPagesSync();
WebInspector.domBreakpointsSidebarPane = new WebInspector.DOMBreakpointsSidebarPane();
WebInspector.actionRegistry = new WebInspector.ActionRegistry();
@@ -317,7 +321,7 @@ WebInspector.Main.prototype = {
this._mainTarget.registerInspectorDispatcher(this);
InspectorFrontendHost.events.addEventListener(InspectorFrontendHostAPI.Events.ReloadInspectedPage, this._reloadInspectedPage, this);
- if (this._mainTarget.isServiceWorker())
+ if (this._mainTarget.isServiceWorker() || this._mainTarget.isPage())
this._mainTarget.runtimeAgent().run();
if (this._appUIPresented)
@@ -1088,4 +1092,41 @@ WebInspector.TargetCrashedScreen.prototype = {
__proto__: WebInspector.VBox.prototype
}
+/**
+ * @constructor
+ * @implements {WebInspector.TargetManager.Observer}
+ */
+WebInspector.AutoAttachToCreatedPagesSync = function()
+{
+ this._setting = WebInspector.settings.moduleSetting("autoAttachToCreatedPages");
+ this._setting.addChangeListener(this._update, this);
+ WebInspector.targetManager.observeTargets(this, WebInspector.Target.Type.Page);
+}
+
+WebInspector.AutoAttachToCreatedPagesSync.prototype = {
+ _update: function()
+ {
+ var value = this._setting.get();
+ for (var target of WebInspector.targetManager.targets(WebInspector.Target.Type.Page))
+ target.pageAgent().setAutoAttachToCreatedPages(value);
+ },
+
+ /**
+ * @param {!WebInspector.Target} target
+ * @override
+ */
+ targetAdded: function(target)
+ {
+ target.pageAgent().setAutoAttachToCreatedPages(this._setting.get());
+ },
+
+ /**
+ * @param {!WebInspector.Target} target
+ * @override
+ */
+ targetRemoved: function(target)
+ {
+ }
+}
+
new WebInspector.Main();
diff --git a/front_end/main/Tests.js b/front_end/main/Tests.js
index 390811fd6f..e63ad97079 100644
--- a/front_end/main/Tests.js
+++ b/front_end/main/Tests.js
@@ -418,6 +418,21 @@ TestSuite.prototype.enableTouchEmulation = function()
deviceModeModel._applyTouch(true, true);
};
+TestSuite.prototype.enableAutoAttachToCreatedPages = function()
+{
+ WebInspector.settingForTest("autoAttachToCreatedPages").set(true);
+}
+
+TestSuite.prototype.waitForDebuggerPaused = function()
+{
+ var debuggerModel = WebInspector.DebuggerModel.fromTarget(WebInspector.targetManager.mainTarget());
+ if (debuggerModel.debuggerPausedDetails)
+ return;
+
+ this.takeControl();
+ this._waitForScriptPause(this.releaseControl.bind(this));
+}
+
TestSuite.prototype.switchToPanel = function(panelName)
{
this.showPanel(panelName).then(this.releaseControl.bind(this));
diff --git a/front_end/main/module.json b/front_end/main/module.json
index c9ad6d98f7..cbf8c5ba3a 100644
--- a/front_end/main/module.json
+++ b/front_end/main/module.json
@@ -217,6 +217,7 @@
"title": "Disable cache (while DevTools is open)",
"settingName": "cacheDisabled",
"settingType": "boolean",
+ "order": 0,
"defaultValue": false
},
{
@@ -225,6 +226,16 @@
"title": "Disable JavaScript",
"settingName": "javaScriptDisabled",
"settingType": "boolean",
+ "order": 1,
+ "defaultValue": false
+ },
+ {
+ "type": "setting",
+ "category": "",
+ "title": "Auto-open DevTools for popups",
+ "settingName": "autoAttachToCreatedPages",
+ "settingType": "boolean",
+ "order": 2,
"defaultValue": false
},
{
diff --git a/front_end/network/NetworkDataGridNode.js b/front_end/network/NetworkDataGridNode.js
index 194f85df49..de2bd9cac4 100644
--- a/front_end/network/NetworkDataGridNode.js
+++ b/front_end/network/NetworkDataGridNode.js
@@ -47,6 +47,21 @@ WebInspector.NetworkDataGridNode = function(parentView, request)
WebInspector.NetworkDataGridNode._hoveredRowSymbol = Symbol("hoveredRow");
WebInspector.NetworkDataGridNode.prototype = {
+ /**
+ * @return {string}
+ */
+ displayType: function()
+ {
+ var mimeType = this._request.mimeType || this._request.requestContentType() || "";
+ var resourceType = this._request.resourceType();
+ var simpleType = resourceType.name();
+
+ if (resourceType == WebInspector.resourceTypes.Other || resourceType == WebInspector.resourceTypes.Image)
+ simpleType = mimeType.replace(/^(application|image)\//, "");
+
+ return simpleType;
+ },
+
/**
* @return {!WebInspector.NetworkRequest}
*/
@@ -309,15 +324,7 @@ WebInspector.NetworkDataGridNode.prototype = {
*/
_renderTypeCell: function(cell)
{
- var mimeType = this._request.mimeType || this._request.requestContentType() || "";
- var resourceType = this._request.resourceType();
- var simpleType = resourceType.name();
-
- if (resourceType == WebInspector.resourceTypes.Other
- || resourceType == WebInspector.resourceTypes.Image)
- simpleType = mimeType.replace(/^(application|image)\//, "");
-
- cell.setTextAndTitle(simpleType);
+ cell.setTextAndTitle(this.displayType());
},
/**
@@ -597,6 +604,23 @@ WebInspector.NetworkDataGridNode.SizeComparator = function(a, b)
return (a._request.transferSize - b._request.transferSize) || a._request.indentityCompare(b._request);
}
+/**
+ * @param {!WebInspector.NetworkDataGridNode} a
+ * @param {!WebInspector.NetworkDataGridNode} b
+ * @return {number}
+ */
+WebInspector.NetworkDataGridNode.TypeComparator = function(a, b)
+{
+ var aSimpleType = a.displayType();
+ var bSimpleType = b.displayType();
+
+ if (aSimpleType > bSimpleType)
+ return 1;
+ if (bSimpleType > aSimpleType)
+ return -1;
+ return a._request.indentityCompare(b._request);
+}
+
/**
* @param {!WebInspector.NetworkDataGridNode} a
* @param {!WebInspector.NetworkDataGridNode} b
diff --git a/front_end/network/NetworkLogView.js b/front_end/network/NetworkLogView.js
index 406dd1d038..133b7d7a09 100644
--- a/front_end/network/NetworkLogView.js
+++ b/front_end/network/NetworkLogView.js
@@ -628,7 +628,7 @@ WebInspector.NetworkLogView.prototype = {
this._sortingFunctions.scheme = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "scheme", false);
this._sortingFunctions.domain = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "domain", false);
this._sortingFunctions.remoteAddress = WebInspector.NetworkDataGridNode.RemoteAddressComparator;
- this._sortingFunctions.type = WebInspector.NetworkDataGridNode.RequestPropertyComparator.bind(null, "mimeType", false);
+ this._sortingFunctions.type = WebInspector.NetworkDataGridNode.TypeComparator;
this._sortingFunctions.initiator = WebInspector.NetworkDataGridNode.InitiatorComparator;
this._sortingFunctions.cookies = WebInspector.NetworkDataGridNode.RequestCookiesCountComparator;
this._sortingFunctions.setCookies = WebInspector.NetworkDataGridNode.ResponseCookiesCountComparator;
@@ -1231,7 +1231,7 @@ WebInspector.NetworkLogView.prototype = {
anchor = element.enclosingNodeOrSelfWithClass("network-script-initiated");
if (anchor && anchor.request) {
var initiator = /** @type {!WebInspector.NetworkRequest} */ (anchor.request).initiator();
- if (initiator && (initiator.stackTrace || initiator.asyncStackTrace))
+ if (initiator && initiator.stack)
return anchor;
}
},
@@ -1246,7 +1246,7 @@ WebInspector.NetworkLogView.prototype = {
if (anchor.classList.contains("network-script-initiated")) {
var request = /** @type {!WebInspector.NetworkRequest} */ (anchor.request);
var initiator = /** @type {!NetworkAgent.Initiator} */ (request.initiator());
- content = WebInspector.DOMPresentationUtils.buildStackTracePreviewContents(request.target(), this._popupLinkifier, initiator.stackTrace, initiator.asyncStackTrace);
+ content = WebInspector.DOMPresentationUtils.buildStackTracePreviewContents(request.target(), this._popupLinkifier, initiator.stack);
popover.setCanShrink(true);
} else {
content = WebInspector.RequestTimingView.createTimingTable(anchor.parentElement.request, this._timeCalculator.minimumBoundary());
diff --git a/front_end/platform/utilities.js b/front_end/platform/utilities.js
index f7e2dd715b..658c4aa6fd 100644
--- a/front_end/platform/utilities.js
+++ b/front_end/platform/utilities.js
@@ -1199,7 +1199,7 @@ function createSearchRegex(query, caseSensitive, isRegex)
*/
function createPlainTextSearchRegex(query, flags)
{
- // This should be kept the same as the one in ContentSearchUtils.cpp.
+ // This should be kept the same as the one in V8StringUtil.cpp.
var regexSpecialCharacters = String.regexSpecialCharacters();
var regex = "";
for (var i = 0; i < query.length; ++i) {
diff --git a/front_end/profiler/CPUProfileDataGrid.js b/front_end/profiler/CPUProfileDataGrid.js
index f22469de52..5b507f74a5 100644
--- a/front_end/profiler/CPUProfileDataGrid.js
+++ b/front_end/profiler/CPUProfileDataGrid.js
@@ -75,7 +75,7 @@ WebInspector.ProfileDataGridNode.prototype = {
if (this.profileNode.scriptId !== "0") {
var target = this.tree.profileView.target();
- var callFrame = /** @type {!ConsoleAgent.CallFrame} */ (this.profileNode);
+ var callFrame = /** @type {!RuntimeAgent.CallFrame} */ (this.profileNode);
var urlElement = this.tree.profileView._linkifier.linkifyConsoleCallFrame(target, callFrame, "profile-node-file");
urlElement.style.maxWidth = "75%";
cell.insertBefore(urlElement, cell.firstChild);
diff --git a/front_end/profiler/CPUProfileFlameChart.js b/front_end/profiler/CPUProfileFlameChart.js
index 9fcbd6067d..5c08f2e78b 100644
--- a/front_end/profiler/CPUProfileFlameChart.js
+++ b/front_end/profiler/CPUProfileFlameChart.js
@@ -229,7 +229,7 @@ WebInspector.CPUFlameChartDataProvider.prototype = {
var totalTime = this._millisecondsToString(timelineData.entryTotalTimes[entryIndex]);
pushEntryInfoRow(WebInspector.UIString("Self time"), selfTime);
pushEntryInfoRow(WebInspector.UIString("Total time"), totalTime);
- var callFrame = /** @type {!ConsoleAgent.CallFrame} */ (node);
+ var callFrame = /** @type {!RuntimeAgent.CallFrame} */ (node);
var text = (new WebInspector.Linkifier()).linkifyConsoleCallFrame(this._target, callFrame).textContent;
pushEntryInfoRow(WebInspector.UIString("URL"), text);
pushEntryInfoRow(WebInspector.UIString("Aggregated self time"), Number.secondsToString(node.selfTime / 1000, true));
@@ -285,7 +285,9 @@ WebInspector.CPUFlameChartDataProvider.prototype = {
entryColor: function(entryIndex)
{
var node = this._entryNodes[entryIndex];
- return this._colorGenerator.colorForID(node.functionName + ":" + node.url);
+ // For idle and program, we want different 'shades of gray', so we fallback to functionName as scriptId = 0
+ // For rest of nodes e.g eval scripts, if url is empty then scriptId will be guaranteed to be non-zero
+ return this._colorGenerator.colorForID(node.url || (node.scriptId !== "0" ? node.scriptId : node.functionName));
},
/**
@@ -359,9 +361,10 @@ WebInspector.CPUFlameChartDataProvider.colorGenerator = function()
{ min: 180, max: 310, count: 7 },
{ min: 50, max: 80, count: 5 },
{ min: 80, max: 90, count: 3 });
- colorGenerator.setColorForID("(idle):", "hsl(0, 0%, 94%)");
- colorGenerator.setColorForID("(program):", "hsl(0, 0%, 80%)");
- colorGenerator.setColorForID("(garbage collector):", "hsl(0, 0%, 80%)");
+
+ colorGenerator.setColorForID("(idle)", "hsl(0, 0%, 94%)");
+ colorGenerator.setColorForID("(program)", "hsl(0, 0%, 80%)");
+ colorGenerator.setColorForID("(garbage collector)", "hsl(0, 0%, 80%)");
WebInspector.CPUFlameChartDataProvider._colorGenerator = colorGenerator;
}
return WebInspector.CPUFlameChartDataProvider._colorGenerator;
diff --git a/front_end/profiler/CPUProfileView.js b/front_end/profiler/CPUProfileView.js
index 2748e31d74..74057f248e 100644
--- a/front_end/profiler/CPUProfileView.js
+++ b/front_end/profiler/CPUProfileView.js
@@ -501,7 +501,6 @@ WebInspector.CPUProfileType.prototype = {
undefined,
undefined,
undefined,
- undefined,
[{
functionName: "",
scriptId: scriptLocation.scriptId,
diff --git a/front_end/profiler/profilesPanel.css b/front_end/profiler/profilesPanel.css
index 13547d8918..d5fa27a776 100644
--- a/front_end/profiler/profilesPanel.css
+++ b/front_end/profiler/profilesPanel.css
@@ -72,10 +72,6 @@
border-bottom: 1px solid rgb(202, 202, 202);
}
-.material .profiles-toolbar {
- flex: 0 0 29px;
-}
-
.profile-launcher-view-tree-item > .icon {
width: 4px !important;
visibility: hidden;
diff --git a/front_end/promises/PromisePane.js b/front_end/promises/PromisePane.js
index a2f2fa499f..24381fe2a6 100644
--- a/front_end/promises/PromisePane.js
+++ b/front_end/promises/PromisePane.js
@@ -104,14 +104,15 @@ WebInspector.PromiseDetails.prototype = {
this.status = details.status;
if (details.parentId)
this.parentId = details.parentId;
- if (details.callFrame)
- this.callFrame = details.callFrame;
if (details.creationTime)
this.creationTime = details.creationTime;
if (details.settlementTime)
this.settlementTime = details.settlementTime;
- if (details.creationStack)
+ if (details.creationStack) {
this.creationStack = details.creationStack;
+ if (this.creationStack.callFrames.length)
+ this.callFrame = this.creationStack.callFrames[0];
+ }
if (details.asyncCreationStack)
this.asyncCreationStack = details.asyncCreationStack;
if (details.settlementStack)
@@ -600,16 +601,12 @@ WebInspector.PromisePane.prototype = {
var details = this._promiseDetailsByDebuggerModel.get(this._debuggerModel).get(node.promiseId());
var stackTrace;
- var asyncStackTrace;
- if (anchor.classList.contains("created-column")) {
+ if (anchor.classList.contains("created-column"))
stackTrace = details.creationStack;
- asyncStackTrace = details.asyncCreationStack;
- } else {
+ else
stackTrace = details.settlementStack;
- asyncStackTrace = details.asyncSettlementStack;
- }
- var content = WebInspector.DOMPresentationUtils.buildStackTracePreviewContents(this._debuggerModel.target(), this._linkifier, stackTrace, asyncStackTrace);
+ var content = WebInspector.DOMPresentationUtils.buildStackTracePreviewContents(this._debuggerModel.target(), this._linkifier, stackTrace);
popover.setCanShrink(true);
popover.showForAnchor(content, anchor);
},
@@ -690,7 +687,7 @@ WebInspector.PromiseDataGridNode.prototype = {
/**
* @param {!Element} cell
- * @param {?ConsoleAgent.CallFrame=} callFrame
+ * @param {?RuntimeAgent.CallFrame=} callFrame
*/
_appendCallFrameAnchor: function(cell, callFrame)
{
@@ -739,7 +736,7 @@ WebInspector.PromiseDataGridNode.prototype = {
break;
case "settled":
- this._appendCallFrameAnchor(cell, details.settlementStack ? details.settlementStack[0] : null);
+ this._appendCallFrameAnchor(cell, details.settlementStack && details.settlementStack.callFrames.length ? details.settlementStack.callFrames[0] : null);
break;
case "tts":
@@ -762,7 +759,7 @@ WebInspector.PromiseDataGridNode.prototype = {
},
/**
- * @param {?ConsoleAgent.CallFrame=} callFrame
+ * @param {?RuntimeAgent.CallFrame=} callFrame
* @return {string}
*/
_callFrameAnchorTextForSearch: function(callFrame)
@@ -784,7 +781,7 @@ WebInspector.PromiseDataGridNode.prototype = {
var texts = [
WebInspector.beautifyFunctionName(details.callFrame ? details.callFrame.functionName : ""),
this._callFrameAnchorTextForSearch(details.callFrame),
- this._callFrameAnchorTextForSearch(details.settlementStack ? details.settlementStack[0] : null),
+ this._callFrameAnchorTextForSearch(details.settlementStack && details.settlementStack.callFrames.length ? details.settlementStack.callFrames[0] : null),
this._ttsCellText().replace(/\u2009/g, " ") // \u2009 is a thin space.
];
return texts.join(" ");
diff --git a/front_end/screencast/module.json b/front_end/screencast/module.json
index ed353043eb..0f9edda280 100644
--- a/front_end/screencast/module.json
+++ b/front_end/screencast/module.json
@@ -15,12 +15,13 @@
"type": "@WebInspector.ActionDelegate",
"actionId": "screencast.request-app-banner",
"className": "WebInspector.ScreencastApp.ActionDelegate",
- "title": "Request app banner"
+ "title": "Request app banner\u2026"
},
{
"type": "context-menu-item",
"condition": "remoteFrontend",
"location": "mainMenu/tools",
+ "experiment": "appBanner",
"order": 10,
"actionId": "screencast.request-app-banner"
}
diff --git a/front_end/sdk/CPUProfileDataModel.js b/front_end/sdk/CPUProfileDataModel.js
index 0a7872fdc5..8a0a92c50b 100644
--- a/front_end/sdk/CPUProfileDataModel.js
+++ b/front_end/sdk/CPUProfileDataModel.js
@@ -16,6 +16,7 @@ WebInspector.CPUProfileDataModel = function(profile)
this.profileEndTime = profile.endTime * 1000;
this._assignParentsInProfile();
if (this.samples) {
+ this._sortSamples();
this._normalizeTimestamps();
this._buildIdToNodeMap();
this._fixMissingSamples();
@@ -156,6 +157,34 @@ WebInspector.CPUProfileDataModel.prototype = {
}
},
+ _sortSamples: function()
+ {
+ var timestamps = this.timestamps;
+ if (!timestamps)
+ return;
+ var samples = this.samples;
+ var indices = timestamps.map((x, index) => index);
+ indices.sort((a, b) => timestamps[a] - timestamps[b]);
+ for (var i = 0; i < timestamps.length; ++i) {
+ var index = indices[i];
+ if (index === i)
+ continue;
+ // Move items in a cycle.
+ var savedTimestamp = timestamps[i];
+ var savedSample = samples[i];
+ var currentIndex = i;
+ while (index !== i) {
+ samples[currentIndex] = samples[index];
+ timestamps[currentIndex] = timestamps[index];
+ currentIndex = index;
+ index = indices[index];
+ indices[currentIndex] = currentIndex;
+ }
+ samples[currentIndex] = savedSample;
+ timestamps[currentIndex] = savedTimestamp;
+ }
+ },
+
_normalizeTimestamps: function()
{
var timestamps = this.timestamps;
@@ -240,7 +269,7 @@ WebInspector.CPUProfileDataModel.prototype = {
*/
function bottomNode(node)
{
- while (node.parent)
+ while (node.parent.parent)
node = node.parent;
return node;
}
diff --git a/front_end/sdk/CSSStyleModel.js b/front_end/sdk/CSSStyleModel.js
index 82577f0148..06759431f7 100644
--- a/front_end/sdk/CSSStyleModel.js
+++ b/front_end/sdk/CSSStyleModel.js
@@ -132,10 +132,11 @@ WebInspector.CSSStyleModel.prototype = {
* @param {!Array.=} matchedPayload
* @param {!Array.=} pseudoPayload
* @param {!Array.=} inheritedPayload
+ * @param {!Array.=} animationsPayload
* @return {?WebInspector.CSSStyleModel.MatchedStyleResult}
* @this {WebInspector.CSSStyleModel}
*/
- function callback(error, inlinePayload, attributesPayload, matchedPayload, pseudoPayload, inheritedPayload)
+ function callback(error, inlinePayload, attributesPayload, matchedPayload, pseudoPayload, inheritedPayload, animationsPayload)
{
if (error)
return null;
@@ -144,7 +145,7 @@ WebInspector.CSSStyleModel.prototype = {
if (!node)
return null;
- return new WebInspector.CSSStyleModel.MatchedStyleResult(this, node, inlinePayload, attributesPayload, matchedPayload, pseudoPayload, inheritedPayload);
+ return new WebInspector.CSSStyleModel.MatchedStyleResult(this, node, inlinePayload, attributesPayload, matchedPayload, pseudoPayload, inheritedPayload, animationsPayload);
}
return this._agent.getMatchedStylesForNode(nodeId, callback.bind(this));
@@ -1034,7 +1035,7 @@ WebInspector.CSSValue.prototype = {
/**
* @constructor
* @param {!WebInspector.CSSStyleModel} cssModel
- * @param {!CSSAgent.CSSRule} payload
+ * @param {{style: !CSSAgent.CSSStyle, styleSheetId: (string|undefined), origin: !CSSAgent.StyleSheetOrigin}} payload
*/
WebInspector.CSSRule = function(cssModel, payload)
{
@@ -1150,9 +1151,9 @@ WebInspector.CSSStyleRule.prototype = {
/**
* @param {!DOMAgent.NodeId} nodeId
* @param {string} newSelector
- * @param {function(boolean)} userCallback
+ * @return {!Promise.}
*/
- setSelectorText: function(nodeId, newSelector, userCallback)
+ setSelectorText: function(nodeId, newSelector)
{
/**
* @param {?Protocol.Error} error
@@ -1175,10 +1176,9 @@ WebInspector.CSSStyleRule.prototype = {
if (!range)
throw "Rule selector is not editable";
WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action.StyleRuleEdited);
- this._cssModel._agent.setRuleSelector(this.styleSheetId, range, newSelector, callback.bind(this))
+ return this._cssModel._agent.setRuleSelector(this.styleSheetId, range, newSelector, callback.bind(this))
.then(onNewSelectors.bind(this))
- .catchException(false)
- .then(userCallback);
+ .catchException(false);
/**
* @param {?Array} selectors
@@ -1304,6 +1304,105 @@ WebInspector.CSSStyleRule.prototype = {
__proto__: WebInspector.CSSRule.prototype
}
+/**
+ * @constructor
+ * @param {!WebInspector.CSSStyleModel} cssModel
+ * @param {!CSSAgent.CSSKeyframesRule} payload
+ */
+WebInspector.CSSKeyframesRule = function(cssModel, payload)
+{
+ this._cssModel = cssModel;
+ this._animationName = new WebInspector.CSSValue(payload.animationName);
+ this._keyframes = payload.keyframes.map(keyframeRule => new WebInspector.CSSKeyframeRule(cssModel, keyframeRule));
+}
+
+WebInspector.CSSKeyframesRule.prototype = {
+ /**
+ * @return {!WebInspector.CSSValue}
+ */
+ name: function()
+ {
+ return this._animationName;
+ },
+
+ /**
+ * @return {!Array.}
+ */
+ keyframes: function()
+ {
+ return this._keyframes;
+ }
+}
+
+/**
+ * @constructor
+ * @extends {WebInspector.CSSRule}
+ * @param {!WebInspector.CSSStyleModel} cssModel
+ * @param {!CSSAgent.CSSKeyframeRule} payload
+ */
+WebInspector.CSSKeyframeRule = function(cssModel, payload)
+{
+ WebInspector.CSSRule.call(this, cssModel, payload);
+ this._keyText = new WebInspector.CSSValue(payload.keyText);
+}
+
+WebInspector.CSSKeyframeRule.prototype = {
+ /**
+ * @return {!WebInspector.CSSValue}
+ */
+ key: function()
+ {
+ return this._keyText;
+ },
+
+ /**
+ * @override
+ * @param {string} styleSheetId
+ * @param {!WebInspector.TextRange} oldRange
+ * @param {!WebInspector.TextRange} newRange
+ */
+ sourceStyleSheetEdited: function(styleSheetId, oldRange, newRange)
+ {
+ if (this.styleSheetId === styleSheetId)
+ this._keyText.sourceStyleRuleEdited(oldRange, newRange);
+ WebInspector.CSSRule.prototype.sourceStyleSheetEdited.call(this, styleSheetId, oldRange, newRange);
+ },
+
+ /**
+ * @param {string} newKeyText
+ * @return {!Promise.}
+ */
+ setKeyText: function(newKeyText)
+ {
+ /**
+ * @param {?Protocol.Error} error
+ * @param {!CSSAgent.Value} payload
+ * @return {boolean}
+ * @this {WebInspector.CSSKeyframeRule}
+ */
+ function callback(error, payload)
+ {
+ if (error || !payload)
+ return false;
+ this._cssModel._domModel.markUndoableState();
+ this._cssModel._fireStyleSheetChanged(/** @type {string} */(this.styleSheetId));
+ this._keyText = new WebInspector.CSSValue(payload);
+ return true;
+ }
+
+ if (!this.styleSheetId)
+ throw "No rule stylesheet id";
+ var range = this._keyText.range;
+ if (!range)
+ throw "Keyframe key is not editable";
+ WebInspector.userMetrics.actionTaken(WebInspector.UserMetrics.Action.StyleRuleEdited);
+ return this._cssModel._agent.setKeyframeKey(this.styleSheetId, range, newKeyText, callback.bind(this))
+ .catchException(false);
+ },
+
+ __proto__: WebInspector.CSSRule.prototype
+}
+
/**
* @constructor
* @param {!WebInspector.CSSStyleDeclaration} ownerStyle
@@ -2115,14 +2214,16 @@ WebInspector.CSSStyleModel.fromNode = function(node)
* @param {!Array.=} matchedPayload
* @param {!Array.=} pseudoPayload
* @param {!Array.=} inheritedPayload
+ * @param {!Array.=} animationsPayload
*/
-WebInspector.CSSStyleModel.MatchedStyleResult = function(cssModel, node, inlinePayload, attributesPayload, matchedPayload, pseudoPayload, inheritedPayload)
+WebInspector.CSSStyleModel.MatchedStyleResult = function(cssModel, node, inlinePayload, attributesPayload, matchedPayload, pseudoPayload, inheritedPayload, animationsPayload)
{
this._cssModel = cssModel;
this._node = node;
this._nodeStyles = [];
this._nodeForStyle = new Map();
this._inheritedStyles = new Set();
+ this._keyframes = [];
/**
* @this {WebInspector.CSSStyleModel.MatchedStyleResult}
@@ -2200,6 +2301,9 @@ WebInspector.CSSStyleModel.MatchedStyleResult = function(cssModel, node, inlineP
}
}
+ if (animationsPayload)
+ this._keyframes = animationsPayload.map(rule => new WebInspector.CSSKeyframesRule(cssModel, rule));
+
this.resetActiveProperties();
}
@@ -2243,6 +2347,14 @@ WebInspector.CSSStyleModel.MatchedStyleResult.prototype = {
return this._nodeStyles;
},
+ /**
+ * @return {!Array.}
+ */
+ keyframes: function()
+ {
+ return this._keyframes;
+ },
+
/**
* @return {!Map.>}
*/
diff --git a/front_end/sdk/ConsoleModel.js b/front_end/sdk/ConsoleModel.js
index 9659f0946a..aff5da3076 100644
--- a/front_end/sdk/ConsoleModel.js
+++ b/front_end/sdk/ConsoleModel.js
@@ -199,7 +199,7 @@ WebInspector.ConsoleModel.evaluateCommandInConsole = function(executionContext,
* @param {?WebInspector.RemoteObject} result
* @param {boolean} wasThrown
* @param {?RuntimeAgent.RemoteObject=} valueResult
- * @param {?DebuggerAgent.ExceptionDetails=} exceptionDetails
+ * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails
*/
function printResult(result, wasThrown, valueResult, exceptionDetails)
{
@@ -239,15 +239,14 @@ WebInspector.ConsoleModel.clearConsole = function()
* @param {number=} column
* @param {!NetworkAgent.RequestId=} requestId
* @param {!Array.=} parameters
- * @param {!Array.=} stackTrace
+ * @param {!RuntimeAgent.StackTrace=} stackTrace
* @param {number=} timestamp
* @param {!RuntimeAgent.ExecutionContextId=} executionContextId
- * @param {!ConsoleAgent.AsyncStackTrace=} asyncStackTrace
* @param {?string=} scriptId
* @param {number=} messageId
* @param {number=} relatedMessageId
*/
-WebInspector.ConsoleMessage = function(target, source, level, messageText, type, url, line, column, requestId, parameters, stackTrace, timestamp, executionContextId, asyncStackTrace, scriptId, messageId, relatedMessageId)
+WebInspector.ConsoleMessage = function(target, source, level, messageText, type, url, line, column, requestId, parameters, stackTrace, timestamp, executionContextId, scriptId, messageId, relatedMessageId)
{
this._target = target;
this.source = source;
@@ -261,11 +260,10 @@ WebInspector.ConsoleMessage = function(target, source, level, messageText, type,
/** @type {number} */
this.column = column || 0;
this.parameters = parameters;
- /** @type {!Array.|undefined} */
+ /** @type {!RuntimeAgent.StackTrace|undefined} */
this.stackTrace = stackTrace;
this.timestamp = timestamp || Date.now();
this.executionContextId = executionContextId || 0;
- this.asyncStackTrace = asyncStackTrace;
this.scriptId = scriptId || null;
this._messageId = messageId || 0;
this._relatedMessageId = relatedMessageId || 0;
@@ -275,8 +273,7 @@ WebInspector.ConsoleMessage = function(target, source, level, messageText, type,
if (this.request) {
var initiator = this.request.initiator();
if (initiator) {
- this.stackTrace = initiator.stackTrace || undefined;
- this.asyncStackTrace = initiator.asyncStackTrace;
+ this.stackTrace = initiator.stack || undefined;
if (initiator.url) {
this.url = initiator.url;
this.line = initiator.lineNumber || 0;
@@ -363,19 +360,6 @@ WebInspector.ConsoleMessage.prototype = {
if (!this._isEqualStackTraces(this.stackTrace, msg.stackTrace))
return false;
- var asyncTrace1 = this.asyncStackTrace;
- var asyncTrace2 = msg.asyncStackTrace;
- while (asyncTrace1 || asyncTrace2) {
- if (!asyncTrace1 || !asyncTrace2)
- return false;
- if (asyncTrace1.description !== asyncTrace2.description)
- return false;
- if (!this._isEqualStackTraces(asyncTrace1.callFrames, asyncTrace2.callFrames))
- return false;
- asyncTrace1 = asyncTrace1.asyncStackTrace;
- asyncTrace2 = asyncTrace2.asyncStackTrace;
- }
-
if (this.parameters) {
if (!msg.parameters || this.parameters.length !== msg.parameters.length)
return false;
@@ -400,24 +384,28 @@ WebInspector.ConsoleMessage.prototype = {
},
/**
- * @param {!Array.|undefined} stackTrace1
- * @param {!Array.|undefined} stackTrace2
+ * @param {!RuntimeAgent.StackTrace|undefined} stackTrace1
+ * @param {!RuntimeAgent.StackTrace|undefined} stackTrace2
* @return {boolean}
*/
_isEqualStackTraces: function(stackTrace1, stackTrace2)
{
- stackTrace1 = stackTrace1 || [];
- stackTrace2 = stackTrace2 || [];
- if (stackTrace1.length !== stackTrace2.length)
+ if (!stackTrace1 !== !stackTrace2)
+ return false;
+ if (!stackTrace1)
+ return true;
+ var callFrames1 = stackTrace1.callFrames;
+ var callFrames2 = stackTrace2.callFrames;
+ if (callFrames1.length !== callFrames2.length)
return false;
- for (var i = 0, n = stackTrace1.length; i < n; ++i) {
- if (stackTrace1[i].url !== stackTrace2[i].url ||
- stackTrace1[i].functionName !== stackTrace2[i].functionName ||
- stackTrace1[i].lineNumber !== stackTrace2[i].lineNumber ||
- stackTrace1[i].columnNumber !== stackTrace2[i].columnNumber)
+ for (var i = 0, n = callFrames1.length; i < n; ++i) {
+ if (callFrames1[i].url !== callFrames2[i].url ||
+ callFrames1[i].functionName !== callFrames2[i].functionName ||
+ callFrames1[i].lineNumber !== callFrames2[i].lineNumber ||
+ callFrames1[i].columnNumber !== callFrames2[i].columnNumber)
return false;
}
- return true;
+ return this._isEqualStackTraces(stackTrace1.parent, stackTrace2.parent);
}
}
@@ -509,10 +497,9 @@ WebInspector.ConsoleDispatcher.prototype = {
payload.column,
payload.networkRequestId,
payload.parameters,
- payload.stackTrace,
+ payload.stack,
payload.timestamp * 1000, // Convert to ms.
payload.executionContextId,
- payload.asyncStackTrace,
payload.scriptId,
payload.messageId,
payload.relatedMessageId);
diff --git a/front_end/sdk/CookieParser.js b/front_end/sdk/CookieParser.js
index 9b2805ae12..1bea7702ad 100644
--- a/front_end/sdk/CookieParser.js
+++ b/front_end/sdk/CookieParser.js
@@ -260,9 +260,9 @@ WebInspector.Cookie.prototype = {
/**
* @return {boolean}
*/
- firstPartyOnly: function ()
+ sameSite: function ()
{
- return "first-party-only" in this._attributes;
+ return "samesite" in this._attributes;
},
/**
@@ -428,8 +428,8 @@ WebInspector.Cookies._parseProtocolCookie = function(target, protocolCookie)
cookie.addAttribute("httpOnly");
if (protocolCookie["secure"])
cookie.addAttribute("secure");
- if (protocolCookie["firstPartyOnly"])
- cookie.addAttribute("first-party-only");
+ if (protocolCookie["sameSite"])
+ cookie.addAttribute("sameSite");
cookie.setSize(protocolCookie["size"]);
return cookie;
}
diff --git a/front_end/sdk/DOMModel.js b/front_end/sdk/DOMModel.js
index 09db47424c..a4bc266262 100644
--- a/front_end/sdk/DOMModel.js
+++ b/front_end/sdk/DOMModel.js
@@ -1826,7 +1826,7 @@ WebInspector.DOMModel.prototype = {
highlightConfig.eventTargetColor = WebInspector.Color.PageHighlight.EventTarget.toProtocolRGBA();
highlightConfig.shapeColor = WebInspector.Color.PageHighlight.Shape.toProtocolRGBA();
highlightConfig.shapeMarginColor = WebInspector.Color.PageHighlight.ShapeMargin.toProtocolRGBA();
- highlightConfig.displayAsMaterial = Runtime.experiments.isEnabled("materialDesign");
+ highlightConfig.displayAsMaterial = Runtime.experiments.isEnabled("inspectTooltip");
}
return highlightConfig;
},
diff --git a/front_end/sdk/DebuggerModel.js b/front_end/sdk/DebuggerModel.js
index b64facf034..308efd7a83 100644
--- a/front_end/sdk/DebuggerModel.js
+++ b/front_end/sdk/DebuggerModel.js
@@ -55,12 +55,8 @@ WebInspector.DebuggerModel = function(target)
WebInspector.moduleSetting("pauseOnExceptionEnabled").addChangeListener(this._pauseOnExceptionStateChanged, this);
WebInspector.moduleSetting("pauseOnCaughtException").addChangeListener(this._pauseOnExceptionStateChanged, this);
WebInspector.moduleSetting("enableAsyncStackTraces").addChangeListener(this.asyncStackTracesStateChanged, this);
- WebInspector.moduleSetting("skipStackFramesPattern").addChangeListener(this._applySkipStackFrameSettings, this);
- WebInspector.moduleSetting("skipContentScripts").addChangeListener(this._applySkipStackFrameSettings, this);
this.enableDebugger();
-
- this._applySkipStackFrameSettings();
}
/** @typedef {{location: ?WebInspector.DebuggerModel.Location, sourceURL: ?string, functionName: string, scopeChain: (Array.|null)}} */
@@ -459,7 +455,7 @@ WebInspector.DebuggerModel.prototype = {
},
/**
- * @param {!DebuggerAgent.ScriptId} scriptId
+ * @param {!RuntimeAgent.ScriptId} scriptId
* @return {!WebInspector.Script}
*/
scriptForId: function(scriptId)
@@ -478,7 +474,7 @@ WebInspector.DebuggerModel.prototype = {
},
/**
- * @param {!DebuggerAgent.ScriptId} scriptId
+ * @param {!RuntimeAgent.ScriptId} scriptId
* @param {string} newSource
* @param {function(?Protocol.Error, !DebuggerAgent.SetScriptSourceError=)} callback
*/
@@ -488,7 +484,7 @@ WebInspector.DebuggerModel.prototype = {
},
/**
- * @param {!DebuggerAgent.ScriptId} scriptId
+ * @param {!RuntimeAgent.ScriptId} scriptId
* @param {string} newSource
* @param {function(?Protocol.Error, !DebuggerAgent.SetScriptSourceError=)} callback
* @param {?Protocol.Error} error
@@ -577,7 +573,7 @@ WebInspector.DebuggerModel.prototype = {
},
/**
- * @param {!DebuggerAgent.ScriptId} scriptId
+ * @param {!RuntimeAgent.ScriptId} scriptId
* @param {string} sourceURL
* @param {number} startLine
* @param {number} startColumn
@@ -658,7 +654,7 @@ WebInspector.DebuggerModel.prototype = {
},
/**
- * @param {!DebuggerAgent.ScriptId} scriptId
+ * @param {!RuntimeAgent.ScriptId} scriptId
* @param {number} lineNumber
* @param {number} columnNumber
* @return {?WebInspector.DebuggerModel.Location}
@@ -712,14 +708,14 @@ WebInspector.DebuggerModel.prototype = {
* @param {boolean} doNotPauseOnExceptionsAndMuteConsole
* @param {boolean} returnByValue
* @param {boolean} generatePreview
- * @param {function(?WebInspector.RemoteObject, boolean, ?RuntimeAgent.RemoteObject=, ?DebuggerAgent.ExceptionDetails=)} callback
+ * @param {function(?WebInspector.RemoteObject, boolean, ?RuntimeAgent.RemoteObject=, ?RuntimeAgent.ExceptionDetails=)} callback
*/
evaluateOnSelectedCallFrame: function(code, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, callback)
{
/**
* @param {?RuntimeAgent.RemoteObject} result
* @param {boolean=} wasThrown
- * @param {?DebuggerAgent.ExceptionDetails=} exceptionDetails
+ * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails
* @this {WebInspector.DebuggerModel}
*/
function didEvaluate(result, wasThrown, exceptionDetails)
@@ -738,11 +734,6 @@ WebInspector.DebuggerModel.prototype = {
this.selectedCallFrame().evaluate(code, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, didEvaluate.bind(this));
},
- _applySkipStackFrameSettings: function()
- {
- this._agent.skipStackFrames(WebInspector.moduleSetting("skipStackFramesPattern").get(), WebInspector.moduleSetting("skipContentScripts").get());
- },
-
/**
* @param {!WebInspector.RemoteObject} remoteObject
* @param {function(?WebInspector.DebuggerModel.FunctionDetails)} callback
@@ -770,60 +761,6 @@ WebInspector.DebuggerModel.prototype = {
}
},
- /**
- * @param {string} expression
- * @param {string} sourceURL
- * @param {boolean} persistScript
- * @param {number} executionContextId
- * @param {function(!DebuggerAgent.ScriptId=, ?DebuggerAgent.ExceptionDetails=)=} callback
- */
- compileScript: function(expression, sourceURL, persistScript, executionContextId, callback)
- {
- this._agent.compileScript(expression, sourceURL, persistScript, executionContextId, innerCallback);
-
- /**
- * @param {?Protocol.Error} error
- * @param {!DebuggerAgent.ScriptId=} scriptId
- * @param {?DebuggerAgent.ExceptionDetails=} exceptionDetails
- */
- function innerCallback(error, scriptId, exceptionDetails)
- {
- if (error) {
- console.error(error);
- return;
- }
- if (callback)
- callback(scriptId, exceptionDetails);
- }
- },
-
- /**
- * @param {!DebuggerAgent.ScriptId} scriptId
- * @param {number} executionContextId
- * @param {string=} objectGroup
- * @param {boolean=} doNotPauseOnExceptionsAndMuteConsole
- * @param {function(?RuntimeAgent.RemoteObject, ?DebuggerAgent.ExceptionDetails=)=} callback
- */
- runScript: function(scriptId, executionContextId, objectGroup, doNotPauseOnExceptionsAndMuteConsole, callback)
- {
- this._agent.runScript(scriptId, executionContextId, objectGroup, doNotPauseOnExceptionsAndMuteConsole, innerCallback);
-
- /**
- * @param {?Protocol.Error} error
- * @param {?RuntimeAgent.RemoteObject} result
- * @param {?DebuggerAgent.ExceptionDetails=} exceptionDetails
- */
- function innerCallback(error, result, exceptionDetails)
- {
- if (error) {
- console.error(error);
- return;
- }
- if (callback)
- callback(result, exceptionDetails);
- }
- },
-
/**
* @param {number} scopeNumber
* @param {string} variableName
@@ -911,8 +848,6 @@ WebInspector.DebuggerModel.prototype = {
return;
WebInspector.moduleSetting("pauseOnExceptionEnabled").removeChangeListener(this._pauseOnExceptionStateChanged, this);
WebInspector.moduleSetting("pauseOnCaughtException").removeChangeListener(this._pauseOnExceptionStateChanged, this);
- WebInspector.moduleSetting("skipStackFramesPattern").removeChangeListener(this._applySkipStackFrameSettings, this);
- WebInspector.moduleSetting("skipContentScripts").removeChangeListener(this._applySkipStackFrameSettings, this);
WebInspector.moduleSetting("enableAsyncStackTraces").removeChangeListener(this.asyncStackTracesStateChanged, this);
},
@@ -1003,7 +938,7 @@ WebInspector.DebuggerDispatcher.prototype = {
/**
* @override
- * @param {!DebuggerAgent.ScriptId} scriptId
+ * @param {!RuntimeAgent.ScriptId} scriptId
* @param {string} sourceURL
* @param {number} startLine
* @param {number} startColumn
@@ -1023,7 +958,7 @@ WebInspector.DebuggerDispatcher.prototype = {
/**
* @override
- * @param {!DebuggerAgent.ScriptId} scriptId
+ * @param {!RuntimeAgent.ScriptId} scriptId
* @param {string} sourceURL
* @param {number} startLine
* @param {number} startColumn
@@ -1276,7 +1211,7 @@ WebInspector.DebuggerModel.CallFrame.prototype = {
* @param {boolean} doNotPauseOnExceptionsAndMuteConsole
* @param {boolean} returnByValue
* @param {boolean} generatePreview
- * @param {function(?RuntimeAgent.RemoteObject, boolean=, ?DebuggerAgent.ExceptionDetails=)} callback
+ * @param {function(?RuntimeAgent.RemoteObject, boolean=, ?RuntimeAgent.ExceptionDetails=)} callback
*/
evaluate: function(code, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, callback)
{
@@ -1284,7 +1219,7 @@ WebInspector.DebuggerModel.CallFrame.prototype = {
* @param {?Protocol.Error} error
* @param {!RuntimeAgent.RemoteObject} result
* @param {boolean=} wasThrown
- * @param {?DebuggerAgent.ExceptionDetails=} exceptionDetails
+ * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails
*/
function didEvaluateOnCallFrame(error, result, wasThrown, exceptionDetails)
{
diff --git a/front_end/sdk/NetworkRequest.js b/front_end/sdk/NetworkRequest.js
index 602c9d52e4..7ef73ea47b 100644
--- a/front_end/sdk/NetworkRequest.js
+++ b/front_end/sdk/NetworkRequest.js
@@ -1083,7 +1083,7 @@ WebInspector.NetworkRequest.prototype = {
url = initiator.url ? initiator.url : url;
lineNumber = initiator.lineNumber ? initiator.lineNumber : lineNumber;
} else if (initiator.type === NetworkAgent.InitiatorType.Script) {
- var topFrame = initiator.stackTrace ? initiator.stackTrace[0] : null;
+ var topFrame = initiator.stack && initiator.stack.callFrames.length ? initiator.stack.callFrames[0] : null;
if (topFrame && topFrame.url) {
type = WebInspector.NetworkRequest.InitiatorType.Script;
url = topFrame.url;
diff --git a/front_end/sdk/RemoteObject.js b/front_end/sdk/RemoteObject.js
index da93ec0038..b48706fb43 100644
--- a/front_end/sdk/RemoteObject.js
+++ b/front_end/sdk/RemoteObject.js
@@ -658,7 +658,7 @@ WebInspector.RemoteObjectImpl.prototype = {
* @param {?Protocol.Error} error
* @param {!Array.} properties
* @param {!Array.=} internalProperties
- * @param {?DebuggerAgent.ExceptionDetails=} exceptionDetails
+ * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails
* @this {WebInspector.RemoteObjectImpl}
*/
function remoteObjectBinder(error, properties, internalProperties, exceptionDetails)
diff --git a/front_end/sdk/RuntimeModel.js b/front_end/sdk/RuntimeModel.js
index 970bbd44db..d5a8cd049f 100644
--- a/front_end/sdk/RuntimeModel.js
+++ b/front_end/sdk/RuntimeModel.js
@@ -160,6 +160,60 @@ WebInspector.RuntimeModel.prototype = {
this._agent.setCustomObjectFormatterEnabled(enabled);
},
+ /**
+ * @param {string} expression
+ * @param {string} sourceURL
+ * @param {boolean} persistScript
+ * @param {number} executionContextId
+ * @param {function(!RuntimeAgent.ScriptId=, ?RuntimeAgent.ExceptionDetails=)=} callback
+ */
+ compileScript: function(expression, sourceURL, persistScript, executionContextId, callback)
+ {
+ this._agent.compileScript(expression, sourceURL, persistScript, executionContextId, innerCallback);
+
+ /**
+ * @param {?Protocol.Error} error
+ * @param {!RuntimeAgent.ScriptId=} scriptId
+ * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails
+ */
+ function innerCallback(error, scriptId, exceptionDetails)
+ {
+ if (error) {
+ console.error(error);
+ return;
+ }
+ if (callback)
+ callback(scriptId, exceptionDetails);
+ }
+ },
+
+ /**
+ * @param {!RuntimeAgent.ScriptId} scriptId
+ * @param {number} executionContextId
+ * @param {string=} objectGroup
+ * @param {boolean=} doNotPauseOnExceptionsAndMuteConsole
+ * @param {function(?RuntimeAgent.RemoteObject, ?RuntimeAgent.ExceptionDetails=)=} callback
+ */
+ runScript: function(scriptId, executionContextId, objectGroup, doNotPauseOnExceptionsAndMuteConsole, callback)
+ {
+ this._agent.runScript(scriptId, executionContextId, objectGroup, doNotPauseOnExceptionsAndMuteConsole, innerCallback);
+
+ /**
+ * @param {?Protocol.Error} error
+ * @param {?RuntimeAgent.RemoteObject} result
+ * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails
+ */
+ function innerCallback(error, result, exceptionDetails)
+ {
+ if (error) {
+ console.error(error);
+ return;
+ }
+ if (callback)
+ callback(result, exceptionDetails);
+ }
+ },
+
__proto__: WebInspector.SDKModel.prototype
}
@@ -268,7 +322,7 @@ WebInspector.ExecutionContext.prototype = {
* @param {boolean} doNotPauseOnExceptionsAndMuteConsole
* @param {boolean} returnByValue
* @param {boolean} generatePreview
- * @param {function(?WebInspector.RemoteObject, boolean, ?RuntimeAgent.RemoteObject=, ?DebuggerAgent.ExceptionDetails=)} callback
+ * @param {function(?WebInspector.RemoteObject, boolean, ?RuntimeAgent.RemoteObject=, ?RuntimeAgent.ExceptionDetails=)} callback
*/
evaluate: function(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, callback)
{
@@ -284,7 +338,7 @@ WebInspector.ExecutionContext.prototype = {
* @param {string} objectGroup
* @param {boolean} returnByValue
* @param {boolean} generatePreview
- * @param {function(?WebInspector.RemoteObject, boolean, ?RuntimeAgent.RemoteObject=, ?DebuggerAgent.ExceptionDetails=)} callback
+ * @param {function(?WebInspector.RemoteObject, boolean, ?RuntimeAgent.RemoteObject=, ?RuntimeAgent.ExceptionDetails=)} callback
*/
globalObject: function(objectGroup, returnByValue, generatePreview, callback)
{
@@ -298,7 +352,7 @@ WebInspector.ExecutionContext.prototype = {
* @param {boolean} doNotPauseOnExceptionsAndMuteConsole
* @param {boolean} returnByValue
* @param {boolean} generatePreview
- * @param {function(?WebInspector.RemoteObject, boolean, ?RuntimeAgent.RemoteObject=, ?DebuggerAgent.ExceptionDetails=)} callback
+ * @param {function(?WebInspector.RemoteObject, boolean, ?RuntimeAgent.RemoteObject=, ?RuntimeAgent.ExceptionDetails=)} callback
*/
_evaluateGlobal: function(expression, objectGroup, includeCommandLineAPI, doNotPauseOnExceptionsAndMuteConsole, returnByValue, generatePreview, callback)
{
@@ -312,7 +366,7 @@ WebInspector.ExecutionContext.prototype = {
* @param {?Protocol.Error} error
* @param {!RuntimeAgent.RemoteObject} result
* @param {boolean=} wasThrown
- * @param {?DebuggerAgent.ExceptionDetails=} exceptionDetails
+ * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails
*/
function evalCallback(error, result, wasThrown, exceptionDetails)
{
diff --git a/front_end/sdk/Script.js b/front_end/sdk/Script.js
index 9614f6277e..d075140b18 100644
--- a/front_end/sdk/Script.js
+++ b/front_end/sdk/Script.js
@@ -289,5 +289,13 @@ WebInspector.Script.prototype = {
return !!this.hasSourceURL && this.isInlineScript();
},
+ /**
+ * @param {!Array} positions
+ */
+ setBlackboxedRanges: function(positions)
+ {
+ this.target().debuggerAgent().setBlackboxedRanges(this.scriptId, positions);
+ },
+
__proto__: WebInspector.SDKObject.prototype
}
diff --git a/front_end/sdk/TracingManager.js b/front_end/sdk/TracingManager.js
index 7bde4866bf..d5838a7dfe 100644
--- a/front_end/sdk/TracingManager.js
+++ b/front_end/sdk/TracingManager.js
@@ -52,7 +52,8 @@ WebInspector.TracingManager = function(target)
name: string,
args: !Object,
dur: number,
- id: number,
+ id: string,
+ bind_id: string,
s: string
}}
*/
diff --git a/front_end/sdk/TracingModel.js b/front_end/sdk/TracingModel.js
index 7b25be3658..ff3d0ff087 100644
--- a/front_end/sdk/TracingModel.js
+++ b/front_end/sdk/TracingModel.js
@@ -462,7 +462,7 @@ WebInspector.TracingModel.Event = function(categories, name, phase, startTime, t
this.warning = null;
/** @type {?WebInspector.TracingModel.Event} */
this.initiator = null;
- /** @type {?Array.} */
+ /** @type {?Array.} */
this.stackTrace = null;
/** @type {?Element} */
this.previewElement = null;
@@ -491,6 +491,9 @@ WebInspector.TracingModel.Event.fromPayload = function(payload, thread)
event.setEndTime((payload.ts + payload.dur) / 1000);
if (payload.id)
event.id = payload.id;
+ if (payload.bind_id)
+ event.bind_id = payload.bind_id;
+
return event;
}
diff --git a/front_end/security/SecurityPanel.js b/front_end/security/SecurityPanel.js
index b678592b1d..33a1673d55 100644
--- a/front_end/security/SecurityPanel.js
+++ b/front_end/security/SecurityPanel.js
@@ -798,8 +798,8 @@ WebInspector.SecurityOriginView = function(panel, origin, originState)
table.addRow("Valid From", validFromString);
table.addRow("Valid Until", validUntilString);
table.addRow("Issuer", certificateDetails.issuer);
+ table.addRow("SCTs", this.sctSummary(originState.securityDetails.certificateValidationDetails));
table.addRow("", WebInspector.SecurityPanel.createCertificateViewerButton(WebInspector.UIString("Open full certificate details"), originState.securityDetails.certificateId));
- // TODO(lgarron): Make SCT status available in certificate details and show it here.
}
function displayCertificateDetailsUnavailable ()
@@ -879,6 +879,26 @@ WebInspector.SecurityOriginView.prototype = {
this._originLockIcon.classList.add("security-property-" + newSecurityState);
},
+ /**
+ * @constructor
+ * @param {?NetworkAgent.CertificateValidationDetails} details
+ * @return {string}
+ */
+ sctSummary: function(details)
+ {
+ if (!details)
+ return WebInspector.UIString("N/A");
+
+ var sctTypeList = [];
+ if (details.numValidScts)
+ sctTypeList.push(WebInspector.UIString("%d valid SCT%s", details.numValidScts, (details.numValidScts > 1) ? "s" : ""));
+ if (details.numInvalidScts)
+ sctTypeList.push(WebInspector.UIString("%d invalid SCT%s", details.numInvalidScts, (details.numInvalidScts > 1) ? "s" : ""));
+ if (details.numUnknownScts)
+ sctTypeList.push(WebInspector.UIString("%d SCT%s from unknown logs", details.numUnknownScts, (details.numUnknownScts > 1) ? "s" : ""));
+ return sctTypeList.length ? sctTypeList.join(", ") : WebInspector.UIString("0 SCTs");
+ },
+
__proto__: WebInspector.VBox.prototype
}
diff --git a/front_end/settings/SettingsScreen.js b/front_end/settings/SettingsScreen.js
index 189895342d..187089d50a 100644
--- a/front_end/settings/SettingsScreen.js
+++ b/front_end/settings/SettingsScreen.js
@@ -293,8 +293,7 @@ WebInspector.WorkspaceSettingsTab = function()
WebInspector.isolatedFileSystemManager.addEventListener(WebInspector.IsolatedFileSystemManager.Events.FileSystemAdded, this._fileSystemAdded, this);
WebInspector.isolatedFileSystemManager.addEventListener(WebInspector.IsolatedFileSystemManager.Events.FileSystemRemoved, this._fileSystemRemoved, this);
- var folderExcludeSetting = WebInspector.isolatedFileSystemManager.workspaceFolderExcludePatternSetting();
- var folderExcludePatternInput = WebInspector.SettingsUI.createSettingInputField(WebInspector.UIString("Folder exclude pattern"), folderExcludeSetting, false, 0, "270px", WebInspector.SettingsUI.regexValidator);
+ var folderExcludePatternInput = this._createFolderExcludePatternInput();
folderExcludePatternInput.classList.add("folder-exclude-pattern");
this.containerElement.appendChild(folderExcludePatternInput);
@@ -314,6 +313,38 @@ WebInspector.WorkspaceSettingsTab = function()
}
WebInspector.WorkspaceSettingsTab.prototype = {
+ /**
+ * @return {!Element}
+ */
+ _createFolderExcludePatternInput: function()
+ {
+ var p = createElement("p");
+ var labelElement = p.createChild("label");
+ labelElement.textContent = WebInspector.UIString("Folder exclude pattern");
+ var inputElement = p.createChild("input");
+ inputElement.type = "text";
+ inputElement.style.width = "270px";
+ var folderExcludeSetting = WebInspector.isolatedFileSystemManager.workspaceFolderExcludePatternSetting();
+ var setValue = WebInspector.bindInput(inputElement, folderExcludeSetting.set.bind(folderExcludeSetting), regexValidator, false);
+ folderExcludeSetting.addChangeListener(() => setValue.call(null, folderExcludeSetting.get()));
+ setValue(folderExcludeSetting.get());
+ return p;
+
+ /**
+ * @param {string} value
+ * @return {boolean}
+ */
+ function regexValidator(value)
+ {
+ var regex;
+ try {
+ regex = new RegExp(value);
+ } catch (e) {
+ }
+ return !!regex;
+ }
+ },
+
/**
* @param {!WebInspector.IsolatedFileSystem} fileSystem
*/
diff --git a/front_end/snippets/ScriptSnippetModel.js b/front_end/snippets/ScriptSnippetModel.js
index 6dd31c0c02..ed412cc538 100644
--- a/front_end/snippets/ScriptSnippetModel.js
+++ b/front_end/snippets/ScriptSnippetModel.js
@@ -219,18 +219,18 @@ WebInspector.ScriptSnippetModel.prototype = {
this._restoreBreakpoints(uiSourceCode, breakpointLocations);
var target = executionContext.target();
- var debuggerModel = executionContext.debuggerModel;
+ var runtimeModel = target.runtimeModel;
var evaluationIndex = this._nextEvaluationIndex();
var mapping = this._mappingForTarget.get(target);
mapping._setEvaluationIndex(evaluationIndex, uiSourceCode);
var evaluationUrl = mapping._evaluationSourceURL(uiSourceCode);
var expression = uiSourceCode.workingCopy();
WebInspector.console.show();
- debuggerModel.compileScript(expression, "", true, executionContext.id, compileCallback.bind(this));
+ runtimeModel.compileScript(expression, "", true, executionContext.id, compileCallback.bind(this));
/**
- * @param {!DebuggerAgent.ScriptId=} scriptId
- * @param {?DebuggerAgent.ExceptionDetails=} exceptionDetails
+ * @param {!RuntimeAgent.ScriptId=} scriptId
+ * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails
* @this {WebInspector.ScriptSnippetModel}
*/
function compileCallback(scriptId, exceptionDetails)
@@ -244,7 +244,7 @@ WebInspector.ScriptSnippetModel.prototype = {
return;
}
- mapping._addScript(debuggerModel.scriptForId(scriptId), uiSourceCode);
+ mapping._addScript(executionContext.debuggerModel.scriptForId(scriptId), uiSourceCode);
var breakpointLocations = this._removeBreakpoints(uiSourceCode);
this._restoreBreakpoints(uiSourceCode, breakpointLocations);
@@ -253,19 +253,19 @@ WebInspector.ScriptSnippetModel.prototype = {
},
/**
- * @param {!DebuggerAgent.ScriptId} scriptId
+ * @param {!RuntimeAgent.ScriptId} scriptId
* @param {!WebInspector.ExecutionContext} executionContext
* @param {?string=} sourceURL
*/
_runScript: function(scriptId, executionContext, sourceURL)
{
var target = executionContext.target();
- executionContext.debuggerModel.runScript(scriptId, executionContext.id, "console", false, runCallback.bind(this, target));
+ target.runtimeModel.runScript(scriptId, executionContext.id, "console", false, runCallback.bind(this, target));
/**
* @param {!WebInspector.Target} target
* @param {?RuntimeAgent.RemoteObject} result
- * @param {?DebuggerAgent.ExceptionDetails=} exceptionDetails
+ * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails
* @this {WebInspector.ScriptSnippetModel}
*/
function runCallback(target, result, exceptionDetails)
@@ -301,7 +301,7 @@ WebInspector.ScriptSnippetModel.prototype = {
/**
* @param {!WebInspector.Target} target
- * @param {?DebuggerAgent.ExceptionDetails=} exceptionDetails
+ * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails
* @param {?string=} sourceURL
*/
_printRunOrCompileScriptResultFailure: function(target, exceptionDetails, sourceURL)
@@ -317,7 +317,7 @@ WebInspector.ScriptSnippetModel.prototype = {
exceptionDetails.column,
undefined,
undefined,
- exceptionDetails.stackTrace);
+ exceptionDetails.stack);
target.consoleModel.addMessage(consoleMessage);
},
diff --git a/front_end/sources/AsyncOperationsSidebarPane.js b/front_end/sources/AsyncOperationsSidebarPane.js
index e04d60dddc..9b9365febf 100644
--- a/front_end/sources/AsyncOperationsSidebarPane.js
+++ b/front_end/sources/AsyncOperationsSidebarPane.js
@@ -279,12 +279,17 @@ WebInspector.AsyncOperationsSidebarPane.prototype = {
{
var element = createElementWithClass("li", "async-operation");
- var title = operation.description || WebInspector.UIString("Async Operation");
+ var title;
+ if (operation.stack)
+ title = operation.stack.description;
+ if (!title)
+ title = WebInspector.UIString("Async Operation");
+
var label = createCheckboxLabel(title, operation[this._checkedSymbol]);
label.checkboxElement.addEventListener("click", this._checkboxClicked.bind(this, operation.id), false);
element.appendChild(label);
var debuggerModel = WebInspector.DebuggerModel.fromTarget(this._target);
- var callFrame = WebInspector.DebuggerPresentationUtils.callFrameAnchorFromStackTrace(debuggerModel, operation.stackTrace, operation.asyncStackTrace, this._revealBlackboxedCallFrames);
+ var callFrame = WebInspector.DebuggerPresentationUtils.callFrameAnchorFromStackTrace(debuggerModel, operation.stack, this._revealBlackboxedCallFrames);
if (callFrame)
element.createChild("div").appendChild(this._linkifier.linkifyConsoleCallFrame(this._target, callFrame));
@@ -353,7 +358,7 @@ WebInspector.AsyncOperationsSidebarPane.prototype = {
var operation = this._operationForPopover(anchor);
if (!operation)
return;
- var content = WebInspector.DOMPresentationUtils.buildStackTracePreviewContents(this._target, this._linkifier, operation.stackTrace, operation.asyncStackTrace);
+ var content = WebInspector.DOMPresentationUtils.buildStackTracePreviewContents(this._target, this._linkifier, operation.stack);
popover.setCanShrink(true);
popover.showForAnchor(content, anchor);
},
@@ -372,7 +377,7 @@ WebInspector.AsyncOperationsSidebarPane.prototype = {
return null;
var operationId = anchor[this._operationIdSymbol];
var operation = operationId && asyncOperations.get(operationId);
- if (!operation || !operation.stackTrace)
+ if (!operation || !operation.stack)
return null;
return operation;
},
diff --git a/front_end/sources/JavaScriptCompiler.js b/front_end/sources/JavaScriptCompiler.js
index 21ce3b2041..48c38108fc 100644
--- a/front_end/sources/JavaScriptCompiler.js
+++ b/front_end/sources/JavaScriptCompiler.js
@@ -46,21 +46,19 @@ WebInspector.JavaScriptCompiler.prototype = {
var target = this._findTarget();
if (!target)
return;
- var debuggerModel = WebInspector.DebuggerModel.fromTarget(target);
- if (!debuggerModel)
- return;
+ var runtimeModel = target.runtimeModel;
var currentExecutionContext = WebInspector.context.flavor(WebInspector.ExecutionContext);
if (!currentExecutionContext)
return;
this._compiling = true;
var code = this._sourceFrame.textEditor.text();
- debuggerModel.compileScript(code, "", false, currentExecutionContext.id, compileCallback.bind(this, target));
+ runtimeModel.compileScript(code, "", false, currentExecutionContext.id, compileCallback.bind(this, target));
/**
* @param {!WebInspector.Target} target
- * @param {!DebuggerAgent.ScriptId=} scriptId
- * @param {?DebuggerAgent.ExceptionDetails=} exceptionDetails
+ * @param {!RuntimeAgent.ScriptId=} scriptId
+ * @param {?RuntimeAgent.ExceptionDetails=} exceptionDetails
* @this {WebInspector.JavaScriptCompiler}
*/
function compileCallback(target, scriptId, exceptionDetails)
diff --git a/front_end/sources/SourcesPanel.js b/front_end/sources/SourcesPanel.js
index 1341f43006..8b98d888ec 100644
--- a/front_end/sources/SourcesPanel.js
+++ b/front_end/sources/SourcesPanel.js
@@ -282,7 +282,7 @@ WebInspector.SourcesPanel.prototype = {
if (Runtime.experiments.isEnabled("stepIntoAsync")) {
var operationId = details.auxData["operationId"];
var operation = this.sidebarPanes.asyncOperationBreakpoints.operationById(details.target(), operationId);
- var description = (operation && operation.description) || WebInspector.UIString("");
+ var description = (operation && operation.stack && operation.stack.description) || WebInspector.UIString("");
this.sidebarPanes.callstack.setStatus(WebInspector.UIString("Paused on a \"%s\" async operation.", description));
this.sidebarPanes.asyncOperationBreakpoints.highlightBreakpoint(operationId);
}
diff --git a/front_end/sources/SourcesSearchScope.js b/front_end/sources/SourcesSearchScope.js
index 5aeeaea738..edf528a606 100644
--- a/front_end/sources/SourcesSearchScope.js
+++ b/front_end/sources/SourcesSearchScope.js
@@ -86,7 +86,7 @@ WebInspector.SourcesSearchScope.prototype = {
*/
function filterOutServiceProjects(project)
{
- return !WebInspector.Project.isServiceProject(project) || project.type() === WebInspector.projectTypes.Formatter;
+ return project.type() !== WebInspector.projectTypes.Service;
}
/**
@@ -176,8 +176,12 @@ WebInspector.SourcesSearchScope.prototype = {
var uiSourceCodes = [];
for (var i = 0; i < files.length; ++i) {
var uiSourceCode = project.uiSourceCodeForURL(files[i]);
- if (uiSourceCode)
+ if (uiSourceCode) {
+ var script = WebInspector.DefaultScriptMapping.scriptForUISourceCode(uiSourceCode);
+ if (script && (script.isInternalScript() || !script.isAnonymousScript()))
+ continue;
uiSourceCodes.push(uiSourceCode);
+ }
}
uiSourceCodes.sort(WebInspector.SourcesSearchScope._filesComparator);
this._searchResultCandidates = this._searchResultCandidates.mergeOrdered(uiSourceCodes, WebInspector.SourcesSearchScope._filesComparator);
diff --git a/front_end/sources/TabbedEditorContainer.js b/front_end/sources/TabbedEditorContainer.js
index 8ae65d1cfa..75e93ff899 100644
--- a/front_end/sources/TabbedEditorContainer.js
+++ b/front_end/sources/TabbedEditorContainer.js
@@ -585,18 +585,16 @@ WebInspector.TabbedEditorContainer.History.prototype = {
*/
index: function(url)
{
- var index = this._itemsIndex[url];
- if (typeof index === "number")
- return index;
- return -1;
+ return this._itemsIndex.has(url) ? /** @type {number} */(this._itemsIndex.get(url)) : -1;
},
_rebuildItemIndex: function()
{
- this._itemsIndex = {};
+ /** @type {!Map} */
+ this._itemsIndex = new Map();
for (var i = 0; i < this._items.length; ++i) {
- console.assert(!this._itemsIndex.hasOwnProperty(this._items[i].url));
- this._itemsIndex[this._items[i].url] = i;
+ console.assert(!this._itemsIndex.has(this._items[i].url));
+ this._itemsIndex.set(this._items[i].url, i);
}
},
diff --git a/front_end/sources/sourcesPanel.css b/front_end/sources/sourcesPanel.css
index f93eea1459..8c62e2724f 100644
--- a/front_end/sources/sourcesPanel.css
+++ b/front_end/sources/sourcesPanel.css
@@ -45,12 +45,6 @@
overflow: hidden;
}
-.material .scripts-debug-toolbar-drawer {
- flex: 0 0 54px;
- margin-top: -28px;
- padding-top: 26px;
-}
-
.scripts-debug-toolbar-drawer.expanded {
margin-top: 0;
}
diff --git a/front_end/timeline/TimelineFlameChart.js b/front_end/timeline/TimelineFlameChart.js
index af2d368b54..383d63bdf2 100644
--- a/front_end/timeline/TimelineFlameChart.js
+++ b/front_end/timeline/TimelineFlameChart.js
@@ -263,6 +263,7 @@ WebInspector.TimelineFlameChartEntryType = {
Header: Symbol("Header"),
Frame: Symbol("Frame"),
Event: Symbol("Event"),
+ InteractionRecord: Symbol("InteractionRecord"),
};
/**
@@ -270,11 +271,13 @@ WebInspector.TimelineFlameChartEntryType = {
* @extends {WebInspector.TimelineFlameChartDataProviderBase}
* @param {!WebInspector.TimelineModel} model
* @param {!WebInspector.TimelineFrameModelBase} frameModel
+ * @param {?WebInspector.TimelineIRModel} irModel
*/
-WebInspector.TimelineFlameChartDataProvider = function(model, frameModel)
+WebInspector.TimelineFlameChartDataProvider = function(model, frameModel, irModel)
{
WebInspector.TimelineFlameChartDataProviderBase.call(this, model);
this._frameModel = frameModel;
+ this._irModel = irModel;
this._consoleColorGenerator = new WebInspector.FlameChart.ColorGenerator(
{ min: 30, max: 55, count: 5 },
{ min: 70, max: 100, count: 6 },
@@ -333,7 +336,7 @@ WebInspector.TimelineFlameChartDataProvider.prototype = {
reset: function()
{
WebInspector.TimelineFlameChartDataProviderBase.prototype.reset.call(this);
- /** @type {!Array} */
+ /** @type {!Array} */
this._entryData = [];
/** @type {!Array} */
this._entryTypeByLevel = [];
@@ -362,6 +365,7 @@ WebInspector.TimelineFlameChartDataProvider.prototype = {
this._timeSpan = this._model.isEmpty() ? 1000 : this._model.maximumRecordTime() - this._minimumBoundary;
this._currentLevel = 0;
this._appendFrameBars(this._frameModel.frames());
+ this._appendInteractionRecords();
this._appendThreadTimelineData(WebInspector.UIString("Main Thread"), this._model.mainThreadEvents(), this._model.mainThreadAsyncEvents());
if (Runtime.experiments.isEnabled("gpuTimeline"))
this._appendGPUEvents();
@@ -522,6 +526,17 @@ WebInspector.TimelineFlameChartDataProvider.prototype = {
++this._currentLevel;
},
+ _appendInteractionRecords: function()
+ {
+ if (!this._irModel)
+ return;
+ var segments = this._irModel.interactionRecords();
+ if (!segments || !segments.length)
+ return;
+ segments.forEach(this._appendSegment, this);
+ this._entryTypeByLevel[this._currentLevel++] = WebInspector.TimelineFlameChartEntryType.InteractionRecord;
+ },
+
/**
* @param {!Array.} frames
*/
@@ -616,6 +631,8 @@ WebInspector.TimelineFlameChartDataProvider.prototype = {
return "white";
if (type === WebInspector.TimelineFlameChartEntryType.Header)
return "#aaa";
+ if (type === WebInspector.TimelineFlameChartEntryType.InteractionRecord)
+ return WebInspector.TimelineUIUtils.interactionPhaseColor(/** @type {!WebInspector.TimelineIRModel.Phases} */ (this._entryData[entryIndex]));
return "";
},
@@ -814,6 +831,19 @@ WebInspector.TimelineFlameChartDataProvider.prototype = {
this._timelineData.entryStartTimes[index] = frame.startTime;
},
+ /**
+ * @param {!WebInspector.Segment} segment
+ */
+ _appendSegment: function(segment)
+ {
+ var index = this._entryData.length;
+ this._entryData.push(segment.data);
+ this._entryIndexToTitle[index] = /** @type {string} */ (segment.data);
+ this._timelineData.entryLevels[index] = this._currentLevel;
+ this._timelineData.entryTotalTimes[index] = segment.end - segment.begin;
+ this._timelineData.entryStartTimes[index] = segment.begin;
+ },
+
/**
* @override
* @param {number} entryIndex
@@ -1195,8 +1225,9 @@ WebInspector.TimelineFlameChartMarker.prototype = {
* @param {!WebInspector.TimelineModeViewDelegate} delegate
* @param {!WebInspector.TimelineModel} timelineModel
* @param {!WebInspector.TimelineFrameModelBase} frameModel
+ * @param {?WebInspector.TimelineIRModel} irModel
*/
-WebInspector.TimelineFlameChartView = function(delegate, timelineModel, frameModel)
+WebInspector.TimelineFlameChartView = function(delegate, timelineModel, frameModel, irModel)
{
WebInspector.VBox.call(this);
this.element.classList.add("timeline-flamechart");
@@ -1205,7 +1236,7 @@ WebInspector.TimelineFlameChartView = function(delegate, timelineModel, frameMod
this._splitWidget = new WebInspector.SplitWidget(false, false, "timelineFlamechartMainView", 150);
- this._dataProvider = new WebInspector.TimelineFlameChartDataProvider(this._model, frameModel);
+ this._dataProvider = new WebInspector.TimelineFlameChartDataProvider(this._model, frameModel, irModel);
this._mainView = new WebInspector.FlameChart(this._dataProvider, this, true);
this._networkDataProvider = new WebInspector.TimelineFlameChartNetworkDataProvider(this._model);
diff --git a/front_end/timeline/TimelineIRModel.js b/front_end/timeline/TimelineIRModel.js
new file mode 100644
index 0000000000..04391d79d3
--- /dev/null
+++ b/front_end/timeline/TimelineIRModel.js
@@ -0,0 +1,395 @@
+// Copyright 2016 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+/**
+ * @constructor
+ */
+WebInspector.TimelineIRModel = function()
+{
+ this.reset();
+}
+
+/**
+ * @enum {string}
+ */
+WebInspector.TimelineIRModel.Phases = {
+ Idle: "Idle",
+ Response: "Response",
+ Scroll: "Scroll",
+ Fling: "Fling",
+ Drag: "Drag",
+ Animation: "Animation"
+};
+
+/**
+ * @enum {string}
+ */
+WebInspector.TimelineIRModel.InputEvents = {
+ Char: "Char",
+ Click: "GestureClick",
+ ContextMenu: "ContextMenu",
+ FlingCancel: "GestureFlingCancel",
+ FlingStart: "GestureFlingStart",
+ ImplSideFling: WebInspector.TimelineModel.RecordType.ImplSideFling,
+ KeyDown: "KeyDown",
+ KeyDownRow: "RawKeyDown",
+ KeyUp: "KeyUp",
+ LatencyScrollUpdate: "ScrollUpdate",
+ MouseDown: "MouseDown",
+ MouseMove: "MouseMove",
+ MouseUp: "MouseUp",
+ MouseWheel: "MouseWheel",
+ PinchBegin: "GesturePinchBegin",
+ PinchEnd: "GesturePinchEnd",
+ PinchUpdate: "GesturePinchUpdate",
+ ScrollBegin: "GestureScrollBegin",
+ ScrollEnd: "GestureScrollEnd",
+ ScrollUpdate: "GestureScrollUpdate",
+ ScrollUpdateRenderer: "ScrollUpdate",
+ ShowPress: "GestureShowPress",
+ Tap: "GestureTap",
+ TapCancel: "GestureTapCancel",
+ TapDown: "GestureTapDown",
+ TouchCancel: "TouchCancel",
+ TouchEnd: "TouchEnd",
+ TouchMove: "TouchMove",
+ TouchStart: "TouchStart"
+};
+
+WebInspector.TimelineIRModel._mergeThresholdsMs = {
+ animation: 1,
+ mouse: 40,
+};
+
+WebInspector.TimelineIRModel.prototype = {
+ /**
+ * @param {!WebInspector.TimelineModel} timelineModel
+ */
+ populate: function(timelineModel)
+ {
+ var eventTypes = WebInspector.TimelineIRModel.InputEvents;
+ var phases = WebInspector.TimelineIRModel.Phases;
+
+ this.reset();
+
+ var groups = WebInspector.TimelineUIUtils.asyncEventGroups();
+ var asyncEventsByGroup = timelineModel.mainThreadAsyncEvents();
+ var inputLatencies = asyncEventsByGroup.get(groups.input);
+ if (!inputLatencies)
+ return;
+ this._processInputLatencies(inputLatencies);
+ var animations = asyncEventsByGroup.get(groups.animation);
+ if (animations)
+ this._processAnimations(animations);
+ var range = new WebInspector.SegmentedRange();
+ range.append(new WebInspector.Segment(timelineModel.minimumRecordTime(), timelineModel.maximumRecordTime(), WebInspector.TimelineIRModel.Phases.Idle));
+ range.appendRange(this._drags); // Drags take lower precedence than animation, as we can't detect them reliably.
+ range.appendRange(this._cssAnimations);
+ range.appendRange(this._scrolls);
+ range.appendRange(this._responses);
+ this._segments = range.segments();
+ },
+
+ /**
+ * @param {!Array} events
+ */
+ _processInputLatencies: function(events)
+ {
+ var eventTypes = WebInspector.TimelineIRModel.InputEvents;
+ var phases = WebInspector.TimelineIRModel.Phases;
+ var thresholdsMs = WebInspector.TimelineIRModel._mergeThresholdsMs;
+
+ var flingStart;
+ var touchStart;
+ var firstTouchMove;
+ var mouseWheel;
+ var mouseDown;
+ var mouseMove;
+
+ for (var i = 0; i < events.length; ++i) {
+ var event = events[i];
+ if (i > 0 && events[i].startTime < events[i - 1].startTime)
+ console.assert(false, "Unordered input events");
+ var type = this._inputEventType(event.name);
+ switch (type) {
+ case eventTypes.ScrollUpdate:
+ touchStart = null; // Since we're scrolling now, disregard other touch gestures.
+ this._scrolls.append(this._segmentForEvent(event, phases.Scroll));
+ break;
+
+ case eventTypes.FlingStart:
+ if (flingStart) {
+ WebInspector.console.error(WebInspector.UIString("Two flings at the same time? %s vs %s", flingStart.startTime, event.startTime));
+ break;
+ }
+ flingStart = event;
+ break;
+
+ case eventTypes.FlingCancel:
+ // FIXME: also process renderer fling events.
+ if (!flingStart)
+ break;
+ this._scrolls.append(new WebInspector.Segment(flingStart.startTime, event.endTime, phases.Fling));
+ flingStart = null;
+ break;
+
+ case eventTypes.ImplSideFling:
+ this._scrolls.append(this._segmentForEvent(event, phases.Fling));
+ break;
+
+ case eventTypes.ShowPress:
+ case eventTypes.Tap:
+ case eventTypes.KeyDown:
+ case eventTypes.KeyDownRow:
+ case eventTypes.KeyUp:
+ case eventTypes.Char:
+ case eventTypes.Click:
+ case eventTypes.ContextMenu:
+ this._responses.append(this._segmentForEvent(event, phases.Response));
+ break;
+
+ case eventTypes.TouchStart:
+ if (touchStart) {
+ WebInspector.console.error(WebInspector.UIString("Two touches at the same time? %s vs %s", touchStart.startTime, event.startTime));
+ break;
+ }
+ touchStart = event;
+ firstTouchMove = null;
+ break;
+
+ case eventTypes.TouchCancel:
+ touchStart = null;
+ break;
+
+ case eventTypes.TouchMove:
+ if (firstTouchMove || !touchStart)
+ break;
+ firstTouchMove = event;
+ this._responses.append(new WebInspector.Segment(touchStart.startTime, firstTouchMove.endTime, phases.Response));
+ break;
+
+ case eventTypes.TouchEnd:
+ if (!touchStart)
+ break;
+ this._drags.append(new WebInspector.Segment(firstTouchMove ? firstTouchMove.endTime : touchStart.startTime, event.endTime, phases.Drag));
+ touchStart = null;
+ break;
+
+ case eventTypes.MouseDown:
+ mouseDown = event;
+ mouseMove = null;
+ break;
+
+ case eventTypes.MouseMove:
+ if (mouseDown && !mouseMove && mouseDown.startTime + thresholdsMs.mouse > event.startTime) {
+ this._responses.append(this._segmentForEvent(mouseDown, phases.Response));
+ this._responses.append(this._segmentForEvent(event, phases.Response));
+ } else if (mouseDown) {
+ if (mouseMove && canMerge(thresholdsMs.mouse, mouseMove, event))
+ this._drags.append(new WebInspector.Segment(mouseMove.endTime, event.startTime, phases.Drag));
+ this._drags.append(this._segmentForEvent(event, phases.Drag));
+ }
+ mouseMove = event;
+ break;
+
+ case eventTypes.MouseUp:
+ this._responses.append(this._segmentForEvent(event, phases.Response));
+ mouseDown = null;
+ break;
+
+ case eventTypes.MouseWheel:
+ // Do not consider first MouseWheel as trace viewer's implementation does -- in case of MouseWheel it's not really special.
+ if (mouseWheel && canMerge(thresholdsMs.mouse, mouseWheel, event))
+ this._scrolls.append(new WebInspector.Segment(mouseWheel.endTime, event.startTime, phases.Scroll));
+ this._scrolls.append(this._segmentForEvent(event, phases.Scroll));
+ mouseWheel = event;
+ break;
+ }
+ }
+
+ /**
+ * @param {number} threshold
+ * @param {!WebInspector.TracingModel.AsyncEvent} first
+ * @param {!WebInspector.TracingModel.AsyncEvent} second
+ * @return {boolean}
+ */
+ function canMerge(threshold, first, second)
+ {
+ return first.endTime < second.startTime && second.startTime < first.endTime + threshold;
+ }
+ },
+
+ /**
+ * @param {!Array} events
+ */
+ _processAnimations: function(events)
+ {
+ for (var i = 0; i < events.length; ++i)
+ this._cssAnimations.append(this._segmentForEvent(events[i], WebInspector.TimelineIRModel.Phases.Animation));
+ },
+
+ /**
+ * @param {!WebInspector.TracingModel.AsyncEvent} event
+ * @param {!WebInspector.TimelineIRModel.Phases} phase
+ * @return {!WebInspector.Segment}
+ */
+ _segmentForEvent: function(event, phase)
+ {
+ return new WebInspector.Segment(event.startTime, event.endTime, phase);
+ },
+
+ /**
+ * @return {!Array}
+ */
+ interactionRecords: function()
+ {
+ return this._segments;
+ },
+
+ reset: function()
+ {
+ var thresholdsMs = WebInspector.TimelineIRModel._mergeThresholdsMs;
+
+ this._segments = [];
+ this._drags = new WebInspector.SegmentedRange(merge.bind(null, 0));
+ this._cssAnimations = new WebInspector.SegmentedRange(merge.bind(null, WebInspector.TimelineIRModel._mergeThresholdsMs.animation));
+ this._responses = new WebInspector.SegmentedRange(merge.bind(null, 0));
+ this._scrolls = new WebInspector.SegmentedRange(merge.bind(null, 0));
+
+ /**
+ * @param {number} threshold
+ * @param {!WebInspector.Segment} first
+ * @param {!WebInspector.Segment} second
+ */
+ function merge(threshold, first, second)
+ {
+ return first.end + threshold >= second.begin && first.data === second.data ? first : null;
+ }
+ },
+
+ /**
+ * @param {string} eventName
+ * @return {?WebInspector.TimelineIRModel.InputEvents}
+ */
+ _inputEventType: function(eventName)
+ {
+ var prefix = "InputLatency::";
+ if (!eventName.startsWith(prefix)) {
+ if (eventName === WebInspector.TimelineIRModel.InputEvents.ImplSideFling)
+ return /** @type {!WebInspector.TimelineIRModel.InputEvents} */ (eventName);
+ console.error("Unrecognized input latency event: " + eventName);
+ return null;
+ }
+ return /** @type {!WebInspector.TimelineIRModel.InputEvents} */ (eventName.substr(prefix.length));
+ }
+};
+
+/**
+ * @constructor
+ * @param {(function(!WebInspector.Segment, !WebInspector.Segment): ?WebInspector.Segment)=} mergeCallback
+ */
+WebInspector.SegmentedRange = function(mergeCallback)
+{
+ /** @type {!Array} */
+ this._segments = [];
+ this._mergeCallback = mergeCallback;
+}
+
+/**
+ * @constructor
+ * @param {number} begin
+ * @param {number} end
+ * @param {*} data
+ */
+WebInspector.Segment = function(begin, end, data)
+{
+ if (begin > end)
+ console.assert(false, "Invalid segment");
+ this.begin = begin;
+ this.end = end;
+ this.data = data;
+}
+
+WebInspector.Segment.prototype = {
+ /**
+ * @param {!WebInspector.Segment} that
+ * @return {boolean}
+ */
+ intersects: function(that)
+ {
+ return this.begin < that.end && that.begin < this.end;
+ }
+};
+
+WebInspector.SegmentedRange.prototype = {
+ /**
+ * @param {!WebInspector.Segment} newSegment
+ */
+ append: function(newSegment)
+ {
+ // 1. Find the proper insertion point for new segment
+ var startIndex = this._segments.lowerBound(newSegment, (a, b) => a.begin - b.begin);
+ var endIndex = startIndex;
+ var merged = null;
+ if (startIndex > 0) {
+ // 2. Try mering the preceding segment
+ var precedingSegment = this._segments[startIndex - 1];
+ merged = this._tryMerge(precedingSegment, newSegment);
+ if (merged) {
+ --startIndex;
+ newSegment = merged;
+ } else if (this._segments[startIndex - 1].end >= newSegment.begin) {
+ // 2a. If merge failed and segments overlap, adjust preceding segment.
+ // If an old segment entirely contains new one, split it in two.
+ if (newSegment.end < precedingSegment.end)
+ this._segments.splice(startIndex, 0, new WebInspector.Segment(newSegment.end, precedingSegment.end, precedingSegment.data));
+ precedingSegment.end = newSegment.begin;
+ }
+ }
+ // 3. Consume all segments that are entirely covered by the new one.
+ while (endIndex < this._segments.length && this._segments[endIndex].end <= newSegment.end)
+ ++endIndex;
+ // 4. Merge or adjust the succeeding segment if it overlaps.
+ if (endIndex < this._segments.length) {
+ merged = this._tryMerge(newSegment, this._segments[endIndex]);
+ if (merged) {
+ endIndex++;
+ newSegment = merged;
+ } else if (newSegment.intersects(this._segments[endIndex]))
+ this._segments[endIndex].begin = newSegment.end;
+ }
+ this._segments.splice(startIndex, endIndex - startIndex, newSegment);
+ },
+
+ /**
+ * @param {!WebInspector.SegmentedRange} that
+ */
+ appendRange: function(that)
+ {
+ that.segments().forEach(segment => this.append(segment));
+ },
+
+ /**
+ * @return {!Array}
+ */
+ segments: function()
+ {
+ return this._segments;
+ },
+
+ /**
+ * @param {!WebInspector.Segment} first
+ * @param {!WebInspector.Segment} second
+ * @return {?WebInspector.Segment}
+ */
+ _tryMerge: function(first, second)
+ {
+ var merged = this._mergeCallback && this._mergeCallback(first, second);
+ if (!merged)
+ return null;
+ merged.begin = first.begin;
+ merged.end = Math.max(first.end, second.end);
+ return merged;
+ }
+}
diff --git a/front_end/timeline/TimelineJSProfile.js b/front_end/timeline/TimelineJSProfile.js
index cf1907a68f..3d74497f41 100644
--- a/front_end/timeline/TimelineJSProfile.js
+++ b/front_end/timeline/TimelineJSProfile.js
@@ -21,21 +21,25 @@ WebInspector.TimelineJSProfileProcessor.generateTracingEventsFromCpuProfile = fu
var samples = jsProfileModel.samples;
var timestamps = jsProfileModel.timestamps;
var jsEvents = [];
+ /** @type {!Map>} */
+ var nodeToStackMap = new Map();
+ nodeToStackMap.set(programNode, []);
for (var i = 0; i < samples.length; ++i) {
var node = jsProfileModel.nodeByIndex(i);
- if (node === programNode || node === gcNode || node === idleNode)
+ if (node === gcNode || node === idleNode)
continue;
- var stackTrace = node._stackTraceArray;
- if (!stackTrace) {
- stackTrace = /** @type {!ConsoleAgent.StackTrace} */ (new Array(node.depth + 1));
- node._stackTraceArray = stackTrace;
+ var callFrames = nodeToStackMap.get(node);
+ if (!callFrames) {
+ callFrames = /** @type {!Array} */ (new Array(node.depth + 1));
+ nodeToStackMap.set(node, callFrames);
for (var j = 0; node.parent; node = node.parent)
- stackTrace[j++] = /** @type {!ConsoleAgent.CallFrame} */ (node);
+ callFrames[j++] = /** @type {!RuntimeAgent.CallFrame} */ (node);
}
- var jsEvent = new WebInspector.TracingModel.Event(WebInspector.TracingModel.DevToolsTimelineEventCategory, WebInspector.TimelineModel.RecordType.JSSample,
+ var jsSampleEvent = new WebInspector.TracingModel.Event(WebInspector.TracingModel.DevToolsTimelineEventCategory,
+ WebInspector.TimelineModel.RecordType.JSSample,
WebInspector.TracingModel.Phase.Instant, timestamps[i], thread);
- jsEvent.args["data"] = { stackTrace: stackTrace };
- jsEvents.push(jsEvent);
+ jsSampleEvent.args["data"] = { stackTrace: callFrames };
+ jsEvents.push(jsSampleEvent);
}
return jsEvents;
}
@@ -47,8 +51,8 @@ WebInspector.TimelineJSProfileProcessor.generateTracingEventsFromCpuProfile = fu
WebInspector.TimelineJSProfileProcessor.generateJSFrameEvents = function(events)
{
/**
- * @param {!ConsoleAgent.CallFrame} frame1
- * @param {!ConsoleAgent.CallFrame} frame2
+ * @param {!RuntimeAgent.CallFrame} frame1
+ * @param {!RuntimeAgent.CallFrame} frame2
* @return {boolean}
*/
function equalFrames(frame1, frame2)
@@ -154,13 +158,15 @@ WebInspector.TimelineJSProfileProcessor.generateJSFrameEvents = function(events)
depth = jsFramesStack.length;
}
var minFrameDurationMs = currentSamplingIntervalMs / 2;
+ for (var k = 0; k < depth; ++k)
+ jsFramesStack[k].setEndTime(time);
for (var k = depth; k < jsFramesStack.length; ++k)
jsFramesStack[k].setEndTime(Math.min(eventEndTime(jsFramesStack[k]) + minFrameDurationMs, time));
jsFramesStack.length = depth;
}
/**
- * @param {!Array} stack
+ * @param {!Array} stack
*/
function filterStackFrames(stack)
{
@@ -178,22 +184,22 @@ WebInspector.TimelineJSProfileProcessor.generateJSFrameEvents = function(events)
*/
function extractStackTrace(e)
{
- var eventData = e.args["data"] || e.args["beginData"];
- var stackTrace = eventData && eventData["stackTrace"];
var recordTypes = WebInspector.TimelineModel.RecordType;
- // GC events do not hold call stack, so make a copy of the current stack.
- if (e.name === recordTypes.GCEvent || e.name === recordTypes.MajorGC || e.name === recordTypes.MinorGC)
- stackTrace = jsFramesStack.map(function(frameEvent) { return frameEvent.args["data"]; }).reverse();
- if (!stackTrace)
- return;
+ var callFrames;
+ if (e.name === recordTypes.JSSample) {
+ var eventData = e.args["data"] || e.args["beginData"];
+ callFrames = /** @type {!Array} */ (eventData && eventData["stackTrace"]);
+ } else {
+ callFrames = /** @type {!Array} */ (jsFramesStack.map(frameEvent => frameEvent.args["data"]).reverse());
+ }
if (filterNativeFunctions)
- filterStackFrames(stackTrace);
+ filterStackFrames(callFrames);
var endTime = eventEndTime(e);
- var numFrames = stackTrace.length;
+ var numFrames = callFrames.length;
var minFrames = Math.min(numFrames, jsFramesStack.length);
var i;
for (i = lockedJsStackDepth.peekLast() || 0; i < minFrames; ++i) {
- var newFrame = stackTrace[numFrames - 1 - i];
+ var newFrame = callFrames[numFrames - 1 - i];
var oldFrame = jsFramesStack[i].args["data"];
if (!equalFrames(newFrame, oldFrame))
break;
@@ -201,8 +207,8 @@ WebInspector.TimelineJSProfileProcessor.generateJSFrameEvents = function(events)
}
truncateJSStack(i, e.startTime);
for (; i < numFrames; ++i) {
- var frame = stackTrace[numFrames - 1 - i];
- var jsFrameEvent = new WebInspector.TracingModel.Event(WebInspector.TracingModel.DevToolsTimelineEventCategory, WebInspector.TimelineModel.RecordType.JSFrame,
+ var frame = callFrames[numFrames - 1 - i];
+ var jsFrameEvent = new WebInspector.TracingModel.Event(WebInspector.TracingModel.DevToolsTimelineEventCategory, recordTypes.JSFrame,
WebInspector.TracingModel.Phase.Complete, e.startTime, e.thread);
jsFrameEvent.ordinal = e.ordinal;
jsFrameEvent.addArgs({ data: frame });
@@ -244,7 +250,7 @@ WebInspector.TimelineJSProfileProcessor.CodeMap = function()
* @constructor
* @param {number} address
* @param {number} size
- * @param {!ConsoleAgent.CallFrame} callFrame
+ * @param {!RuntimeAgent.CallFrame} callFrame
*/
WebInspector.TimelineJSProfileProcessor.CodeMap.Entry = function(address, size, callFrame)
{
@@ -267,7 +273,7 @@ WebInspector.TimelineJSProfileProcessor.CodeMap.prototype = {
/**
* @param {string} addressHex
* @param {number} size
- * @param {!ConsoleAgent.CallFrame} callFrame
+ * @param {!RuntimeAgent.CallFrame} callFrame
*/
addEntry: function(addressHex, size, callFrame)
{
@@ -294,7 +300,7 @@ WebInspector.TimelineJSProfileProcessor.CodeMap.prototype = {
/**
* @param {string} addressHex
- * @return {?ConsoleAgent.CallFrame}
+ * @return {?RuntimeAgent.CallFrame}
*/
lookupEntry: function(addressHex)
{
@@ -369,7 +375,7 @@ WebInspector.TimelineJSProfileProcessor.CodeMap.Bank.prototype = {
/**
* @param {number} address
- * @return {?ConsoleAgent.CallFrame}
+ * @return {?RuntimeAgent.CallFrame}
*/
lookupEntry: function(address)
{
@@ -400,7 +406,7 @@ WebInspector.TimelineJSProfileProcessor.CodeMap.Bank.prototype = {
/**
* @param {string} name
* @param {number} scriptId
- * @return {!ConsoleAgent.CallFrame}
+ * @return {!RuntimeAgent.CallFrame}
*/
WebInspector.TimelineJSProfileProcessor._buildCallFrame = function(name, scriptId)
{
@@ -411,11 +417,11 @@ WebInspector.TimelineJSProfileProcessor._buildCallFrame = function(name, scriptI
* @param {number=} line
* @param {number=} column
* @param {boolean=} isNative
- * @return {!ConsoleAgent.CallFrame}
+ * @return {!RuntimeAgent.CallFrame}
*/
function createFrame(functionName, url, scriptId, line, column, isNative)
{
- return /** @type {!ConsoleAgent.CallFrame} */ ({
+ return /** @type {!RuntimeAgent.CallFrame} */ ({
"functionName": functionName,
"url": url || "",
"scriptId": scriptId || "0",
@@ -463,7 +469,7 @@ WebInspector.TimelineJSProfileProcessor.processRawV8Samples = function(events)
/**
* @param {string} address
- * @return {?ConsoleAgent.CallFrame}
+ * @return {?RuntimeAgent.CallFrame}
*/
function convertRawFrame(address)
{
diff --git a/front_end/timeline/TimelineModel.js b/front_end/timeline/TimelineModel.js
index 831a3ceaae..fada4fde44 100644
--- a/front_end/timeline/TimelineModel.js
+++ b/front_end/timeline/TimelineModel.js
@@ -157,7 +157,10 @@ WebInspector.TimelineModel.RecordType = {
PictureSnapshot: "cc::Picture",
DisplayItemListSnapshot: "cc::DisplayItemList",
LatencyInfo: "LatencyInfo",
+ LatencyInfoFlow: "LatencyInfo.Flow",
InputLatencyMouseMove: "InputLatency::MouseMove",
+ InputLatencyMouseWheel: "InputLatency::MouseWheel",
+ ImplSideFling: "InputHandlerProxy::HandleGestureFling::started",
// CpuProfile is a virtual event created on frontend to support
// serialization of CPU Profiles within tracing timeline data.
@@ -893,7 +896,10 @@ WebInspector.TimelineModel.prototype = {
var browserMain = this._tracingModel.threadByName("Browser", "CrBrowserMain");
if (!browserMain)
return;
- this._processAsyncEvents(this._mainThreadAsyncEventsByGroup, browserMain.asyncEvents());
+ /** @type {!Map>} */
+ var asyncEventsByGroup = new Map();
+ this._processAsyncEvents(asyncEventsByGroup, browserMain.asyncEvents());
+ this._mergeAsyncEvents(this._mainThreadAsyncEventsByGroup, asyncEventsByGroup);
},
_buildTimelineRecords: function()
@@ -979,6 +985,8 @@ WebInspector.TimelineModel.prototype = {
this._eventStack = [];
this._hadCommitLoad = false;
this._firstCompositeLayers = null;
+ /** @type {!Set} */
+ this._knownInputEvents = new Set();
this._currentPage = null;
},
@@ -1038,6 +1046,11 @@ WebInspector.TimelineModel.prototype = {
this._inspectedTargetEvents.push(event);
}
this._processAsyncEvents(threadAsyncEventsByGroup, asyncEvents, startTime, endTime);
+ // Pretend the compositor's async events are on the main thread.
+ if (thread.name() === "Compositor") {
+ this._mergeAsyncEvents(this._mainThreadAsyncEventsByGroup, threadAsyncEventsByGroup);
+ threadAsyncEventsByGroup.clear();
+ }
},
/**
@@ -1233,9 +1246,14 @@ WebInspector.TimelineModel.prototype = {
}
break;
+ case recordTypes.LatencyInfoFlow:
+ if (typeof event.args["layerTreeId"] !== "undefined" && event.args["layerTreeId"] !== this._inspectedTargetLayerTreeId)
+ break;
+ this._knownInputEvents.add(event.bind_id);
+ break;
+
case recordTypes.Animation:
- // FIXME: bring back Animation events as we figure out a way to show them while not cluttering the UI.
- return false;
+ break;
}
if (WebInspector.TracingModel.isAsyncPhase(event.phase))
return true;
@@ -1268,14 +1286,26 @@ WebInspector.TimelineModel.prototype = {
return groups.console;
if (asyncEvent.hasCategory(WebInspector.TimelineModel.Category.UserTiming))
return groups.userTiming;
- if (asyncEvent.hasCategory(WebInspector.TimelineModel.Category.LatencyInfo)) {
- if (!Runtime.experiments.isEnabled("timelineLatencyInfo"))
- return null;
+ if (!Runtime.experiments.isEnabled("timelineLatencyInfo"))
+ return null;
+ if (asyncEvent.name === WebInspector.TimelineModel.RecordType.Animation)
+ return groups.animation;
+ if (asyncEvent.hasCategory(WebInspector.TimelineModel.Category.LatencyInfo) || asyncEvent.name === WebInspector.TimelineModel.RecordType.ImplSideFling) {
+ var lastStep = asyncEvent.steps.peekLast();
// FIXME: fix event termination on the back-end instead.
- if (asyncEvent.steps.peekLast().phase !== WebInspector.TracingModel.Phase.AsyncEnd)
- return null;
- if (asyncEvent.name === WebInspector.TimelineModel.RecordType.InputLatencyMouseMove)
+ if (lastStep.phase !== WebInspector.TracingModel.Phase.AsyncEnd)
return null;
+ var data = lastStep.args["data"];
+ asyncEvent.causedFrame = !!(data && data["INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT"]);
+ if (asyncEvent.name === WebInspector.TimelineModel.RecordType.InputLatencyMouseMove) {
+ // Skip events that don't belong to this renderer.
+ // FIXME: this should eventually be applied to all input latencies, but it only works for certain events now.
+ if (!this._knownInputEvents.has(lastStep.id))
+ return null;
+ if (!asyncEvent.causedFrame)
+ return null;
+
+ }
return groups.input;
}
return null;
@@ -1295,6 +1325,19 @@ WebInspector.TimelineModel.prototype = {
return null;
},
+ /**
+ * @param {!Map>} target
+ * @param {!Map>} source
+ */
+ _mergeAsyncEvents: function(target, source)
+ {
+ for (var group of source.keys()) {
+ var events = target.get(group) || [];
+ events = events.mergeOrdered(source.get(group) || [], WebInspector.TracingModel.Event.compareStartAndEndTime);
+ target.set(group, events);
+ }
+ },
+
/**
* @param {!Blob} file
* @param {!WebInspector.Progress} progress
@@ -1922,7 +1965,7 @@ WebInspector.InvalidationTrackingEvent = function(event)
this.cause.reason = "Layout forced";
}
-/** @typedef {{reason: string, stackTrace: ?Array.}} */
+/** @typedef {{reason: string, stackTrace: ?Array.}} */
WebInspector.InvalidationCause;
/**
diff --git a/front_end/timeline/TimelinePanel.js b/front_end/timeline/TimelinePanel.js
index 97a665a55d..c9d3fa671e 100644
--- a/front_end/timeline/TimelinePanel.js
+++ b/front_end/timeline/TimelinePanel.js
@@ -54,6 +54,8 @@ WebInspector.TimelinePanel = function()
this._tracingModel = new WebInspector.TracingModel(this._tracingModelBackingStorage);
this._model = new WebInspector.TimelineModel(this._tracingModel, WebInspector.TimelineUIUtils.visibleEventsFilter());
this._frameModel = new WebInspector.TracingTimelineFrameModel();
+ if (Runtime.experiments.isEnabled("timelineLatencyInfo"))
+ this._irModel = new WebInspector.TimelineIRModel();
this._model.addEventListener(WebInspector.TimelineModel.Events.RecordingStarted, this._onRecordingStarted, this);
this._model.addEventListener(WebInspector.TimelineModel.Events.RecordingStopped, this._onRecordingStopped, this);
@@ -578,7 +580,7 @@ WebInspector.TimelinePanel.prototype = {
this._stackView.show(this._tabbedPane.visibleView.element);
}
if (viewMode === WebInspector.TimelinePanel.ViewMode.FlameChart) {
- this._flameChart = new WebInspector.TimelineFlameChartView(this, this._model, this._frameModel);
+ this._flameChart = new WebInspector.TimelineFlameChartView(this, this._model, this._frameModel, this._irModel);
this._flameChart.enableNetworkPane(this._captureNetworkSetting.get());
this._addModeView(this._flameChart);
} else if (viewMode === WebInspector.TimelinePanel.ViewMode.CallTree || viewMode === WebInspector.TimelinePanel.ViewMode.BottomUp) {
@@ -791,6 +793,8 @@ WebInspector.TimelinePanel.prototype = {
this._setState(WebInspector.TimelinePanel.State.Idle);
this._frameModel.reset();
this._frameModel.addTraceEvents(this._model.target(), this._model.inspectedTargetEvents(), this._model.sessionId() || "");
+ if (this._irModel)
+ this._irModel.populate(this._model);
this._overviewPane.reset();
this._overviewPane.setBounds(this._model.minimumRecordTime(), this._model.maximumRecordTime());
this._setAutoWindowTimes();
diff --git a/front_end/timeline/TimelineTreeView.js b/front_end/timeline/TimelineTreeView.js
index 7839b1814a..68f328cf33 100644
--- a/front_end/timeline/TimelineTreeView.js
+++ b/front_end/timeline/TimelineTreeView.js
@@ -29,6 +29,7 @@ WebInspector.TimelineTreeView = function(model)
this._dataGrid = new WebInspector.SortableDataGrid(columns);
this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SortingChanged, this._sortingChanged, this);
this._dataGrid.element.addEventListener("mousemove", this._onMouseMove.bind(this), true)
+ this._dataGrid.setResizeMethod(WebInspector.DataGrid.ResizeMethod.Last);
this._dataGrid.asWidget().show(mainView.element);
this._splitWidget = new WebInspector.SplitWidget(true, true, "timelineTreeViewDetailsSplitWidget");
@@ -106,7 +107,7 @@ WebInspector.TimelineTreeView.prototype = {
_onHover: function(node) { },
/**
- * @param {!ConsoleAgent.CallFrame} frame
+ * @param {!RuntimeAgent.CallFrame} frame
* @return {!Element}
*/
linkifyLocation: function(frame)
@@ -238,8 +239,8 @@ WebInspector.TimelineTreeView.prototype = {
*/
_populateColumns: function(columns)
{
- columns.push({id: "self", title: WebInspector.UIString("Self Time"), width: "110px", sortable: true});
- columns.push({id: "total", title: WebInspector.UIString("Total Time"), width: "110px", sortable: true});
+ columns.push({id: "self", title: WebInspector.UIString("Self Time"), width: "110px", fixedWidth: true, sortable: true});
+ columns.push({id: "total", title: WebInspector.UIString("Total Time"), width: "110px", fixedWidth: true, sortable: true});
columns.push({id: "activity", title: WebInspector.UIString("Activity"), disclosure: true, sortable: true});
},
@@ -460,7 +461,7 @@ WebInspector.TimelineTreeView.GridNode.prototype = {
: WebInspector.TimelineUIUtils.eventTitle(event);
var frame = WebInspector.TimelineTreeView.eventStackFrame(event);
if (frame && frame["url"]) {
- var callFrame = /** @type {!ConsoleAgent.CallFrame} */ (frame);
+ var callFrame = /** @type {!RuntimeAgent.CallFrame} */ (frame);
container.createChild("div", "activity-link").appendChild(this._treeView.linkifyLocation(callFrame));
}
icon.style.backgroundColor = WebInspector.TimelineUIUtils.eventColor(event);
@@ -1052,7 +1053,7 @@ WebInspector.EventsTimelineTreeView.prototype = {
*/
_populateColumns: function(columns)
{
- columns.push({id: "startTime", title: WebInspector.UIString("Start Time"), width: "110px", sortable: true});
+ columns.push({id: "startTime", title: WebInspector.UIString("Start Time"), width: "110px", fixedWidth: true, sortable: true});
WebInspector.TimelineTreeView.prototype._populateColumns.call(this, columns);
},
@@ -1113,10 +1114,11 @@ WebInspector.TimelineStackView = function(treeView)
header.textContent = WebInspector.UIString("Heaviest stack");
this._treeView = treeView;
var columns = [
- {id: "total", title: WebInspector.UIString("Total Time"), width: "110px"},
+ {id: "total", title: WebInspector.UIString("Total Time"), fixedWidth: true, width: "110px"},
{id: "activity", title: WebInspector.UIString("Activity")}
];
this._dataGrid = new WebInspector.ViewportDataGrid(columns);
+ this._dataGrid.setResizeMethod(WebInspector.DataGrid.ResizeMethod.Last);
this._dataGrid.addEventListener(WebInspector.DataGrid.Events.SelectedNode, this._onSelectionChanged, this);
this._dataGrid.asWidget().show(this.element);
}
diff --git a/front_end/timeline/TimelineUIUtils.js b/front_end/timeline/TimelineUIUtils.js
index cf40c9bd06..d1a2a24d76 100644
--- a/front_end/timeline/TimelineUIUtils.js
+++ b/front_end/timeline/TimelineUIUtils.js
@@ -175,8 +175,11 @@ WebInspector.TimelineUIUtils.eventStyle = function(event)
*/
WebInspector.TimelineUIUtils.eventColor = function(event)
{
- if (event.name === WebInspector.TimelineModel.RecordType.JSFrame)
- return WebInspector.TimelineUIUtils.colorForURL(event.args["data"]["url"]);
+ if (event.name === WebInspector.TimelineModel.RecordType.JSFrame) {
+ var frame = event.args["data"];
+ if (WebInspector.TimelineUIUtils.isUserFrame(frame))
+ return WebInspector.TimelineUIUtils.colorForURL(frame.url);
+ }
return WebInspector.TimelineUIUtils.eventStyle(event).category.color;
}
@@ -196,6 +199,45 @@ WebInspector.TimelineUIUtils.eventTitle = function(event)
return title;
}
+
+/**
+ * !Map
+ */
+WebInspector.TimelineUIUtils._interactionPhaseStyles = function()
+{
+ var map = WebInspector.TimelineUIUtils._interactionPhaseStylesMap;
+ if (!map) {
+ map = new Map([
+ [WebInspector.TimelineIRModel.Phases.Idle, {color: "white", label: "Idle"}],
+ [WebInspector.TimelineIRModel.Phases.Response, {color: "hsl(43, 83%, 64%)", label: WebInspector.UIString("Response")}],
+ [WebInspector.TimelineIRModel.Phases.Scroll, {color: "hsl(256, 67%, 70%)", label: WebInspector.UIString("Scroll")}],
+ [WebInspector.TimelineIRModel.Phases.Fling, {color: "hsl(256, 67%, 70%)", label: WebInspector.UIString("Fling")}],
+ [WebInspector.TimelineIRModel.Phases.Drag, {color: "hsl(256, 67%, 70%)", label: WebInspector.UIString("Drag")}],
+ [WebInspector.TimelineIRModel.Phases.Animation, {color: "hsl(256, 67%, 70%)", label: WebInspector.UIString("Animation")}]
+ ]);
+ WebInspector.TimelineUIUtils._interactionPhaseStylesMap = map;
+ }
+ return map;
+}
+
+/**
+ * @param {!WebInspector.TimelineIRModel.Phases} phase
+ * @return {string}
+ */
+WebInspector.TimelineUIUtils.interactionPhaseColor = function(phase)
+{
+ return WebInspector.TimelineUIUtils._interactionPhaseStyles().get(phase).color;
+}
+
+/**
+ * @param {!WebInspector.TimelineIRModel.Phases} phase
+ * @return {string}
+ */
+WebInspector.TimelineUIUtils.interactionPhaseLabel = function(phase)
+{
+ return WebInspector.TimelineUIUtils._interactionPhaseStyles().get(phase).label;
+}
+
/**
* @param {!WebInspector.TracingModel.Event} event
* @return {boolean}
@@ -215,6 +257,25 @@ WebInspector.TimelineUIUtils.isMarkerEvent = function(event)
}
}
+/**
+ * @param {!RuntimeAgent.CallFrame} frame
+ * @return {boolean}
+ */
+WebInspector.TimelineUIUtils.isUserFrame = function(frame)
+{
+ return frame.scriptId !== "0" && !frame.url.startsWith("native ");
+}
+
+/**
+ * @param {!WebInspector.TracingModel.Event} event
+ * @return {?RuntimeAgent.CallFrame}
+ */
+WebInspector.TimelineUIUtils.topStackFrame = function(event)
+{
+ var stackTrace = event.stackTrace || event.initiator && event.initiator.stackTrace;
+ return stackTrace && stackTrace.length ? stackTrace[0] : null;
+}
+
/**
* @enum {symbol}
*/
@@ -383,16 +444,8 @@ WebInspector.TimelineUIUtils.buildDetailsTextForTraceEvent = function(event, tar
*/
function linkifyTopCallFrameAsText()
{
- var stackTrace = event.stackTrace;
- if (!stackTrace) {
- var initiator = event.initiator;
- if (initiator)
- stackTrace = initiator.stackTrace;
- }
- if (!stackTrace || !stackTrace.length)
- return null;
- var callFrame = stackTrace[0];
- return linkifyLocationAsText(callFrame.scriptId, callFrame.lineNumber, callFrame.columnNumber);
+ var frame = WebInspector.TimelineUIUtils.topStackFrame(event);
+ return frame ? linkifyLocationAsText(frame.scriptId, frame.lineNumber, frame.columnNumber) : null;
}
}
@@ -487,15 +540,8 @@ WebInspector.TimelineUIUtils.buildDetailsNodeForTraceEvent = function(event, tar
*/
function linkifyTopCallFrame()
{
- var stackTrace = event.stackTrace;
- if (!stackTrace) {
- var initiator = event.initiator;
- if (initiator)
- stackTrace = initiator.stackTrace;
- }
- if (!stackTrace || !stackTrace.length)
- return null;
- return linkifier.linkifyConsoleCallFrame(target, stackTrace[0], "timeline-details");
+ var frame = WebInspector.TimelineUIUtils.topStackFrame(event);
+ return frame ? linkifier.linkifyConsoleCallFrame(target, frame, "timeline-details") : null;
}
}
@@ -912,6 +958,15 @@ WebInspector.TimelineUIUtils.buildNetworkRequestDetails = function(request, mode
return previewPromise.then(appendPreview);
}
+/**
+ * @param {!Array} callFrames
+ * @return {!RuntimeAgent.StackTrace}
+ */
+WebInspector.TimelineUIUtils._stackTraceFromCallFrames = function(callFrames)
+{
+ return /** @type {!RuntimeAgent.StackTrace} */ ({ callFrames: callFrames });
+}
+
/**
* @param {!WebInspector.TracingModel.Event} event
* @param {?WebInspector.Target} target
@@ -949,7 +1004,7 @@ WebInspector.TimelineUIUtils._generateCauses = function(event, target, relatedNo
// Direct cause.
if (event.stackTrace && event.stackTrace.length) {
contentHelper.addSection(WebInspector.UIString("Call Stacks"));
- contentHelper.appendStackTrace(stackLabel || WebInspector.UIString("Stack Trace"), event.stackTrace);
+ contentHelper.appendStackTrace(stackLabel || WebInspector.UIString("Stack Trace"), WebInspector.TimelineUIUtils._stackTraceFromCallFrames(event.stackTrace));
}
// Indirect causes.
@@ -957,7 +1012,7 @@ WebInspector.TimelineUIUtils._generateCauses = function(event, target, relatedNo
contentHelper.addSection(WebInspector.UIString("Invalidations"));
WebInspector.TimelineUIUtils._generateInvalidations(event, target, relatedNodesMap, contentHelper);
} else if (initiator && initiator.stackTrace) { // Partial invalidation tracking.
- contentHelper.appendStackTrace(callSiteStackLabel || WebInspector.UIString("First Invalidated"), initiator.stackTrace);
+ contentHelper.appendStackTrace(callSiteStackLabel || WebInspector.UIString("First Invalidated"), WebInspector.TimelineUIUtils._stackTraceFromCallFrames(initiator.stackTrace));
}
}
@@ -1125,7 +1180,7 @@ WebInspector.TimelineUIUtils.InvalidationsGroupElement.prototype = {
if (first.cause.stackTrace) {
var stack = content.createChild("div");
stack.createTextChild(WebInspector.UIString("Stack trace:"));
- this._contentHelper.createChildStackTraceElement(stack, first.cause.stackTrace);
+ this._contentHelper.createChildStackTraceElement(stack, WebInspector.TimelineUIUtils._stackTraceFromCallFrames(first.cause.stackTrace));
}
content.createTextChild(this._invalidations.length > 1 ? WebInspector.UIString("Nodes:") : WebInspector.UIString("Node:"));
@@ -1413,6 +1468,7 @@ WebInspector.TimelineUIUtils.asyncEventGroups = function()
if (WebInspector.TimelineUIUtils._asyncEventGroups)
return WebInspector.TimelineUIUtils._asyncEventGroups;
WebInspector.TimelineUIUtils._asyncEventGroups = {
+ animation: new WebInspector.AsyncEventGroup(WebInspector.UIString("Animation")),
console: new WebInspector.AsyncEventGroup(WebInspector.UIString("Console")),
userTiming: new WebInspector.AsyncEventGroup(WebInspector.UIString("User Timing")),
input: new WebInspector.AsyncEventGroup(WebInspector.UIString("Input Events"))
@@ -1945,7 +2001,7 @@ WebInspector.TimelineDetailsContentHelper.prototype = {
/**
* @param {string} title
- * @param {!Array.} stackTrace
+ * @param {!RuntimeAgent.StackTrace} stackTrace
*/
appendStackTrace: function(title, stackTrace)
{
@@ -1959,7 +2015,7 @@ WebInspector.TimelineDetailsContentHelper.prototype = {
/**
* @param {!Element} parentElement
- * @param {!Array.} stackTrace
+ * @param {!RuntimeAgent.StackTrace} stackTrace
*/
createChildStackTraceElement: function(parentElement, stackTrace)
{
diff --git a/front_end/timeline/module.json b/front_end/timeline/module.json
index 980a766a85..f90cdd8ace 100644
--- a/front_end/timeline/module.json
+++ b/front_end/timeline/module.json
@@ -107,6 +107,7 @@
"Layers3DView.js",
"MemoryCountersGraph.js",
"TimelineModel.js",
+ "TimelineIRModel.js",
"TimelineJSProfile.js",
"TimelineFrameModel.js",
"TimelineEventOverview.js",
diff --git a/front_end/ui/SettingsUI.js b/front_end/ui/SettingsUI.js
index 05c2a7ca80..5b35756227 100644
--- a/front_end/ui/SettingsUI.js
+++ b/front_end/ui/SettingsUI.js
@@ -77,139 +77,6 @@ WebInspector.SettingsUI.bindCheckbox = function(input, setting)
input.addEventListener("change", inputChanged, false);
}
-/**
- * @param {string} label
- * @param {!WebInspector.Setting} setting
- * @param {boolean} numeric
- * @param {number=} maxLength
- * @param {string=} width
- * @param {function(string):?string=} validatorCallback
- * @param {boolean=} instant
- * @param {boolean=} clearForZero
- * @param {string=} placeholder
- * @return {!Element}
- */
-WebInspector.SettingsUI.createSettingInputField = function(label, setting, numeric, maxLength, width, validatorCallback, instant, clearForZero, placeholder)
-{
- var p = createElement("p");
- var labelElement = p.createChild("label");
- labelElement.textContent = label;
- var inputElement = p.createChild("input");
- inputElement.type = "text";
- if (numeric)
- inputElement.className = "numeric";
- if (maxLength)
- inputElement.maxLength = maxLength;
- if (width)
- inputElement.style.width = width;
- inputElement.placeholder = placeholder || "";
-
- var errorMessageLabel;
- if (validatorCallback)
- errorMessageLabel = p.createChild("div", "field-error-message");
- WebInspector.SettingsUI.bindSettingInputField(inputElement, setting, numeric, validatorCallback, instant, clearForZero, errorMessageLabel);
- return p;
-}
-
-/**
- * @param {!Element} inputElement
- * @param {!WebInspector.Setting} setting
- * @param {boolean} numeric
- * @param {function(string):?string=} validatorCallback
- * @param {boolean=} instant
- * @param {boolean=} clearForZero
- * @param {!Element=} errorMessageLabel
- */
-WebInspector.SettingsUI.bindSettingInputField = function(inputElement, setting, numeric, validatorCallback, instant, clearForZero, errorMessageLabel)
-{
- if (validatorCallback || instant) {
- inputElement.addEventListener("change", onInput, false);
- inputElement.addEventListener("input", onInput, false);
- }
- inputElement.addEventListener("keydown", onKeyDown, false);
-
- function onInput()
- {
- if (validatorCallback)
- validate();
- if (instant)
- apply();
- }
-
- function onKeyDown(event)
- {
- if (isEnterKey(event))
- apply();
- incrementForArrows(event);
- }
-
- function incrementForArrows(event)
- {
- if (!numeric)
- return;
-
- var increment = event.keyIdentifier === "Up" ? 1 : event.keyIdentifier === "Down" ? -1 : 0;
- if (!increment)
- return;
- if (event.shiftKey)
- increment *= 10;
-
- var value = inputElement.value;
- if (validatorCallback && validatorCallback(value))
- return;
- value = Number(value);
- if (clearForZero && !value)
- return;
- value += increment;
- if (clearForZero && !value)
- return;
- value = String(value);
- if (validatorCallback && validatorCallback(value))
- return;
-
- inputElement.value = value;
- apply();
- event.preventDefault();
- }
-
- function validate()
- {
- var error = validatorCallback(inputElement.value);
- if (!error)
- error = "";
- inputElement.classList.toggle("error-input", !!error);
- if (errorMessageLabel)
- errorMessageLabel.textContent = error;
- }
-
- if (!instant)
- inputElement.addEventListener("blur", apply, false);
-
- function apply()
- {
- if (validatorCallback && validatorCallback(inputElement.value))
- return;
- setting.removeChangeListener(onSettingChange);
- setting.set(numeric ? Number(inputElement.value) : inputElement.value);
- setting.addChangeListener(onSettingChange);
- }
-
- setting.addChangeListener(onSettingChange);
-
- function onSettingChange()
- {
- var value = setting.get();
- if (clearForZero && !value)
- value = "";
- inputElement.value = value;
- validate();
- }
- onSettingChange();
-
- if (validatorCallback)
- validate();
-}
-
/**
* @param {string} name
* @param {!Element} element
@@ -241,20 +108,6 @@ WebInspector.SettingsUI.createSettingFieldset = function(setting)
}
}
-/**
- * @param {string} text
- * @return {?string}
- */
-WebInspector.SettingsUI.regexValidator = function(text)
-{
- var regex;
- try {
- regex = new RegExp(text);
- } catch (e) {
- }
- return regex ? null : WebInspector.UIString("Invalid pattern");
-}
-
/**
* Creates an input element under the parentElement with the given id and defaultText.
* @param {!Element} parentElement
diff --git a/front_end/ui/UIUtils.js b/front_end/ui/UIUtils.js
index 9778f343bf..415b2f1630 100644
--- a/front_end/ui/UIUtils.js
+++ b/front_end/ui/UIUtils.js
@@ -673,8 +673,6 @@ WebInspector.installComponentRootStyles = function(element)
WebInspector.appendStyle(element, "ui/inspectorCommon.css");
WebInspector.themeSupport.injectHighlightStyleSheets(element);
element.classList.add("platform-" + WebInspector.platform());
- if (Runtime.experiments.isEnabled("materialDesign"))
- element.classList.add("material");
}
/**
@@ -1450,6 +1448,83 @@ WebInspector.appendStyle = function(node, cssFile)
});
})();
+/**
+ * @param {!Element} input
+ * @param {function(string)} apply
+ * @param {function(string):boolean} validate
+ * @param {boolean} numeric
+ * @return {function(string)}
+ */
+WebInspector.bindInput = function(input, apply, validate, numeric)
+{
+ input.addEventListener("change", onChange, false);
+ input.addEventListener("input", onInput, false);
+ input.addEventListener("keydown", onKeyDown, false);
+ input.addEventListener("focus", input.select.bind(input), false);
+
+ function onInput()
+ {
+ input.classList.toggle("error-input", !validate(input.value));
+ }
+
+ function onChange()
+ {
+ var valid = validate(input.value);
+ input.classList.toggle("error-input", !valid);
+ if (valid)
+ apply(input.value);
+ }
+
+ /**
+ * @param {!Event} event
+ */
+ function onKeyDown(event)
+ {
+ if (isEnterKey(event)) {
+ if (validate(input.value))
+ apply(input.value);
+ return;
+ }
+
+ if (!numeric)
+ return;
+
+ var increment = event.keyIdentifier === "Up" ? 1 : event.keyIdentifier === "Down" ? -1 : 0;
+ if (!increment)
+ return;
+ if (event.shiftKey)
+ increment *= 10;
+
+ var value = input.value;
+ if (!validate(value) || !value)
+ return;
+
+ value = (value ? Number(value) : 0) + increment;
+ var stringValue = value ? String(value) : "";
+ if (!validate(stringValue) || !value)
+ return;
+
+ input.value = stringValue;
+ apply(input.value);
+ event.preventDefault();
+ }
+
+ /**
+ * @param {string} value
+ */
+ function setValue(value)
+ {
+ if (value === input.value)
+ return;
+ var valid = validate(value);
+ input.classList.toggle("error-input", !valid);
+ input.value = value;
+ input.setSelectionRange(value.length, value.length);
+ }
+
+ return setValue;
+}
+
/**
* @constructor
*/
diff --git a/front_end/ui/inspectorCommon.css b/front_end/ui/inspectorCommon.css
index fa2794d690..3fd0816c72 100644
--- a/front_end/ui/inspectorCommon.css
+++ b/front_end/ui/inspectorCommon.css
@@ -200,6 +200,10 @@ input[type="text"]:focus {
text-decoration: none !important;
}
+.error-input {
+ outline: auto 2px red !important;
+}
+
.chrome-select {
-webkit-appearance: none;
-webkit-user-select: none;
diff --git a/front_end/ui/inspectorStyle.css b/front_end/ui/inspectorStyle.css
index d56a8d6c6c..cb9af59e1b 100644
--- a/front_end/ui/inspectorStyle.css
+++ b/front_end/ui/inspectorStyle.css
@@ -108,10 +108,6 @@ fieldset[disabled] label:hover input {
color: hsl(0, 100%, 65%);
}
-.error-input {
- background-color: rgb(220, 130, 130);
-}
-
.panel {
display: flex;
overflow: hidden;
diff --git a/front_end/ui/listWidget.css b/front_end/ui/listWidget.css
index 1dd4e3e234..713b94673f 100644
--- a/front_end/ui/listWidget.css
+++ b/front_end/ui/listWidget.css
@@ -128,6 +128,5 @@
}
.editor-content input.error-input {
- outline: auto 2px red;
background-color: white;
}
diff --git a/front_end/ui/splitWidget.css b/front_end/ui/splitWidget.css
index 067861fc45..f2ba11e1eb 100644
--- a/front_end/ui/splitWidget.css
+++ b/front_end/ui/splitWidget.css
@@ -132,21 +132,11 @@
left: 5px;
}
-:host-context(.material) .shadow-split-widget button.left-sidebar-show-hide-button,
-:host-context(.material) .shadow-split-widget button.top-sidebar-show-hide-button {
- top: 5px;
-}
-
.shadow-split-widget button.right-sidebar-show-hide-button {
top: 5px;
right:4px;
}
-:host-context(.material) .shadow-split-widget button.right-sidebar-show-hide-button {
- top: 5px;
- right: 5px;
-}
-
.shadow-split-widget button.bottom-sidebar-show-hide-button {
bottom: 5px;
right: 3px;
diff --git a/front_end/ui/toolbar.css b/front_end/ui/toolbar.css
index b2bcdd483b..15f9ba3b9f 100644
--- a/front_end/ui/toolbar.css
+++ b/front_end/ui/toolbar.css
@@ -91,6 +91,11 @@
flex: auto;
overflow: hidden;
text-align: right;
+ color: #333 !important;
+}
+
+.toolbar-button .toolbar-dropdown-arrow {
+ background-color: #333 !important;
}
.toolbar-has-glyph .toolbar-text {
@@ -127,8 +132,7 @@
opacity: 0.5;
}
-.toolbar-button:enabled.hover:not(:active) .toolbar-glyph,
-.toolbar-button:enabled.hover:not(:active) .toolbar-dropdown-arrow {
+.toolbar-button:enabled.hover:not(:active) .toolbar-glyph {
background-color: #333;
}
diff --git a/front_end/ui_lazy/DataGrid.js b/front_end/ui_lazy/DataGrid.js
index c10fbd1495..07724d12ff 100644
--- a/front_end/ui_lazy/DataGrid.js
+++ b/front_end/ui_lazy/DataGrid.js
@@ -181,6 +181,8 @@ WebInspector.DataGrid.Align = {
Right: "right"
}
+WebInspector.DataGrid._preferredWidthSymbol = Symbol("preferredWidth");
+
WebInspector.DataGrid.prototype = {
/**
* @param {string} cellClass
@@ -341,7 +343,8 @@ WebInspector.DataGrid.prototype = {
* @param {boolean} wasChange
* @this {WebInspector.DataGrid}
*/
- function moveToNextIfNeeded(wasChange) {
+ function moveToNextIfNeeded(wasChange)
+ {
if (!moveDirection)
return;
@@ -659,19 +662,32 @@ WebInspector.DataGrid.prototype = {
return;
var sumOfWeights = 0.0;
- for (var i = 0; i < this._visibleColumnsArray.length; ++i)
- sumOfWeights += this._visibleColumnsArray[i].weight;
-
+ var fixedColumnWidths = [];
+ for (var i = 0; i < this._visibleColumnsArray.length; ++i) {
+ var column = this._visibleColumnsArray[i];
+ if (column.fixedWidth) {
+ var width = this._headerTableColumnGroup.children[i][WebInspector.DataGrid._preferredWidthSymbol] || this.headerTableBody.rows[0].cells[i].offsetWidth;
+ fixedColumnWidths[i] = width;
+ tableWidth -= width;
+ } else {
+ sumOfWeights += this._visibleColumnsArray[i].weight;
+ }
+ }
var sum = 0;
var lastOffset = 0;
for (var i = 0; i < this._visibleColumnsArray.length; ++i) {
- sum += this._visibleColumnsArray[i].weight;
- var offset = (sum * tableWidth / sumOfWeights) | 0;
- var width = (offset - lastOffset) + "px";
- this._headerTableColumnGroup.children[i].style.width = width;
- this._dataTableColumnGroup.children[i].style.width = width;
- lastOffset = offset;
+ var column = this._visibleColumnsArray[i];
+ var width;
+ if (column.fixedWidth) {
+ width = fixedColumnWidths[i];
+ } else {
+ sum += column.weight;
+ var offset = (sum * tableWidth / sumOfWeights) | 0;
+ width = offset - lastOffset;
+ lastOffset = offset;
+ }
+ this._setPreferredWidth(i, width);
}
this._positionResizers();
@@ -1041,13 +1057,8 @@ WebInspector.DataGrid.prototype = {
resizer.__position = position;
resizer.style.left = position + "px";
- var pxLeftColumn = (dragPoint - leftEdgeOfPreviousColumn) + "px";
- this._headerTableColumnGroup.children[leftCellIndex].style.width = pxLeftColumn;
- this._dataTableColumnGroup.children[leftCellIndex].style.width = pxLeftColumn;
-
- var pxRightColumn = (rightEdgeOfNextColumn - dragPoint) + "px";
- this._headerTableColumnGroup.children[rightCellIndex].style.width = pxRightColumn;
- this._dataTableColumnGroup.children[rightCellIndex].style.width = pxRightColumn;
+ this._setPreferredWidth(leftCellIndex, dragPoint - leftEdgeOfPreviousColumn);
+ this._setPreferredWidth(rightCellIndex, rightEdgeOfNextColumn - dragPoint);
var leftColumn = this._visibleColumnsArray[leftCellIndex];
var rightColumn = this._visibleColumnsArray[rightCellIndex];
@@ -1063,6 +1074,18 @@ WebInspector.DataGrid.prototype = {
this.dispatchEventToListeners(WebInspector.DataGrid.Events.ColumnsResized);
},
+ /**
+ * @param {number} columnIndex
+ * @param {number} width
+ */
+ _setPreferredWidth: function(columnIndex, width)
+ {
+ var pxWidth = width + "px";
+ this._headerTableColumnGroup.children[columnIndex][WebInspector.DataGrid._preferredWidthSymbol] = width;
+ this._headerTableColumnGroup.children[columnIndex].style.width = pxWidth;
+ this._dataTableColumnGroup.children[columnIndex].style.width = pxWidth;
+ },
+
/**
* @param {string} columnId
* @return {number}
diff --git a/protocol.json b/protocol.json
index 0ab4bca05d..d14c5d8b3f 100644
--- a/protocol.json
+++ b/protocol.json
@@ -203,6 +203,14 @@
],
"hidden": true
},
+ {
+ "name": "setAutoAttachToCreatedPages",
+ "parameters": [
+ { "name": "autoAttach", "type": "boolean", "description": "If true, browser will open a new inspector window for every page created from this one." }
+ ],
+ "description": "Controls whether browser will open a new inspector window for connected pages.",
+ "hidden": true
+ },
{
"name": "reload",
"parameters": [
@@ -632,22 +640,6 @@
"domain": "Emulation",
"description": "This domain emulates different environments for the page.",
"hidden": true,
- "types": [
- {
- "id": "Viewport",
- "type": "object",
- "description": "Visible page viewport",
- "properties": [
- { "name": "scrollX", "type": "number", "description": "X scroll offset in CSS pixels." },
- { "name": "scrollY", "type": "number", "description": "Y scroll offset in CSS pixels." },
- { "name": "contentsWidth", "type": "number", "description": "Contents width in CSS pixels." },
- { "name": "contentsHeight", "type": "number", "description": "Contents height in CSS pixels." },
- { "name": "pageScaleFactor", "type": "number", "description": "Page scale factor." },
- { "name": "minimumPageScaleFactor", "type": "number", "description": "Minimum page scale factor." },
- { "name": "maximumPageScaleFactor", "type": "number", "description": "Maximum page scale factor." }
- ]
- }
- ],
"commands": [
{
"name": "setDeviceMetricsOverride",
@@ -737,21 +729,17 @@
],
"handlers": ["browser"]
}
- ],
- "events": [
- {
- "name": "viewportChanged",
- "description": "Fired when a visible page viewport has changed. Only fired when device metrics are overridden.",
- "parameters": [
- { "name": "viewport", "$ref": "Viewport", "description": "Viewport description." }
- ]
- }
]
},
{
"domain": "Runtime",
"description": "Runtime domain exposes JavaScript runtime by means of remote evaluation and mirror objects. Evaluation results are returned as mirror object that expose object type, string representation and unique identifier that can be used for further object reference. Original objects are maintained in memory unless they are either explicitly released or are released along with the other objects in their object group.",
"types": [
+ {
+ "id": "ScriptId",
+ "type": "string",
+ "description": "Unique script identifier."
+ },
{
"id": "RemoteObjectId",
"type": "string",
@@ -871,6 +859,41 @@
{ "name": "name", "type": "string", "description": "Human readable name describing given context.", "hidden": true},
{ "name": "frameId", "type": "string", "description": "Id of the owning frame. May be an empty string if the context is not associated with a frame." }
]
+ },
+ {
+ "id": "ExceptionDetails",
+ "type": "object",
+ "description": "Detailed information on exception (or error) that was thrown during script compilation or execution.",
+ "properties": [
+ { "name": "text", "type": "string", "description": "Exception text." },
+ { "name": "url", "type": "string", "optional": true, "description": "URL of the message origin." },
+ { "name": "scriptId", "type": "string", "optional": true, "description": "Script ID of the message origin." },
+ { "name": "line", "type": "integer", "optional": true, "description": "Line number in the resource that generated this message." },
+ { "name": "column", "type": "integer", "optional": true, "description": "Column number in the resource that generated this message." },
+ { "name": "stack", "$ref": "StackTrace", "optional": true, "description": "JavaScript stack trace for assertions and error messages." }
+ ]
+ },
+ {
+ "id": "CallFrame",
+ "type": "object",
+ "description": "Stack entry for runtime errors and assertions.",
+ "properties": [
+ { "name": "functionName", "type": "string", "description": "JavaScript function name." },
+ { "name": "scriptId", "$ref": "ScriptId", "description": "JavaScript script id." },
+ { "name": "url", "type": "string", "description": "JavaScript script name or url." },
+ { "name": "lineNumber", "type": "integer", "description": "JavaScript script line number." },
+ { "name": "columnNumber", "type": "integer", "description": "JavaScript script column number." }
+ ]
+ },
+ {
+ "id": "StackTrace",
+ "type": "object",
+ "description": "Call frames for assertions or error messages.",
+ "properties": [
+ { "name": "description", "type": "string", "optional": true, "description": "String label of this stack trace. For async traces this may be a name of the function that initiated the async call." },
+ { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "JavaScript function name." },
+ { "name": "parent", "$ref": "StackTrace", "optional": true, "hidden": true, "hidden": true, "description": "Asynchronous JavaScript stack trace that preceded this stack, if available." }
+ ]
}
],
"commands": [
@@ -888,7 +911,7 @@
"returns": [
{ "name": "result", "$ref": "RemoteObject", "description": "Evaluation result." },
{ "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." },
- { "name": "exceptionDetails", "$ref": "Debugger.ExceptionDetails", "optional": true, "hidden": true, "description": "Exception details."}
+ { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "hidden": true, "description": "Exception details."}
],
"description": "Evaluates expression on global object."
},
@@ -919,7 +942,7 @@
"returns": [
{ "name": "result", "type": "array", "items": { "$ref": "PropertyDescriptor" }, "description": "Object properties." },
{ "name": "internalProperties", "optional": true, "type": "array", "items": { "$ref": "InternalPropertyDescriptor" }, "description": "Internal object properties (only of the element itself).", "hidden": true },
- { "name": "exceptionDetails", "$ref": "Debugger.ExceptionDetails", "optional": true, "hidden": true, "description": "Exception details."}
+ { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "hidden": true, "description": "Exception details."}
],
"description": "Returns properties of a given object. Object group of the result is inherited from the target object."
},
@@ -967,6 +990,36 @@
}
],
"hidden": true
+ },
+ {
+ "name": "compileScript",
+ "hidden": true,
+ "parameters": [
+ { "name": "expression", "type": "string", "description": "Expression to compile." },
+ { "name": "sourceURL", "type": "string", "description": "Source url to be set for the script." },
+ { "name": "persistScript", "type": "boolean", "description": "Specifies whether the compiled script should be persisted." },
+ { "name": "executionContextId", "$ref": "ExecutionContextId", "description": "Specifies in which isolated context to perform script run. Each content script lives in an isolated context and this parameter is used to specify one of those contexts." }
+ ],
+ "returns": [
+ { "name": "scriptId", "$ref": "ScriptId", "optional": true, "description": "Id of the script." },
+ { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."}
+ ],
+ "description": "Compiles expression."
+ },
+ {
+ "name": "runScript",
+ "hidden": true,
+ "parameters": [
+ { "name": "scriptId", "$ref": "ScriptId", "description": "Id of the script to run." },
+ { "name": "executionContextId", "$ref": "ExecutionContextId", "description": "Specifies in which isolated context to perform script run. Each content script lives in an isolated context and this parameter is used to specify one of those contexts." },
+ { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." },
+ { "name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true, "description": "Specifies whether script run should stop on exceptions and mute console. Overrides setPauseOnException state." }
+ ],
+ "returns": [
+ { "name": "result", "$ref": "RemoteObject", "description": "Run result." },
+ { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."}
+ ],
+ "description": "Runs script with given id in a given context."
}
],
"events": [
@@ -1015,43 +1068,13 @@
{ "name": "column", "type": "integer", "optional": true, "description": "Column number in the resource that generated this message." },
{ "name": "repeatCount", "type": "integer", "optional": true, "description": "Repeat count for repeated messages." },
{ "name": "parameters", "type": "array", "items": { "$ref": "Runtime.RemoteObject" }, "optional": true, "description": "Message parameters in case of the formatted message." },
- { "name": "stackTrace", "$ref": "StackTrace", "optional": true, "description": "JavaScript stack trace for assertions and error messages." },
- { "name": "asyncStackTrace", "$ref": "AsyncStackTrace", "optional": true, "description": "Asynchronous JavaScript stack trace that preceded this message, if available.", "hidden": true },
+ { "name": "stack", "$ref": "Runtime.StackTrace", "optional": true, "description": "JavaScript stack trace for assertions and error messages." },
{ "name": "networkRequestId", "$ref": "Network.RequestId", "optional": true, "description": "Identifier of the network request associated with this message." },
{ "name": "timestamp", "$ref": "Timestamp", "description": "Timestamp, when this message was fired.", "hidden": true },
{ "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "optional": true, "description": "Identifier of the context where this message was created", "hidden": true },
{ "name": "messageId", "type": "integer", "hidden": true, "optional": true, "description": "Message id." },
{ "name": "relatedMessageId", "type": "integer", "hidden": true, "optional": true, "description": "Related message id." }
]
- },
- {
- "id": "CallFrame",
- "type": "object",
- "description": "Stack entry for console errors and assertions.",
- "properties": [
- { "name": "functionName", "type": "string", "description": "JavaScript function name." },
- { "name": "scriptId", "type": "string", "description": "JavaScript script id." },
- { "name": "url", "type": "string", "description": "JavaScript script name or url." },
- { "name": "lineNumber", "type": "integer", "description": "JavaScript script line number." },
- { "name": "columnNumber", "type": "integer", "description": "JavaScript script column number." }
- ]
- },
- {
- "id": "StackTrace",
- "type": "array",
- "items": { "$ref": "CallFrame" },
- "description": "Call frames for assertions or error messages."
- },
- {
- "id": "AsyncStackTrace",
- "type": "object",
- "properties": [
- { "name": "callFrames", "type": "array", "items": { "$ref": "CallFrame" }, "description": "Call frames of the stack trace." },
- { "name": "description", "type": "string", "optional": true, "description": "String label of this stack trace. For async traces this may be a name of the function that initiated the async call." },
- { "name": "asyncStackTrace", "$ref": "AsyncStackTrace", "optional": true, "description": "Next asynchronous stack trace, if any." }
- ],
- "description": "Asynchronous JavaScript call stack.",
- "hidden": true
}
],
"commands": [
@@ -1241,6 +1264,16 @@
{ "name": "validTo", "$ref": "Timestamp", "description": "Certificate valid to (expiration) date" }
]
},
+ {
+ "id": "CertificateValidationDetails",
+ "type": "object",
+ "description": "Details about the validation status of a request's certificate.",
+ "properties": [
+ { "name": "numUnknownScts", "type": "integer", "description": "The number of SCTs from unknown logs." },
+ { "name": "numInvalidScts", "type": "integer", "description": "The number of invalid SCTs." },
+ { "name": "numValidScts", "type": "integer", "description": "The number of valid SCTs." }
+ ]
+ },
{
"id": "SecurityDetails",
"type": "object",
@@ -1250,7 +1283,8 @@
{ "name": "keyExchange", "type": "string", "description": "Key Exchange used by the connection." },
{ "name": "cipher", "type": "string", "description": "Cipher name." },
{ "name": "mac", "type": "string", "optional": true, "description": "TLS MAC. Note that AEAD ciphers do not have separate MACs." },
- { "name": "certificateId", "$ref": "CertificateId", "description": "Certificate ID value." }
+ { "name": "certificateId", "$ref": "CertificateId", "description": "Certificate ID value." },
+ { "name": "certificateValidationDetails", "$ref": "CertificateValidationDetails", "optional": true, "description": "Validation details for the request's certficate." }
]
},
{
@@ -1337,10 +1371,9 @@
"description": "Information about the request initiator.",
"properties": [
{ "name": "type", "type": "string", "enum": ["parser", "script", "other"], "description": "Type of this initiator." },
- { "name": "stackTrace", "$ref": "Console.StackTrace", "optional": true, "description": "Initiator JavaScript stack trace, set for Script only." },
+ { "name": "stack", "$ref": "Runtime.StackTrace", "optional": true, "description": "Initiator JavaScript stack trace, set for Script only." },
{ "name": "url", "type": "string", "optional": true, "description": "Initiator URL, set for Parser type only." },
- { "name": "lineNumber", "type": "number", "optional": true, "description": "Initiator line number, set for Parser type only." },
- { "name": "asyncStackTrace", "$ref": "Console.AsyncStackTrace", "optional": true, "description": "Initiator asynchronous JavaScript stack trace, if available.", "hidden": true }
+ { "name": "lineNumber", "type": "number", "optional": true, "description": "Initiator line number, set for Parser type only." }
]
},
{
@@ -3135,6 +3168,8 @@
"id": "CSSKeyframeRule",
"type": "object",
"properties": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId", "optional": true, "description": "The css style sheet identifier (absent for user agent stylesheet and user-specified stylesheet rules) this rule came from." },
+ { "name": "origin", "$ref": "StyleSheetOrigin", "description": "Parent stylesheet's origin."},
{ "name": "keyText", "$ref": "Value", "description": "Associated key text." },
{ "name": "style", "$ref": "CSSStyle", "description": "Associated style declaration." }
],
@@ -3161,7 +3196,8 @@
{ "name": "attributesStyle", "$ref": "CSSStyle", "optional": true, "description": "Attribute-defined element style (e.g. resulting from \"width=20 height=100%\")."},
{ "name": "matchedCSSRules", "type": "array", "items": { "$ref": "RuleMatch" }, "optional": true, "description": "CSS rules matching this node, from all applicable stylesheets." },
{ "name": "pseudoElements", "type": "array", "items": { "$ref": "PseudoElementMatches" }, "optional": true, "description": "Pseudo style matches for this node." },
- { "name": "inherited", "type": "array", "items": { "$ref": "InheritedStyleEntry" }, "optional": true, "description": "A chain of inherited styles (from the immediate node parent up to the DOM tree root)." }
+ { "name": "inherited", "type": "array", "items": { "$ref": "InheritedStyleEntry" }, "optional": true, "description": "A chain of inherited styles (from the immediate node parent up to the DOM tree root)." },
+ { "name": "cssKeyframesRules", "type": "array", "items": { "$ref": "CSSKeyframesRule" }, "optional": true, "description": "A list of CSS keyframed animations matching this node." }
],
"description": "Returns requested styles for a DOM node identified by nodeId
."
},
@@ -3197,16 +3233,6 @@
"description": "Requests information about platform fonts which we used to render child TextNodes in the given node.",
"hidden": true
},
- {
- "name": "getCSSAnimationsForNode",
- "parameters": [
- { "name": "nodeId", "$ref": "DOM.NodeId" }
- ],
- "returns": [
- { "name": "cssKeyframesRules", "type": "array", "items": { "$ref": "CSSKeyframesRule" }, "optional": true, "description": "A list of CSS keyframed animations matching this node." }
- ],
- "description": "Returns all CSS keyframed animations mtaching this node."
- },
{
"name": "getStyleSheetText",
"parameters": [
@@ -3240,6 +3266,18 @@
],
"description": "Modifies the rule selector."
},
+ {
+ "name": "setKeyframeKey",
+ "parameters": [
+ { "name": "styleSheetId", "$ref": "StyleSheetId" },
+ { "name": "range", "$ref": "SourceRange" },
+ { "name": "keyText", "type": "string" }
+ ],
+ "returns": [
+ { "name": "keyText", "$ref": "Value", "description": "The resulting key text after modification." }
+ ],
+ "description": "Modifies the keyframe rule key text."
+ },
{
"name": "setStyleText",
"parameters": [
@@ -3394,61 +3432,6 @@
}
]
},
- {
- "domain": "Timeline",
- "description": "Timeline domain is deprecated. Please use Tracing instead.",
- "types": [
- {
- "id": "TimelineEvent",
- "type": "object",
- "properties": [
- { "name": "type", "type": "string", "description": "Event type." },
- { "name": "data", "type": "object", "description": "Event data." },
- { "name": "startTime", "type": "number", "description": "Start time." },
- { "name": "endTime", "type": "number", "optional": true, "description": "End time." },
- { "name": "children", "type": "array", "optional": true, "items": { "$ref": "TimelineEvent" }, "description": "Nested records." },
- { "name": "thread", "type": "string", "optional": true, "hidden": true, "description": "If present, identifies the thread that produced the event." },
- { "name": "stackTrace", "$ref": "Console.StackTrace", "optional": true, "hidden": true, "description": "Stack trace." },
- { "name": "frameId", "type": "string", "optional": true, "hidden": true, "description": "Unique identifier of the frame within the page that the event relates to." }
- ],
- "description": "Timeline record contains information about the recorded activity."
- }
- ],
- "commands": [
- {
- "name": "enable",
- "description": "Deprecated."
- },
- {
- "name": "disable",
- "description": "Deprecated."
- },
- {
- "name": "start",
- "parameters": [
- { "name": "maxCallStackDepth", "optional": true, "type": "integer", "description": "Samples JavaScript stack traces up to maxCallStackDepth
, defaults to 5." },
- { "name": "bufferEvents", "optional": true, "type": "boolean", "hidden": true, "description": "Whether instrumentation events should be buffered and returned upon stop
call." },
- { "name": "liveEvents", "optional": true, "type": "string", "hidden": true, "description": "Coma separated event types to issue although bufferEvents is set."},
- { "name": "includeCounters", "optional": true, "type": "boolean", "hidden": true, "description": "Whether counters data should be included into timeline events." },
- { "name": "includeGPUEvents", "optional": true, "type": "boolean", "hidden": true, "description": "Whether events from GPU process should be collected." }
- ],
- "description": "Deprecated."
- },
- {
- "name": "stop",
- "description": "Deprecated."
- }
- ],
- "events": [
- {
- "name": "eventRecorded",
- "parameters": [
- { "name": "record", "$ref": "TimelineEvent", "description": "Timeline event record data." }
- ],
- "description": "Deprecated."
- }
- ]
- },
{
"domain": "Debugger",
"description": "Debugger domain exposes JavaScript debugging capabilities. It allows setting and removing breakpoints, stepping through execution, exploring stack traces, etc.",
@@ -3458,11 +3441,6 @@
"type": "string",
"description": "Breakpoint identifier."
},
- {
- "id": "ScriptId",
- "type": "string",
- "description": "Unique script identifier."
- },
{
"id": "CallFrameId",
"type": "string",
@@ -3472,12 +3450,22 @@
"id": "Location",
"type": "object",
"properties": [
- { "name": "scriptId", "$ref": "ScriptId", "description": "Script identifier as reported in the Debugger.scriptParsed
." },
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Script identifier as reported in the Debugger.scriptParsed
." },
{ "name": "lineNumber", "type": "integer", "description": "Line number in the script (0-based)." },
{ "name": "columnNumber", "type": "integer", "optional": true, "description": "Column number in the script (0-based)." }
],
"description": "Location in the source code."
},
+ {
+ "id": "ScriptPosition",
+ "hidden": true,
+ "type": "object",
+ "properties": [
+ { "name": "line", "type": "integer" },
+ { "name": "column", "type": "integer" }
+ ],
+ "description": "Location in the source code."
+ },
{
"id": "FunctionDetails",
"hidden": true,
@@ -3547,19 +3535,6 @@
],
"description": "Scope description."
},
- {
- "id": "ExceptionDetails",
- "type": "object",
- "description": "Detailed information on exception (or error) that was thrown during script compilation or execution.",
- "properties": [
- { "name": "text", "type": "string", "description": "Exception text." },
- { "name": "url", "type": "string", "optional": true, "description": "URL of the message origin." },
- { "name": "scriptId", "type": "string", "optional": true, "description": "Script ID of the message origin." },
- { "name": "line", "type": "integer", "optional": true, "description": "Line number in the resource that generated this message." },
- { "name": "column", "type": "integer", "optional": true, "description": "Column number in the resource that generated this message." },
- { "name": "stackTrace", "$ref": "Console.StackTrace", "optional": true, "description": "JavaScript stack trace for assertions and error messages." }
- ]
- },
{
"id": "SetScriptSourceError",
"type": "object",
@@ -3583,13 +3558,10 @@
{ "name": "id", "type": "integer", "description": "Unique id of the promise." },
{ "name": "status", "type": "string", "optional": true, "enum": ["pending", "resolved", "rejected"], "description": "Status of the promise." },
{ "name": "parentId", "type": "integer", "optional": true, "description": "Id of the parent promise." },
- { "name": "callFrame", "$ref": "Console.CallFrame", "optional": true, "description": "Top call frame on promise creation."},
{ "name": "creationTime", "type": "number", "optional": true, "description": "Creation time of the promise." },
{ "name": "settlementTime", "type": "number", "optional": true, "description": "Settlement time of the promise." },
- { "name": "creationStack", "$ref": "Console.StackTrace", "optional": true, "description": "JavaScript stack trace on promise creation." },
- { "name": "asyncCreationStack", "$ref": "Console.AsyncStackTrace", "optional": true, "description": "JavaScript asynchronous stack trace on promise creation, if available." },
- { "name": "settlementStack", "$ref": "Console.StackTrace", "optional": true, "description": "JavaScript stack trace on promise settlement." },
- { "name": "asyncSettlementStack", "$ref": "Console.AsyncStackTrace", "optional": true, "description": "JavaScript asynchronous stack trace on promise settlement, if available." }
+ { "name": "creationStack", "$ref": "Runtime.StackTrace", "optional": true, "description": "JavaScript stack trace on promise creation." },
+ { "name": "settlementStack", "$ref": "Runtime.StackTrace", "optional": true, "description": "JavaScript stack trace on promise settlement." }
],
"hidden": true
},
@@ -3599,9 +3571,7 @@
"description": "Information about the async operation.",
"properties": [
{ "name": "id", "type": "integer", "description": "Unique id of the async operation." },
- { "name": "description", "type": "string", "description": "String description of the async operation." },
- { "name": "stackTrace", "$ref": "Console.StackTrace", "optional": true, "description": "Stack trace where async operation was scheduled." },
- { "name": "asyncStackTrace", "$ref": "Console.AsyncStackTrace", "optional": true, "description": "Asynchronous stack trace where async operation was scheduled, if available." }
+ { "name": "stack", "$ref": "Runtime.StackTrace", "optional": true, "description": "Stack trace where async operation was scheduled." }
],
"hidden": true
},
@@ -3710,7 +3680,7 @@
{
"name": "searchInContent",
"parameters": [
- { "name": "scriptId", "$ref": "ScriptId", "description": "Id of the script to search in." },
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Id of the script to search in." },
{ "name": "query", "type": "string", "description": "String to search for." },
{ "name": "caseSensitive", "type": "boolean", "optional": true, "description": "If true, search is case sensitive." },
{ "name": "isRegex", "type": "boolean", "optional": true, "description": "If true, treats string parameter as regex." }
@@ -3730,7 +3700,7 @@
{
"name": "setScriptSource",
"parameters": [
- { "name": "scriptId", "$ref": "ScriptId", "description": "Id of the script to edit." },
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Id of the script to edit." },
{ "name": "scriptSource", "type": "string", "description": "New content of the script." },
{ "name": "preview", "type": "boolean", "optional": true, "description": " If true the change will not actually be applied. Preview mode may be used to get result description without actually modifying the code.", "hidden": true }
],
@@ -3759,7 +3729,7 @@
{
"name": "getScriptSource",
"parameters": [
- { "name": "scriptId", "$ref": "ScriptId", "description": "Id of the script to get source for." }
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Id of the script to get source for." }
],
"returns": [
{ "name": "scriptSource", "type": "string", "description": "Script source." }
@@ -3820,40 +3790,10 @@
"returns": [
{ "name": "result", "$ref": "Runtime.RemoteObject", "description": "Object wrapper for the evaluation result." },
{ "name": "wasThrown", "type": "boolean", "optional": true, "description": "True if the result was thrown during the evaluation." },
- { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "hidden": true, "description": "Exception details."}
+ { "name": "exceptionDetails", "$ref": "Runtime.ExceptionDetails", "optional": true, "hidden": true, "description": "Exception details."}
],
"description": "Evaluates expression on a given call frame."
},
- {
- "name": "compileScript",
- "hidden": true,
- "parameters": [
- { "name": "expression", "type": "string", "description": "Expression to compile." },
- { "name": "sourceURL", "type": "string", "description": "Source url to be set for the script." },
- { "name": "persistScript", "type": "boolean", "description": "Specifies whether the compiled script should be persisted." },
- { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "description": "Specifies in which isolated context to perform script run. Each content script lives in an isolated context and this parameter is used to specify one of those contexts." }
- ],
- "returns": [
- { "name": "scriptId", "$ref": "ScriptId", "optional": true, "description": "Id of the script." },
- { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."}
- ],
- "description": "Compiles expression."
- },
- {
- "name": "runScript",
- "hidden": true,
- "parameters": [
- { "name": "scriptId", "$ref": "ScriptId", "description": "Id of the script to run." },
- { "name": "executionContextId", "$ref": "Runtime.ExecutionContextId", "description": "Specifies in which isolated context to perform script run. Each content script lives in an isolated context and this parameter is used to specify one of those contexts." },
- { "name": "objectGroup", "type": "string", "optional": true, "description": "Symbolic group name that can be used to release multiple objects." },
- { "name": "doNotPauseOnExceptionsAndMuteConsole", "type": "boolean", "optional": true, "description": "Specifies whether script run should stop on exceptions and mute console. Overrides setPauseOnException state." }
- ],
- "returns": [
- { "name": "result", "$ref": "Runtime.RemoteObject", "description": "Run result." },
- { "name": "exceptionDetails", "$ref": "ExceptionDetails", "optional": true, "description": "Exception details."}
- ],
- "description": "Runs script with given id in a given context."
- },
{
"name": "setVariableValue",
"parameters": [
@@ -3886,15 +3826,6 @@
"hidden": true,
"description": "Returns call stack including variables changed since VM was paused. VM must be paused."
},
- {
- "name": "skipStackFrames",
- "parameters": [
- { "name": "script", "type": "string", "optional": true, "description": "Regular expression defining the scripts to ignore while stepping." },
- { "name": "skipContentScripts", "type": "boolean", "optional": true, "description": "True, if all content scripts should be ignored." }
- ],
- "hidden": true,
- "description": "Makes backend skip steps in the sources with names matching given pattern. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful."
- },
{
"name": "setAsyncCallStackDepth",
"parameters": [
@@ -3948,6 +3879,15 @@
],
"hidden": true,
"description": "Removes AsyncOperation breakpoint."
+ },
+ {
+ "name": "setBlackboxedRanges",
+ "parameters": [
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Id of the script." },
+ { "name": "positions", "type": "array", "items": { "$ref": "ScriptPosition" } }
+ ],
+ "hidden": true,
+ "description": "Makes backend skip steps in the script in blackboxed ranges. VM will try leave blacklisted scripts by performing 'step in' several times, finally resorting to 'step out' if unsuccessful. Positions array contains positions where blackbox state is changed. First interval isn't blackboxed. Array should be sorted."
}
],
"events": [
@@ -3958,7 +3898,7 @@
{
"name": "scriptParsed",
"parameters": [
- { "name": "scriptId", "$ref": "ScriptId", "description": "Identifier of the script parsed." },
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Identifier of the script parsed." },
{ "name": "url", "type": "string", "description": "URL or name of the script parsed (if any)." },
{ "name": "startLine", "type": "integer", "description": "Line offset of the script within the resource with given URL (for script tags)." },
{ "name": "startColumn", "type": "integer", "description": "Column offset of the script within the resource with given URL." },
@@ -3976,7 +3916,7 @@
{
"name": "scriptFailedToParse",
"parameters": [
- { "name": "scriptId", "$ref": "ScriptId", "description": "Identifier of the script parsed." },
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Identifier of the script parsed." },
{ "name": "url", "type": "string", "description": "URL or name of the script parsed (if any)." },
{ "name": "startLine", "type": "integer", "description": "Line offset of the script within the resource with given URL (for script tags)." },
{ "name": "startColumn", "type": "integer", "description": "Column offset of the script within the resource with given URL." },
@@ -4150,7 +4090,7 @@
"description": "CPU Profile node. Holds callsite information, execution statistics and child nodes.",
"properties": [
{ "name": "functionName", "type": "string", "description": "Function name." },
- { "name": "scriptId", "$ref": "Debugger.ScriptId", "description": "Script identifier." },
+ { "name": "scriptId", "$ref": "Runtime.ScriptId", "description": "Script identifier." },
{ "name": "url", "type": "string", "description": "URL." },
{ "name": "lineNumber", "type": "integer", "description": "1-based line number of the function start position." },
{ "name": "columnNumber", "type": "integer", "description": "1-based column number of the function start position." },
@@ -5003,6 +4943,14 @@
{ "name": "success", "type": "boolean", "description": "True iff the global memory dump succeeded." }
],
"handlers": ["browser"]
+ },
+ {
+ "name": "recordClockSyncMarker",
+ "description": "Record a clock sync marker in the trace.",
+ "parameters": [
+ { "name": "syncId", "type": "string", "description": "The ID of this clock sync marker" }
+ ],
+ "handlers": ["browser"]
}
],
"events": [
@@ -5225,9 +5173,11 @@
"properties": [
{ "name": "type", "$ref": "AXValueSourceType", "description": "What type of source this is." },
{ "name": "value", "$ref": "AXValue", "description": "The value of this property source.", "optional": true },
- { "name": "attribute", "type": "string", "description": "The attribute, if any.", "optional": true },
+ { "name": "attribute", "type": "string", "description": "The name of the relevant attribute, if any.", "optional": true },
+ { "name": "attributeValue", "$ref": "AXValue", "description": "The value of the relevant attribute, if any.", "optional": true },
{ "name": "superseded", "type": "boolean", "description": "Whether this source is superseded by a higher priority source.", "optional": true },
{ "name": "nativeSource", "$ref": "AXValueNativeSourceType", "description": "The native markup source for this value, e.g. a