2010-08-26 Andrey Kosyakov <caseq@chromium.org>
authorcaseq@chromium.org <caseq@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Aug 2010 13:57:54 +0000 (13:57 +0000)
committercaseq@chromium.org <caseq@chromium.org@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Fri, 27 Aug 2010 13:57:54 +0000 (13:57 +0000)
        Reviewed by Pavel Feldman.

        Web Inspector: add audits support to extension API
        Exposed (late) adding of categories from AuditPanel.
        Removed indexOfObjectInListSortedByFunction in favor of
        insertionIndexForObjectInListSortedByFunction (the former had
        weird interface always returning negative numbers and was only used in
        the latter).
        https://bugs.webkit.org/show_bug.cgi?id=44518

        Tests: inspector/extensions-audits-api.html

        * WebCore.gypi:
        * WebCore.vcproj/WebCore.vcproj:
        * inspector/front-end/AuditFormatters.js: Added.
        (WebInspector.applyFormatters):
        (WebInspector.AuditFormatters.text):
        (WebInspector.AuditFormatters.snippet):
        (WebInspector.AuditFormatters.concat):
        (WebInspector.AuditFormatters.url):
        * inspector/front-end/AuditLauncherView.js:
        (WebInspector.AuditLauncherView):
        (WebInspector.AuditLauncherView.prototype.addCategory.compareCategories):
        (WebInspector.AuditLauncherView.prototype.addCategory):
        (WebInspector.AuditLauncherView.prototype._launchButtonClicked):
        (WebInspector.AuditLauncherView.prototype._selectAllClicked):
        (WebInspector.AuditLauncherView.prototype._categoryClicked):
        (WebInspector.AuditLauncherView.prototype._createCategoryElement):
        (WebInspector.AuditLauncherView.prototype._createLauncherUI):
        * inspector/front-end/AuditResultView.js:
        (WebInspector.AuditCategoryResultPane.prototype._appendResult):
        * inspector/front-end/AuditsPanel.js:
        (WebInspector.AuditsPanel):
        (WebInspector.AuditsPanel.prototype.addCategory):
        (WebInspector.AuditsPanel.prototype.getCategory):
        (WebInspector.AuditsPanel.prototype._executeAudit):
        (WebInspector.AuditCategory.prototype.run):
        * inspector/front-end/ExtensionAPI.js:
        (WebInspector.injectedExtensionAPI):
        (WebInspector.injectedExtensionAPI.EventSinkImpl.prototype.addListener):
        (WebInspector.injectedExtensionAPI.EventSinkImpl.prototype._fire):
        (WebInspector.injectedExtensionAPI.EventSinkImpl.prototype._dispatch):
        (WebInspector.injectedExtensionAPI.EventSink):
        (WebInspector.injectedExtensionAPI.InspectorExtensionAPI):
        (WebInspector.injectedExtensionAPI.Panels.prototype.create):
        (WebInspector.injectedExtensionAPI.Audits):
        (WebInspector.injectedExtensionAPI.Audits.prototype.addCategory):
        (WebInspector.injectedExtensionAPI.AuditCategory.customDispatch):
        (WebInspector.injectedExtensionAPI.AuditCategory):
        (WebInspector.injectedExtensionAPI.AuditCategoryImpl):
        (WebInspector.injectedExtensionAPI.AuditResult):
        (WebInspector.injectedExtensionAPI.AuditResult.prototype.get Severity):
        (WebInspector.injectedExtensionAPI.AuditResultImpl):
        (WebInspector.injectedExtensionAPI.AuditResultImpl.prototype.addResult):
        (WebInspector.injectedExtensionAPI.AuditResultImpl.prototype.createResult):
        (WebInspector.injectedExtensionAPI.AuditResultImpl.prototype.done):
        (WebInspector.injectedExtensionAPI.AuditResultImpl.prototype._nodeFactory):
        (WebInspector.injectedExtensionAPI.AuditResultNode):
        (WebInspector.injectedExtensionAPI.AuditResultNode.prototype.addChild):
        * inspector/front-end/ExtensionAuditCategory.js: Added.
        (WebInspector.ExtensionAuditCategory):
        (WebInspector.ExtensionAuditCategory.prototype.get id):
        (WebInspector.ExtensionAuditCategory.prototype.get displayName):
        (WebInspector.ExtensionAuditCategory.prototype.get ruleCount):
        (WebInspector.ExtensionAuditCategory.prototype.run):
        (WebInspector.ExtensionAuditCategoryResults):
        (WebInspector.ExtensionAuditCategoryResults.prototype.get complete):
        (WebInspector.ExtensionAuditCategoryResults.prototype.cancel):
        (WebInspector.ExtensionAuditCategoryResults.prototype.addResult):
        (WebInspector.ExtensionAuditCategoryResults.prototype._addNode):
        (WebInspector.ExtensionAuditCategoryResults.prototype._addResult):
        * inspector/front-end/ExtensionCommon.js: Added.
        (WebInspector.commonExtensionSymbols):
        * inspector/front-end/ExtensionServer.js:
        (WebInspector.ExtensionServer):
        (WebInspector.ExtensionServer.prototype.startAuditRun):
        (WebInspector.ExtensionServer.prototype.stopAuditRun):
        (WebInspector.ExtensionServer.prototype._postNotification):
        (WebInspector.ExtensionServer.prototype._onAddAuditCategory):
        (WebInspector.ExtensionServer.prototype._onAddAuditResult):
        (WebInspector.ExtensionServer.prototype._onStopAuditCategoryRun):
        (WebInspector.ExtensionServer.prototype._addExtensions):
        (WebInspector.ExtensionServer.prototype._buildExtensionAPIInjectedScript):
        (WebInspector.ExtensionStatus):
        * inspector/front-end/WebKit.qrc:
        * inspector/front-end/inspector.html:
        * inspector/front-end/utilities.js:
        ():

2010-08-26  Andrey Kosyakov  <caseq@chromium.org>

        Reviewed by Pavel Feldman.

        Web Inspector: add audits support to extension API
        https://bugs.webkit.org/show_bug.cgi?id=44518

        * inspector/audits-panel-functional.html:
        * inspector/audits-tests.js: Added.
        (frontend_collectAuditResults):
        (frontend_collectTextContent):
        * inspector/extensions-api-expected.txt:
        * inspector/extensions-audits-api-expected.txt: Added.
        * inspector/extensions-audits-api.html: Added.
        * inspector/extensions-audits-expected.txt: Added.
        * inspector/extensions-audits-tests.js: Added.
        (extension_runAudits.onMessage):
        (extension_runAudits):
        (frontend_runExtensionAudits.onAuditsDone):
        * inspector/extensions-audits.html: Added.
        * inspector/extensions-expected.txt:
        * inspector/resources/audits-script3.js: Removed.
        * platform/chromium/test_expectations.txt:

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@66218 268f45cc-cd09-0410-ab3c-d52691b4dbfc

23 files changed:
LayoutTests/ChangeLog
LayoutTests/inspector/audits-panel-functional.html
LayoutTests/inspector/audits-tests.js [new file with mode: 0755]
LayoutTests/inspector/extensions-api-expected.txt
LayoutTests/inspector/extensions-audits-api-expected.txt [new file with mode: 0644]
LayoutTests/inspector/extensions-audits-api.html [new file with mode: 0755]
LayoutTests/inspector/extensions-audits-expected.txt [new file with mode: 0644]
LayoutTests/inspector/extensions-audits-tests.js [new file with mode: 0755]
LayoutTests/inspector/extensions-audits.html [new file with mode: 0755]
LayoutTests/inspector/extensions-expected.txt
LayoutTests/inspector/resources/audits-script3.js [deleted file]
LayoutTests/platform/chromium/test_expectations.txt
WebCore/ChangeLog
WebCore/WebCore.gypi
WebCore/WebCore.vcproj/WebCore.vcproj
WebCore/inspector/front-end/AuditLauncherView.js
WebCore/inspector/front-end/AuditResultView.js
WebCore/inspector/front-end/AuditsPanel.js
WebCore/inspector/front-end/ExtensionAPI.js
WebCore/inspector/front-end/ExtensionServer.js
WebCore/inspector/front-end/WebKit.qrc
WebCore/inspector/front-end/inspector.html
WebCore/inspector/front-end/utilities.js

index daa9714..92ae5f1 100644 (file)
@@ -1,3 +1,27 @@
+2010-08-26  Andrey Kosyakov  <caseq@chromium.org>
+
+        Reviewed by Pavel Feldman.
+
+        Web Inspector: add audits support to extension API
+        https://bugs.webkit.org/show_bug.cgi?id=44518
+
+        * inspector/audits-panel-functional.html:
+        * inspector/audits-tests.js: Added.
+        (frontend_collectAuditResults):
+        (frontend_collectTextContent):
+        * inspector/extensions-api-expected.txt:
+        * inspector/extensions-audits-api-expected.txt: Added.
+        * inspector/extensions-audits-api.html: Added.
+        * inspector/extensions-audits-expected.txt: Added.
+        * inspector/extensions-audits-tests.js: Added.
+        (extension_runAudits.onMessage):
+        (extension_runAudits):
+        (frontend_runExtensionAudits.onAuditsDone):
+        * inspector/extensions-audits.html: Added.
+        * inspector/extensions-expected.txt:
+        * inspector/resources/audits-script3.js: Removed.
+        * platform/chromium/test_expectations.txt:
+
 2010-08-25  Jeremy Orlow  <jorlow@chromium.org>
 
         Reviewed by Steve Block.
index 71537f4..e7a2804 100644 (file)
@@ -7,12 +7,12 @@
 }
 </style>
 <script src="../http/tests/inspector/inspector-test.js"></script>
+<script src="audits-tests.js"></script>
 
 <!-- These scripts are needed to result in a violation of the max JS resource count from the same domain -->
 <script src="resources/audits-script1.js"></script>
 <link rel="stylesheet" href="resources/audits-style1.css" type="text/css">
 <script src="resources/audits-script2.js"></script>
-<script src="resources/audits-script3.js"></script>
 <script>
 
 function doit()
@@ -50,14 +50,7 @@ function frontend_runAudits(testController)
 
         testController.runAfterPendingDispatches(function() {
             // Audits are done, check results.
-            WebInspector.panels.audits.showResults(WebInspector.panels.audits.auditResultsTreeElement.children[0].results);
-            var liElements = WebInspector.panels.audits.visibleView.element.getElementsByTagName("li");
-            for (var j = 0; j < liElements.length; ++j) {
-                if (liElements[j].treeElement)
-                    liElements[j].treeElement.expand();
-            }
-            var output = [];
-            frontend_collectTextContent(WebInspector.panels.audits.visibleView.element, 0, output);
+            var output = frontend_collectAuditResults();
             // Avoid influencing tests that require resource tracking to be disabled.
             InspectorBackend.disableResourceTracking(false);
             testController.runAfterPendingDispatches(function() {
@@ -69,29 +62,6 @@ function frontend_runAudits(testController)
     }
 }
 
-function frontend_collectTextContent(element, level, output)
-{
-    var nodeOutput = "";
-    var child = element.firstChild;
-    while (child) {
-        if (child.nodeType === Node.TEXT_NODE) {
-            for (var i = 0; i < level; ++i)
-                nodeOutput += " ";
-            nodeOutput += child.nodeValue;
-        } else if (child.nodeType === Node.ELEMENT_NODE) {
-            if (nodeOutput !== "") {
-                output.push(nodeOutput);
-                nodeOutput = "";
-            }
-            frontend_collectTextContent(child, level + 1, output);
-        }
-        child = child.nextSibling;
-    }
-    if (nodeOutput !== "")
-        output.push(nodeOutput);
-    return;
-}
-
 </script>
 </head>
 
diff --git a/LayoutTests/inspector/audits-tests.js b/LayoutTests/inspector/audits-tests.js
new file mode 100755 (executable)
index 0000000..102c6b4
--- /dev/null
@@ -0,0 +1,35 @@
+function frontend_collectAuditResults()
+{
+    WebInspector.panels.audits.showResults(WebInspector.panels.audits.auditResultsTreeElement.children[0].results);
+    var liElements = WebInspector.panels.audits.visibleView.element.getElementsByTagName("li");
+    for (var j = 0; j < liElements.length; ++j) {
+        if (liElements[j].treeElement)
+            liElements[j].treeElement.expand();
+    }
+    var output = [];
+    frontend_collectTextContent(WebInspector.panels.audits.visibleView.element, 0, output);
+    return output;
+}
+
+function frontend_collectTextContent(element, level, output)
+{
+    var nodeOutput = "";
+    var child = element.firstChild;
+
+    while (child) {
+        if (child.nodeType === Node.TEXT_NODE) {
+            for (var i = 0; i < level; ++i)
+                nodeOutput += " ";
+            nodeOutput += child.nodeValue;
+        } else if (child.nodeType === Node.ELEMENT_NODE) {
+            if (nodeOutput !== "") {
+                output.push(nodeOutput);
+                nodeOutput = "";
+            }
+            frontend_collectTextContent(child, level + 1, output);
+        }
+        child = child.nextSibling;
+    }
+    if (nodeOutput !== "")
+        output.push(nodeOutput);
+}
index 35a99d2..c07471b 100644 (file)
@@ -4,6 +4,9 @@ Started extension.
 Running tests...
 RUNNING TEST: extension_testAPI
 {
+    audits : {
+        addCategory : <function>
+    }
     inspectedWindow : {
         onLoaded : {
             addListener : <function>
diff --git a/LayoutTests/inspector/extensions-audits-api-expected.txt b/LayoutTests/inspector/extensions-audits-api-expected.txt
new file mode 100644 (file)
index 0000000..19f31bb
--- /dev/null
@@ -0,0 +1,39 @@
+Tests audits support in WebInspector Extensions API
+
+Started extension.
+Running tests...
+RUNNING TEST: extension_testAuditsAPI
+Added audit category, result dump follows:
+{
+    onAuditStarted : {
+        addListener : <function>
+        removeListener : <function>
+    }
+}
+category.onAuditStarted fired, results dump follows:
+{
+    addResult : <function>
+    createResult : <function>
+    done : <function>
+    url : <function>
+    snippet : <function>
+    text : <function>
+    Severity : {
+        Info : "info"
+        Warning : "warning"
+        Severe : "severe"
+    }
+}
+{
+    contents : {
+        0 : "Subtree"
+    }
+    children : {
+    }
+    expanded : false
+    addChild : <function>
+}
+Audits complete:
+  Extension audits
+All tests done.
+
diff --git a/LayoutTests/inspector/extensions-audits-api.html b/LayoutTests/inspector/extensions-audits-api.html
new file mode 100755 (executable)
index 0000000..57f62b3
--- /dev/null
@@ -0,0 +1,37 @@
+<html>
+<head>
+<script src="../http/tests/inspector/inspector-test.js"></script>
+<script src="extensions-test.js"></script>
+<script src="audits-tests.js"></script>
+<script src="extensions-audits-tests.js"></script>
+
+<script type="text/javascript">
+
+function extension_testAuditsAPI(nextTest)
+{
+    function onStartAuditCategory(results)
+    {
+        log("category.onAuditStarted fired, results dump follows:");
+        dumpObject(results);
+        var node = results.createResult("Subtree");
+        dumpObject(node);
+        results.done();
+    }
+    var category = webInspector.audits.addCategory("Extension audits", 20);
+    category.onAuditStarted.addListener(onStartAuditCategory);
+    log("Added audit category, result dump follows:");
+    dumpObject(category);
+    extension_runAudits(nextTest);
+}
+
+function runAudits()
+{
+    evaluateInWebInspector("frontend_runAudits");
+}
+
+</script>
+</head>
+<body onload="onload()">
+<p>Tests audits support in WebInspector Extensions API</p>
+</body>
+</html>
diff --git a/LayoutTests/inspector/extensions-audits-expected.txt b/LayoutTests/inspector/extensions-audits-expected.txt
new file mode 100644 (file)
index 0000000..d99ef90
--- /dev/null
@@ -0,0 +1,29 @@
+Tests audits support in WebInspector Extensions API
+
+Started extension.
+Running tests...
+RUNNING TEST: extension_testAudits
+Added audit category.
+category.onAuditStarted fired
+failedCategory.onAuditStarted fired, throwing exception
+Audits complete:
+  Extension audits
+    Failed rule (42)
+     this rule always fails
+    Rule with details subtree (1)
+     This rule has a lot of details
+      Subtree
+       Some url: 
+        WebKit
+        more text 
+        http://www.google.com
+       ... and a snippet
+         function rand()
+         {
+             return 4;
+         }
+    Passed rule
+     this rule always passes ok
+  Extension audits that fail
+All tests done.
+
diff --git a/LayoutTests/inspector/extensions-audits-tests.js b/LayoutTests/inspector/extensions-audits-tests.js
new file mode 100755 (executable)
index 0000000..125e78b
--- /dev/null
@@ -0,0 +1,34 @@
+function extension_runAudits(callback)\r
+{\r
+    function onMessage(event)\r
+    {\r
+        if (event.data === "audit-tests-done")\r
+            callback();\r
+    }\r
+    top.addEventListener("message", onMessage, false);\r
+    webInspector.inspectedWindow.evaluate("evaluateInWebInspector('frontend_runExtensionAudits')");\r
+}\r
+\r
+function frontend_runExtensionAudits(testController)\r
+{\r
+    const launcherView = WebInspector.panels.audits._launcherView;\r
+    launcherView._selectAllClicked(false);\r
+    launcherView._auditPresentStateElement.checked = true;\r
+\r
+    var extensionCategories = document.evaluate("label[starts-with(.,'Extension ')]/input[@type='checkbox']",\r
+        WebInspector.panels.audits._launcherView._categoriesElement, null, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);\r
+\r
+    for (var i = 0; i < extensionCategories.snapshotLength; ++i)\r
+        extensionCategories.snapshotItem(i).click();\r
+\r
+    function onAuditsDone()\r
+    {\r
+        var output = frontend_collectAuditResults();\r
+        InjectedScriptAccess.getDefault().evaluate("log(unescape('" + escape("Audits complete:\n" + output.join("\n")) + "'));", function() {\r
+            top.postMessage("audit-tests-done", "*");\r
+        });\r
+    }\r
+\r
+    frontend_addSniffer(WebInspector.panels.audits, "_auditFinishedCallback", onAuditsDone, true);\r
+    launcherView._launchButtonClicked();\r
+}\r
diff --git a/LayoutTests/inspector/extensions-audits.html b/LayoutTests/inspector/extensions-audits.html
new file mode 100755 (executable)
index 0000000..4fa932a
--- /dev/null
@@ -0,0 +1,59 @@
+<html>
+<head>
+<script src="../http/tests/inspector/inspector-test.js"></script>
+<script src="extensions-test.js"></script>
+<script src="audits-tests.js"></script>
+<script src="extensions-audits-tests.js"></script>
+
+<script type="text/javascript">
+
+function extension_testAudits(nextTest)
+{
+    function onStartAuditCategory(results)
+    {
+        log("category.onAuditStarted fired");
+        results.addResult("Passed rule", "this rule always passes ok", results.Severity.Info);
+        results.addResult("Failed rule (42)", "this rule always fails", results.Severity.Severe);
+
+        var node = results.createResult("Subtree");
+        node.addChild("Some url: ", results.url("http://www.webkit.org", "WebKit"), " more text ", results.url("http://www.google.com"));
+        var nestedNode = node.addChild("... and a snippet");
+        nestedNode.expanded = true;
+        nestedNode.addChild(results.snippet("function rand()\n{\n    return 4;\n}"));
+
+        results.addResult("Rule with details subtree (1)", "This rule has a lot of details", results.Severity.Warning, node);
+        // Audit normally terminates when number of added rule results is equal to
+        // the rule count declared when adding a category. done() is only for
+        // emergency cases, when we know we won't be able to run the rest of the rules.
+        results.done();
+    }
+    function onStartAuditFailedCategory()
+    {
+        log("failedCategory.onAuditStarted fired, throwing exception");
+        throw "oops!";
+    }
+    function onStartAuditDisabledCategory(results)
+    {
+        log("FAIL: failedCategory.onAuditStarted fired");
+        results.done();
+    }
+
+    var category = webInspector.audits.addCategory("Extension audits", 20);
+    category.onAuditStarted.addListener(onStartAuditCategory);
+    log("Added audit category.");
+
+    var failedCategory = webInspector.audits.addCategory("Extension audits that fail", 2);
+    failedCategory.onAuditStarted.addListener(onStartAuditFailedCategory);
+
+    var disabledCategory = webInspector.audits.addCategory("Disabled extension audits", 2);
+    disabledCategory.onAuditStarted.addListener(onStartAuditDisabledCategory);
+
+    extension_runAudits(nextTest);
+}
+
+</script>
+</head>
+<body onload="onload()">
+<p>Tests audits support in WebInspector Extensions API</p>
+</body>
+</html>
index 3924a6a..9934f52 100644 (file)
@@ -31,7 +31,7 @@ resource: .../tests/inspector/inspector-test.js
 resource: .../LayoutTests/inspector/extensions-test.js
 resource: .../LayoutTests/inspector/extensions.html
 RUNNING TEST: extension_testGetInvalidResource
-Attempted to retrieve invalid resource: {"code":"E_NOTFOUND","description":"Object not found (%s)","details":[2128506],"isError":true}
+Attempted to retrieve invalid resource: {"code":"E_NOTFOUND","description":"Object not found: %s","details":[2128506],"isError":true}
 RUNNING TEST: extension_testResourceNotification
 Resource finished: .../inspector/resources/extension-main.html
 All tests done.
diff --git a/LayoutTests/inspector/resources/audits-script3.js b/LayoutTests/inspector/resources/audits-script3.js
deleted file mode 100755 (executable)
index fd60504..0000000
+++ /dev/null
@@ -1,3 +0,0 @@
-function foo3()
-{
-}
index 4980ac9..7eb2191 100644 (file)
@@ -200,6 +200,8 @@ WONTFIX SKIP : fast/events/message-port-multi.html = FAIL
 WONTFIX SKIP : http/tests/security/MessagePort/event-listener-context.html = FAIL
 WONTFIX SKIP : inspector/extensions.html = FAIL
 WONTFIX SKIP : inspector/extensions-api.html = FAIL
+WONTFIX SKIP : inspector/extensions-audits.html = FAIL
+WONTFIX SKIP : inspector/extensions-audits-api.html = FAIL
 
 // Implement java testing harness.
 BUG36681 DEFER SKIP : java = TEXT
index c7a404d..9ba67b5 100644 (file)
@@ -1,3 +1,94 @@
+2010-08-26  Andrey Kosyakov  <caseq@chromium.org>
+
+        Reviewed by Pavel Feldman.
+
+        Web Inspector: add audits support to extension API
+        Exposed (late) adding of categories from AuditPanel.
+        Removed indexOfObjectInListSortedByFunction in favor of
+        insertionIndexForObjectInListSortedByFunction (the former had
+        weird interface always returning negative numbers and was only used in
+        the latter).
+        https://bugs.webkit.org/show_bug.cgi?id=44518
+
+        Tests: inspector/extensions-audits-api.html
+
+        * WebCore.gypi:
+        * WebCore.vcproj/WebCore.vcproj:
+        * inspector/front-end/AuditFormatters.js: Added.
+        (WebInspector.applyFormatters):
+        (WebInspector.AuditFormatters.text):
+        (WebInspector.AuditFormatters.snippet):
+        (WebInspector.AuditFormatters.concat):
+        (WebInspector.AuditFormatters.url):
+        * inspector/front-end/AuditLauncherView.js:
+        (WebInspector.AuditLauncherView):
+        (WebInspector.AuditLauncherView.prototype.addCategory.compareCategories):
+        (WebInspector.AuditLauncherView.prototype.addCategory):
+        (WebInspector.AuditLauncherView.prototype._launchButtonClicked):
+        (WebInspector.AuditLauncherView.prototype._selectAllClicked):
+        (WebInspector.AuditLauncherView.prototype._categoryClicked):
+        (WebInspector.AuditLauncherView.prototype._createCategoryElement):
+        (WebInspector.AuditLauncherView.prototype._createLauncherUI):
+        * inspector/front-end/AuditResultView.js:
+        (WebInspector.AuditCategoryResultPane.prototype._appendResult):
+        * inspector/front-end/AuditsPanel.js:
+        (WebInspector.AuditsPanel):
+        (WebInspector.AuditsPanel.prototype.addCategory):
+        (WebInspector.AuditsPanel.prototype.getCategory):
+        (WebInspector.AuditsPanel.prototype._executeAudit):
+        (WebInspector.AuditCategory.prototype.run):
+        * inspector/front-end/ExtensionAPI.js:
+        (WebInspector.injectedExtensionAPI):
+        (WebInspector.injectedExtensionAPI.EventSinkImpl.prototype.addListener):
+        (WebInspector.injectedExtensionAPI.EventSinkImpl.prototype._fire):
+        (WebInspector.injectedExtensionAPI.EventSinkImpl.prototype._dispatch):
+        (WebInspector.injectedExtensionAPI.EventSink):
+        (WebInspector.injectedExtensionAPI.InspectorExtensionAPI):
+        (WebInspector.injectedExtensionAPI.Panels.prototype.create):
+        (WebInspector.injectedExtensionAPI.Audits):
+        (WebInspector.injectedExtensionAPI.Audits.prototype.addCategory):
+        (WebInspector.injectedExtensionAPI.AuditCategory.customDispatch):
+        (WebInspector.injectedExtensionAPI.AuditCategory):
+        (WebInspector.injectedExtensionAPI.AuditCategoryImpl):
+        (WebInspector.injectedExtensionAPI.AuditResult):
+        (WebInspector.injectedExtensionAPI.AuditResult.prototype.get Severity):
+        (WebInspector.injectedExtensionAPI.AuditResultImpl):
+        (WebInspector.injectedExtensionAPI.AuditResultImpl.prototype.addResult):
+        (WebInspector.injectedExtensionAPI.AuditResultImpl.prototype.createResult):
+        (WebInspector.injectedExtensionAPI.AuditResultImpl.prototype.done):
+        (WebInspector.injectedExtensionAPI.AuditResultImpl.prototype._nodeFactory):
+        (WebInspector.injectedExtensionAPI.AuditResultNode):
+        (WebInspector.injectedExtensionAPI.AuditResultNode.prototype.addChild):
+        * inspector/front-end/ExtensionAuditCategory.js: Added.
+        (WebInspector.ExtensionAuditCategory):
+        (WebInspector.ExtensionAuditCategory.prototype.get id):
+        (WebInspector.ExtensionAuditCategory.prototype.get displayName):
+        (WebInspector.ExtensionAuditCategory.prototype.get ruleCount):
+        (WebInspector.ExtensionAuditCategory.prototype.run):
+        (WebInspector.ExtensionAuditCategoryResults):
+        (WebInspector.ExtensionAuditCategoryResults.prototype.get complete):
+        (WebInspector.ExtensionAuditCategoryResults.prototype.cancel):
+        (WebInspector.ExtensionAuditCategoryResults.prototype.addResult):
+        (WebInspector.ExtensionAuditCategoryResults.prototype._addNode):
+        (WebInspector.ExtensionAuditCategoryResults.prototype._addResult):
+        * inspector/front-end/ExtensionCommon.js: Added.
+        (WebInspector.commonExtensionSymbols):
+        * inspector/front-end/ExtensionServer.js:
+        (WebInspector.ExtensionServer):
+        (WebInspector.ExtensionServer.prototype.startAuditRun):
+        (WebInspector.ExtensionServer.prototype.stopAuditRun):
+        (WebInspector.ExtensionServer.prototype._postNotification):
+        (WebInspector.ExtensionServer.prototype._onAddAuditCategory):
+        (WebInspector.ExtensionServer.prototype._onAddAuditResult):
+        (WebInspector.ExtensionServer.prototype._onStopAuditCategoryRun):
+        (WebInspector.ExtensionServer.prototype._addExtensions):
+        (WebInspector.ExtensionServer.prototype._buildExtensionAPIInjectedScript):
+        (WebInspector.ExtensionStatus):
+        * inspector/front-end/WebKit.qrc:
+        * inspector/front-end/inspector.html:
+        * inspector/front-end/utilities.js:
+        ():
+
 2010-08-25  Jeremy Orlow  <jorlow@chromium.org>
 
         Reviewed by Steve Block.
index 5d86552..1c2fe75 100644 (file)
             'inspector/front-end/AbstractTimelinePanel.js',
             'inspector/front-end/ApplicationCacheItemsView.js',
             'inspector/front-end/AuditCategories.js',
+            'inspector/front-end/AuditFormatters.js',
             'inspector/front-end/AuditLauncherView.js',
             'inspector/front-end/AuditResultView.js',
             'inspector/front-end/AuditRules.js',
             'inspector/front-end/ElementsTreeOutline.js',
             'inspector/front-end/EventListenersSidebarPane.js',
             'inspector/front-end/ExtensionAPI.js',
+            'inspector/front-end/ExtensionAuditCategory.js',
+            'inspector/front-end/ExtensionCommon.js',
             'inspector/front-end/ExtensionPanel.js',
             'inspector/front-end/ExtensionRegistryStub.js',
             'inspector/front-end/ExtensionServer.js',
index 00c0fcc..03af224 100644 (file)
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath="..\inspector\front-end\AuditFormatters.js"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath="..\inspector\front-end\AuditLauncherView.js"\r
                                        >\r
                                </File>\r
                                        >\r
                                </File>\r
                                <File\r
+                                       RelativePath="..\inspector\front-end\ExtensionAuditCategory.js"\r
+                                       >\r
+                               </File>\r
+                               <File\r
+                                       RelativePath="..\inspector\front-end\ExtensionCommon.js"\r
+                                       >\r
+                               </File>\r
+                               <File\r
                                        RelativePath="..\inspector\front-end\ExtensionPanel.js"\r
                                        >\r
                                </File>\r
index 33d3872..18daee6 100644 (file)
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-WebInspector.AuditLauncherView = function(categoriesById, runnerCallback)
+WebInspector.AuditLauncherView = function(runnerCallback)
 {
     WebInspector.View.call(this);
-    this._categoriesById = categoriesById;
     this._runnerCallback = runnerCallback;
     this._categoryIdPrefix = "audit-category-item-";
     this._auditRunning = false;
@@ -41,27 +40,16 @@ WebInspector.AuditLauncherView = function(categoriesById, runnerCallback)
     this._contentElement = document.createElement("div");
     this._contentElement.className = "audit-launcher-view-content";
     this.element.appendChild(this._contentElement);
+    this._boundCategoryClickListener = this._categoryClicked.bind(this);
 
     this._resetResourceCount();
 
-    function categorySortFunction(a, b)
-    {
-        var aTitle = a.displayName || "";
-        var bTitle = b.displayName || "";
-        return aTitle.localeCompare(bTitle);
-    }
-    var sortedCategories = [];
-    for (var id in this._categoriesById)
-        sortedCategories.push(this._categoriesById[id]);
-    sortedCategories.sort(categorySortFunction);
+    this._sortedCategories = [];
 
-    if (!sortedCategories.length) {
-        this._headerElement = document.createElement("h1");
-        this._headerElement.className = "no-audits";
-        this._headerElement.textContent = WebInspector.UIString("No audits to run");
-        this._contentElement.appendChild(this._headerElement);
-    } else
-        this._createLauncherUI(sortedCategories);
+    this._headerElement = document.createElement("h1");
+    this._headerElement.className = "no-audits";
+    this._headerElement.textContent = WebInspector.UIString("No audits to run");
+    this._contentElement.appendChild(this._headerElement);
 }
 
 WebInspector.AuditLauncherView.prototype = {
@@ -133,6 +121,30 @@ WebInspector.AuditLauncherView.prototype = {
         this._resetResourceCount();
     },
 
+    addCategory: function(category)
+    {
+        if (!this._sortedCategories.length)
+            this._createLauncherUI();
+
+        var categoryElement = this._createCategoryElement(category.displayName, category.id);
+        category._checkboxElement = categoryElement.firstChild;
+        if (this._selectAllCheckboxElement.checked) {
+            category._checkboxElement.checked = true;
+            ++this._currentCategoriesCount;
+        }
+
+        function compareCategories(a, b)
+        {
+            var aTitle = a.displayName || "";
+            var bTitle = b.displayName || "";
+            return aTitle.localeCompare(bTitle);
+        }
+        var insertBefore = insertionIndexForObjectInListSortedByFunction(category, this._sortedCategories, compareCategories);
+        this._categoriesElement.insertBefore(categoryElement, this._categoriesElement.children[insertBefore]);
+        this._sortedCategories.splice(insertBefore, 0, category);
+        this._updateButton();
+    },
+
     _setAuditRunning: function(auditRunning)
     {
         if (this._auditRunning === auditRunning)
@@ -146,10 +158,11 @@ WebInspector.AuditLauncherView.prototype = {
     {
         var catIds = [];
         var childNodes = this._categoriesElement.childNodes;
-        for (var id in this._categoriesById) {
-            if (this._categoriesById[id]._checkboxElement.checked)
-                catIds.push(id);
+        for (var category = 0; category < this._sortedCategories.length; ++category) {
+            if (this._sortedCategories[category]._checkboxElement.checked)
+                catIds.push(this._sortedCategories[category].id);
         }
+
         this._setAuditRunning(true);
         this._runnerCallback(catIds, this._auditPresentStateElement.checked, this._setAuditRunning.bind(this, false));
     },
@@ -159,14 +172,14 @@ WebInspector.AuditLauncherView.prototype = {
         var childNodes = this._categoriesElement.childNodes;
         for (var i = 0, length = childNodes.length; i < length; ++i)
             childNodes[i].firstChild.checked = checkCategories;
-        this._currentCategoriesCount = checkCategories ? this._totalCategoriesCount : 0;
+        this._currentCategoriesCount = checkCategories ? this._sortedCategories.length : 0;
         this._updateButton();
     },
 
     _categoryClicked: function(event)
     {
         this._currentCategoriesCount += event.target.checked ? 1 : -1;
-        this._selectAllCheckboxElement.checked = this._currentCategoriesCount === this._totalCategoriesCount;
+        this._selectAllCheckboxElement.checked = this._currentCategoriesCount === this._sortedCategories.length;
         this._updateButton();
     },
 
@@ -177,16 +190,21 @@ WebInspector.AuditLauncherView.prototype = {
 
         var element = document.createElement("input");
         element.type = "checkbox";
+        element.addEventListener("click", this._boundCategoryClickListener, false);
         labelElement.appendChild(element);
         labelElement.appendChild(document.createTextNode(title));
 
         return labelElement;
     },
 
-    _createLauncherUI: function(sortedCategories)
+    _createLauncherUI: function()
     {
         this._headerElement = document.createElement("h1");
         this._headerElement.textContent = WebInspector.UIString("Select audits to run");
+
+        for (var child = 0; child < this._contentElement.children.length; ++child)
+            this._contentElement.removeChild(this._contentElement.children[child]);
+
         this._contentElement.appendChild(this._headerElement);
 
         function handleSelectAllClick(event)
@@ -204,16 +222,6 @@ WebInspector.AuditLauncherView.prototype = {
         this._categoriesElement.className = "audit-categories-container";
         this._contentElement.appendChild(this._categoriesElement);
 
-        var boundCategoryClickListener = this._categoryClicked.bind(this);
-
-        for (var i = 0; i < sortedCategories.length; ++i) {
-            categoryElement = this._createCategoryElement(sortedCategories[i].displayName, sortedCategories[i].id);
-            categoryElement.firstChild.addEventListener("click", boundCategoryClickListener, false);
-            sortedCategories[i]._checkboxElement = categoryElement.firstChild;
-            this._categoriesElement.appendChild(categoryElement);
-        }
-
-        this._totalCategoriesCount = this._categoriesElement.childNodes.length;
         this._currentCategoriesCount = 0;
 
         var flexibleSpaceElement = document.createElement("div");
index 2f4afbd..2636463 100644 (file)
@@ -81,15 +81,22 @@ WebInspector.AuditCategoryResultPane = function(categoryResult)
 WebInspector.AuditCategoryResultPane.prototype = {
     _appendResult: function(parentTreeElement, result)
     {
-        var title = result.value;
-        if (result.violationCount)
-            title = String.sprintf("%s (%d)", title, result.violationCount);
+        var title = "";
+        
+        if (typeof result.value === "string") {
+            title = result.value;
+            if (result.violationCount)
+                title = String.sprintf("%s (%d)", title, result.violationCount);
+        }
 
         var treeElement = new TreeElement(title, null, !!result.children);
         parentTreeElement.appendChild(treeElement);
 
         if (result.className)
             treeElement.listItemElement.addStyleClass(result.className);
+        if (typeof result.value !== "string")
+            treeElement.listItemElement.appendChild(WebInspector.applyFormatters(result.value));
+
         if (result.children) {
             for (var i = 0; i < result.children.length; ++i)
                 this._appendResult(treeElement, result.children[i]);
index bc7f3b3..f6cbed0 100644 (file)
@@ -32,8 +32,6 @@ WebInspector.AuditsPanel = function()
 {
     WebInspector.Panel.call(this, "audits");
 
-    this._constructCategories();
-
     this.createSidebar();
     this.auditsTreeElement = new WebInspector.SidebarSectionTreeElement("", {}, true);
     this.sidebarTree.appendChild(this.auditsTreeElement);
@@ -54,7 +52,11 @@ WebInspector.AuditsPanel = function()
     this.viewsContainerElement.id = "audit-views";
     this.element.appendChild(this.viewsContainerElement);
 
-    this._launcherView = new WebInspector.AuditLauncherView(this.categoriesById, this.initiateAudit.bind(this));
+    this._constructCategories();
+
+    this._launcherView = new WebInspector.AuditLauncherView(this.initiateAudit.bind(this));
+    for (id in this.categoriesById)
+        this._launcherView.addCategory(this.categoriesById[id]);
 }
 
 WebInspector.AuditsPanel.prototype = {
@@ -104,6 +106,17 @@ WebInspector.AuditsPanel.prototype = {
         this._launcherView.resourceFinished(resource);
     },
 
+    addCategory: function(category)
+    {
+        this.categoriesById[category.id] = category;
+        this._launcherView.addCategory(category);
+    },
+
+    getCategory: function(id)
+    {
+        return this.categoriesById[id];
+    },
+
     _constructCategories: function()
     {
         this._auditCategoriesById = {};
@@ -147,7 +160,7 @@ WebInspector.AuditsPanel.prototype = {
             var category = categories[i];
             var result = new WebInspector.AuditCategoryResult(category);
             results.push(result);
-            category.runRules(resources, ruleResultReadyCallback.bind(null, result));
+            category.run(resources, ruleResultReadyCallback.bind(null, result));
         }
     },
 
@@ -220,7 +233,7 @@ WebInspector.AuditsPanel.prototype = {
     {
         this.visibleView = this._launcherView;
     },
-    
+
     get visibleView()
     {
         return this._visibleView;
@@ -311,7 +324,7 @@ WebInspector.AuditCategory.prototype = {
         this._rules.push(rule);
     },
 
-    runRules: function(resources, callback)
+    run: function(resources, callback)
     {
         this._ensureInitialized();
         for (var i = 0; i < this._rules.length; ++i)
index a89dcf1..9d996bf 100644 (file)
@@ -28,7 +28,7 @@
  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
-var injectedExtensionAPI = function(InjectedScriptHost, inspectedWindow, injectedScriptId)
+WebInspector.injectedExtensionAPI = function(InjectedScriptHost, inspectedWindow, injectedScriptId)
 {
 
 // Here and below, all constructors are private to API implementation.
@@ -37,19 +37,22 @@ var injectedExtensionAPI = function(InjectedScriptHost, inspectedWindow, injecte
 // by Foo consutrctor to re-bind publicly exported members to an instance
 // of Foo.
 
-function EventSinkImpl(type)
+function EventSinkImpl(type, customDispatch)
 {
     this._type = type;
     this._listeners = [];
+    this._customDispatch = customDispatch;
 }
 
 EventSinkImpl.prototype = {
     addListener: function(callback)
     {
+        if (typeof callback != "function")
+            throw new "addListener: callback is not a function";
         if (this._listeners.length === 0)
             extensionServer.sendRequest({ command: "subscribe", type: this._type });
         this._listeners.push(callback);
-        extensionServer.registerHandler("notify-" + this._type, bind(this._fire, this));
+        extensionServer.registerHandler("notify-" + this._type, bind(this._dispatch, this));
     },
 
     removeListener: function(callback)
@@ -66,26 +69,36 @@ EventSinkImpl.prototype = {
             extensionServer.sendRequest({ command: "unsubscribe", type: this._type });
     },
 
-    _fire: function(request)
+    _fire: function()
     {
         var listeners = this._listeners.slice();
         for (var i = 0; i < listeners.length; ++i)
-            listeners[i].apply(null, request.arguments);
+            listeners[i].apply(null, arguments);
+    },
+
+    _dispatch: function(request)
+    {
+         if (this._customDispatch)
+             this._customDispatch.call(this, request);
+         else
+             this._fire.apply(this, request.arguments);
     }
 }
 
-function EventSink(type)
+function EventSink(type, customDispatch)
 {
-    var impl = new EventSinkImpl(type);
+    var impl = new EventSinkImpl(type, customDispatch);
     this.addListener = bind(impl.addListener, impl);
     this.removeListener = bind(impl.removeListener, impl);
 }
 
 function InspectorExtensionAPI()
 {
+    this.audits = new Audits();
     this.inspectedWindow = new InspectedWindow();
     this.panels = new Panels();
     this.resources = new Resources();
+
     this.onReset = new EventSink("reset");
 }
 
@@ -125,7 +138,7 @@ function Panels()
     {
         return panels[name];
     }
-    
+
     for (var i = 0; i < wellKnownPanelNames.length; ++i) {
         var name = wellKnownPanelNames[i];
         panels[name] = new Panel(name);
@@ -151,7 +164,7 @@ Panels.prototype = {
             id: id,
             label: label,
             url: expandURL(pageURL),
-            icon: expandURL(iconURL) 
+            icon: expandURL(iconURL)
         };
         extensionServer.sendRequest(request, callback && bind(callbackWrapper, this));
     }
@@ -219,6 +232,124 @@ function ExtensionSidebarPane(id)
     this.setExpanded = bind(impl.setExpanded, impl);
 }
 
+function Audits()
+{
+}
+
+Audits.prototype = {
+    addCategory: function(displayName, ruleCount)
+    {
+        var id = "extension-audit-category-" + extensionServer.nextObjectId();
+        extensionServer.sendRequest({ command: "addAuditCategory", id: id, displayName: displayName, ruleCount: ruleCount });
+        return new AuditCategory(id);
+    }
+}
+
+function AuditCategory(id)
+{
+    function customDispatch(request)
+    {
+        var auditResult = new AuditResult(request.arguments[0]);
+        try {
+            this._fire(auditResult);
+        } catch (e) {
+            console.error("Uncaught exception in extension audit event handler: " + e);
+            auditResult.done();
+        }
+    }
+    var impl = new AuditCategoryImpl(id);
+    this.onAuditStarted = new EventSink("audit-started-" + id, customDispatch);
+}
+
+function AuditCategoryImpl(id)
+{
+    this._id = id;
+}
+
+function AuditResult(id)
+{
+    var impl = new AuditResultImpl(id);
+
+    this.addResult = bind(impl.addResult, impl);
+    this.createResult = bind(impl.createResult, impl);
+    this.done = bind(impl.done, impl);
+
+    var formatterTypes = [
+        "url",
+        "snippet",
+        "text"
+    ];
+    for (var i = 0; i < formatterTypes.length; ++i)
+        this[formatterTypes[i]] = bind(impl._nodeFactory, null, formatterTypes[i]);
+}
+
+AuditResult.prototype = {
+    get Severity()
+    {
+        return private.audits.Severity;
+    }
+}
+
+function AuditResultImpl(id)
+{
+    this._id = id;
+}
+
+AuditResultImpl.prototype = {
+    addResult: function(displayName, description, severity, details)
+    {
+        // shorthand for specifying details directly in addResult().
+        if (details && !(details instanceof AuditResultNode))
+            details = details instanceof Array ? this.createNode.apply(this, details) : this.createNode(details);
+
+        var request = {
+            command: "addAuditResult",
+            resultId: this._id,
+            displayName: displayName,
+            description: description,
+            severity: severity,
+            details: details
+        };
+        extensionServer.sendRequest(request);
+    },
+
+    createResult: function()
+    {
+        var node = new AuditResultNode();
+        node.contents = Array.prototype.slice.call(arguments);
+        return node;
+    },
+
+    done: function()
+    {
+        extensionServer.sendRequest({ command: "stopAuditCategoryRun", resultId: this._id });
+    },
+
+    _nodeFactory: function(type)
+    {
+        return {
+            type: type,
+            arguments: Array.prototype.slice.call(arguments, 1)
+        };
+    }
+}
+
+function AuditResultNode(contents)
+{
+    this.contents = contents;
+    this.children = [];
+    this.expanded = false;
+}
+
+AuditResultNode.prototype = {
+    addChild: function()
+    {
+        var node = AuditResultImpl.prototype.createResult.apply(null, arguments);
+        this.children.push(node);
+        return node;
+    }
+};
+
 function InspectedWindow()
 {
     this.onLoaded = new EventSink("inspectedPageLoaded");
index 95f373f..0ff035c 100644 (file)
@@ -40,11 +40,15 @@ WebInspector.ExtensionServer = function()
     this._registerHandler("getResources", this._onGetResources.bind(this));
     this._registerHandler("createPanel", this._onCreatePanel.bind(this));
     this._registerHandler("createSidebarPane", this._onCreateSidebar.bind(this));
-    this._registerHandler("log", this._onLog.bind(this)); 
+    this._registerHandler("log", this._onLog.bind(this));
     this._registerHandler("evaluateOnInspectedPage", this._onEvaluateOnInspectedPage.bind(this));
     this._registerHandler("setSidebarHeight", this._onSetSidebarHeight.bind(this));
     this._registerHandler("setSidebarExpanded", this._onSetSidebarExpansion.bind(this));
 
+    this._registerHandler("addAuditCategory", this._onAddAuditCategory.bind(this));
+    this._registerHandler("addAuditResult", this._onAddAuditResult.bind(this));
+    this._registerHandler("stopAuditCategoryRun", this._onStopAuditCategoryRun.bind(this));
+
     window.addEventListener("message", this._onWindowMessage.bind(this), false);
 }
 
@@ -84,6 +88,17 @@ WebInspector.ExtensionServer.prototype = {
         this._postNotification("reset");
     },
 
+    startAuditRun: function(category, auditRun)
+    {
+        this._clientObjects[auditRun.id] = auditRun;
+        this._postNotification("audit-started-" + category.id, auditRun.id);
+    },
+
+    stopAuditRun: function(auditRun)
+    {
+        delete this._clientObjects[auditRun.id];
+    },
+
     _convertResource: function(resource)
     {
         return {
@@ -100,7 +115,7 @@ WebInspector.ExtensionServer.prototype = {
             return;
         var message = {
             command: "notify-" + type,
-            arguments: Array.prototype.slice.call(arguments, 1) 
+            arguments: Array.prototype.slice.call(arguments, 1)
         };
         for (var i = 0; i < subscribers.length; ++i)
             subscribers[i].postMessage(message);
@@ -248,6 +263,36 @@ WebInspector.ExtensionServer.prototype = {
         return response;
     },
 
+    _onAddAuditCategory: function(request)
+    {
+        var category = new WebInspector.ExtensionAuditCategory(request.id, request.displayName, request.ruleCount);
+        if (WebInspector.panels.audits.getCategory(category.id))
+            return this._status.E_EXISTS(category.id);
+        this._clientObjects[request.id] = category;
+        WebInspector.panels.audits.addCategory(category);
+    },
+
+    _onAddAuditResult: function(request)
+    {
+        var auditResult = this._clientObjects[request.resultId];
+        if (!auditResult)
+            return this._status.E_NOTFOUND(request.resultId);
+        try {
+            auditResult.addResult(request.displayName, request.description, request.severity, request.details);
+        } catch (e) {
+            return e;
+        }
+        return this._status.OK();
+    },
+
+    _onStopAuditCategoryRun: function(request)
+    {
+        var auditRun = this._clientObjects[request.resultId];
+        if (!auditRun)
+            return this._status.E_NOTFOUND(request.resultId);
+        auditRun.cancel();
+    },
+
     initExtensions: function()
     {
         InspectorExtensionRegistry.getExtensionsAsync();
@@ -255,7 +300,8 @@ WebInspector.ExtensionServer.prototype = {
 
     _addExtensions: function(extensions)
     {
-        InspectorFrontendHost.setExtensionAPI("(" + injectedExtensionAPI.toString() + ")"); // See ExtensionAPI.js for details.
+        // See ExtensionAPI.js and ExtensionCommon.js for details.
+        InspectorFrontendHost.setExtensionAPI(this._buildExtensionAPIInjectedScript());
         for (var i = 0; i < extensions.length; ++i) {
             var extension = extensions[i];
             try {
@@ -271,6 +317,15 @@ WebInspector.ExtensionServer.prototype = {
         }
     },
 
+    _buildExtensionAPIInjectedScript: function()
+    {
+        return "(function(){ " +
+            "var private = {};" +
+            "(" + WebInspector.commonExtensionSymbols.toString() + ")(private);" +
+            "(" + WebInspector.injectedExtensionAPI.toString() + ").apply(this, arguments);" +
+            "})";
+    },
+
     _onWindowMessage: function(event)
     {
         if (event.data !== "registerExtension")
@@ -300,12 +355,14 @@ WebInspector.ExtensionServer.prototype = {
     }
 }
 
-WebInspector.ExtensionServer._statuses = 
+WebInspector.ExtensionServer._statuses =
 {
     OK: "",
-    E_NOTFOUND: "Object not found (%s)",
-    E_NOTSUPPORTED: "Object does not support requested operation (%s)",
-    E_EXISTS: "Object already exists (%s)"
+    E_EXISTS: "Object already exists: %s",
+    E_BADARG: "Invalid argument %s: %s",
+    E_BADARGTYPE: "Invalid type for argument %s: got %s, expected %s",
+    E_NOTFOUND: "Object not found: %s",
+    E_NOTSUPPORTED: "Object does not support requested operation: %s",
 }
 
 WebInspector.ExtensionStatus = function()
@@ -319,7 +376,7 @@ WebInspector.ExtensionStatus = function()
             status.isError = true;
             console.log("Extension server error: " + String.vsprintf(description, details));
         }
-        return status; 
+        return status;
     }
     for (status in WebInspector.ExtensionServer._statuses)
         this[status] = makeStatus.bind(null, status);
index 1f15db3..b640936 100644 (file)
@@ -4,6 +4,7 @@
     <file>AbstractTimelinePanel.js</file>
     <file>ApplicationCacheItemsView.js</file>
     <file>AuditCategories.js</file>
+    <file>AuditFormatters.js</file>
     <file>AuditLauncherView.js</file>
     <file>AuditResultView.js</file>
     <file>AuditRules.js</file>
@@ -35,6 +36,8 @@
     <file>ElementsTreeOutline.js</file>
     <file>EventListenersSidebarPane.js</file>
     <file>ExtensionAPI.js</file>
+    <file>ExtensionAuditCategory.js</file>
+    <file>ExtensionCommon.js</file>
     <file>ExtensionPanel.js</file>
     <file>ExtensionRegistryStub.js</file>
     <file>ExtensionServer.js</file>
index 4968685..3e4b6c1 100644 (file)
@@ -98,6 +98,8 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     <script type="text/javascript" src="ProfilesPanel.js"></script>
     <script type="text/javascript" src="ConsolePanel.js"></script>
     <script type="text/javascript" src="ExtensionAPI.js"></script>
+    <script type="text/javascript" src="ExtensionAuditCategory.js"></script>
+    <script type="text/javascript" src="ExtensionCommon.js"></script>
     <script type="text/javascript" src="ExtensionServer.js"></script>
     <script type="text/javascript" src="ExtensionPanel.js"></script>
     <script type="text/javascript" src="AuditsPanel.js"></script>
@@ -105,6 +107,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     <script type="text/javascript" src="AuditLauncherView.js"></script>
     <script type="text/javascript" src="AuditRules.js"></script>
     <script type="text/javascript" src="AuditCategories.js"></script>
+    <script type="text/javascript" src="AuditFormatters.js"></script>
     <script type="text/javascript" src="ResourceView.js"></script>
     <script type="text/javascript" src="SourceFrame.js"></script>
     <script type="text/javascript" src="DOMSyntaxHighlighter.js"></script>
index 66cf284..e8adff6 100644 (file)
@@ -732,12 +732,6 @@ Array.convert = function(list)
 
 function insertionIndexForObjectInListSortedByFunction(anObject, aList, aFunction)
 {
-    // indexOf returns (-lowerBound - 1). Taking (-result - 1) works out to lowerBound.
-    return (-indexOfObjectInListSortedByFunction(anObject, aList, aFunction) - 1);
-}
-
-function indexOfObjectInListSortedByFunction(anObject, aList, aFunction)
-{
     var first = 0;
     var last = aList.length - 1;
     var floor = Math.floor;
@@ -760,9 +754,7 @@ function indexOfObjectInListSortedByFunction(anObject, aList, aFunction)
         }
     }
 
-    // By returning 1 less than the negative lower search bound, we can reuse this function
-    // for both indexOf and insertionIndexFor, with some simple arithmetic.
-    return (-first - 1);
+    return first;
 }
 
 String.sprintf = function(format)