Merge m-c to inbound.

This commit is contained in:
Ryan VanderMeulen 2013-02-15 11:55:36 -05:00
commit 67e48c76be
14 changed files with 241 additions and 14 deletions

View File

@ -6,6 +6,7 @@
const Cu = Components.utils;
Cu.import("resource:///modules/devtools/gDevTools.jsm");
Cu.import("resource:///modules/devtools/ProfilerController.jsm");
Cu.import("resource:///modules/devtools/ProfilerHelpers.jsm");
Cu.import("resource://gre/modules/commonjs/sdk/core/promise.js");
@ -14,10 +15,11 @@ Cu.import("resource://gre/modules/XPCOMUtils.jsm");
this.EXPORTED_SYMBOLS = ["ProfilerPanel"];
XPCOMUtils.defineLazyGetter(this, "DebuggerServer", function () {
Cu.import("resource://gre/modules/devtools/dbg-server.jsm");
return DebuggerServer;
});
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
"resource://gre/modules/devtools/dbg-server.jsm");
XPCOMUtils.defineLazyModuleGetter(this, "Services",
"resource://gre/modules/Services.jsm");
/**
* An instance of a profile UI. Profile UI consists of
@ -105,6 +107,9 @@ function ProfileUI(uid, panel) {
break;
case "enabled":
this.emit("enabled");
break;
case "displaysource":
this.panel.displaySource(event.data.data);
}
}.bind(this));
}
@ -219,6 +224,7 @@ ProfilerPanel.prototype = {
_uid: null,
_activeUid: null,
_runningUid: null,
_browserWin: null,
get activeProfile() {
return this.profiles.get(this._activeUid);
@ -228,6 +234,21 @@ ProfilerPanel.prototype = {
this._activeUid = profile.uid;
},
get browserWindow() {
if (this._browserWin) {
return this._browserWin;
}
let win = this.window.top;
let type = win.document.documentElement.getAttribute("windowtype");
if (type !== "navigator:browser") {
win = Services.wm.getMostRecentWindow("navigator:browser");
}
return this._browserWin = win;
},
/**
* Open a debug connection and, on success, switch to the newly created
* profile.
@ -416,6 +437,48 @@ ProfilerPanel.prototype = {
}
},
/**
* Open file specified in data in either a debugger or view-source.
*
* @param object data
* An object describing the file. It must have three properties:
* - uri
* - line
* - isChrome (chrome files are opened via view-source)
*/
displaySource: function PP_displaySource(data, onOpen=function() {}) {
let win = this.window;
let panelWin, timeout;
function onSourceShown(event) {
if (event.detail.url !== data.uri) {
return;
}
panelWin.removeEventListener("Debugger:SourceShown", onSourceShown, false);
panelWin.editor.setCaretPosition(data.line - 1);
onOpen();
}
if (data.isChrome) {
return void this.browserWindow.gViewSourceUtils.
viewSource(data.uri, null, this.document, data.line);
}
gDevTools.showToolbox(this.target, "jsdebugger").then(function (toolbox) {
let dbg = toolbox.getCurrentPanel();
panelWin = dbg.panelWin;
let view = dbg.panelWin.DebuggerView;
if (view.Source && view.Sources.selectedValue === data.uri) {
return void view.editor.setCaretPosition(data.line - 1);
}
panelWin.addEventListener("Debugger:SourceShown", onSourceShown, false);
panelWin.DebuggerView.Sources.preferredSource = data.uri;
}.bind(this));
},
/**
* Cleanup.
*/

View File

@ -15,15 +15,19 @@ var gInstanceUID;
* - stop, when user wants to stop profiling.
* - disabled, when the profiler was disabled
* - enabled, when the profiler was enabled
* - displaysource, when user wants to display source
* @param object data (optional)
* Additional data to send to the parent page.
*/
function notifyParent(status) {
function notifyParent(status, data={}) {
if (!gInstanceUID) {
gInstanceUID = window.location.search.substr(1);
}
window.parent.postMessage({
uid: gInstanceUID,
status: status
status: status,
data: data
}, "*");
}
@ -197,7 +201,7 @@ function enterFinishedProfileUI() {
var currentBreadcrumb = gSampleFilters;
gBreadcrumbTrail.add({
title: "Complete Profile",
title: gStrings["Complete Profile"],
enterCallback: function () {
gSampleFilters = [];
filtersChanged();

View File

@ -466,7 +466,8 @@ TreeView.prototype = {
'<span class="resourceIcon" data-resource="' + node.library + '"></span> ' +
'<span class="functionName">' + nodeName + '</span>' +
'<span class="libraryName">' + libName + '</span>' +
'<input type="button" value="Focus Callstack" title="Focus Callstack" class="focusCallstackButton" tabindex="-1">';
(nodeName === '(total)' ? '' :
'<input type="button" value="Focus Callstack" title="Focus Callstack" class="focusCallstackButton" tabindex="-1">');
},
_resolveChildren: function TreeView__resolveChildren(div, childrenCollapsedValue) {
while (div.pendingExpand != null && div.pendingExpand.length > 0) {

View File

@ -169,8 +169,12 @@ function ProfileTreeManager() {
self._onContextMenuClick(e);
});
this.treeView.addEventListener("focusCallstackButtonClicked", function (frameData) {
var focusedCallstack = self._getCallstackUpTo(frameData);
focusOnCallstack(focusedCallstack, frameData.name);
// NOTE: Not in the original Cleopatra source code.
notifyParent("displaysource", {
line: frameData.scriptLocation.lineInformation,
uri: frameData.scriptLocation.scriptURI,
isChrome: /^otherhost_*/.test(frameData.library)
});
});
this._container = document.createElement("div");
this._container.className = "tree";
@ -1566,7 +1570,8 @@ function focusOnSymbol(focusSymbol, name) {
}
function focusOnCallstack(focusedCallstack, name, overwriteCallstack) {
var invertCallback = gInvertCallstack;
var invertCallstack = gInvertCallstack;
if (overwriteCallstack != null) {
invertCallstack = overwriteCallstack;
}

View File

@ -10,12 +10,21 @@ relativesrcdir = @relativesrcdir@
include $(DEPTH)/config/autoconf.mk
MOCHITEST_BROWSER_FILES = \
MOCHITEST_BROWSER_TESTS = \
browser_profiler_run.js \
browser_profiler_controller.js \
browser_profiler_profiles.js \
browser_profiler_remote.js \
browser_profiler_bug_830664_multiple_profiles.js \
browser_profiler_bug_834878_source_buttons.js \
head.js \
$(NULL)
MOCHITEST_BROWSER_PAGES = \
mock_profiler_bug_834878_page.html \
mock_profiler_bug_834878_script.js \
$(NULL)
MOCHITEST_BROWSER_FILES_PARTS = MOCHITEST_BROWSER_TESTS MOCHITEST_BROWSER_PAGES
include $(topsrcdir)/config/rules.mk

View File

@ -0,0 +1,29 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
const BASE = "http://example.com/browser/browser/devtools/profiler/test/";
const URL = BASE + "mock_profiler_bug_834878_page.html";
const SCRIPT = BASE + "mock_profiler_bug_834878_script.js";
function test() {
waitForExplicitFinish();
setUp(URL, function onSetUp(tab, browser, panel) {
panel.once("profileCreated", function () {
let data = { uri: SCRIPT, line: 5, isChrome: false };
panel.displaySource(data, function onOpen() {
let target = TargetFactory.forTab(tab);
let dbg = gDevTools.getToolbox(target).getPanel("jsdebugger");
let view = dbg.panelWin.DebuggerView;
is(view.Sources.selectedValue, data.uri, "URI is different");
is(view.editor.getCaretPosition().line, data.line - 1, "Line is different");
tearDown(tab);
});
});
panel.createProfile();
});
}

View File

@ -0,0 +1,14 @@
<!-- Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ -->
<!DOCTYPE HTML>
<html>
<head>
<meta charset='utf-8'/>
<title>Profiler Script Linking Test</title>
<script type="text/javascript" src="mock_profiler_bug_834878_script.js">
</script>
</head>
<body>
</body>
</html>

View File

@ -0,0 +1,7 @@
/* Any copyright is dedicated to the Public Domain.
http://creativecommons.org/publicdomain/zero/1.0/ */
function main() {
console.log("Hello, World!");
return 0;
}

View File

@ -18,7 +18,7 @@ profiler.label=Profiler
# LOCALIZATION NOTE (profiler.commandkey, profiler.accesskey)
# Used for the menuitem in the tool menu
profiler.commandkey=Y
profiler.accesskey=Y
profiler.accesskey=P
# LOCALIZATION NOTE (profiler.tooltip):
# This string is displayed in the tooltip of the tab when the profiler is

View File

@ -1439,6 +1439,37 @@ nsDOMWindowUtils::GetScrollXY(bool aFlushLayout, int32_t* aScrollX, int32_t* aSc
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetScrollbarWidth(bool aFlushLayout, int32_t* aResult)
{
if (!nsContentUtils::IsCallerChrome()) {
return NS_ERROR_DOM_SECURITY_ERR;
}
*aResult = 0;
nsCOMPtr<nsPIDOMWindow> window = do_QueryReferent(mWindow);
NS_ENSURE_STATE(window);
nsCOMPtr<nsIDocument> doc(do_QueryInterface(window->GetExtantDocument()));
NS_ENSURE_STATE(doc);
if (aFlushLayout) {
doc->FlushPendingNotifications(Flush_Layout);
}
nsIPresShell* presShell = doc->GetShell();
NS_ENSURE_TRUE(presShell, NS_ERROR_NOT_AVAILABLE);
nsIScrollableFrame* scrollFrame = presShell->GetRootScrollFrameAsScrollable();
NS_ENSURE_TRUE(scrollFrame, NS_OK);
nsMargin sizes = scrollFrame->GetActualScrollbarSizes();
*aResult = nsPresContext::AppUnitsToIntCSSPixels(sizes.LeftRight());
return NS_OK;
}
NS_IMETHODIMP
nsDOMWindowUtils::GetRootBounds(nsIDOMClientRect** aResult)
{

View File

@ -41,7 +41,7 @@ interface nsIDOMClientRect;
interface nsIURI;
interface nsIDOMEventTarget;
[scriptable, uuid(020deb5a-cba6-41dd-8551-72a880d01970)]
[scriptable, uuid(16b3bdcc-75d4-11e2-8a20-aaff78957a39)]
interface nsIDOMWindowUtils : nsISupports {
/**
@ -647,6 +647,13 @@ interface nsIDOMWindowUtils : nsISupports {
*/
void getScrollXY(in boolean aFlushLayout, out long aScrollX, out long aScrollY);
/**
* Returns the scrollbar width of the window's scroll frame.
*
* @param aFlushLayout flushes layout if true. Otherwise, no flush occurs.
*/
long getScrollbarWidth(in boolean aFlushLayout);
/**
* Returns the bounds of the window's currently loaded document. This will
* generally be (0, 0, pageWidth, pageHeight) but in some cases (e.g. RTL

View File

@ -29,6 +29,8 @@ MOCHITEST_FILES = \
test_consoleAPI.html \
test_domWindowUtils.html \
test_domWindowUtils_scrollXY.html \
test_domWindowUtils_scrollbarWidth.html \
file_domWindowUtils_scrollbarWidth.html \
test_offsets.html \
test_offsets.js \
test_windowProperties.html \

View File

@ -0,0 +1,7 @@
<!DOCTYPE HTML>
<html>
<body style='width: 100000px; overflow: hidden;'></body>
<div id="float" style="float: left; overflow: scroll;">
<div style="width: 200px;"></div>
</div>
</html>

View File

@ -0,0 +1,48 @@
<!DOCTYPE HTML>
<html>
<head>
<title>nsIDOMWindowUtils::getScrollbarWidth test</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css">
</head>
<body id="body">
<script type="application/javascript;version=1.8">
function doTests() {
let iframe = document.getElementById("iframe");
let cwindow = iframe.contentWindow;
let utils = SpecialPowers.getDOMWindowUtils(cwindow);
let doc = cwindow.document;
function haveNonFloatingScrollbars() {
return doc.getElementById("float").offsetWidth > 200;
}
is(utils.getScrollbarWidth(true), 0,
"getScrollbarWidth returns zero without a scrollbar");
// Some platforms (esp. mobile) may have floating scrollbars that don't
// affect layout. Thus getScrollbarWidth() would always return 0.
if (haveNonFloatingScrollbars()) {
let body = doc.querySelector("body");
body.style.overflowY = "scroll";
is(utils.getScrollbarWidth(false), 0,
"getScrollbarWidth returns zero with a vertical scrollbar w/o flushing");
ok(utils.getScrollbarWidth(true) > 0,
"getScrollbarWidth returns non-zero with a vertical scrollbar with flushing");
}
SimpleTest.finish();
}
SimpleTest.waitForExplicitFinish();
</script>
<iframe src="http://mochi.test:8888/tests/dom/tests/mochitest/general/file_domWindowUtils_scrollbarWidth.html"
id="iframe" onload="doTests();">
</iframe>
</body>
</html>