diff options
Diffstat (limited to 'Source/WebKit/chromium/src/js')
13 files changed, 1145 insertions, 0 deletions
diff --git a/Source/WebKit/chromium/src/js/DevTools.js b/Source/WebKit/chromium/src/js/DevTools.js new file mode 100644 index 0000000..d6536bc --- /dev/null +++ b/Source/WebKit/chromium/src/js/DevTools.js @@ -0,0 +1,190 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +/** + * FIXME: change field naming style to use trailing underscore. + * @fileoverview Tools is a main class that wires all components of the + * DevTools frontend together. It is also responsible for overriding existing + * WebInspector functionality while it is getting upstreamed into WebCore. + */ + +var context = {}; // Used by WebCore's inspector routines. + +(function () { + Preferences.ignoreWhitespace = false; + Preferences.samplingCPUProfiler = true; + Preferences.heapProfilerPresent = true; + Preferences.debuggerAlwaysEnabled = true; + Preferences.profilerAlwaysEnabled = true; + Preferences.canEditScriptSource = true; + Preferences.onlineDetectionEnabled = false; + Preferences.nativeInstrumentationEnabled = true; + Preferences.fileSystemEnabled = false; + Preferences.resourceExportEnabled = true; + Preferences.showTimingTab = true; + Preferences.showCookiesTab = true; +})(); + +var devtools = devtools || {}; + +devtools.domContentLoaded = function() +{ + WebInspector.setAttachedWindow(WebInspector.queryParamsObject.docked === "true"); + if (WebInspector.queryParamsObject.toolbar_color && WebInspector.queryParamsObject.text_color) + WebInspector.setToolbarColors(WebInspector.queryParamsObject.toolbar_color, WebInspector.queryParamsObject.text_color); +} +document.addEventListener("DOMContentLoaded", devtools.domContentLoaded, false); + + +// FIXME: This needs to be upstreamed. +(function InterceptProfilesPanelEvents() +{ + var oldShow = WebInspector.ProfilesPanel.prototype.show; + WebInspector.ProfilesPanel.prototype.show = function() + { + this.enableToggleButton.visible = false; + oldShow.call(this); + // Show is called on every show event of a panel, so + // we only need to intercept it once. + WebInspector.ProfilesPanel.prototype.show = oldShow; + }; +})(); + + +/* + * @override + * TODO(mnaganov): Restore l10n when it will be agreed that it is needed. + */ +WebInspector.UIString = function(string) +{ + return String.vsprintf(string, Array.prototype.slice.call(arguments, 1)); +}; + + +/** Pending WebKit upstream by apavlov). Fixes iframe vs drag problem. */ +(function() +{ + var originalDragStart = WebInspector.elementDragStart; + WebInspector.elementDragStart = function(element) + { + if (element) { + var glassPane = document.createElement("div"); + glassPane.style.cssText = "position:absolute;width:100%;height:100%;opacity:0;z-index:1"; + glassPane.id = "glass-pane-for-drag"; + element.parentElement.appendChild(glassPane); + } + + originalDragStart.apply(this, arguments); + }; + + var originalDragEnd = WebInspector.elementDragEnd; + WebInspector.elementDragEnd = function() + { + originalDragEnd.apply(this, arguments); + + var glassPane = document.getElementById("glass-pane-for-drag"); + if (glassPane) + glassPane.parentElement.removeChild(glassPane); + }; +})(); + + + +/////////////////////////////////////////// +// Chromium layout test harness support. // +/////////////////////////////////////////// + +WebInspector.runAfterPendingDispatchesQueue = []; + +WebInspector.TestController.prototype.runAfterPendingDispatches = function(callback) +{ + WebInspector.runAfterPendingDispatchesQueue.push(callback); +}; + +WebInspector.queuesAreEmpty = function() +{ + var copy = this.runAfterPendingDispatchesQueue.slice(); + this.runAfterPendingDispatchesQueue = []; + for (var i = 0; i < copy.length; ++i) + copy[i].call(this); +}; + + +///////////////////////////// +// Chromium theme support. // +///////////////////////////// + +WebInspector.setToolbarColors = function(backgroundColor, color) +{ + if (!WebInspector._themeStyleElement) { + WebInspector._themeStyleElement = document.createElement("style"); + document.head.appendChild(WebInspector._themeStyleElement); + } + WebInspector._themeStyleElement.textContent = + "#toolbar {\ + background-image: none !important;\ + background-color: " + backgroundColor + " !important;\ + }\ + \ + .toolbar-label {\ + color: " + color + " !important;\ + text-shadow: none;\ + }"; +} + +WebInspector.resetToolbarColors = function() +{ + if (WebInspector._themeStyleElement) + WebInspector._themeStyleElement.textContent = ""; + +} + +//////////////////////////////////////////////////////// +// Platform-specific WebInspector extensions support. // +//////////////////////////////////////////////////////// + +WebInspector.platformExtensionAPI = function(tabId) +{ + function getTabId() + { + return tabId; + } + webInspector.inspectedWindow.__proto__.__defineGetter__("tabId", getTabId); +} + +WebInspector.buildPlatformExtensionAPI = function() +{ + return "(" + WebInspector.platformExtensionAPI + ")(" + WebInspector._inspectedTabId + ");"; +} + +WebInspector.setInspectedTabId = function(tabId) +{ + WebInspector._inspectedTabId = tabId; +} diff --git a/Source/WebKit/chromium/src/js/Images/segmentChromium.png b/Source/WebKit/chromium/src/js/Images/segmentChromium.png Binary files differnew file mode 100755 index 0000000..f4248e1 --- /dev/null +++ b/Source/WebKit/chromium/src/js/Images/segmentChromium.png diff --git a/Source/WebKit/chromium/src/js/Images/segmentHoverChromium.png b/Source/WebKit/chromium/src/js/Images/segmentHoverChromium.png Binary files differnew file mode 100755 index 0000000..0a743d9 --- /dev/null +++ b/Source/WebKit/chromium/src/js/Images/segmentHoverChromium.png diff --git a/Source/WebKit/chromium/src/js/Images/segmentHoverEndChromium.png b/Source/WebKit/chromium/src/js/Images/segmentHoverEndChromium.png Binary files differnew file mode 100755 index 0000000..cf62072 --- /dev/null +++ b/Source/WebKit/chromium/src/js/Images/segmentHoverEndChromium.png diff --git a/Source/WebKit/chromium/src/js/Images/segmentSelectedChromium.png b/Source/WebKit/chromium/src/js/Images/segmentSelectedChromium.png Binary files differnew file mode 100755 index 0000000..a1f7251 --- /dev/null +++ b/Source/WebKit/chromium/src/js/Images/segmentSelectedChromium.png diff --git a/Source/WebKit/chromium/src/js/Images/segmentSelectedEndChromium.png b/Source/WebKit/chromium/src/js/Images/segmentSelectedEndChromium.png Binary files differnew file mode 100755 index 0000000..07641db --- /dev/null +++ b/Source/WebKit/chromium/src/js/Images/segmentSelectedEndChromium.png diff --git a/Source/WebKit/chromium/src/js/Images/statusbarBackgroundChromium.png b/Source/WebKit/chromium/src/js/Images/statusbarBackgroundChromium.png Binary files differnew file mode 100755 index 0000000..7a760c1 --- /dev/null +++ b/Source/WebKit/chromium/src/js/Images/statusbarBackgroundChromium.png diff --git a/Source/WebKit/chromium/src/js/Images/statusbarBottomBackgroundChromium.png b/Source/WebKit/chromium/src/js/Images/statusbarBottomBackgroundChromium.png Binary files differnew file mode 100755 index 0000000..e3bc944 --- /dev/null +++ b/Source/WebKit/chromium/src/js/Images/statusbarBottomBackgroundChromium.png diff --git a/Source/WebKit/chromium/src/js/Images/statusbarButtonsChromium.png b/Source/WebKit/chromium/src/js/Images/statusbarButtonsChromium.png Binary files differnew file mode 100755 index 0000000..136d5a8 --- /dev/null +++ b/Source/WebKit/chromium/src/js/Images/statusbarButtonsChromium.png diff --git a/Source/WebKit/chromium/src/js/Images/statusbarMenuButtonChromium.png b/Source/WebKit/chromium/src/js/Images/statusbarMenuButtonChromium.png Binary files differnew file mode 100755 index 0000000..5ff61d9 --- /dev/null +++ b/Source/WebKit/chromium/src/js/Images/statusbarMenuButtonChromium.png diff --git a/Source/WebKit/chromium/src/js/Images/statusbarMenuButtonSelectedChromium.png b/Source/WebKit/chromium/src/js/Images/statusbarMenuButtonSelectedChromium.png Binary files differnew file mode 100755 index 0000000..3c0aeec --- /dev/null +++ b/Source/WebKit/chromium/src/js/Images/statusbarMenuButtonSelectedChromium.png diff --git a/Source/WebKit/chromium/src/js/Tests.js b/Source/WebKit/chromium/src/js/Tests.js new file mode 100644 index 0000000..f2e8dcb --- /dev/null +++ b/Source/WebKit/chromium/src/js/Tests.js @@ -0,0 +1,838 @@ +/* + * Copyright (C) 2010 Google Inc. All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above + * copyright notice, this list of conditions and the following disclaimer + * in the documentation and/or other materials provided with the + * distribution. + * * Neither the name of Google Inc. nor the names of its + * contributors may be used to endorse or promote products derived from + * this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT + * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, + * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY + * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + + +/** + * @fileoverview This file contains small testing framework along with the + * test suite for the frontend. These tests are a part of the continues build + * and are executed by the devtools_sanity_unittest.cc as a part of the + * Interactive UI Test suite. + * FIXME: change field naming style to use trailing underscore. + */ + +if (window.domAutomationController) { + +var ___interactiveUiTestsMode = true; + +/** + * Test suite for interactive UI tests. + * @constructor + */ +TestSuite = function() +{ + this.controlTaken_ = false; + this.timerId_ = -1; +}; + + +/** + * Reports test failure. + * @param {string} message Failure description. + */ +TestSuite.prototype.fail = function(message) +{ + if (this.controlTaken_) + this.reportFailure_(message); + else + throw message; +}; + + +/** + * Equals assertion tests that expected === actual. + * @param {Object} expected Expected object. + * @param {Object} actual Actual object. + * @param {string} opt_message User message to print if the test fails. + */ +TestSuite.prototype.assertEquals = function(expected, actual, opt_message) +{ + if (expected !== actual) { + var message = "Expected: '" + expected + "', but was '" + actual + "'"; + if (opt_message) + message = opt_message + "(" + message + ")"; + this.fail(message); + } +}; + + +/** + * True assertion tests that value == true. + * @param {Object} value Actual object. + * @param {string} opt_message User message to print if the test fails. + */ +TestSuite.prototype.assertTrue = function(value, opt_message) +{ + this.assertEquals(true, !!value, opt_message); +}; + + +/** + * Contains assertion tests that string contains substring. + * @param {string} string Outer. + * @param {string} substring Inner. + */ +TestSuite.prototype.assertContains = function(string, substring) +{ + if (string.indexOf(substring) === -1) + this.fail("Expected to: '" + string + "' to contain '" + substring + "'"); +}; + + +/** + * Takes control over execution. + */ +TestSuite.prototype.takeControl = function() +{ + this.controlTaken_ = true; + // Set up guard timer. + var self = this; + this.timerId_ = setTimeout(function() { + self.reportFailure_("Timeout exceeded: 20 sec"); + }, 20000); +}; + + +/** + * Releases control over execution. + */ +TestSuite.prototype.releaseControl = function() +{ + if (this.timerId_ !== -1) { + clearTimeout(this.timerId_); + this.timerId_ = -1; + } + this.reportOk_(); +}; + + +/** + * Async tests use this one to report that they are completed. + */ +TestSuite.prototype.reportOk_ = function() +{ + window.domAutomationController.send("[OK]"); +}; + + +/** + * Async tests use this one to report failures. + */ +TestSuite.prototype.reportFailure_ = function(error) +{ + if (this.timerId_ !== -1) { + clearTimeout(this.timerId_); + this.timerId_ = -1; + } + window.domAutomationController.send("[FAILED] " + error); +}; + + +/** + * Runs all global functions starting with "test" as unit tests. + */ +TestSuite.prototype.runTest = function(testName) +{ + try { + this[testName](); + if (!this.controlTaken_) + this.reportOk_(); + } catch (e) { + this.reportFailure_(e); + } +}; + + +/** + * @param {string} panelName Name of the panel to show. + */ +TestSuite.prototype.showPanel = function(panelName) +{ + // Open Scripts panel. + var toolbar = document.getElementById("toolbar"); + var button = toolbar.getElementsByClassName(panelName)[0]; + button.click(); + this.assertEquals(WebInspector.panels[panelName], WebInspector.currentPanel); +}; + + +/** + * Overrides the method with specified name until it's called first time. + * @param {Object} receiver An object whose method to override. + * @param {string} methodName Name of the method to override. + * @param {Function} override A function that should be called right after the + * overriden method returns. + * @param {boolean} opt_sticky Whether restore original method after first run + * or not. + */ +TestSuite.prototype.addSniffer = function(receiver, methodName, override, opt_sticky) +{ + var orig = receiver[methodName]; + if (typeof orig !== "function") + this.fail("Cannot find method to override: " + methodName); + var test = this; + receiver[methodName] = function(var_args) { + try { + var result = orig.apply(this, arguments); + } finally { + if (!opt_sticky) + receiver[methodName] = orig; + } + // In case of exception the override won't be called. + try { + override.apply(this, arguments); + } catch (e) { + test.fail("Exception in overriden method '" + methodName + "': " + e); + } + return result; + }; +}; + + +TestSuite.prototype.testEnableResourcesTab = function() +{ + // FIXME once reference is removed downstream. +} + +TestSuite.prototype.testCompletionOnPause = function() +{ + // FIXME once reference is removed downstream. +} + +// UI Tests + + +/** + * Tests that profiler works. + */ +TestSuite.prototype.testProfilerTab = function() +{ + this.showPanel("profiles"); + + var panel = WebInspector.panels.profiles; + var test = this; + + function findDisplayedNode() { + var node = panel.visibleView.profileDataGridTree.children[0]; + if (!node) { + // Profile hadn't been queried yet, re-schedule. + window.setTimeout(findDisplayedNode, 100); + return; + } + + // Iterate over displayed functions and search for a function + // that is called "fib" or "eternal_fib". If found, this will mean + // that we actually have profiled page's code. + while (node) { + if (node.functionName.indexOf("fib") !== -1) + test.releaseControl(); + node = node.traverseNextNode(true, null, true); + } + + test.fail(); + } + + function findVisibleView() { + if (!panel.visibleView) { + setTimeout(findVisibleView, 0); + return; + } + setTimeout(findDisplayedNode, 0); + } + + findVisibleView(); + this.takeControl(); +}; + + +/** + * Tests that heap profiler works. + */ +TestSuite.prototype.testHeapProfiler = function() +{ + this.showPanel("profiles"); + + var panel = WebInspector.panels.profiles; + var test = this; + + function findDisplayedNode() { + var node = panel.visibleView.dataGrid.children[0]; + if (!node) { + // Profile hadn't been queried yet, re-schedule. + window.setTimeout(findDisplayedNode, 100); + return; + } + + // Iterate over displayed functions and find node called "A" + // If found, this will mean that we actually have taken heap snapshot. + while (node) { + if (node.constructorName.indexOf("A") !== -1) { + test.releaseControl(); + return; + } + node = node.traverseNextNode(false, null, true); + } + + test.fail(); + } + + function findVisibleView() { + if (!panel.visibleView) { + setTimeout(findVisibleView, 0); + return; + } + setTimeout(findDisplayedNode, 0); + } + + WebInspector.HeapSnapshotProfileType.prototype.buttonClicked(); + findVisibleView(); + this.takeControl(); +}; + + +/** + * Tests that scripts tab can be open and populated with inspected scripts. + */ +TestSuite.prototype.testShowScriptsTab = function() +{ + this.showPanel("scripts"); + var test = this; + // There should be at least main page script. + this._waitUntilScriptsAreParsed(["debugger_test_page.html"], + function() { + test.releaseControl(); + }); + // Wait until all scripts are added to the debugger. + this.takeControl(); +}; + + +/** + * Tests that scripts tab is populated with inspected scripts even if it + * hadn't been shown by the moment inspected paged refreshed. + * @see http://crbug.com/26312 + */ +TestSuite.prototype.testScriptsTabIsPopulatedOnInspectedPageRefresh = function() +{ + var test = this; + this.assertEquals(WebInspector.panels.elements, WebInspector.currentPanel, "Elements panel should be current one."); + + this.addSniffer(WebInspector.panels.scripts, "reset", waitUntilScriptIsParsed); + + // Reload inspected page. It will reset the debugger agent. + test.evaluateInConsole_( + "window.location.reload(true);", + function(resultText) {}); + + function waitUntilScriptIsParsed() { + test.showPanel("scripts"); + test._waitUntilScriptsAreParsed(["debugger_test_page.html"], + function() { + test.releaseControl(); + }); + } + + // Wait until all scripts are added to the debugger. + this.takeControl(); +}; + + +/** + * Tests that scripts list contains content scripts. + */ +TestSuite.prototype.testContentScriptIsPresent = function() +{ + this.showPanel("scripts"); + var test = this; + + test._waitUntilScriptsAreParsed( + ["page_with_content_script.html", "simple_content_script.js"], + function() { + test.releaseControl(); + }); + + // Wait until all scripts are added to the debugger. + this.takeControl(); +}; + + +/** + * Tests that scripts are not duplicaed on Scripts tab switch. + */ +TestSuite.prototype.testNoScriptDuplicatesOnPanelSwitch = function() +{ + var test = this; + + // There should be two scripts: one for the main page and another + // one which is source of console API(see + // InjectedScript._ensureCommandLineAPIInstalled). + var expectedScriptsCount = 2; + var parsedScripts = []; + + this.showPanel("scripts"); + + + function switchToElementsTab() { + test.showPanel("elements"); + setTimeout(switchToScriptsTab, 0); + } + + function switchToScriptsTab() { + test.showPanel("scripts"); + setTimeout(checkScriptsPanel, 0); + } + + function checkScriptsPanel() { + test.assertTrue(!!WebInspector.panels.scripts.visibleView, "No visible script view."); + test.assertTrue(test._scriptsAreParsed(["debugger_test_page.html"]), "Some scripts are missing."); + checkNoDuplicates(); + test.releaseControl(); + } + + function checkNoDuplicates() { + var scriptSelect = document.getElementById("scripts-files"); + var options = scriptSelect.options; + for (var i = 0; i < options.length; i++) { + var scriptName = options[i].text; + for (var j = i + 1; j < options.length; j++) + test.assertTrue(scriptName !== options[j].text, "Found script duplicates: " + test.optionsToString_(options)); + } + } + + test._waitUntilScriptsAreParsed( + ["debugger_test_page.html"], + function() { + checkNoDuplicates(); + setTimeout(switchToElementsTab, 0); + }); + + + // Wait until all scripts are added to the debugger. + this.takeControl(); +}; + + +// Tests that debugger works correctly if pause event occurs when DevTools +// frontend is being loaded. +TestSuite.prototype.testPauseWhenLoadingDevTools = function() +{ + this.showPanel("scripts"); + var test = this; + + var expectations = { + functionsOnStack: ["callDebugger"], + lineNumber: 8, + lineText: " debugger;" + }; + + + // Script execution can already be paused. + if (WebInspector.currentPanel.paused) { + var callFrame = WebInspector.currentPanel.sidebarPanes.callstack.selectedCallFrame; + this.assertEquals(expectations.functionsOnStack[0], callFrame.functionName); + var callbackInvoked = false; + this._checkSourceFrameWhenLoaded(expectations, function() { + callbackInvoked = true; + if (test.controlTaken_) + test.releaseControl(); + }); + if (!callbackInvoked) { + test.takeControl(); + } + return; + } + + this._waitForScriptPause( + { + functionsOnStack: ["callDebugger"], + lineNumber: 8, + lineText: " debugger;" + }, + function() { + test.releaseControl(); + }); + this.takeControl(); +}; + + +// Tests that pressing "Pause" will pause script execution if the script +// is already running. +TestSuite.prototype.testPauseWhenScriptIsRunning = function() +{ + this.showPanel("scripts"); + var test = this; + + test.evaluateInConsole_( + 'setTimeout("handleClick()" , 0)', + function(resultText) { + test.assertTrue(!isNaN(resultText), "Failed to get timer id: " + resultText); + testScriptPauseAfterDelay(); + }); + + // Wait for some time to make sure that inspected page is running the + // infinite loop. + function testScriptPauseAfterDelay() { + setTimeout(testScriptPause, 300); + } + + function testScriptPause() { + // The script should be in infinite loop. Click "Pause" button to + // pause it and wait for the result. + WebInspector.panels.scripts.pauseButton.click(); + + test._waitForScriptPause( + { + functionsOnStack: ["handleClick", ""], + lineNumber: 5, + lineText: " while(true) {" + }, + function() { + test.releaseControl(); + }); + } + + this.takeControl(); +}; + + +/** + * Serializes options collection to string. + * @param {HTMLOptionsCollection} options + * @return {string} + */ +TestSuite.prototype.optionsToString_ = function(options) +{ + var names = []; + for (var i = 0; i < options.length; i++) + names.push('"' + options[i].text + '"'); + return names.join(","); +}; + + +/** + * Ensures that main HTML resource is selected in Scripts panel and that its + * source frame is setup. Invokes the callback when the condition is satisfied. + * @param {HTMLOptionsCollection} options + * @param {function(WebInspector.SourceView,string)} callback + */ +TestSuite.prototype.showMainPageScriptSource_ = function(scriptName, callback) +{ + var test = this; + + var scriptSelect = document.getElementById("scripts-files"); + var options = scriptSelect.options; + + test.assertTrue(options.length, "Scripts list is empty"); + + // Select page's script if it's not current option. + var scriptResource; + if (options[scriptSelect.selectedIndex].text === scriptName) + scriptResource = options[scriptSelect.selectedIndex].representedObject; + else { + var pageScriptIndex = -1; + for (var i = 0; i < options.length; i++) { + if (options[i].text === scriptName) { + pageScriptIndex = i; + break; + } + } + test.assertTrue(-1 !== pageScriptIndex, "Script with url " + scriptName + " not found among " + test.optionsToString_(options)); + scriptResource = options[pageScriptIndex].representedObject; + + // Current panel is "Scripts". + WebInspector.currentPanel._showScriptOrResource(scriptResource); + test.assertEquals(pageScriptIndex, scriptSelect.selectedIndex, "Unexpected selected option index."); + } + + test.assertTrue(scriptResource instanceof WebInspector.Resource, + "Unexpected resource class."); + test.assertTrue(!!scriptResource.url, "Resource URL is null."); + test.assertTrue(scriptResource.url.search(scriptName + "$") !== -1, "Main HTML resource should be selected."); + + var scriptsPanel = WebInspector.panels.scripts; + + var view = scriptsPanel.visibleView; + test.assertTrue(view instanceof WebInspector.SourceView); + + if (!view.sourceFrame._loaded) { + test.addSniffer(view, "_sourceFrameSetupFinished", function(event) { + callback(view, scriptResource.url); + }); + } else + callback(view, scriptResource.url); +}; + + +/* + * Evaluates the code in the console as if user typed it manually and invokes + * the callback when the result message is received and added to the console. + * @param {string} code + * @param {function(string)} callback + */ +TestSuite.prototype.evaluateInConsole_ = function(code, callback) +{ + WebInspector.showConsole(); + WebInspector.console.prompt.text = code; + WebInspector.console.promptElement.dispatchEvent( TestSuite.createKeyEvent("Enter")); + + this.addSniffer(WebInspector.ConsoleView.prototype, "addMessage", + function(commandResult) { + callback(commandResult.toMessageElement().textContent); + }); +}; + + +/** + * Checks current execution line against expectations. + * @param {WebInspector.SourceFrame} sourceFrame + * @param {number} lineNumber Expected line number + * @param {string} lineContent Expected line text + */ +TestSuite.prototype._checkExecutionLine = function(sourceFrame, lineNumber, lineContent) +{ + this.assertEquals(lineNumber, sourceFrame.executionLine, "Unexpected execution line number."); + this.assertEquals(lineContent, sourceFrame._textModel.line(lineNumber - 1), "Unexpected execution line text."); +} + + +/** + * Checks that all expected scripts are present in the scripts list + * in the Scripts panel. + * @param {Array.<string>} expected Regular expressions describing + * expected script names. + * @return {boolean} Whether all the scripts are in "scripts-files" select + * box + */ +TestSuite.prototype._scriptsAreParsed = function(expected) +{ + var scriptSelect = document.getElementById("scripts-files"); + var options = scriptSelect.options; + + // Check that at least all the expected scripts are present. + var missing = expected.slice(0); + for (var i = 0 ; i < options.length; i++) { + for (var j = 0; j < missing.length; j++) { + if (options[i].text.search(missing[j]) !== -1) { + missing.splice(j, 1); + break; + } + } + } + return missing.length === 0; +}; + + +/** + * Waits for script pause, checks expectations, and invokes the callback. + * @param {Object} expectations Dictionary of expectations + * @param {function():void} callback + */ +TestSuite.prototype._waitForScriptPause = function(expectations, callback) +{ + var test = this; + // Wait until script is paused. + test.addSniffer( + WebInspector.debuggerModel, + "_pausedScript", + function(details) { + var callFrames = details.callFrames; + var functionsOnStack = []; + for (var i = 0; i < callFrames.length; i++) + functionsOnStack.push(callFrames[i].functionName); + + test.assertEquals(expectations.functionsOnStack.join(","), functionsOnStack.join(","), "Unexpected stack."); + + // Check that execution line where the script is paused is + // expected one. + test._checkSourceFrameWhenLoaded(expectations, callback); + }); +}; + + +/** + * Waits for current source frame to load, checks expectations, and invokes + * the callback. + * @param {Object} expectations Dictionary of expectations + * @param {function():void} callback + */ +TestSuite.prototype._checkSourceFrameWhenLoaded = function(expectations, callback) +{ + var test = this; + + var frame = WebInspector.currentPanel.visibleView.sourceFrame; + if (frame._loaded) + checkExecLine(); + else { + setTimeout(function() { + test._checkSourceFrameWhenLoaded(expectations, callback); + }, 100); + } + function checkExecLine() { + test._checkExecutionLine(frame, expectations.lineNumber, expectations.lineText); + callback(); + } +}; + + +/** + * Waits until all the scripts are parsed and asynchronously executes the code + * in the inspected page. + */ +TestSuite.prototype._executeCodeWhenScriptsAreParsed = function(code, expectedScripts) +{ + var test = this; + + function executeFunctionInInspectedPage() { + // Since breakpoints are ignored in evals' calculate() function is + // execute after zero-timeout so that the breakpoint is hit. + test.evaluateInConsole_( + 'setTimeout("' + code + '" , 0)', + function(resultText) { + test.assertTrue(!isNaN(resultText), "Failed to get timer id: " + resultText + ". Code: " + code); + }); + } + + test._waitUntilScriptsAreParsed(expectedScripts, executeFunctionInInspectedPage); +}; + + +/** + * Waits until all the scripts are parsed and invokes the callback. + */ +TestSuite.prototype._waitUntilScriptsAreParsed = function(expectedScripts, callback) +{ + var test = this; + + function waitForAllScripts() { + if (test._scriptsAreParsed(expectedScripts)) + callback(); + else + test.addSniffer(WebInspector.debuggerModel, "_parsedScriptSource", waitForAllScripts); + } + + waitForAllScripts(); +}; + + +/** + * Executes the 'code' with InjectedScriptAccess.getProperties overriden + * so that all callbacks passed to InjectedScriptAccess.getProperties are + * extended with the "hook". + * @param {Function} hook The hook function. + * @param {Function} code A code snippet to be executed. + */ +TestSuite.prototype._hookGetPropertiesCallback = function(hook, code) +{ + var accessor = InjectedScriptAccess.prototype; + var orig = accessor.getProperties; + accessor.getProperties = function(objectProxy, ignoreHasOwnProperty, abbreviate, callback) { + orig.call(this, objectProxy, ignoreHasOwnProperty, abbreviate, + function() { + callback.apply(this, arguments); + hook(); + }); + }; + try { + code(); + } finally { + accessor.getProperties = orig; + } +}; + + +/** + * Key event with given key identifier. + */ +TestSuite.createKeyEvent = function(keyIdentifier) +{ + var evt = document.createEvent("KeyboardEvent"); + evt.initKeyboardEvent("keydown", true /* can bubble */, true /* can cancel */, null /* view */, keyIdentifier, ""); + return evt; +}; + + +/** + * Test runner for the test suite. + */ +var uiTests = {}; + + +/** + * Run each test from the test suit on a fresh instance of the suite. + */ +uiTests.runAllTests = function() +{ + // For debugging purposes. + for (var name in TestSuite.prototype) { + if (name.substring(0, 4) === "test" && typeof TestSuite.prototype[name] === "function") + uiTests.runTest(name); + } +}; + + +/** + * Run specified test on a fresh instance of the test suite. + * @param {string} name Name of a test method from TestSuite class. + */ +uiTests.runTest = function(name) +{ + if (uiTests._populatedInterface) + new TestSuite().runTest(name); + else + uiTests._pendingTestName = name; +}; + +(function() { + +function runTests() +{ + uiTests._populatedInterface = true; + var name = uiTests._pendingTestName; + delete uiTests._pendingTestName; + if (name) + new TestSuite().runTest(name); +} + +var oldShowElementsPanel = WebInspector.showElementsPanel; +WebInspector.showElementsPanel = function() +{ + oldShowElementsPanel.call(this); + runTests(); +} + +var oldShowPanel = WebInspector.showPanel; +WebInspector.showPanel = function(name) +{ + oldShowPanel.call(this, name); + runTests(); +} + +})(); + +} diff --git a/Source/WebKit/chromium/src/js/devTools.css b/Source/WebKit/chromium/src/js/devTools.css new file mode 100644 index 0000000..64ea9d5 --- /dev/null +++ b/Source/WebKit/chromium/src/js/devTools.css @@ -0,0 +1,117 @@ +.data-grid table { + line-height: 120%; +} + +body.attached #toolbar { + height: 34px; + border-top: 1px solid rgb(100, 100, 100); + cursor: default; /* overriden */ + padding-left: 0; +} + +/* Chrome theme overrides */ + +body.platform-windows #toolbar, body.platform-windows.inactive #toolbar { + background-image: none; +} + +body.detached.platform-mac-leopard #toolbar { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(175, 175, 175)), to(rgb(151, 151, 151))) !important; +} + +body.detached.platform-mac-leopard.inactive #toolbar { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(221, 221, 221)), to(rgb(207, 207, 207))) !important; +} + +body.detached.platform-mac-snowleopard #toolbar { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(189, 189, 189)), to(rgb(151, 151, 151))) !important; +} + +body.detached.platform-mac-snowleopard.inactive #toolbar { + background-image: -webkit-gradient(linear, left top, left bottom, from(rgb(215, 215, 215)), to(rgb(207, 207, 207))) !important; +} + +body.platform-linux #scripts-files { + font-size: 11px; + font-weight: normal; + line-height: 12px; +} + +.console-group-messages .section > .header { + padding: 0 8px 0 0; + background-image: none; + border: none; + min-height: 0; +} + +#resources-filter { + background: -webkit-gradient(linear, left top, left bottom, from(rgb(233, 233, 233)), to(rgb(233, 233, 233))); +} + +.crumbs .crumb { + -webkit-border-image: url(Images/segmentChromium.png) 0 12 0 2; + margin-right: -3px; + padding-left: 6px; +} + +.crumbs .crumb.selected { + -webkit-border-image: url(Images/segmentSelectedChromium.png) 0 12 0 2; + color: white; + text-shadow: rgba(255, 255, 255, 0.5) 0 0px 0; +} + +.crumbs .crumb.selected:hover { + -webkit-border-image: url(Images/segmentSelectedChromium.png) 0 12 0 2; +} + +.crumbs .crumb.selected.end, .crumbs .crumb.selected.end:hover { + -webkit-border-image: url(Images/segmentSelectedEndChromium.png) 0 2 0 2; +} + +.crumbs .crumb:hover { + -webkit-border-image: url(Images/segmentHoverChromium.png) 0 12 0 2; +} + +.crumbs .crumb.dimmed:hover { + -webkit-border-image: url(Images/segmentHoverChromium.png) 0 12 0 2; +} + +.crumbs .crumb.end:hover { + -webkit-border-image: url(Images/segmentHoverEndChromium.png) 0 2 0 2; +} + +body.drawer-visible #main-status-bar { + background-image: url(Images/statusbarResizerVertical.png), url(Images/statusbarBackgroundChromium.png); +} + +.status-bar { + background-image: url(Images/statusbarBackgroundChromium.png); +} + +button.status-bar-item { + background-image: url(Images/statusbarButtonsChromium.png); +} + +select.status-bar-item:active { + -webkit-border-image: url(Images/statusbarMenuButtonSelectedChromium.png) 0 17 0 2; +} + +#drawer { + background-image: url(Images/statusbarBottomBackgroundChromium.png); +} + +select.status-bar-item { + -webkit-border-image: url(Images/statusbarMenuButtonChromium.png) 0 17 0 2; +} + +.scope-bar li.selected { + -webkit-box-shadow: 0px 0px 0px rgba(0, 0, 0, 0.0); +} + +.scope-bar li:active { + -webkit-box-shadow: 0px 0px 0px rgba(0, 0, 0, 0.0); +} + +.timeline-category-statusbar-item input { + vertical-align: middle; +} |