Title: [188539] trunk
Revision
188539
Author
[email protected]
Date
2015-08-17 13:33:48 -0700 (Mon, 17 Aug 2015)

Log Message

Web Inspector: load ProtocolTestStub from the WebInspectorUI bundle
https://bugs.webkit.org/show_bug.cgi?id=147955

Reviewed by Timothy Hatcher.

Source/WebInspectorUI:

Move ProtocolTestStub.{html,js} into the actual WebInspectorUI project.

* UserInterface/Base/TestStub.js: Renamed from LayoutTests/http/tests/inspector/resources/ProtocolTestStub.js.
* UserInterface/TestStub.html: Renamed from LayoutTests/http/tests/inspector/resources/ProtocolTestStub.html.

Tools:

To enable sharing of common test code between protocol and model tests,
start loading the protocol TestStub.js through the WebInspectorUI bundle.

This patch adds the read-only getter TestRunner.inspectorTestStubURL, which
protocol-test.js uses to load the inspector frontend stub into its iframe
from an arbitrary local file URL.

* DumpRenderTree/TestRunner.cpp:
(getInspectorTestStubURLCallback):
(TestRunner::staticValues):
* DumpRenderTree/TestRunner.h:
* DumpRenderTree/mac/TestRunnerMac.mm:
(SOFT_LINK_STAGED_FRAMEWORK):
(TestRunner::inspectorTestStubURL):
* DumpRenderTree/win/TestRunnerWin.cpp:
(TestRunner::inspectorTestStubURL):
* WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
* WebKitTestRunner/InjectedBundle/TestRunner.h:
* WebKitTestRunner/InjectedBundle/efl/TestRunnerEfl.cpp:
(WTR::TestRunner::inspectorTestStubURL):
* WebKitTestRunner/InjectedBundle/gtk/TestRunnerGtk.cpp:
(WTR::TestRunner::inspectorTestStubURL):
* WebKitTestRunner/InjectedBundle/mac/TestRunnerMac.mm:
(WTR::TestRunner::inspectorTestStubURL):

LayoutTests:

Since the inspector stub cannot open files that live in the LayoutTests
directory, adopt the test helper marshalling approach used by inspector.js.
Each helper must register its code for marshalling and explicitly put globals
on the window object.

Use script tags rather than importScript to include helpers in a test.

* TestExpectations: For now, skip inspector http tests. These should be rewritten
to use inspector-test.js, which does not run into cross-origin problems.

Rebaseline some test results to account for shifted line numbers (yuck).

* http/tests/inspector/dom/resources/InspectorDOMListener.js:
* http/tests/inspector/resources/console-test.js:
* http/tests/inspector/resources/probe-test.js:
* http/tests/inspector/resources/protocol-test.js:
(ProtocolTestProxy.registerInitializer):
(log):
(runTest.runInitializationMethodsInFrontend):
(runTest.runTestMethodInFrontend):
(runTest):
* inspector/console/console-message.html:
* inspector/console/css-source-locations-expected.txt:
* inspector/console/css-source-locations.html:
* inspector/console/js-source-locations-expected.txt:
* inspector/console/js-source-locations.html:
* inspector/console/x-frame-options-message-expected.txt:
* inspector/console/x-frame-options-message.html:
* inspector/debugger/didSampleProbe-multiple-probes.html:
* inspector/debugger/setBreakpoint-actions.html:
* inspector/debugger/setBreakpoint-options-exception.html:
* inspector/dom/dom-search-expected.txt:
* inspector/dom/dom-search-with-context.html:
* inspector/dom/dom-search.html:
* inspector/dom/resources/dom-search-queries.js:

Modified Paths

Added Paths

Removed Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (188538 => 188539)


--- trunk/LayoutTests/ChangeLog	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/ChangeLog	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,3 +1,46 @@
+2015-08-17  Brian Burg  <[email protected]>
+
+        Web Inspector: load ProtocolTestStub from the WebInspectorUI bundle
+        https://bugs.webkit.org/show_bug.cgi?id=147955
+
+        Reviewed by Timothy Hatcher.
+
+        Since the inspector stub cannot open files that live in the LayoutTests
+        directory, adopt the test helper marshalling approach used by inspector.js.
+        Each helper must register its code for marshalling and explicitly put globals
+        on the window object.
+
+        Use script tags rather than importScript to include helpers in a test.
+
+        * TestExpectations: For now, skip inspector http tests. These should be rewritten
+        to use inspector-test.js, which does not run into cross-origin problems.
+
+        Rebaseline some test results to account for shifted line numbers (yuck).
+
+        * http/tests/inspector/dom/resources/InspectorDOMListener.js:
+        * http/tests/inspector/resources/console-test.js:
+        * http/tests/inspector/resources/probe-test.js:
+        * http/tests/inspector/resources/protocol-test.js:
+        (ProtocolTestProxy.registerInitializer):
+        (log):
+        (runTest.runInitializationMethodsInFrontend):
+        (runTest.runTestMethodInFrontend):
+        (runTest):
+        * inspector/console/console-message.html:
+        * inspector/console/css-source-locations-expected.txt:
+        * inspector/console/css-source-locations.html:
+        * inspector/console/js-source-locations-expected.txt:
+        * inspector/console/js-source-locations.html:
+        * inspector/console/x-frame-options-message-expected.txt:
+        * inspector/console/x-frame-options-message.html:
+        * inspector/debugger/didSampleProbe-multiple-probes.html:
+        * inspector/debugger/setBreakpoint-actions.html:
+        * inspector/debugger/setBreakpoint-options-exception.html:
+        * inspector/dom/dom-search-expected.txt:
+        * inspector/dom/dom-search-with-context.html:
+        * inspector/dom/dom-search.html:
+        * inspector/dom/resources/dom-search-queries.js:
+
 2015-08-17  Simon Fraser  <[email protected]>
 
         will-change should sometimes trigger compositing

Modified: trunk/LayoutTests/TestExpectations (188538 => 188539)


--- trunk/LayoutTests/TestExpectations	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/TestExpectations	2015-08-17 20:33:48 UTC (rev 188539)
@@ -94,6 +94,9 @@
 
 webkit.org/b/129057 media/controls-styling-strict.html [ Pass Failure ]
 
+# These tests will be rewritten, just skip them until that time.
+webkit.org/b/148036 http/tests/inspector/ [ Skip ]
+
 webkit.org/b/129639 inspector/dom/dom-search-crash.html [ Skip ]
 
 webkit.org/b/133761 inspector/debugger/breakpoint-action-detach.html [ Skip ]

Modified: trunk/LayoutTests/http/tests/inspector/dom/resources/InspectorDOMListener.js (188538 => 188539)


--- trunk/LayoutTests/http/tests/inspector/dom/resources/InspectorDOMListener.js	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/http/tests/inspector/dom/resources/InspectorDOMListener.js	2015-08-17 20:33:48 UTC (rev 188539)
@@ -27,7 +27,9 @@
  * SUCH DAMAGE.
  */
 
-function createDOMListener()
+ProtocolTestProxy.registerInitializer(function(){
+
+window.createDOMListener = function()
 {
     var nodesById = {};
 
@@ -101,3 +103,5 @@
         collectNode: collectNode
     };
 }
+
+});

Deleted: trunk/LayoutTests/http/tests/inspector/resources/ProtocolTestStub.html (188538 => 188539)


--- trunk/LayoutTests/http/tests/inspector/resources/ProtocolTestStub.html	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/http/tests/inspector/resources/ProtocolTestStub.html	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,30 +0,0 @@
-<!--
-Copyright (C) 2012 Samsung Electronics. All rights reserved.
-Copyright (C) 2015 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 AND ITS CONTRIBUTORS "AS IS" AND ANY
-EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
-DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
-DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
-ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
-THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
--->
-<html>
-<head>
-    <script type="text/_javascript_" src=""
-</head>
-</html>

Deleted: trunk/LayoutTests/http/tests/inspector/resources/ProtocolTestStub.js (188538 => 188539)


--- trunk/LayoutTests/http/tests/inspector/resources/ProtocolTestStub.js	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/http/tests/inspector/resources/ProtocolTestStub.js	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,498 +0,0 @@
-/*
- * Copyright (C) 2012 Samsung Electronics. All rights reserved.
- * Copyright (C) 2014, 2015 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 AND ITS CONTRIBUTORS "AS IS" AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
- * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-InspectorFrontendAPI = {};
-
-InjectedTestHarness = class InjectedTestHarness
-{
-    constructor()
-    {
-        this._logCount = 0;
-        this.forceSyncDebugLogging = false;
-    }
-
-    completeTest()
-    {
-        throw new Error("Must be implemented by subclasses.");
-    }
-
-    addResult()
-    {
-        throw new Error("Must be implemented by subclasses.");
-    }
-
-    debugLog()
-    {
-        throw new Error("Must be implemented by subclasses.");
-    }
-
-    evaluateInPage(string, callback)
-    {
-        throw new Error("Must be implemented by subclasses.");
-    }
-
-    createAsyncSuite(name)
-    {
-        return new InjectedTestHarness.AsyncTestSuite(this, name);
-    }
-
-    createSyncSuite(name)
-    {
-        return new InjectedTestHarness.SyncTestSuite(this, name);
-    }
-
-    importScript(scriptName)
-    {
-        var xhr = new XMLHttpRequest();
-        var isAsyncRequest = false;
-        xhr.open("GET", scriptName, isAsyncRequest);
-        xhr.send(null);
-        if (xhr.status !== 0 && xhr.status !== 200)
-            throw new Error("Invalid script URL: " + scriptName);
-        var script = `// From InjectedTestHarness.importScript(${scriptName})
-try {
-    ${xhr.responseText}
-} catch (e) {
-    alert(${JSON.stringify("Error in: " + scriptName)});
-    throw e;
-}`;
-        window.eval(script);
-    }
-
-    get logCount()
-    {
-        return this._logCount;
-    }
-
-    log(message)
-    {
-        ++this._logCount;
-
-        if (this.forceSyncDebugLogging)
-            this.debugLog(message);
-        else
-            this.addResult(message);
-    }
-
-    assert(condition, message)
-    {
-        if (condition)
-            return;
-
-        let stringifiedMessage = typeof message !== "object" ? message : JSON.stringify(message);
-        this.addResult("ASSERT: " + stringifiedMessage);
-    }
-
-    expectThat(condition, message)
-    {
-        let prefix = condition ? "PASS" : "FAIL";
-        let stringifiedMessage = typeof message !== "object" ? message : JSON.stringify(message);
-        this.addResult(prefix + ": " + stringifiedMessage);
-    }
-}
-
-InjectedTestHarness.AsyncTestSuite = class AsyncTestSuite
-{
-    constructor(harness, name) {
-        if (!(harness instanceof InjectedTestHarness))
-            throw new Error("Must pass the test's harness as the first argument.");
-
-        if (!name || typeof name !== "string")
-            throw new Error("Tried to create AsyncTestSuite without string suite name.");
-
-        this.name = name;
-        this._harness = harness;
-
-        this.testcases = [];
-        this.runCount = 0;
-        this.failCount = 0;
-    }
-
-    get passCount()
-    {
-        return this.runCount - this.failCount;
-    }
-
-    get skipCount()
-    {
-        if (this.failCount)
-            return this.testcases.length - this.runCount;
-        else
-            return 0;
-    }
-
-    addTestCase(testcase)
-    {
-        if (!testcase || !(testcase instanceof Object))
-            throw new Error("Tried to add non-object test case.");
-
-        if (typeof testcase.name !== "string")
-            throw new Error("Tried to add test case without a name.");
-
-        if (typeof testcase.test !== "function")
-            throw new Error("Tried to add test case without `test` function.");
-
-        this.testcases.push(testcase);
-    }
-
-    // Use this if the test file only has one suite, and no handling
-    // of the promise returned by runTestCases() is needed.
-    runTestCasesAndFinish()
-    {
-        function finish() {
-            this._harness.completeTest();
-        }
-
-        this.runTestCases()
-            .then(finish.bind(this))
-            .catch(finish.bind(this));
-    }
-
-    runTestCases()
-    {
-        if (!this.testcases.length)
-            throw new Error("Tried to call runTestCases() for suite with no test cases");
-        if (this._startedRunning)
-            throw new Error("Tried to call runTestCases() more than once.");
-
-        this._startedRunning = true;
-
-        this._harness.log("");
-        this._harness.log("== Running test suite: " + this.name);
-
-        // Avoid adding newlines if nothing was logged.
-        var priorLogCount = this._harness.logCount;
-        var suite = this;
-        var result = this.testcases.reduce(function(chain, testcase, i) {
-            return chain.then(function() {
-                if (i > 0 && priorLogCount + 1 < suite._harness.logCount)
-                    suite._harness.log("");
-
-                priorLogCount = suite._harness.logCount;
-                suite._harness.log("-- Running test case: " + testcase.name);
-                suite.runCount++;
-                return new Promise(testcase.test);
-            });
-        }, Promise.resolve());
-
-        return result.catch(function(e) {
-            suite.failCount++;
-            var message = e;
-            if (e instanceof Error)
-                message = e.message;
-
-            if (typeof message !== "string")
-                message = JSON.stringify(message);
-
-            suite._harness.log("!! EXCEPTION: " + message);
-            throw e; // Reject this promise by re-throwing the error.
-        });
-    }
-}
-
-InjectedTestHarness.SyncTestSuite = class SyncTestSuite
-{
-    constructor(harness, name) {
-        if (!(harness instanceof InjectedTestHarness))
-            throw new Error("Must pass the test's harness as the first argument.");
-
-        if (!name || typeof name !== "string")
-            throw new Error("Tried to create SyncTestSuite without string suite name.");
-
-        this.name = name;
-        this._harness = harness;
-
-        this.testcases = [];
-        this.runCount = 0;
-        this.failCount = 0;
-    }
-
-    get passCount()
-    {
-        return this.runCount - this.failCount;
-    }
-
-    get skipCount()
-    {
-        if (this.failCount)
-            return this.testcases.length - this.runCount;
-        else
-            return 0;
-    }
-
-    addTestCase(testcase)
-    {
-        if (!testcase || !(testcase instanceof Object))
-            throw new Error("Tried to add non-object test case.");
-
-        if (typeof testcase.name !== "string")
-            throw new Error("Tried to add test case without a name.");
-
-        if (typeof testcase.test !== "function")
-            throw new Error("Tried to add test case without `test` function.");
-
-        this.testcases.push(testcase);
-    }
-
-    // Use this if the test file only has one suite.
-    runTestCasesAndFinish()
-    {
-        this.runTestCases();
-        this._harness.completeTest();
-    }
-
-    runTestCases()
-    {
-        if (!this.testcases.length)
-            throw new Error("Tried to call runTestCases() for suite with no test cases");
-        if (this._startedRunning)
-            throw new Error("Tried to call runTestCases() more than once.");
-
-        this._startedRunning = true;
-
-        this._harness.log("");
-        this._harness.log("== Running test suite: " + this.name);
-
-        var priorLogCount = this._harness.logCount;
-        var suite = this;
-        for (var i = 0; i < this.testcases.length; i++) {
-            var testcase = this.testcases[i];
-            if (i > 0 && priorLogCount + 1 < this._harness.logCount)
-                this._harness.log("");
-
-            priorLogCount = this._harness.logCount;
-
-            this._harness.log("-- Running test case: " + testcase.name);
-            suite.runCount++;
-            try {
-                var result = testcase.test.call(null);
-                if (result === false) {
-                    suite.failCount++;
-                    return false;
-                }
-            } catch (e) {
-                suite.failCount++;
-                var message = e;
-                if (e instanceof Error)
-                    message = e.message;
-                else
-                    e = new Error(e);
-
-                if (typeof message !== "string")
-                    message = JSON.stringify(message);
-
-                this._harness.log("!! EXCEPTION: " + message);
-                return false;
-            }
-        }
-
-        return true;
-    }
-}
-
-class ProtocolTestHarness extends InjectedTestHarness
-{
-    // InjectedTestHarness Overrides
-
-    completeTest()
-    {
-        this.evaluateInPage("closeTest();");
-    }
-
-    addResult(message)
-    {
-        // Unfortunately, every string argument must be escaped because tests are not consistent
-        // with respect to escaping with single or double quotes. Some exceptions use single quotes.
-        var stringifiedMessage = typeof message !== "string" ? JSON.stringify(message) : message;
-        this.evaluateInPage("log(unescape('" + escape(stringifiedMessage) + "'));");
-    }
-
-    debugLog(message)
-    {
-        var stringifiedMessage = typeof message !== "string" ? JSON.stringify(message) : message;
-        this.evaluateInPage("debugLog(unescape('" + escape(stringifiedMessage) + "'));")
-    }
-
-    evaluateInPage(_expression_, callback)
-    {
-        let args = {
-            method: "Runtime.evaluate",
-            params: {_expression_}
-        }
-
-        if (typeof callback === "function")
-            InspectorProtocol.sendCommand(args, callback);
-        else
-            return InspectorProtocol.awaitCommand(args);
-    }
-}
-
-window.ProtocolTest = new ProtocolTestHarness();
-
-InspectorProtocol = {};
-InspectorProtocol._dispatchTable = [];
-InspectorProtocol._requestId = -1;
-InspectorProtocol.eventHandler = {};
-
-InspectorProtocol.dumpInspectorProtocolMessages = false;
-
-InspectorProtocol.sendCommand = function(methodOrObject, params, handler)
-{
-    // Allow new-style arguments object, as in awaitCommand.
-    var method = methodOrObject;
-    if (typeof methodOrObject === "object")
-        var {method, params, handler} = methodOrObject;
-
-    this._dispatchTable[++this._requestId] = handler;
-    var messageObject = {method, params, "id": this._requestId};
-    this.sendMessage(messageObject);
-
-    return this._requestId;
-}
-
-InspectorProtocol.awaitCommand = function(args)
-{
-    var {method, params} = args;
-    return new Promise(function(resolve, reject) {
-        this._dispatchTable[++this._requestId] = {resolve, reject};
-        var messageObject = {method, params, "id": this._requestId};
-        this.sendMessage(messageObject);
-    }.bind(this));
-}
-
-InspectorProtocol.awaitEvent = function(args)
-{
-    var {event} = args;
-    if (typeof event !== "string")
-        throw new Error("Event must be a string.");
-
-    return new Promise(function(resolve, reject) {
-        InspectorProtocol.eventHandler[event] = function(message) {
-            InspectorProtocol.eventHandler[event] = undefined;
-            resolve(message);
-        }
-    });
-}
-
-InspectorProtocol.addEventListener = function(eventTypeOrObject, listener)
-{
-    var event = eventTypeOrObject;
-    if (typeof eventTypeOrObject === "object")
-        var {event, listener} = eventTypeOrObject;
-
-    if (typeof event !== "string")
-        throw new Error("Event name must be a string.");
-
-    if (typeof listener !== "function")
-        throw new Error("Event listener must be callable.");
-
-    // Convert to an array of listeners.
-    var listeners = InspectorProtocol.eventHandler[event];
-    if (!listeners)
-        listeners = InspectorProtocol.eventHandler[event] = [];
-    else if (typeof listeners === "function")
-        listeners = InspectorProtocol.eventHandler[event] = [listeners];
-
-    // Prevent registering multiple times.
-    if (listeners.includes(listener))
-        throw new Error("Cannot register the same listener more than once.");
-
-    listeners.push(listener);
-}
-
-InspectorProtocol.sendMessage = function(messageObject)
-{
-    // This matches the debug dumping in InspectorBackend, which is bypassed
-    // by InspectorProtocol. Return messages should be dumped by InspectorBackend.
-    if (InspectorProtocol.dumpInspectorProtocolMessages)
-        console.log("frontend: " + JSON.stringify(messageObject));
-
-    InspectorFrontendHost.sendMessageToBackend(JSON.stringify(messageObject));
-}
-
-InspectorProtocol.checkForError = function(responseObject)
-{
-    if (responseObject.error) {
-        ProtocolTest.log("PROTOCOL ERROR: " + JSON.stringify(responseObject.error));
-        ProtocolTest.completeTest();
-        throw "PROTOCOL ERROR";
-    }
-}
-
-InspectorFrontendAPI.dispatchMessageAsync = function(messageObject)
-{
-    // This matches the debug dumping in InspectorBackend, which is bypassed
-    // by InspectorProtocol. Return messages should be dumped by InspectorBackend.
-    if (InspectorProtocol.dumpInspectorProtocolMessages)
-        console.log("backend: " + JSON.stringify(messageObject));
-
-    // If the message has an id, then it is a reply to a command.
-    var messageId = messageObject["id"];
-    if (typeof messageId === "number") {
-        var handler = InspectorProtocol._dispatchTable[messageId];
-        if (!handler)
-            return;
-
-        if (typeof handler === "function")
-            handler(messageObject);
-        else if (typeof handler === "object") {
-            var {resolve, reject} = handler;
-            if ("error" in messageObject)
-                reject(messageObject.error.message);
-            else
-                resolve(messageObject.result);
-        }
-    // Otherwise, it is an event.
-    } else {
-        var eventName = messageObject["method"];
-        var handler = InspectorProtocol.eventHandler[eventName];
-        if (!handler)
-            return;
-
-        if (typeof handler === "function")
-            handler(messageObject);
-        else if (handler instanceof Array) {
-            handler.map(function(listener) {
-                listener.call(null, messageObject);
-            });
-        } else if (typeof handler === "object") {
-            var {resolve, reject} = handler;
-            if ("error" in messageObject)
-                reject(messageObject.error.message);
-            else
-                resolve(messageObject.result);
-        }
-    }
-}
-
-window.addEventListener("message", function(event) {
-    try {
-        eval(event.data);
-    } catch (e) {
-        alert(e.stack);
-        ProtocolTest.completeTest();
-        throw e;
-    }
-});
\ No newline at end of file

Modified: trunk/LayoutTests/http/tests/inspector/resources/console-test.js (188538 => 188539)


--- trunk/LayoutTests/http/tests/inspector/resources/console-test.js	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/http/tests/inspector/resources/console-test.js	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,3 +1,5 @@
+ProtocolTestProxy.registerInitializer(function() {
+
 ProtocolTest.Console = {};
 
 ProtocolTest.Console.sanitizeConsoleMessage = function(messageObject)
@@ -73,3 +75,5 @@
         }
     });
 }
+
+});

Modified: trunk/LayoutTests/http/tests/inspector/resources/probe-test.js (188538 => 188539)


--- trunk/LayoutTests/http/tests/inspector/resources/probe-test.js	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/http/tests/inspector/resources/probe-test.js	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,3 +1,5 @@
+ProtocolTestProxy.registerInitializer(function() {
+
 ProtocolTest.Probe = {};
 
 ProtocolTest.Probe.sanitizeProbeSample = function(messageObject)
@@ -125,3 +127,5 @@
         InspectorTest.log("Probe set's probe count: " + probeSet.probes.length);
     });
 }
+
+});

Modified: trunk/LayoutTests/http/tests/inspector/resources/protocol-test.js (188538 => 188539)


--- trunk/LayoutTests/http/tests/inspector/resources/protocol-test.js	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/http/tests/inspector/resources/protocol-test.js	2015-08-17 20:33:48 UTC (rev 188539)
@@ -23,8 +23,22 @@
  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
  * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
-var outputElement;
 
+// This namespace is injected into every test page. Its functions are invoked by
+// ProtocolTest methods on the inspector page via InjectedTestHarness.
+ProtocolTestProxy = {};
+ProtocolTestProxy._initializers = [];
+
+// Helper scripts like `console-test.js` must register their initialization
+// function with this method so it will be marshalled to the inspector page.
+ProtocolTestProxy.registerInitializer = function(initializer)
+{
+    if (typeof initializer === "function")
+        this._initializers.push(initializer.toString());
+}
+
+let outputElement;
+
 /**
  * Logs message to process stdout via alert (hopefully implemented with immediate flush).
  * @param {string} text
@@ -40,10 +54,10 @@
 function log(text)
 {
     if (!outputElement) {
-        var intermediate = document.createElement("div");
+        let intermediate = document.createElement("div");
         document.body.appendChild(intermediate);
 
-        var intermediate2 = document.createElement("div");
+        let intermediate2 = document.createElement("div");
         intermediate.appendChild(intermediate2);
 
         outputElement = document.createElement("div");
@@ -77,27 +91,46 @@
     testRunner.waitUntilDone();
     testRunner.setCanOpenWindows(true);
 
-    var scriptTags = document.getElementsByTagName("script");
-    var scriptUrlBasePath = "";
-    for (var i = 0; i < scriptTags.length; ++i) {
-        var index = scriptTags[i].src.lastIndexOf("/protocol-test.js");
-        if (index > -1 ) {
-            scriptUrlBasePath = scriptTags[i].src.slice(0, index);
-            break;
+    let testFunction = window.test;
+    if (!(typeof testFunction === "function")) {
+        alert("Failed to send test() because it is not a function.");
+        testRunner.notifyDone();
+    }
+
+    let url = ""
+    if (!url) {
+        alert("Failed to obtain inspector test stub URL.");
+        testRunner.notifyDone();
+    }
+
+    function runInitializationMethodsInFrontend(initializers)
+    {
+        for (let initializer of initializers) {
+            try {
+                initializer();
+            } catch (e) {
+                ProtocolTest.log("Exception in test initialization: " + e, e.stack || "(no stack trace)");
+                ProtocolTest.completeTest();
+            }
         }
     }
 
-    var url = "" + "/ProtocolTestStub.html";
-    var inspectorFrontend = window.internals.openDummyInspectorFrontend(url);
+    function runTestMethodInFrontend(testFunction)
+    {
+        try {
+            testFunction();
+        } catch (e) {
+            ProtocolTest.log("Exception during test execution: " + e, e.stack || "(no stack trace)");
+            ProtocolTest.completeTest();
+        }
+    }
+
+    let inspectorFrontend = window.internals.openDummyInspectorFrontend(url);
     inspectorFrontend.addEventListener("load", function(event) {
-        // FIXME: rename this 'test' global field across all tests.
-        var testFunction = window.test;
-        if (typeof testFunction === "function") {
-            inspectorFrontend.postMessage("(" + testFunction.toString() +")();", "*");
-            return;
-        }
-        // Kill waiting process if failed to send.
-        alert("Failed to send test function");
-        testRunner.notifyDone();
+        let initializationCodeString = `(${runInitializationMethodsInFrontend.toString()})([${ProtocolTestProxy._initializers}]);`;
+        let testFunctionCodeString = `(${runTestMethodInFrontend.toString()})(${testFunction.toString()});`;
+
+        inspectorFrontend.postMessage(initializationCodeString, "*");
+        inspectorFrontend.postMessage(testFunctionCodeString, "*");
     });
 }

Modified: trunk/LayoutTests/inspector/console/console-message.html (188538 => 188539)


--- trunk/LayoutTests/inspector/console/console-message.html	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/inspector/console/console-message.html	2015-08-17 20:33:48 UTC (rev 188539)
@@ -2,6 +2,7 @@
 <html>
 <head>
 <script src=""
+<script src=""
 <script>
 function generateSimpleConsoleMessages()
 {
@@ -14,7 +15,6 @@
 
 function test()
 {
-    ProtocolTest.importScript("console-test.js");
 
     var suite = ProtocolTest.createAsyncSuite("Console.MessagesFromCommandLineAPI");
 

Modified: trunk/LayoutTests/inspector/console/css-source-locations-expected.txt (188538 => 188539)


--- trunk/LayoutTests/inspector/console/css-source-locations-expected.txt	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/inspector/console/css-source-locations-expected.txt	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,8 +1,8 @@
 Tests that CSS parser warnings from inline style tags and external stylesheets are sent to the console with correct line and column information.
-{"source":"css","level":"warning","text":"Invalid CSS property declaration at: *","location":"css-source-locations.html:6:20"}
-{"source":"css","level":"warning","text":"Invalid CSS property declaration at: *","location":"css-source-locations.html:7:14"}
-{"source":"css","level":"warning","text":"Invalid CSS property declaration at: *","location":"css-source-locations.html:8:7"}
-{"source":"css","level":"warning","text":"Invalid CSS property declaration at: *","location":"css-source-locations.html:10:8"}
+{"source":"css","level":"warning","text":"Invalid CSS property declaration at: *","location":"css-source-locations.html:7:20"}
+{"source":"css","level":"warning","text":"Invalid CSS property declaration at: *","location":"css-source-locations.html:8:14"}
+{"source":"css","level":"warning","text":"Invalid CSS property declaration at: *","location":"css-source-locations.html:9:7"}
+{"source":"css","level":"warning","text":"Invalid CSS property declaration at: *","location":"css-source-locations.html:11:8"}
 {"source":"css","level":"warning","text":"Invalid CSS property declaration at: *","location":"errors.css:1:7"}
 {"source":"css","level":"warning","text":"Invalid CSS property declaration at: *","location":"errors.css:1:29"}
 {"source":"css","level":"warning","text":"Invalid CSS property declaration at: *","location":"errors.css:4:5"}

Modified: trunk/LayoutTests/inspector/console/css-source-locations.html (188538 => 188539)


--- trunk/LayoutTests/inspector/console/css-source-locations.html	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/inspector/console/css-source-locations.html	2015-08-17 20:33:48 UTC (rev 188539)
@@ -2,6 +2,7 @@
 <html>
 <head>
 <script src=""
+<script src=""
 <link rel="stylesheet" href=""
   <style>    div { * color: red; }</style>
 <style>div { * color: red; }
@@ -15,8 +16,6 @@
 <script>
 function test()
 {
-    ProtocolTest.importScript("console-test.js");
-
     var consoleMessageCount = 0;
     const expectedConsoleMessageCount = 7;
 

Modified: trunk/LayoutTests/inspector/console/js-source-locations-expected.txt (188538 => 188539)


--- trunk/LayoutTests/inspector/console/js-source-locations-expected.txt	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/inspector/console/js-source-locations-expected.txt	2015-08-17 20:33:48 UTC (rev 188539)
@@ -2,17 +2,17 @@
 CONSOLE MESSAGE: line 1: warn script
 CONSOLE MESSAGE: line 5: error script
 CONSOLE MESSAGE: line 6: warn script
-CONSOLE MESSAGE: line 6: TypeError: undefined is not an object (evaluating '[].x.x')
-CONSOLE MESSAGE: line 8: warn 1
-CONSOLE MESSAGE: line 8: error 1
-CONSOLE MESSAGE: line 9: error 2
+CONSOLE MESSAGE: line 7: TypeError: undefined is not an object (evaluating '[].x.x')
+CONSOLE MESSAGE: line 9: warn 1
+CONSOLE MESSAGE: line 9: error 1
+CONSOLE MESSAGE: line 10: error 2
 Tests that _javascript_ errors and warnings from inline script tags and external files are sent to the console with correct line and column information.
 {"source":"console-api","level":"error","text":"error script","location":"errors.js:1:14","parameters":[{"type":"string"}]}
 {"source":"console-api","level":"warning","text":"warn script","location":"errors.js:1:44","parameters":[{"type":"string"}]}
 {"source":"console-api","level":"error","text":"error script","location":"errors.js:5:18","parameters":[{"type":"string"}]}
 {"source":"console-api","level":"warning","text":"warn script","location":"errors.js:6:17","parameters":[{"type":"string"}]}
-{"source":"_javascript_","level":"error","text":"TypeError: undefined is not an object (evaluating '[].x.x')","location":"js-source-locations.html:6:18"}
-{"source":"console-api","level":"warning","text":"warn 1","location":"js-source-locations.html:8:13","parameters":[{"type":"string"}]}
-{"source":"console-api","level":"error","text":"error 1","location":"js-source-locations.html:8:38","parameters":[{"type":"string"}]}
-{"source":"console-api","level":"error","text":"error 2","location":"js-source-locations.html:9:17","parameters":[{"type":"string"}]}
+{"source":"_javascript_","level":"error","text":"TypeError: undefined is not an object (evaluating '[].x.x')","location":"js-source-locations.html:7:18"}
+{"source":"console-api","level":"warning","text":"warn 1","location":"js-source-locations.html:9:13","parameters":[{"type":"string"}]}
+{"source":"console-api","level":"error","text":"error 1","location":"js-source-locations.html:9:38","parameters":[{"type":"string"}]}
+{"source":"console-api","level":"error","text":"error 2","location":"js-source-locations.html:10:17","parameters":[{"type":"string"}]}
 

Modified: trunk/LayoutTests/inspector/console/js-source-locations.html (188538 => 188539)


--- trunk/LayoutTests/inspector/console/js-source-locations.html	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/inspector/console/js-source-locations.html	2015-08-17 20:33:48 UTC (rev 188539)
@@ -2,6 +2,7 @@
 <html>
 <head>
 <script src=""
+<script src=""
 <script src=""
   <script>   [].x.x   </script>
 <script>
@@ -11,8 +12,6 @@
 <script>
 function test()
 {
-    ProtocolTest.importScript("console-test.js");
-
     var consoleMessageCount = 0;
     const expectedConsoleMessageCount = 8;
 

Modified: trunk/LayoutTests/inspector/console/x-frame-options-message-expected.txt (188538 => 188539)


--- trunk/LayoutTests/inspector/console/x-frame-options-message-expected.txt	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/inspector/console/x-frame-options-message-expected.txt	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,4 +1,4 @@
-CONSOLE MESSAGE: line 42: Refused to display 'x-frame-options-message.html' in a frame because it set 'X-Frame-Options' to 'deny'.
+CONSOLE MESSAGE: line 41: Refused to display 'x-frame-options-message.html' in a frame because it set 'X-Frame-Options' to 'deny'.
 
 
 == Running test suite: Console.XFrameOptionsMessages

Modified: trunk/LayoutTests/inspector/console/x-frame-options-message.html (188538 => 188539)


--- trunk/LayoutTests/inspector/console/x-frame-options-message.html	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/inspector/console/x-frame-options-message.html	2015-08-17 20:33:48 UTC (rev 188539)
@@ -2,11 +2,10 @@
 <html>
 <head>
 <script src=""
+<script src=""
 <script>
 function test()
 {
-    ProtocolTest.importScript("console-test.js");
-
     let suite = ProtocolTest.createAsyncSuite("Console.XFrameOptionsMessages");
 
     ProtocolTest.Console.addTestCase(suite, {

Modified: trunk/LayoutTests/inspector/debugger/didSampleProbe-multiple-probes.html (188538 => 188539)


--- trunk/LayoutTests/inspector/debugger/didSampleProbe-multiple-probes.html	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/inspector/debugger/didSampleProbe-multiple-probes.html	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,12 +1,11 @@
 <html>
 <head>
 <script src=""
+<script src=""
 <script src=""
 <script>
 function test()
 {
-    ProtocolTest.importScript("probe-test.js");
-
     InspectorProtocol.sendCommand("Debugger.enable", {});
 
     var samples = [];

Modified: trunk/LayoutTests/inspector/debugger/setBreakpoint-actions.html (188538 => 188539)


--- trunk/LayoutTests/inspector/debugger/setBreakpoint-actions.html	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/inspector/debugger/setBreakpoint-actions.html	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,13 +1,12 @@
 <html>
 <head>
 <script src=""
+<script src=""
+<script src=""
 <script src=""
 <script>
 function test()
 {
-    ProtocolTest.importScript("console-test.js");
-    ProtocolTest.importScript("probe-test.js");
-
     InspectorProtocol.sendCommand("Console.enable", {});
     InspectorProtocol.sendCommand("Debugger.enable", {});
 

Modified: trunk/LayoutTests/inspector/debugger/setBreakpoint-options-exception.html (188538 => 188539)


--- trunk/LayoutTests/inspector/debugger/setBreakpoint-options-exception.html	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/inspector/debugger/setBreakpoint-options-exception.html	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,12 +1,11 @@
 <html>
 <head>
 <script src=""
+<script src=""
 <script src=""
 <script>
 function test()
 {
-    ProtocolTest.importScript("console-test.js");
-
     InspectorProtocol.sendCommand("Console.enable", {});
     InspectorProtocol.sendCommand("Debugger.enable", {});
 

Modified: trunk/LayoutTests/inspector/dom/dom-search-expected.txt (188538 => 188539)


--- trunk/LayoutTests/inspector/dom/dom-search-expected.txt	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/inspector/dom/dom-search-expected.txt	2015-08-17 20:33:48 UTC (rev 188539)
@@ -48,11 +48,13 @@
 === Query: ".body-inside-iframe" ===
 Count: 0
 === Query: "*" ===
-Count: 12
+Count: 14
 html
 head
 script
 script
+script
+script
 body.main-frame
 p
 iframe

Modified: trunk/LayoutTests/inspector/dom/dom-search-with-context.html (188538 => 188539)


--- trunk/LayoutTests/inspector/dom/dom-search-with-context.html	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/inspector/dom/dom-search-with-context.html	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,11 +1,11 @@
 <html>
 <head>
 <script type="text/_javascript_" src=""
+<script type="text/_javascript_" src=""
 <script>
 function test()
 {
     // Create a DOM listener to convert nodeIds to tag names.
-    ProtocolTest.importScript("../dom/resources/InspectorDOMListener.js");
     var dom = createDOMListener();
 
     // Caching the output to avoid searching through the log.

Modified: trunk/LayoutTests/inspector/dom/dom-search.html (188538 => 188539)


--- trunk/LayoutTests/inspector/dom/dom-search.html	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/inspector/dom/dom-search.html	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,14 +1,13 @@
 <html>
 <head>
 <script type="text/_javascript_" src=""
+<script type="text/_javascript_" src=""
+<!-- Loading the queries from external file to avoid having them show up in the results. -->
+<script type="text/_javascript_" src=""
 <script>
 function test()
 {
-    // Loading the queries from external file to avoid having them show up in the results.
-    ProtocolTest.importScript("../../../../inspector/dom/resources/dom-search-queries.js");
-
     // Create a DOM listener to convert nodeIds to tag names.
-    ProtocolTest.importScript("../dom/resources/InspectorDOMListener.js");
     var dom = createDOMListener();
 
     // Caching the output to avoid searching through the log.

Modified: trunk/LayoutTests/inspector/dom/resources/dom-search-queries.js (188538 => 188539)


--- trunk/LayoutTests/inspector/dom/resources/dom-search-queries.js	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/LayoutTests/inspector/dom/resources/dom-search-queries.js	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,6 +1,8 @@
+ProtocolTestProxy.registerInitializer(function() {
+
 // Having the queries in an external file, so that DOM search will not find the script when searching for values.
 
-var domSearchQueries = [
+window.domSearchQueries = [
     "body",
     "<body",
     "body>",
@@ -28,4 +30,6 @@
     "/html/body",
     "/html/body/@onload",
     "/HTML/BODY"
-];
\ No newline at end of file
+];
+
+});
\ No newline at end of file

Modified: trunk/Source/WebInspectorUI/ChangeLog (188538 => 188539)


--- trunk/Source/WebInspectorUI/ChangeLog	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/Source/WebInspectorUI/ChangeLog	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,3 +1,15 @@
+2015-08-17  Brian Burg  <[email protected]>
+
+        Web Inspector: load ProtocolTestStub from the WebInspectorUI bundle
+        https://bugs.webkit.org/show_bug.cgi?id=147955
+
+        Reviewed by Timothy Hatcher.
+
+        Move ProtocolTestStub.{html,js} into the actual WebInspectorUI project.
+
+        * UserInterface/Base/TestStub.js: Renamed from LayoutTests/http/tests/inspector/resources/ProtocolTestStub.js.
+        * UserInterface/TestStub.html: Renamed from LayoutTests/http/tests/inspector/resources/ProtocolTestStub.html.
+
 2015-08-17  Simon Fraser  <[email protected]>
 
         will-change should sometimes trigger compositing

Copied: trunk/Source/WebInspectorUI/UserInterface/Base/TestStub.js (from rev 188538, trunk/LayoutTests/http/tests/inspector/resources/ProtocolTestStub.js) (0 => 188539)


--- trunk/Source/WebInspectorUI/UserInterface/Base/TestStub.js	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/Base/TestStub.js	2015-08-17 20:33:48 UTC (rev 188539)
@@ -0,0 +1,480 @@
+/*
+ * Copyright (C) 2012 Samsung Electronics. All rights reserved.
+ * Copyright (C) 2014, 2015 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 AND ITS CONTRIBUTORS "AS IS" AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+InspectorFrontendAPI = {};
+
+InjectedTestHarness = class InjectedTestHarness
+{
+    constructor()
+    {
+        this._logCount = 0;
+        this.forceSyncDebugLogging = false;
+    }
+
+    completeTest()
+    {
+        throw new Error("Must be implemented by subclasses.");
+    }
+
+    addResult()
+    {
+        throw new Error("Must be implemented by subclasses.");
+    }
+
+    debugLog()
+    {
+        throw new Error("Must be implemented by subclasses.");
+    }
+
+    evaluateInPage(string, callback)
+    {
+        throw new Error("Must be implemented by subclasses.");
+    }
+
+    createAsyncSuite(name)
+    {
+        return new InjectedTestHarness.AsyncTestSuite(this, name);
+    }
+
+    createSyncSuite(name)
+    {
+        return new InjectedTestHarness.SyncTestSuite(this, name);
+    }
+
+    get logCount()
+    {
+        return this._logCount;
+    }
+
+    log(message)
+    {
+        ++this._logCount;
+
+        if (this.forceSyncDebugLogging)
+            this.debugLog(message);
+        else
+            this.addResult(message);
+    }
+
+    assert(condition, message)
+    {
+        if (condition)
+            return;
+
+        let stringifiedMessage = typeof message !== "object" ? message : JSON.stringify(message);
+        this.addResult("ASSERT: " + stringifiedMessage);
+    }
+
+    expectThat(condition, message)
+    {
+        let prefix = condition ? "PASS" : "FAIL";
+        let stringifiedMessage = typeof message !== "object" ? message : JSON.stringify(message);
+        this.addResult(prefix + ": " + stringifiedMessage);
+    }
+}
+
+InjectedTestHarness.AsyncTestSuite = class AsyncTestSuite
+{
+    constructor(harness, name) {
+        if (!(harness instanceof InjectedTestHarness))
+            throw new Error("Must pass the test's harness as the first argument.");
+
+        if (!name || typeof name !== "string")
+            throw new Error("Tried to create AsyncTestSuite without string suite name.");
+
+        this.name = name;
+        this._harness = harness;
+
+        this.testcases = [];
+        this.runCount = 0;
+        this.failCount = 0;
+    }
+
+    get passCount()
+    {
+        return this.runCount - this.failCount;
+    }
+
+    get skipCount()
+    {
+        if (this.failCount)
+            return this.testcases.length - this.runCount;
+        else
+            return 0;
+    }
+
+    addTestCase(testcase)
+    {
+        if (!testcase || !(testcase instanceof Object))
+            throw new Error("Tried to add non-object test case.");
+
+        if (typeof testcase.name !== "string")
+            throw new Error("Tried to add test case without a name.");
+
+        if (typeof testcase.test !== "function")
+            throw new Error("Tried to add test case without `test` function.");
+
+        this.testcases.push(testcase);
+    }
+
+    // Use this if the test file only has one suite, and no handling
+    // of the promise returned by runTestCases() is needed.
+    runTestCasesAndFinish()
+    {
+        function finish() {
+            this._harness.completeTest();
+        }
+
+        this.runTestCases()
+            .then(finish.bind(this))
+            .catch(finish.bind(this));
+    }
+
+    runTestCases()
+    {
+        if (!this.testcases.length)
+            throw new Error("Tried to call runTestCases() for suite with no test cases");
+        if (this._startedRunning)
+            throw new Error("Tried to call runTestCases() more than once.");
+
+        this._startedRunning = true;
+
+        this._harness.log("");
+        this._harness.log("== Running test suite: " + this.name);
+
+        // Avoid adding newlines if nothing was logged.
+        var priorLogCount = this._harness.logCount;
+        var suite = this;
+        var result = this.testcases.reduce(function(chain, testcase, i) {
+            return chain.then(function() {
+                if (i > 0 && priorLogCount + 1 < suite._harness.logCount)
+                    suite._harness.log("");
+
+                priorLogCount = suite._harness.logCount;
+                suite._harness.log("-- Running test case: " + testcase.name);
+                suite.runCount++;
+                return new Promise(testcase.test);
+            });
+        }, Promise.resolve());
+
+        return result.catch(function(e) {
+            suite.failCount++;
+            var message = e;
+            if (e instanceof Error)
+                message = e.message;
+
+            if (typeof message !== "string")
+                message = JSON.stringify(message);
+
+            suite._harness.log("!! EXCEPTION: " + message);
+            throw e; // Reject this promise by re-throwing the error.
+        });
+    }
+}
+
+InjectedTestHarness.SyncTestSuite = class SyncTestSuite
+{
+    constructor(harness, name) {
+        if (!(harness instanceof InjectedTestHarness))
+            throw new Error("Must pass the test's harness as the first argument.");
+
+        if (!name || typeof name !== "string")
+            throw new Error("Tried to create SyncTestSuite without string suite name.");
+
+        this.name = name;
+        this._harness = harness;
+
+        this.testcases = [];
+        this.runCount = 0;
+        this.failCount = 0;
+    }
+
+    get passCount()
+    {
+        return this.runCount - this.failCount;
+    }
+
+    get skipCount()
+    {
+        if (this.failCount)
+            return this.testcases.length - this.runCount;
+        else
+            return 0;
+    }
+
+    addTestCase(testcase)
+    {
+        if (!testcase || !(testcase instanceof Object))
+            throw new Error("Tried to add non-object test case.");
+
+        if (typeof testcase.name !== "string")
+            throw new Error("Tried to add test case without a name.");
+
+        if (typeof testcase.test !== "function")
+            throw new Error("Tried to add test case without `test` function.");
+
+        this.testcases.push(testcase);
+    }
+
+    // Use this if the test file only has one suite.
+    runTestCasesAndFinish()
+    {
+        this.runTestCases();
+        this._harness.completeTest();
+    }
+
+    runTestCases()
+    {
+        if (!this.testcases.length)
+            throw new Error("Tried to call runTestCases() for suite with no test cases");
+        if (this._startedRunning)
+            throw new Error("Tried to call runTestCases() more than once.");
+
+        this._startedRunning = true;
+
+        this._harness.log("");
+        this._harness.log("== Running test suite: " + this.name);
+
+        var priorLogCount = this._harness.logCount;
+        var suite = this;
+        for (var i = 0; i < this.testcases.length; i++) {
+            var testcase = this.testcases[i];
+            if (i > 0 && priorLogCount + 1 < this._harness.logCount)
+                this._harness.log("");
+
+            priorLogCount = this._harness.logCount;
+
+            this._harness.log("-- Running test case: " + testcase.name);
+            suite.runCount++;
+            try {
+                var result = testcase.test.call(null);
+                if (result === false) {
+                    suite.failCount++;
+                    return false;
+                }
+            } catch (e) {
+                suite.failCount++;
+                var message = e;
+                if (e instanceof Error)
+                    message = e.message;
+                else
+                    e = new Error(e);
+
+                if (typeof message !== "string")
+                    message = JSON.stringify(message);
+
+                this._harness.log("!! EXCEPTION: " + message);
+                return false;
+            }
+        }
+
+        return true;
+    }
+}
+
+class ProtocolTestHarness extends InjectedTestHarness
+{
+    // InjectedTestHarness Overrides
+
+    completeTest()
+    {
+        this.evaluateInPage("closeTest();");
+    }
+
+    addResult(message)
+    {
+        // Unfortunately, every string argument must be escaped because tests are not consistent
+        // with respect to escaping with single or double quotes. Some exceptions use single quotes.
+        var stringifiedMessage = typeof message !== "string" ? JSON.stringify(message) : message;
+        this.evaluateInPage("log(unescape('" + escape(stringifiedMessage) + "'));");
+    }
+
+    debugLog(message)
+    {
+        var stringifiedMessage = typeof message !== "string" ? JSON.stringify(message) : message;
+        this.evaluateInPage("debugLog(unescape('" + escape(stringifiedMessage) + "'));")
+    }
+
+    evaluateInPage(_expression_, callback)
+    {
+        let args = {
+            method: "Runtime.evaluate",
+            params: {_expression_}
+        }
+
+        if (typeof callback === "function")
+            InspectorProtocol.sendCommand(args, callback);
+        else
+            return InspectorProtocol.awaitCommand(args);
+    }
+}
+
+window.ProtocolTest = new ProtocolTestHarness();
+
+InspectorProtocol = {};
+InspectorProtocol._dispatchTable = [];
+InspectorProtocol._requestId = -1;
+InspectorProtocol.eventHandler = {};
+
+InspectorProtocol.dumpInspectorProtocolMessages = false;
+
+InspectorProtocol.sendCommand = function(methodOrObject, params, handler)
+{
+    // Allow new-style arguments object, as in awaitCommand.
+    var method = methodOrObject;
+    if (typeof methodOrObject === "object")
+        var {method, params, handler} = methodOrObject;
+
+    this._dispatchTable[++this._requestId] = handler;
+    var messageObject = {method, params, "id": this._requestId};
+    this.sendMessage(messageObject);
+
+    return this._requestId;
+}
+
+InspectorProtocol.awaitCommand = function(args)
+{
+    var {method, params} = args;
+    return new Promise(function(resolve, reject) {
+        this._dispatchTable[++this._requestId] = {resolve, reject};
+        var messageObject = {method, params, "id": this._requestId};
+        this.sendMessage(messageObject);
+    }.bind(this));
+}
+
+InspectorProtocol.awaitEvent = function(args)
+{
+    var {event} = args;
+    if (typeof event !== "string")
+        throw new Error("Event must be a string.");
+
+    return new Promise(function(resolve, reject) {
+        InspectorProtocol.eventHandler[event] = function(message) {
+            InspectorProtocol.eventHandler[event] = undefined;
+            resolve(message);
+        }
+    });
+}
+
+InspectorProtocol.addEventListener = function(eventTypeOrObject, listener)
+{
+    var event = eventTypeOrObject;
+    if (typeof eventTypeOrObject === "object")
+        var {event, listener} = eventTypeOrObject;
+
+    if (typeof event !== "string")
+        throw new Error("Event name must be a string.");
+
+    if (typeof listener !== "function")
+        throw new Error("Event listener must be callable.");
+
+    // Convert to an array of listeners.
+    var listeners = InspectorProtocol.eventHandler[event];
+    if (!listeners)
+        listeners = InspectorProtocol.eventHandler[event] = [];
+    else if (typeof listeners === "function")
+        listeners = InspectorProtocol.eventHandler[event] = [listeners];
+
+    // Prevent registering multiple times.
+    if (listeners.includes(listener))
+        throw new Error("Cannot register the same listener more than once.");
+
+    listeners.push(listener);
+}
+
+InspectorProtocol.sendMessage = function(messageObject)
+{
+    // This matches the debug dumping in InspectorBackend, which is bypassed
+    // by InspectorProtocol. Return messages should be dumped by InspectorBackend.
+    if (InspectorProtocol.dumpInspectorProtocolMessages)
+        console.log("frontend: " + JSON.stringify(messageObject));
+
+    InspectorFrontendHost.sendMessageToBackend(JSON.stringify(messageObject));
+}
+
+InspectorProtocol.checkForError = function(responseObject)
+{
+    if (responseObject.error) {
+        ProtocolTest.log("PROTOCOL ERROR: " + JSON.stringify(responseObject.error));
+        ProtocolTest.completeTest();
+        throw "PROTOCOL ERROR";
+    }
+}
+
+InspectorFrontendAPI.dispatchMessageAsync = function(messageObject)
+{
+    // This matches the debug dumping in InspectorBackend, which is bypassed
+    // by InspectorProtocol. Return messages should be dumped by InspectorBackend.
+    if (InspectorProtocol.dumpInspectorProtocolMessages)
+        console.log("backend: " + JSON.stringify(messageObject));
+
+    // If the message has an id, then it is a reply to a command.
+    var messageId = messageObject["id"];
+    if (typeof messageId === "number") {
+        var handler = InspectorProtocol._dispatchTable[messageId];
+        if (!handler)
+            return;
+
+        if (typeof handler === "function")
+            handler(messageObject);
+        else if (typeof handler === "object") {
+            var {resolve, reject} = handler;
+            if ("error" in messageObject)
+                reject(messageObject.error.message);
+            else
+                resolve(messageObject.result);
+        }
+    // Otherwise, it is an event.
+    } else {
+        var eventName = messageObject["method"];
+        var handler = InspectorProtocol.eventHandler[eventName];
+        if (!handler)
+            return;
+
+        if (typeof handler === "function")
+            handler(messageObject);
+        else if (handler instanceof Array) {
+            handler.map(function(listener) {
+                listener.call(null, messageObject);
+            });
+        } else if (typeof handler === "object") {
+            var {resolve, reject} = handler;
+            if ("error" in messageObject)
+                reject(messageObject.error.message);
+            else
+                resolve(messageObject.result);
+        }
+    }
+}
+
+window.addEventListener("message", function(event) {
+    try {
+        eval(event.data);
+    } catch (e) {
+        alert(e.stack);
+        ProtocolTest.completeTest();
+        throw e;
+    }
+});
\ No newline at end of file

Copied: trunk/Source/WebInspectorUI/UserInterface/TestStub.html (from rev 188538, trunk/LayoutTests/http/tests/inspector/resources/ProtocolTestStub.html) (0 => 188539)


--- trunk/Source/WebInspectorUI/UserInterface/TestStub.html	                        (rev 0)
+++ trunk/Source/WebInspectorUI/UserInterface/TestStub.html	2015-08-17 20:33:48 UTC (rev 188539)
@@ -0,0 +1,29 @@
+<!--
+Copyright (C) 2015 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 AND ITS CONTRIBUTORS "AS IS" AND ANY
+EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+DISCLAIMED. IN NO EVENT SHALL APPLE OR ITS CONTRIBUTORS BE LIABLE FOR ANY
+DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+-->
+<html>
+<head>
+    <script type="text/_javascript_" src=""
+</head>
+</html>

Modified: trunk/Tools/ChangeLog (188538 => 188539)


--- trunk/Tools/ChangeLog	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/Tools/ChangeLog	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1,3 +1,35 @@
+2015-08-17  Brian Burg  <[email protected]>
+
+        Web Inspector: load ProtocolTestStub from the WebInspectorUI bundle
+        https://bugs.webkit.org/show_bug.cgi?id=147955
+
+        Reviewed by Timothy Hatcher.
+
+        To enable sharing of common test code between protocol and model tests,
+        start loading the protocol TestStub.js through the WebInspectorUI bundle.
+
+        This patch adds the read-only getter TestRunner.inspectorTestStubURL, which
+        protocol-test.js uses to load the inspector frontend stub into its iframe
+        from an arbitrary local file URL.
+
+        * DumpRenderTree/TestRunner.cpp:
+        (getInspectorTestStubURLCallback):
+        (TestRunner::staticValues):
+        * DumpRenderTree/TestRunner.h:
+        * DumpRenderTree/mac/TestRunnerMac.mm:
+        (SOFT_LINK_STAGED_FRAMEWORK):
+        (TestRunner::inspectorTestStubURL):
+        * DumpRenderTree/win/TestRunnerWin.cpp:
+        (TestRunner::inspectorTestStubURL):
+        * WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl:
+        * WebKitTestRunner/InjectedBundle/TestRunner.h:
+        * WebKitTestRunner/InjectedBundle/efl/TestRunnerEfl.cpp:
+        (WTR::TestRunner::inspectorTestStubURL):
+        * WebKitTestRunner/InjectedBundle/gtk/TestRunnerGtk.cpp:
+        (WTR::TestRunner::inspectorTestStubURL):
+        * WebKitTestRunner/InjectedBundle/mac/TestRunnerMac.mm:
+        (WTR::TestRunner::inspectorTestStubURL):
+
 2015-08-17  Saam barati  <[email protected]>
 
         Change email address from [email protected] to [email protected]

Modified: trunk/Tools/DumpRenderTree/TestRunner.cpp (188538 => 188539)


--- trunk/Tools/DumpRenderTree/TestRunner.cpp	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/Tools/DumpRenderTree/TestRunner.cpp	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1790,6 +1790,13 @@
     return JSValueMakeString(context, titleDirection.get());
 }
 
+static JSValueRef getInspectorTestStubURLCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef* exception)
+{
+    TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
+    JSRetainPtr<JSStringRef> url(Adopt, controller->inspectorTestStubURL());
+    return JSValueMakeString(context, url.get());
+}
+
 static bool setGlobalFlagCallback(JSContextRef context, JSObjectRef thisObject, JSStringRef propertyName, JSValueRef value, JSValueRef* exception)
 {
     TestRunner* controller = static_cast<TestRunner*>(JSObjectGetPrivate(thisObject));
@@ -1983,6 +1990,7 @@
         { "titleTextDirection", getTitleTextDirectionCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { "databaseDefaultQuota", getDatabaseDefaultQuotaCallback, setDatabaseDefaultQuotaCallback, kJSPropertyAttributeNone },
         { "databaseMaxQuota", getDatabaseMaxQuotaCallback, setDatabaseMaxQuotaCallback, kJSPropertyAttributeNone },
+        { "inspectorTestStubURL", getInspectorTestStubURLCallback, 0, kJSPropertyAttributeReadOnly | kJSPropertyAttributeDontDelete },
         { 0, 0, 0, 0 }
     };
     return staticValues;

Modified: trunk/Tools/DumpRenderTree/TestRunner.h (188538 => 188539)


--- trunk/Tools/DumpRenderTree/TestRunner.h	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/Tools/DumpRenderTree/TestRunner.h	2015-08-17 20:33:48 UTC (rev 188539)
@@ -308,6 +308,8 @@
     void showWebInspector();
     void closeWebInspector();
     void evaluateInWebInspector(JSStringRef script);
+    JSStringRef inspectorTestStubURL();
+
     void evaluateScriptInIsolatedWorld(unsigned worldID, JSObjectRef globalObject, JSStringRef script);
     void evaluateScriptInIsolatedWorldAndReturnValue(unsigned worldID, JSObjectRef globalObject, JSStringRef script);
 

Modified: trunk/Tools/DumpRenderTree/mac/TestRunnerMac.mm (188538 => 188539)


--- trunk/Tools/DumpRenderTree/mac/TestRunnerMac.mm	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/Tools/DumpRenderTree/mac/TestRunnerMac.mm	2015-08-17 20:33:48 UTC (rev 188539)
@@ -43,6 +43,7 @@
 #import <_javascript_Core/JSStringRef.h>
 #import <_javascript_Core/JSStringRefCF.h>
 #import <WebCore/GeolocationPosition.h>
+#import <WebCore/SoftLinking.h>
 #import <WebKit/DOMDocument.h>
 #import <WebKit/DOMElement.h>
 #import <WebKit/DOMHTMLInputElementPrivate.h>
@@ -88,6 +89,8 @@
 #import <WebKit/WebDOMOperationsPrivate.h>
 #endif
 
+SOFT_LINK_STAGED_FRAMEWORK(WebInspectorUI, PrivateFrameworks, A)
+
 #if !PLATFORM(IOS)
 @interface CommandValidationTarget : NSObject <NSValidatedUserInterfaceItem>
 {
@@ -780,6 +783,23 @@
     [[[mainFrame webView] inspector] evaluateInFrontend:nil script:scriptNS];
 }
 
+JSStringRef TestRunner::inspectorTestStubURL()
+{
+    // Call the soft link framework function to dlopen it, then CFBundleGetBundleWithIdentifier will work.
+    WebInspectorUILibrary();
+
+    CFBundleRef inspectorBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.WebInspectorUI"));
+    if (!inspectorBundle)
+        return nullptr;
+
+    RetainPtr<CFURLRef> url = "" CFSTR("TestStub"), CFSTR("html"), NULL));
+    if (!url)
+        return nullptr;
+
+    CFStringRef urlString = CFURLGetString(url.get());
+    return JSStringCreateWithCFString(urlString);
+}
+
 typedef HashMap<unsigned, RetainPtr<WebScriptWorld> > WorldMap;
 static WorldMap& worldMap()
 {

Modified: trunk/Tools/DumpRenderTree/win/TestRunnerWin.cpp (188538 => 188539)


--- trunk/Tools/DumpRenderTree/win/TestRunnerWin.cpp	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/Tools/DumpRenderTree/win/TestRunnerWin.cpp	2015-08-17 20:33:48 UTC (rev 188539)
@@ -1093,6 +1093,15 @@
     inspectorPrivate->evaluateInFrontend(bstrT(script).GetBSTR());
 }
 
+JSStringRef TestRunner::inspectorTestStubURL()
+{
+    // FIXME: Implement this to support Web Inspector tests using `protocol-test.js`.
+    // See https://bugs.webkit.org/show_bug.cgi?id=148025.
+    printf("ERROR: TestRunner::inspectorTestStubURL() not implemented\n");
+
+    return nullptr;
+}
+
 typedef HashMap<unsigned, COMPtr<IWebScriptWorld> > WorldMap;
 static WorldMap& worldMap()
 {

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl (188538 => 188539)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/Bindings/TestRunner.idl	2015-08-17 20:33:48 UTC (rev 188539)
@@ -125,6 +125,7 @@
     void showWebInspector();
     void closeWebInspector();
     void evaluateInWebInspector(DOMString script);
+    readonly attribute DOMString inspectorTestStubURL;
 
     void setPOSIXLocale(DOMString locale);
 

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h (188538 => 188539)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/TestRunner.h	2015-08-17 20:33:48 UTC (rev 188539)
@@ -199,6 +199,7 @@
     void showWebInspector();
     void closeWebInspector();
     void evaluateInWebInspector(JSStringRef script);
+    JSRetainPtr<JSStringRef> inspectorTestStubURL();
 
     void setPOSIXLocale(JSStringRef);
 

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/efl/TestRunnerEfl.cpp (188538 => 188539)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/efl/TestRunnerEfl.cpp	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/efl/TestRunnerEfl.cpp	2015-08-17 20:33:48 UTC (rev 188539)
@@ -23,7 +23,9 @@
 #include "InjectedBundle.h"
 #include <Ecore.h>
 #include <_javascript_Core/OpaqueJSString.h>
+#include <WebCore/EflInspectorUtilities.h>
 #include <wtf/text/CString.h>
+#include <wtf/text/StringBuilder.h>
 #include <wtf/text/WTFString.h>
 
 namespace WTR {
@@ -82,4 +84,14 @@
     return JSStringCreateWithUTF8CString(fullPathToUrl.utf8().data());
 }
 
+JSRetainPtr<JSStringRef> TestRunner::inspectorTestStubURL()
+{
+    StringBuilder builder;
+    builder.append("file://");
+    builder.append(WebCore::inspectorResourcePath());
+    builder.appendLiteral("/TestStub.html");
+
+    return JSStringCreateWithUTF8CString(builder.toString().utf8().data());
+}
+
 } // namespace WTR

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/gtk/TestRunnerGtk.cpp (188538 => 188539)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/gtk/TestRunnerGtk.cpp	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/gtk/TestRunnerGtk.cpp	2015-08-17 20:33:48 UTC (rev 188539)
@@ -67,4 +67,9 @@
     return JSStringCreateWithUTF8CString(testURI.get());
 }
 
+JSRetainPtr<JSStringRef> TestRunner::inspectorTestStubURL()
+{
+    return JSStringCreateWithUTF8CString("resource:///org/webkitgtk/inspector/UserInterface/TestStub.html");
+}
+
 } // namespace WTR

Modified: trunk/Tools/WebKitTestRunner/InjectedBundle/mac/TestRunnerMac.mm (188538 => 188539)


--- trunk/Tools/WebKitTestRunner/InjectedBundle/mac/TestRunnerMac.mm	2015-08-17 20:29:09 UTC (rev 188538)
+++ trunk/Tools/WebKitTestRunner/InjectedBundle/mac/TestRunnerMac.mm	2015-08-17 20:33:48 UTC (rev 188539)
@@ -26,7 +26,11 @@
 #include "TestRunner.h"
 
 #include "InjectedBundle.h"
+#include <_javascript_Core/JSStringRefCF.h>
+#include <WebCore/SoftLinking.h>
 
+SOFT_LINK_STAGED_FRAMEWORK(WebInspectorUI, PrivateFrameworks, A)
+
 namespace WTR {
 
 void TestRunner::platformInitialize()
@@ -62,4 +66,21 @@
     return JSStringRetain(url); // Do nothing on mac.
 }
 
+JSRetainPtr<JSStringRef> TestRunner::inspectorTestStubURL()
+{
+    // Call the soft link framework function to dlopen it, then CFBundleGetBundleWithIdentifier will work.
+    WebInspectorUILibrary();
+
+    CFBundleRef inspectorBundle = CFBundleGetBundleWithIdentifier(CFSTR("com.apple.WebInspectorUI"));
+    if (!inspectorBundle)
+        return nullptr;
+
+    RetainPtr<CFURLRef> url = "" CFSTR("TestStub"), CFSTR("html"), NULL));
+    if (!url)
+        return nullptr;
+
+    CFStringRef urlString = CFURLGetString(url.get());
+    return adopt(JSStringCreateWithCFString(urlString));
+}
+
 } // namespace WTR
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to