Commit 1a45048e authored by achicu@adobe.com's avatar achicu@adobe.com

Web Inspector: Add a way to test the Manager and model classes

https://bugs.webkit.org/show_bug.cgi?id=123223

Reviewed by Timothy Hatcher.

Source/WebInspectorUI:

Moved some global functions out of Main.js, so that they can be used in the
layout tests without including Main.js.

* UserInterface/Main.html: Referenced the new JS files.
* UserInterface/Main.js:
* UserInterface/MessageDispatcher.js: Added.
(WebInspector.dispatchNextQueuedMessageFromBackend):
(WebInspector.dispatchMessageFromBackend):
* UserInterface/URLUtilities.js: Added.
(removeURLFragment):
(relativePath):
(parseURL):
(absoluteURL):
(parseLocationQueryParameters):
(parseQueryString):
(WebInspector.displayNameForURL):
(WebInspector.displayNameForHost):
* UserInterface/Utilities.js:

LayoutTests:

Added the first new WebInspector layout test file. The test is using InspectorTest.importInspectorScripts
to bootstrap some of the managers/observers/models from the new WebInspector.

* http/tests/inspector-protocol/resources/InspectorTest.js:
(InspectorTest.importScript):
(InspectorTest.importInspectorScripts):
* inspector-protocol/model/main-frame-resource-expected.txt: Added.
* inspector-protocol/model/main-frame-resource.html: Added.


git-svn-id: http://svn.webkit.org/repository/webkit/trunk@157938 268f45cc-cd09-0410-ab3c-d52691b4dbfc
parent 00724432
2013-10-24 Alexandru Chiculita <achicu@adobe.com>
Web Inspector: Add a way to test the Manager and model classes
https://bugs.webkit.org/show_bug.cgi?id=123223
Reviewed by Timothy Hatcher.
Added the first new WebInspector layout test file. The test is using InspectorTest.importInspectorScripts
to bootstrap some of the managers/observers/models from the new WebInspector.
* http/tests/inspector-protocol/resources/InspectorTest.js:
(InspectorTest.importScript):
(InspectorTest.importInspectorScripts):
* inspector-protocol/model/main-frame-resource-expected.txt: Added.
* inspector-protocol/model/main-frame-resource.html: Added.
2013-10-24 Alexey Proskuryakov <ap@apple.com>
Freshly landed webgl-1.0.1 tests are failing.
......
......@@ -106,9 +106,62 @@ InspectorTest.importScript = function(scriptName)
var xhr = new XMLHttpRequest();
xhr.open("GET", scriptName, false);
xhr.send(null);
window.eval(xhr.responseText);
if (xhr.status !== 0 && xhr.status !== 200)
throw new Error("Invalid script URL: " + scriptName);
var script = "try { " + xhr.responseText + "} catch (e) { alert(" + JSON.stringify("Error in: " + scriptName) + "); throw e; }";
window.eval(script);
}
InspectorTest.importInspectorScripts = function()
{
// Note: This function overwrites the InspectorFrontendAPI, so there's currently no
// way to intercept the messages from the backend.
var inspectorScripts = [
"Utilities",
"WebInspector",
"Object",
"InspectorBackend",
"InspectorFrontendAPI",
"InspectorFrontendHostStub",
"InspectorBackendCommands",
"URLUtilities",
"MessageDispatcher",
"Setting",
"PageObserver",
"DOMObserver",
"FrameResourceManager",
"RuntimeManager",
"Frame",
"Revision",
"SourceCodeRevision",
"SourceCode",
"Resource",
"ResourceCollection",
"DOMTreeManager",
"DOMNode",
"ContentFlow",
"DOMTree",
"ExecutionContext",
"ExecutionContextList"
];
for (var i = 0; i < inspectorScripts.length; ++i)
InspectorTest.importScript("../../../../../Source/WebInspectorUI/UserInterface/" + inspectorScripts[i] + ".js");
// The initialization should be in sync with WebInspector.loaded in Main.js.
// FIXME: As soon as we can support all the observers and managers we should remove UI related tasks
// from WebInspector.loaded, so that it can be used from the LayoutTests.
InspectorBackend.registerPageDispatcher(new WebInspector.PageObserver);
InspectorBackend.registerDOMDispatcher(new WebInspector.DOMObserver);
WebInspector.frameResourceManager = new WebInspector.FrameResourceManager;
WebInspector.domTreeManager = new WebInspector.DOMTreeManager;
InspectorFrontendHost.loaded();
}
window.addEventListener("message", function(event) {
try {
eval(event.data);
......
Testing that the inspector scripts are loaded and the main frame URL can be received.
Main frame: main-frame-resource.html
<!doctype html>
<html>
<head>
<script type="text/javascript" src="../../http/tests/inspector-protocol/resources/protocol-test.js"></script>
<script>
function test()
{
InspectorTest.importInspectorScripts();
WebInspector.frameResourceManager.addEventListener(WebInspector.FrameResourceManager.Event.MainFrameDidChange, function(event) {
var url = WebInspector.frameResourceManager.mainFrame.url;
InspectorTest.log("Main frame: " + url.substring(url.lastIndexOf("/") + 1));
InspectorTest.completeTest();
});
}
</script>
</head>
<body onload="runTest()">
<p>Testing that the inspector scripts are loaded and the main frame URL can be received.</p>
</body>
</html>
2013-10-24 Alexandru Chiculita <achicu@adobe.com>
Web Inspector: Add a way to test the Manager and model classes
https://bugs.webkit.org/show_bug.cgi?id=123223
Reviewed by Timothy Hatcher.
Moved some global functions out of Main.js, so that they can be used in the
layout tests without including Main.js.
* UserInterface/Main.html: Referenced the new JS files.
* UserInterface/Main.js:
* UserInterface/MessageDispatcher.js: Added.
(WebInspector.dispatchNextQueuedMessageFromBackend):
(WebInspector.dispatchMessageFromBackend):
* UserInterface/URLUtilities.js: Added.
(removeURLFragment):
(relativePath):
(parseURL):
(absoluteURL):
(parseLocationQueryParameters):
(parseQueryString):
(WebInspector.displayNameForURL):
(WebInspector.displayNameForHost):
* UserInterface/Utilities.js:
2013-10-21 Alexandru Chiculita <achicu@adobe.com>
Web Inspector: [CSS Regions] Flows are not loading if you refresh the page several times
......
......@@ -143,6 +143,8 @@
<script src="Utilities.js"></script>
<script src="WebInspector.js"></script>
<script src="URLUtilities.js"></script>
<script src="MessageDispatcher.js"></script>
<script src="Object.js"></script>
<script src="CodeMirrorDragToAlterNumberController.js"></script>
<script src="CodeMirrorAdditions.js"></script>
......
......@@ -311,31 +311,6 @@ WebInspector.contentLoaded = function()
this.showSplitConsole();
}
WebInspector.messagesToDispatch = [];
WebInspector.dispatchNextQueuedMessageFromBackend = function()
{
for (var i = 0; i < this.messagesToDispatch.length; ++i)
InspectorBackend.dispatch(this.messagesToDispatch[i]);
this.messagesToDispatch = [];
this._dispatchTimeout = null;
}
WebInspector.dispatchMessageFromBackend = function(message)
{
// Enforce asynchronous interaction between the backend and the frontend by queueing messages.
// The messages are dequeued on a zero delay timeout.
this.messagesToDispatch.push(message);
if (this._dispatchTimeout)
return;
this._dispatchTimeout = setTimeout(this.dispatchNextQueuedMessageFromBackend.bind(this), 0);
}
WebInspector.sidebarPanelForCurrentContentView = function()
{
var currentContentView = this.contentBrowser.currentContentView;
......@@ -378,27 +353,6 @@ WebInspector.contentBrowserTreeElementForRepresentedObject = function(contentBro
return null;
}
WebInspector.displayNameForURL = function(url, urlComponents)
{
if (!urlComponents)
urlComponents = parseURL(url);
var displayName;
try {
displayName = decodeURIComponent(urlComponents.lastPathComponent || "");
} catch (e) {
displayName = urlComponents.lastPathComponent;
}
return displayName || WebInspector.displayNameForHost(urlComponents.host) || url;
}
WebInspector.displayNameForHost = function(host)
{
// FIXME <rdar://problem/11237413>: This should decode punycode hostnames.
return host;
}
WebInspector.updateWindowTitle = function()
{
var mainFrame = this.frameResourceManager.mainFrame;
......
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
WebInspector.messagesToDispatch = [];
WebInspector.dispatchNextQueuedMessageFromBackend = function()
{
for (var i = 0; i < this.messagesToDispatch.length; ++i)
InspectorBackend.dispatch(this.messagesToDispatch[i]);
this.messagesToDispatch = [];
this._dispatchTimeout = null;
}
WebInspector.dispatchMessageFromBackend = function(message)
{
// Enforce asynchronous interaction between the backend and the frontend by queueing messages.
// The messages are dequeued on a zero delay timeout.
this.messagesToDispatch.push(message);
if (this._dispatchTimeout)
return;
this._dispatchTimeout = setTimeout(this.dispatchNextQueuedMessageFromBackend.bind(this), 0);
}
/*
* Copyright (C) 2013 Apple Inc. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS''
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
* THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
* PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
* THE POSSIBILITY OF SUCH DAMAGE.
*/
function removeURLFragment(url)
{
var hashIndex = url.indexOf("#");
if (hashIndex >= 0)
return url.substring(0, hashIndex);
return url;
}
function relativePath(path, basePath)
{
console.assert(path.charAt(0) === "/");
console.assert(basePath.charAt(0) === "/");
var pathComponents = path.split("/");
var baseComponents = basePath.replace(/\/$/, "").split("/");
var finalComponents = [];
var index = 1;
for (; index < pathComponents.length && index < baseComponents.length; ++index) {
if (pathComponents[index] !== baseComponents[index])
break;
}
for (var i = index; i < baseComponents.length; ++i)
finalComponents.push("..");
for (var i = index; i < pathComponents.length; ++i)
finalComponents.push(pathComponents[i]);
return finalComponents.join("/");
}
function parseURL(url)
{
url = url ? url.trim() : "";
var match = url.match(/^([^:]+):\/\/([^\/:]*)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i);
if (!match)
return {scheme: null, host: null, port: null, path: null, queryString: null, fragment: null, lastPathComponent: null};
var scheme = match[1].toLowerCase();
var host = match[2].toLowerCase();
var port = Number(match[3]) || null;
var wholePath = match[4] || null;
var fragment = match[5] || null;
var path = wholePath;
var queryString = null;
// Split the path and the query string.
if (wholePath) {
var indexOfQuery = wholePath.indexOf("?");
if (indexOfQuery !== -1) {
path = wholePath.substring(0, indexOfQuery);
queryString = wholePath.substring(indexOfQuery + 1);
}
path = resolveDotsInPath(path);
}
// Find last path component.
var lastPathComponent = null;
if (path && path !== "/") {
// Skip the trailing slash if there is one.
var endOffset = path[path.length - 1] === "/" ? 1 : 0;
var lastSlashIndex = path.lastIndexOf("/", path.length - 1 - endOffset);
if (lastSlashIndex !== -1)
lastPathComponent = path.substring(lastSlashIndex + 1, path.length - endOffset);
}
return {scheme: scheme, host: host, port: port, path: path, queryString: queryString, fragment: fragment, lastPathComponent: lastPathComponent};
}
function absoluteURL(partialURL, baseURL)
{
partialURL = partialURL ? partialURL.trim() : "";
// Return data and javascript URLs as-is.
if (partialURL.startsWith("data:") || partialURL.startsWith("javascript:") || partialURL.startsWith("mailto:"))
return partialURL;
// If the URL has a scheme it is already a full URL, so return it.
if (parseURL(partialURL).scheme)
return partialURL;
// If there is no partial URL, just return the base URL.
if (!partialURL)
return baseURL || null;
var baseURLComponents = parseURL(baseURL);
// The base URL needs to be an absolute URL. Return null if it isn't.
if (!baseURLComponents.scheme)
return null;
// A URL that starts with "//" is a full URL without the scheme. Use the base URL scheme.
if (partialURL[0] === "/" && partialURL[1] === "/")
return baseURLComponents.scheme + ":" + partialURL;
// The path can be null for URLs that have just a scheme and host (like "http://apple.com"). So make the path be "/".
if (!baseURLComponents.path)
baseURLComponents.path = "/";
// Generate the base URL prefix that is used in the rest of the cases.
var baseURLPrefix = baseURLComponents.scheme + "://" + baseURLComponents.host + (baseURLComponents.port ? (":" + baseURLComponents.port) : "");
// A URL that starts with "?" is just a query string that gets applied to the base URL (replacing the base URL query string and fragment).
if (partialURL[0] === "?")
return baseURLPrefix + baseURLComponents.path + partialURL;
// A URL that starts with "/" is an absolute path that gets applied to the base URL (replacing the base URL path, query string and fragment).
if (partialURL[0] === "/")
return baseURLPrefix + resolveDotsInPath(partialURL);
// Generate the base path that is used in the final case by removing everything after the last "/" from the base URL's path.
var basePath = baseURLComponents.path.substring(0, baseURLComponents.path.lastIndexOf("/")) + "/";
return baseURLPrefix + resolveDotsInPath(basePath + partialURL);
}
function parseLocationQueryParameters(arrayResult)
{
// The first character is always the "?".
return parseQueryString(window.location.search.substring(1), arrayResult);
}
function parseQueryString(queryString, arrayResult)
{
if (!queryString)
return arrayResult ? [] : {};
function decode(string)
{
try {
// Replace "+" with " " then decode precent encoded values.
return decodeURIComponent(string.replace(/\+/g, " "));
} catch (e) {
return string;
}
}
var parameters = arrayResult ? [] : {};
var parameterStrings = queryString.split("&");
for (var i = 0; i < parameterStrings.length; ++i) {
var pair = parameterStrings[i].split("=").map(decode);
if (arrayResult)
parameters.push({name: pair[0], value: pair[1]});
else
parameters[pair[0]] = pair[1];
}
return parameters;
}
WebInspector.displayNameForURL = function(url, urlComponents)
{
if (!urlComponents)
urlComponents = parseURL(url);
var displayName;
try {
displayName = decodeURIComponent(urlComponents.lastPathComponent || "");
} catch (e) {
displayName = urlComponents.lastPathComponent;
}
return displayName || WebInspector.displayNameForHost(urlComponents.host) || url;
}
WebInspector.displayNameForHost = function(host)
{
// FIXME <rdar://problem/11237413>: This should decode punycode hostnames.
return host;
}
......@@ -981,38 +981,6 @@ function isEnterKey(event)
return event.keyCode !== 229 && event.keyIdentifier === "Enter";
}
function removeURLFragment(url)
{
var hashIndex = url.indexOf("#");
if (hashIndex >= 0)
return url.substring(0, hashIndex);
return url;
}
function relativePath(path, basePath)
{
console.assert(path.charAt(0) === "/");
console.assert(basePath.charAt(0) === "/");
var pathComponents = path.split("/");
var baseComponents = basePath.replace(/\/$/, "").split("/");
var finalComponents = [];
var index = 1;
for (; index < pathComponents.length && index < baseComponents.length; ++index) {
if (pathComponents[index] !== baseComponents[index])
break;
}
for (var i = index; i < baseComponents.length; ++i)
finalComponents.push("..");
for (var i = index; i < pathComponents.length; ++i)
finalComponents.push(pathComponents[i]);
return finalComponents.join("/");
}
function resolveDotsInPath(path)
{
if (!path)
......@@ -1047,91 +1015,6 @@ function resolveDotsInPath(path)
return result.join("/");
}
function parseURL(url)
{
url = url ? url.trim() : "";
var match = url.match(/^([^:]+):\/\/([^\/:]*)(?::([\d]+))?(?:(\/[^#]*)(?:#(.*))?)?$/i);
if (!match)
return {scheme: null, host: null, port: null, path: null, queryString: null, fragment: null, lastPathComponent: null};
var scheme = match[1].toLowerCase();
var host = match[2].toLowerCase();
var port = Number(match[3]) || null;
var wholePath = match[4] || null;
var fragment = match[5] || null;
var path = wholePath;
var queryString = null;
// Split the path and the query string.
if (wholePath) {
var indexOfQuery = wholePath.indexOf("?");
if (indexOfQuery !== -1) {
path = wholePath.substring(0, indexOfQuery);
queryString = wholePath.substring(indexOfQuery + 1);
}
path = resolveDotsInPath(path);
}
// Find last path component.
var lastPathComponent = null;
if (path && path !== "/") {
// Skip the trailing slash if there is one.
var endOffset = path[path.length - 1] === "/" ? 1 : 0;
var lastSlashIndex = path.lastIndexOf("/", path.length - 1 - endOffset);
if (lastSlashIndex !== -1)
lastPathComponent = path.substring(lastSlashIndex + 1, path.length - endOffset);
}
return {scheme: scheme, host: host, port: port, path: path, queryString: queryString, fragment: fragment, lastPathComponent: lastPathComponent};
}
function absoluteURL(partialURL, baseURL)
{
partialURL = partialURL ? partialURL.trim() : "";
// Return data and javascript URLs as-is.
if (partialURL.startsWith("data:") || partialURL.startsWith("javascript:") || partialURL.startsWith("mailto:"))
return partialURL;
// If the URL has a scheme it is already a full URL, so return it.
if (parseURL(partialURL).scheme)
return partialURL;
// If there is no partial URL, just return the base URL.
if (!partialURL)
return baseURL || null;
var baseURLComponents = parseURL(baseURL);
// The base URL needs to be an absolute URL. Return null if it isn't.
if (!baseURLComponents.scheme)
return null;
// A URL that starts with "//" is a full URL without the scheme. Use the base URL scheme.
if (partialURL[0] === "/" && partialURL[1] === "/")
return baseURLComponents.scheme + ":" + partialURL;
// The path can be null for URLs that have just a scheme and host (like "http://apple.com"). So make the path be "/".
if (!baseURLComponents.path)
baseURLComponents.path = "/";
// Generate the base URL prefix that is used in the rest of the cases.
var baseURLPrefix = baseURLComponents.scheme + "://" + baseURLComponents.host + (baseURLComponents.port ? (":" + baseURLComponents.port) : "");
// A URL that starts with "?" is just a query string that gets applied to the base URL (replacing the base URL query string and fragment).
if (partialURL[0] === "?")
return baseURLPrefix + baseURLComponents.path + partialURL;
// A URL that starts with "/" is an absolute path that gets applied to the base URL (replacing the base URL path, query string and fragment).
if (partialURL[0] === "/")
return baseURLPrefix + resolveDotsInPath(partialURL);
// Generate the base path that is used in the final case by removing everything after the last "/" from the base URL's path.
var basePath = baseURLComponents.path.substring(0, baseURLComponents.path.lastIndexOf("/")) + "/";
return baseURLPrefix + resolveDotsInPath(basePath + partialURL);
}
function parseMIMEType(fullMimeType)
{
if (!fullMimeType)
......@@ -1190,37 +1073,3 @@ function simpleGlobStringToRegExp(globString, regExpFlags)
return new RegExp(regexString, regExpFlags);
}
function parseLocationQueryParameters(arrayResult)
{
// The first character is always the "?".
return parseQueryString(window.location.search.substring(1), arrayResult);
}
function parseQueryString(queryString, arrayResult)
{
if (!queryString)
return arrayResult ? [] : {};
function decode(string)
{
try {
// Replace "+" with " " then decode precent encoded values.
return decodeURIComponent(string.replace(/\+/g, " "));
} catch (e) {
return string;
}
}
var parameters = arrayResult ? [] : {};
var parameterStrings = queryString.split("&");
for (var i = 0; i < parameterStrings.length; ++i) {
var pair = parameterStrings[i].split("=").map(decode);
if (arrayResult)
parameters.push({name: pair[0], value: pair[1]});
else
parameters[pair[0]] = pair[1];
}
return parameters;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment