зеркало из https://github.com/mozilla/gecko-dev.git
Merge m-c to inbound.
This commit is contained in:
Коммит
7cf590e075
|
@ -117,7 +117,7 @@ DeviceTabActor.prototype.grip = function DTA_grip() {
|
|||
|
||||
// Walk over tab actors added by extensions and add them to a new ActorPool.
|
||||
let actorPool = new ActorPool(this.conn);
|
||||
this._createExtraActors(DebuggerServer.globalActorFactories, actorPool);
|
||||
this._createExtraActors(DebuggerServer.tabActorFactories, actorPool);
|
||||
if (!actorPool.isEmpty()) {
|
||||
this._tabActorPool = actorPool;
|
||||
this.conn.addActorPool(this._tabActorPool);
|
||||
|
|
|
@ -152,6 +152,7 @@
|
|||
<menupopup id="appmenu_webDeveloper_popup">
|
||||
<menuitem id="appmenu_devToolbar" observes="devtoolsMenuBroadcaster_DevToolbar"/>
|
||||
<menuitem id="appmenu_webConsole" observes="devtoolsMenuBroadcaster_WebConsole"/>
|
||||
<menuitem id="appmenu_remoteWebConsole" observes="devtoolsMenuBroadcaster_RemoteWebConsole"/>
|
||||
<menuitem id="appmenu_pageinspect" observes="devtoolsMenuBroadcaster_Inspect"/>
|
||||
<menuitem id="appmenu_responsiveUI" observes="devtoolsMenuBroadcaster_ResponsiveUI"/>
|
||||
<menuitem id="appmenu_debugger" observes="devtoolsMenuBroadcaster_Debugger"/>
|
||||
|
|
|
@ -534,6 +534,7 @@
|
|||
<menupopup id="menuWebDeveloperPopup">
|
||||
<menuitem id="menu_devToolbar" observes="devtoolsMenuBroadcaster_DevToolbar" accesskey="&devToolbarMenu.accesskey;"/>
|
||||
<menuitem id="webConsole" observes="devtoolsMenuBroadcaster_WebConsole" accesskey="&webConsoleCmd.accesskey;"/>
|
||||
<menuitem id="menu_remoteWebConsole" observes="devtoolsMenuBroadcaster_RemoteWebConsole"/>
|
||||
<menuitem id="menu_pageinspect" observes="devtoolsMenuBroadcaster_Inspect" accesskey="&inspectMenu.accesskey;"/>
|
||||
<menuitem id="menu_responsiveUI" observes="devtoolsMenuBroadcaster_ResponsiveUI" accesskey="&responsiveDesignTool.accesskey;"/>
|
||||
<menuitem id="menu_debugger" observes="devtoolsMenuBroadcaster_Debugger" accesskey="&debuggerMenu.accesskey;"/>
|
||||
|
|
|
@ -91,6 +91,7 @@
|
|||
<command id="Tools:DevToolbar" oncommand="DeveloperToolbar.toggle();" disabled="true" hidden="true"/>
|
||||
<command id="Tools:DevToolbarFocus" oncommand="DeveloperToolbar.focusToggle();" disabled="true"/>
|
||||
<command id="Tools:WebConsole" oncommand="HUDConsoleUI.toggleHUD();"/>
|
||||
<command id="Tools:RemoteWebConsole" oncommand="HUDConsoleUI.toggleRemoteHUD();" disabled="true" hidden="true"/>
|
||||
<command id="Tools:Inspect" oncommand="InspectorUI.toggleInspectorUI();"/>
|
||||
<command id="Tools:Debugger" oncommand="DebuggerUI.toggleDebugger();" disabled="true" hidden="true"/>
|
||||
<command id="Tools:RemoteDebugger" oncommand="DebuggerUI.toggleRemoteDebugger();" disabled="true" hidden="true"/>
|
||||
|
@ -203,6 +204,10 @@
|
|||
type="checkbox" autocheck="false"
|
||||
key="key_webConsole"
|
||||
command="Tools:WebConsole"/>
|
||||
<broadcaster id="devtoolsMenuBroadcaster_RemoteWebConsole"
|
||||
label="&remoteWebConsoleCmd.label;"
|
||||
type="checkbox" autocheck="false"
|
||||
command="Tools:RemoteWebConsole"/>
|
||||
<broadcaster id="devtoolsMenuBroadcaster_Inspect"
|
||||
label="&inspectMenu.label;"
|
||||
type="checkbox" autocheck="false"
|
||||
|
|
|
@ -1446,6 +1446,10 @@ var gBrowserInit = {
|
|||
let cmd = document.getElementById("Tools:RemoteDebugger");
|
||||
cmd.removeAttribute("disabled");
|
||||
cmd.removeAttribute("hidden");
|
||||
|
||||
cmd = document.getElementById("Tools:RemoteWebConsole");
|
||||
cmd.removeAttribute("disabled");
|
||||
cmd.removeAttribute("hidden");
|
||||
}
|
||||
|
||||
// Enable Chrome Debugger?
|
||||
|
|
|
@ -23,6 +23,7 @@ Cu.import("resource://gre/modules/Services.jsm");
|
|||
*/
|
||||
var ScratchpadManager = {
|
||||
|
||||
_nextUid: 1,
|
||||
_scratchpads: [],
|
||||
|
||||
/**
|
||||
|
@ -89,16 +90,20 @@ var ScratchpadManager = {
|
|||
*/
|
||||
openScratchpad: function SPM_openScratchpad(aState)
|
||||
{
|
||||
let params = null;
|
||||
let params = Cc["@mozilla.org/embedcomp/dialogparam;1"]
|
||||
.createInstance(Ci.nsIDialogParamBlock);
|
||||
|
||||
params.SetNumberStrings(2);
|
||||
params.SetString(0, JSON.stringify(this._nextUid++));
|
||||
|
||||
if (aState) {
|
||||
if (typeof aState != 'object') {
|
||||
return;
|
||||
}
|
||||
params = Cc["@mozilla.org/embedcomp/dialogparam;1"]
|
||||
.createInstance(Ci.nsIDialogParamBlock);
|
||||
params.SetNumberStrings(1);
|
||||
params.SetString(0, JSON.stringify(aState));
|
||||
|
||||
params.SetString(1, JSON.stringify(aState));
|
||||
}
|
||||
|
||||
let win = Services.ww.openWindow(null, SCRATCHPAD_WINDOW_URL, "_blank",
|
||||
SCRATCHPAD_WINDOW_FEATURES, params);
|
||||
// Only add the shutdown observer if we've opened a scratchpad window.
|
||||
|
|
|
@ -41,6 +41,7 @@ const BUTTON_POSITION_REVERT=0;
|
|||
* The scratchpad object handles the Scratchpad window functionality.
|
||||
*/
|
||||
var Scratchpad = {
|
||||
_instanceId: null,
|
||||
_initialWindowTitle: document.title,
|
||||
|
||||
/**
|
||||
|
@ -204,6 +205,15 @@ var Scratchpad = {
|
|||
*/
|
||||
_contentSandbox: null,
|
||||
|
||||
/**
|
||||
* Unique name for the current Scratchpad instance. Used to distinguish
|
||||
* Scratchpad windows between each other. See bug 661762.
|
||||
*/
|
||||
get uniqueName()
|
||||
{
|
||||
return "Scratchpad/" + this._instanceId;
|
||||
},
|
||||
|
||||
/**
|
||||
* Get the Cu.Sandbox object for the active tab content window object. Note
|
||||
* that the returned object is cached for later reuse. The cached object is
|
||||
|
@ -225,7 +235,7 @@ var Scratchpad = {
|
|||
this._previousLocation != this.gBrowser.contentWindow.location.href) {
|
||||
let contentWindow = this.gBrowser.selectedBrowser.contentWindow;
|
||||
this._contentSandbox = new Cu.Sandbox(contentWindow,
|
||||
{ sandboxPrototype: contentWindow, wantXrays: false,
|
||||
{ sandboxPrototype: contentWindow, wantXrays: false,
|
||||
sandboxName: 'scratchpad-content'});
|
||||
this._contentSandbox.__SCRATCHPAD__ = this;
|
||||
|
||||
|
@ -260,7 +270,7 @@ var Scratchpad = {
|
|||
if (!this._chromeSandbox ||
|
||||
this.browserWindow != this._previousBrowserWindow) {
|
||||
this._chromeSandbox = new Cu.Sandbox(this.browserWindow,
|
||||
{ sandboxPrototype: this.browserWindow, wantXrays: false,
|
||||
{ sandboxPrototype: this.browserWindow, wantXrays: false,
|
||||
sandboxName: 'scratchpad-chrome'});
|
||||
this._chromeSandbox.__SCRATCHPAD__ = this;
|
||||
addDebuggerToGlobal(this._chromeSandbox);
|
||||
|
@ -317,7 +327,7 @@ var Scratchpad = {
|
|||
let error, result;
|
||||
try {
|
||||
result = Cu.evalInSandbox(aString, this.contentSandbox, "1.8",
|
||||
"Scratchpad", 1);
|
||||
this.uniqueName, 1);
|
||||
}
|
||||
catch (ex) {
|
||||
error = ex;
|
||||
|
@ -339,7 +349,7 @@ var Scratchpad = {
|
|||
let error, result;
|
||||
try {
|
||||
result = Cu.evalInSandbox(aString, this.chromeSandbox, "1.8",
|
||||
"Scratchpad", 1);
|
||||
this.uniqueName, 1);
|
||||
}
|
||||
catch (ex) {
|
||||
error = ex;
|
||||
|
@ -676,8 +686,6 @@ var Scratchpad = {
|
|||
}
|
||||
|
||||
if (shouldOpen) {
|
||||
this._skipClosePrompt = true;
|
||||
|
||||
let file;
|
||||
if (aFile) {
|
||||
file = aFile;
|
||||
|
@ -1087,6 +1095,7 @@ var Scratchpad = {
|
|||
if (aEvent.target != document) {
|
||||
return;
|
||||
}
|
||||
|
||||
let chrome = Services.prefs.getBoolPref(DEVTOOLS_CHROME_ENABLED);
|
||||
if (chrome) {
|
||||
let environmentMenu = document.getElementById("sp-environment-menu");
|
||||
|
@ -1097,8 +1106,6 @@ var Scratchpad = {
|
|||
errorConsoleCommand.removeAttribute("disabled");
|
||||
}
|
||||
|
||||
let state = null;
|
||||
|
||||
let initialText = this.strings.formatStringFromName(
|
||||
"scratchpadIntro1",
|
||||
[LayoutHelpers.prettyKey(document.getElementById("sp-key-run")),
|
||||
|
@ -1106,9 +1113,21 @@ var Scratchpad = {
|
|||
LayoutHelpers.prettyKey(document.getElementById("sp-key-display"))],
|
||||
3);
|
||||
|
||||
if ("arguments" in window &&
|
||||
window.arguments[0] instanceof Ci.nsIDialogParamBlock) {
|
||||
state = JSON.parse(window.arguments[0].GetString(0));
|
||||
let args = window.arguments;
|
||||
|
||||
if (args && args[0] instanceof Ci.nsIDialogParamBlock) {
|
||||
args = args[0];
|
||||
} else {
|
||||
// If this Scratchpad window doesn't have any arguments, horrible
|
||||
// things might happen so we need to report an error.
|
||||
Cu.reportError(this.strings. GetStringFromName("scratchpad.noargs"));
|
||||
}
|
||||
|
||||
this._instanceId = args.GetString(0);
|
||||
|
||||
let state = args.GetString(1) || null;
|
||||
if (state) {
|
||||
state = JSON.parse(state);
|
||||
this.setState(state);
|
||||
initialText = state.text;
|
||||
}
|
||||
|
@ -1217,8 +1236,13 @@ var Scratchpad = {
|
|||
}
|
||||
|
||||
this.resetContext();
|
||||
this.gBrowser.selectedBrowser.removeEventListener("load",
|
||||
this._reloadAndRunEvent, true);
|
||||
|
||||
// This event is created only after user uses 'reload and run' feature.
|
||||
if (this._reloadAndRunEvent) {
|
||||
this.gBrowser.selectedBrowser.removeEventListener("load",
|
||||
this._reloadAndRunEvent, true);
|
||||
}
|
||||
|
||||
this.editor.removeEventListener(SourceEditor.EVENTS.DIRTY_CHANGED,
|
||||
this._onDirtyChanged);
|
||||
PreferenceObserver.uninit();
|
||||
|
@ -1282,25 +1306,14 @@ var Scratchpad = {
|
|||
* there are unsaved changes.
|
||||
*
|
||||
* @param nsIDOMEvent aEvent
|
||||
* @param function aCallback
|
||||
* Optional function you want to call when file is saved/closed.
|
||||
* Used mainly for tests.
|
||||
*/
|
||||
onClose: function SP_onClose(aEvent)
|
||||
onClose: function SP_onClose(aEvent, aCallback)
|
||||
{
|
||||
if (this._skipClosePrompt) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.promptSave(function(aShouldClose, aSaved, aStatus) {
|
||||
let shouldClose = aShouldClose;
|
||||
if (aSaved && !Components.isSuccessCode(aStatus)) {
|
||||
shouldClose = false;
|
||||
}
|
||||
|
||||
if (shouldClose) {
|
||||
this._skipClosePrompt = true;
|
||||
window.close();
|
||||
}
|
||||
}.bind(this));
|
||||
aEvent.preventDefault();
|
||||
this.close(aCallback);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -1319,7 +1332,6 @@ var Scratchpad = {
|
|||
}
|
||||
|
||||
if (shouldClose) {
|
||||
this._skipClosePrompt = true;
|
||||
window.close();
|
||||
}
|
||||
if (aCallback) {
|
||||
|
|
|
@ -35,6 +35,7 @@ MOCHITEST_BROWSER_FILES = \
|
|||
browser_scratchpad_bug756681_display_non_error_exceptions.js \
|
||||
browser_scratchpad_bug_751744_revert_to_saved.js \
|
||||
browser_scratchpad_bug740948_reload_and_run.js \
|
||||
browser_scratchpad_bug_661762_wrong_window_focus.js \
|
||||
head.js \
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -36,7 +36,8 @@ function runTests()
|
|||
scratchpad.setText(error);
|
||||
scratchpad.display();
|
||||
is(scratchpad.getText(),
|
||||
error + openComment + "Exception: Ouch!\n@Scratchpad:1" + closeComment,
|
||||
error + openComment +
|
||||
"Exception: Ouch!\n@" + scratchpad.uniqueName + ":1" + closeComment,
|
||||
"error display output");
|
||||
|
||||
scratchpad.setText(message);
|
||||
|
@ -46,7 +47,8 @@ function runTests()
|
|||
scratchpad.setText(error);
|
||||
scratchpad.run();
|
||||
is(scratchpad.getText(),
|
||||
error + openComment + "Exception: Ouch!\n@Scratchpad:1" + closeComment,
|
||||
error + openComment +
|
||||
"Exception: Ouch!\n@" + scratchpad.uniqueName + ":1" + closeComment,
|
||||
"error display output");
|
||||
|
||||
finish();
|
||||
|
|
|
@ -41,7 +41,8 @@ function runTests()
|
|||
scratchpad.setText(error1);
|
||||
scratchpad.display();
|
||||
is(scratchpad.getText(),
|
||||
error1 + openComment + "Exception: Ouch!\n@Scratchpad:1" + closeComment,
|
||||
error1 + openComment +
|
||||
"Exception: Ouch!\n@" + scratchpad.uniqueName + ":1" + closeComment,
|
||||
"error display output");
|
||||
|
||||
// Display error2, throw "A thrown string"
|
||||
|
@ -75,7 +76,8 @@ function runTests()
|
|||
scratchpad.setText(error1);
|
||||
scratchpad.run();
|
||||
is(scratchpad.getText(),
|
||||
error1 + openComment + "Exception: Ouch!\n@Scratchpad:1" + closeComment,
|
||||
error1 + openComment +
|
||||
"Exception: Ouch!\n@" + scratchpad.uniqueName + ":1" + closeComment,
|
||||
"error run output");
|
||||
|
||||
// Run error2, throw "A thrown string"
|
||||
|
|
|
@ -9,7 +9,7 @@ let NetUtil = tempScope.NetUtil;
|
|||
let FileUtils = tempScope.FileUtils;
|
||||
|
||||
// only finish() when correct number of tests are done
|
||||
const expected = 5;
|
||||
const expected = 6;
|
||||
var count = 0;
|
||||
function done()
|
||||
{
|
||||
|
@ -69,6 +69,7 @@ function testSavedFile()
|
|||
function testUnsaved()
|
||||
{
|
||||
testUnsavedFileCancel();
|
||||
testCancelAfterLoad();
|
||||
testUnsavedFileSave();
|
||||
testUnsavedFileDontSave();
|
||||
}
|
||||
|
@ -89,6 +90,34 @@ function testUnsavedFileCancel()
|
|||
}, {noFocus: true});
|
||||
}
|
||||
|
||||
// Test a regression where our confirmation dialog wasn't appearing
|
||||
// after openFile calls. See bug 801982.
|
||||
function testCancelAfterLoad()
|
||||
{
|
||||
openScratchpad(function(win) {
|
||||
win.Scratchpad.setRecentFile(gFile);
|
||||
win.Scratchpad.openFile(0);
|
||||
win.Scratchpad.editor.dirty = true;
|
||||
promptButton = win.BUTTON_POSITION_CANCEL;
|
||||
|
||||
let EventStub = {
|
||||
called: false,
|
||||
preventDefault: function() {
|
||||
EventStub.called = true;
|
||||
}
|
||||
};
|
||||
|
||||
win.Scratchpad.onClose(EventStub, function() {
|
||||
ok(!win.closed, "cancelling dialog shouldn't close scratchpad");
|
||||
ok(EventStub.called, "aEvent.preventDefault was called");
|
||||
|
||||
win.Scratchpad.editor.dirty = false;
|
||||
win.close();
|
||||
done();
|
||||
});
|
||||
}, {noFocus: true});
|
||||
}
|
||||
|
||||
function testUnsavedFileSave()
|
||||
{
|
||||
openScratchpad(function(win) {
|
||||
|
|
|
@ -0,0 +1,93 @@
|
|||
/* vim:set ts=2 sw=2 sts=2 et: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
let tempScope = {};
|
||||
Cu.import("resource:///modules/HUDService.jsm", tempScope);
|
||||
let HUDService = tempScope.HUDService;
|
||||
|
||||
function test()
|
||||
{
|
||||
waitForExplicitFinish();
|
||||
|
||||
// To test for this bug we open a Scratchpad window, save its
|
||||
// reference and then open another one. This way the first window
|
||||
// loses its focus.
|
||||
//
|
||||
// Then we open a web console and execute a console.log statement
|
||||
// from the first Scratch window (that's why we needed to save its
|
||||
// reference).
|
||||
//
|
||||
// Then we wait for our message to appear in the console and click
|
||||
// on the location link. After that we check which Scratchpad window
|
||||
// is currently active (it should be the older one).
|
||||
|
||||
gBrowser.selectedTab = gBrowser.addTab();
|
||||
gBrowser.selectedBrowser.addEventListener("load", function onLoad() {
|
||||
gBrowser.selectedBrowser.removeEventListener("load", onLoad, true);
|
||||
|
||||
openScratchpad(function () {
|
||||
let sw = gScratchpadWindow;
|
||||
|
||||
openScratchpad(function () {
|
||||
function onWebConsoleOpen(subj) {
|
||||
Services.obs.removeObserver(onWebConsoleOpen,
|
||||
"web-console-created");
|
||||
subj.QueryInterface(Ci.nsISupportsString);
|
||||
|
||||
let hud = HUDService.getHudReferenceById(subj.data);
|
||||
hud.jsterm.clearOutput(true);
|
||||
executeSoon(testFocus.bind(null, sw, hud));
|
||||
}
|
||||
|
||||
Services.obs.
|
||||
addObserver(onWebConsoleOpen, "web-console-created", false);
|
||||
|
||||
HUDService.consoleUI.toggleHUD();
|
||||
});
|
||||
});
|
||||
}, true);
|
||||
|
||||
content.location = "data:text/html;charset=utf8,<p>test window focus for Scratchpad.";
|
||||
}
|
||||
|
||||
function testFocus(sw, hud) {
|
||||
let sp = sw.Scratchpad;
|
||||
|
||||
function onMessage(subj) {
|
||||
Services.obs.removeObserver(onMessage, "web-console-message-created");
|
||||
|
||||
var loc = hud.jsterm.outputNode.querySelector(".webconsole-location");
|
||||
ok(loc, "location element exists");
|
||||
is(loc.value, sw.Scratchpad.uniqueName + ":1",
|
||||
"location value is correct");
|
||||
|
||||
sw.addEventListener("focus", function onFocus() {
|
||||
sw.removeEventListener("focus", onFocus, true);
|
||||
|
||||
let win = Services.wm.getMostRecentWindow("devtools:scratchpad");
|
||||
|
||||
ok(win, "there are active Scratchpad windows");
|
||||
is(win.Scratchpad.uniqueName, sw.Scratchpad.uniqueName,
|
||||
"correct window is in focus");
|
||||
|
||||
// gScratchpadWindow will be closed automatically but we need to
|
||||
// close the second window ourselves.
|
||||
sw.close();
|
||||
finish();
|
||||
}, true);
|
||||
|
||||
// Simulate a click on the "Scratchpad/N:1" link.
|
||||
EventUtils.synthesizeMouse(loc, 2, 2, {}, hud.iframeWindow);
|
||||
}
|
||||
|
||||
// Sending messages to web console is an asynchronous operation. That's
|
||||
// why we have to setup an observer here.
|
||||
Services.obs.addObserver(onMessage, "web-console-message-created", false);
|
||||
|
||||
sp.setText("console.log('foo');");
|
||||
let [selection, error, result] = sp.run();
|
||||
is(selection, "console.log('foo');", "selection is correct");
|
||||
is(error, undefined, "error is correct");
|
||||
is(result, undefined, "result is correct");
|
||||
}
|
|
@ -5,6 +5,7 @@
|
|||
// only finish() when correct number of tests are done
|
||||
const expected = 3;
|
||||
var count = 0;
|
||||
var lastUniqueName = null;
|
||||
|
||||
function done()
|
||||
{
|
||||
|
@ -21,6 +22,19 @@ function test()
|
|||
testOpenInvalidState();
|
||||
}
|
||||
|
||||
function testUniqueName(name)
|
||||
{
|
||||
ok(name, "Scratchpad has a uniqueName");
|
||||
|
||||
if (lastUniqueName === null) {
|
||||
lastUniqueName = name;
|
||||
return;
|
||||
}
|
||||
|
||||
ok(name !== lastUniqueName,
|
||||
"Unique name for this instance differs from the last one.");
|
||||
}
|
||||
|
||||
function testOpen()
|
||||
{
|
||||
openScratchpad(function(win) {
|
||||
|
@ -28,6 +42,7 @@ function testOpen()
|
|||
isnot(win.Scratchpad.getText(), null, "Default text should not be null");
|
||||
is(win.Scratchpad.executionContext, win.SCRATCHPAD_CONTEXT_CONTENT,
|
||||
"Default execution context is content");
|
||||
testUniqueName(win.Scratchpad.uniqueName);
|
||||
|
||||
win.close();
|
||||
done();
|
||||
|
@ -46,6 +61,7 @@ function testOpenWithState()
|
|||
is(win.Scratchpad.filename, state.filename, "Filename loaded from state");
|
||||
is(win.Scratchpad.executionContext, state.executionContext, "Execution context loaded from state");
|
||||
is(win.Scratchpad.getText(), state.text, "Content loaded from state");
|
||||
testUniqueName(win.Scratchpad.uniqueName);
|
||||
|
||||
win.close();
|
||||
done();
|
||||
|
|
|
@ -1231,6 +1231,7 @@ SourceEditor.prototype = {
|
|||
// If the caret is not at the closing bracket "}", find the index of the
|
||||
// opening bracket "{" for the current code block.
|
||||
if (matchingIndex == -1 || matchingIndex > caretOffset) {
|
||||
matchingIndex = -1;
|
||||
let text = this.getText();
|
||||
let closingOffset = text.indexOf("}", caretOffset);
|
||||
while (closingOffset > -1) {
|
||||
|
@ -1241,18 +1242,34 @@ SourceEditor.prototype = {
|
|||
}
|
||||
closingOffset = text.indexOf("}", closingOffset + 1);
|
||||
}
|
||||
// Moving to the previous code block starting bracket if caret not inside
|
||||
// any code block.
|
||||
if (matchingIndex == -1) {
|
||||
let lastClosingOffset = text.lastIndexOf("}", caretOffset);
|
||||
while (lastClosingOffset > -1) {
|
||||
let closingMatchingIndex =
|
||||
this._getMatchingBracketIndex(lastClosingOffset);
|
||||
if (closingMatchingIndex < caretOffset &&
|
||||
closingMatchingIndex != -1) {
|
||||
matchingIndex = closingMatchingIndex;
|
||||
break;
|
||||
}
|
||||
lastClosingOffset = text.lastIndexOf("}", lastClosingOffset - 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchingIndex > -1) {
|
||||
this.setCaretOffset(matchingIndex);
|
||||
this.setCaretOffset(matchingIndex + 1);
|
||||
}
|
||||
|
||||
return true;
|
||||
},
|
||||
|
||||
/**
|
||||
* Moves the cursor to the matching closing bracket if at corresponding opening
|
||||
* bracket, otherwise move to the closing bracket for the current block of code.
|
||||
* Moves the cursor to the matching closing bracket if at corresponding
|
||||
* opening bracket, otherwise move to the closing bracket for the current
|
||||
* block of code.
|
||||
*
|
||||
* @private
|
||||
*/
|
||||
|
@ -1271,6 +1288,7 @@ SourceEditor.prototype = {
|
|||
// If the caret is not at the opening bracket "{", find the index of the
|
||||
// closing bracket "}" for the current code block.
|
||||
if (matchingIndex == -1 || matchingIndex < caretOffset) {
|
||||
matchingIndex = -1;
|
||||
let text = this.getText();
|
||||
let openingOffset = text.lastIndexOf("{", caretOffset);
|
||||
while (openingOffset > -1) {
|
||||
|
@ -1281,6 +1299,20 @@ SourceEditor.prototype = {
|
|||
}
|
||||
openingOffset = text.lastIndexOf("{", openingOffset - 1);
|
||||
}
|
||||
// Moving to the next code block ending bracket if caret not inside
|
||||
// any code block.
|
||||
if (matchingIndex == -1) {
|
||||
let nextOpeningIndex = text.indexOf("{", caretOffset + 1);
|
||||
while (nextOpeningIndex > -1) {
|
||||
let openingMatchingIndex =
|
||||
this._getMatchingBracketIndex(nextOpeningIndex);
|
||||
if (openingMatchingIndex > caretOffset) {
|
||||
matchingIndex = openingMatchingIndex;
|
||||
break;
|
||||
}
|
||||
nextOpeningIndex = text.indexOf("{", nextOpeningIndex + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (matchingIndex > -1) {
|
||||
|
|
|
@ -30,6 +30,7 @@ MOCHITEST_BROWSER_FILES = \
|
|||
browser_bug725430_comment_uncomment.js \
|
||||
browser_bug731721_debugger_stepping.js \
|
||||
browser_bug729960_block_bracket_jump.js \
|
||||
browser_bug744021_next_prev_bracket_jump.js \
|
||||
head.js \
|
||||
|
||||
include $(topsrcdir)/config/rules.mk
|
||||
|
|
|
@ -58,13 +58,13 @@ function test() {
|
|||
"JS : Jump to closing bracket of the code block when caret at block start");
|
||||
|
||||
EventUtils.synthesizeKey("[", {accelKey: true}, testWin);
|
||||
is(editor.getCaretOffset(), 19,
|
||||
is(editor.getCaretOffset(), 20,
|
||||
"JS : Jump to opening bracket of the code block when caret at block end");
|
||||
|
||||
// Setting caret at Line 10 start.
|
||||
editor.setCaretOffset(161);
|
||||
EventUtils.synthesizeKey("[", {accelKey: true}, testWin);
|
||||
is(editor.getCaretOffset(), 19,
|
||||
is(editor.getCaretOffset(), 20,
|
||||
"JS : Jump to opening bracket of code block when inside the function");
|
||||
|
||||
editor.setCaretOffset(161);
|
||||
|
@ -80,7 +80,7 @@ function test() {
|
|||
|
||||
editor.setCaretOffset(67);
|
||||
EventUtils.synthesizeKey("[", {accelKey: true}, testWin);
|
||||
is(editor.getCaretOffset(), 61,
|
||||
is(editor.getCaretOffset(), 62,
|
||||
"JS : Jump to opening bracket in a nested function with caret inside");
|
||||
|
||||
let CSSText = "#object {\n" +
|
||||
|
@ -98,13 +98,13 @@ function test() {
|
|||
"CSS : Jump to closing bracket of the code block when caret at block start");
|
||||
|
||||
EventUtils.synthesizeKey("[", {accelKey: true}, testWin);
|
||||
is(editor.getCaretOffset(), 8,
|
||||
is(editor.getCaretOffset(), 9,
|
||||
"CSS : Jump to opening bracket of the code block when caret at block end");
|
||||
|
||||
// Setting caret at Line 3 start.
|
||||
editor.setCaretOffset(28);
|
||||
EventUtils.synthesizeKey("[", {accelKey: true}, testWin);
|
||||
is(editor.getCaretOffset(), 8,
|
||||
is(editor.getCaretOffset(), 9,
|
||||
"CSS : Jump to opening bracket of code block when inside the function");
|
||||
|
||||
editor.setCaretOffset(28);
|
||||
|
|
|
@ -0,0 +1,104 @@
|
|||
/* vim: set ts=2 et sw=2 tw=80: */
|
||||
/* Any copyright is dedicated to the Public Domain.
|
||||
http://creativecommons.org/publicdomain/zero/1.0/ */
|
||||
|
||||
"use strict";
|
||||
|
||||
function test() {
|
||||
|
||||
let temp = {};
|
||||
Cu.import("resource:///modules/source-editor.jsm", temp);
|
||||
let SourceEditor = temp.SourceEditor;
|
||||
|
||||
waitForExplicitFinish();
|
||||
|
||||
let editor;
|
||||
|
||||
const windowUrl = "data:text/xml;charset=utf8,<?xml version='1.0'?><window " +
|
||||
"xmlns='http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul' " +
|
||||
"title='test for bug 744021' width='600' height='500'><hbox flex='1'/>" +
|
||||
"</window>";
|
||||
const windowFeatures = "chrome,titlebar,toolbar,centerscreen,resizable," +
|
||||
"dialog=no";
|
||||
|
||||
let testWin = Services.ww.openWindow(null, windowUrl, "_blank",
|
||||
windowFeatures, null);
|
||||
testWin.addEventListener("load", function onWindowLoad() {
|
||||
testWin.removeEventListener("load", onWindowLoad, false);
|
||||
waitForFocus(initEditor, testWin);
|
||||
}, false);
|
||||
|
||||
function initEditor()
|
||||
{
|
||||
let hbox = testWin.document.querySelector("hbox");
|
||||
editor = new SourceEditor();
|
||||
editor.init(hbox, {showLineNumbers: true}, editorLoaded);
|
||||
}
|
||||
|
||||
function editorLoaded()
|
||||
{
|
||||
editor.focus();
|
||||
let JSText = "function foo() {\n" +
|
||||
" \n" +
|
||||
" function level2() {\n" +
|
||||
" \n" +
|
||||
" function level3() {\n" +
|
||||
" \n" +
|
||||
" }\n" +
|
||||
" }\n" +
|
||||
" function bar() { /* Block Level 2 */ }\n" +
|
||||
"}\n" +
|
||||
"function baz() {\n" +
|
||||
" \n" +
|
||||
"}";
|
||||
|
||||
editor.setMode(SourceEditor.MODES.JAVASCRIPT);
|
||||
editor.setText(JSText);
|
||||
|
||||
// Setting caret at end of line 11 (function baz() {).
|
||||
editor.setCaretOffset(147);
|
||||
EventUtils.synthesizeKey("[", {accelKey: true}, testWin);
|
||||
is(editor.getCaretOffset(), 16,
|
||||
"JS : Jump to opening bracket of previous sibling block when no parent");
|
||||
|
||||
EventUtils.synthesizeKey("]", {accelKey: true}, testWin);
|
||||
is(editor.getCaretOffset(), 129,
|
||||
"JS : Jump to closing bracket of same code block");
|
||||
|
||||
EventUtils.synthesizeKey("]", {accelKey: true}, testWin);
|
||||
is(editor.getCaretOffset(), 151,
|
||||
"JS : Jump to closing bracket of next sibling code block");
|
||||
|
||||
let CSSText = "#object1 {\n" +
|
||||
" property: value;\n" +
|
||||
" /* comment */\n" +
|
||||
"}\n" +
|
||||
".class1 {\n" +
|
||||
" property: value;\n" +
|
||||
"}";
|
||||
|
||||
editor.setMode(SourceEditor.MODES.CSS);
|
||||
editor.setText(CSSText);
|
||||
|
||||
// Setting caret at Line 5 end (.class1 {).
|
||||
editor.setCaretOffset(57);
|
||||
EventUtils.synthesizeKey("[", {accelKey: true}, testWin);
|
||||
is(editor.getCaretOffset(), 10,
|
||||
"CSS : Jump to opening bracket of previous sibling code block");
|
||||
|
||||
EventUtils.synthesizeKey("]", {accelKey: true}, testWin);
|
||||
is(editor.getCaretOffset(), 46,
|
||||
"CSS : Jump to closing bracket of same code block");
|
||||
|
||||
EventUtils.synthesizeKey("]", {accelKey: true}, testWin);
|
||||
is(editor.getCaretOffset(), 77,
|
||||
"CSS : Jump to closing bracket of next sibling code block");
|
||||
|
||||
editor.destroy();
|
||||
|
||||
testWin.close();
|
||||
testWin = editor = null;
|
||||
|
||||
waitForFocus(finish, window);
|
||||
}
|
||||
}
|
|
@ -113,10 +113,17 @@ HUD_SERVICE.prototype =
|
|||
* The xul:tab element.
|
||||
* @param boolean aAnimated
|
||||
* True if you want to animate the opening of the Web console.
|
||||
* @param object aOptions
|
||||
* Options for the Web Console:
|
||||
* - host
|
||||
* Server to connect to.
|
||||
* - port
|
||||
* Port to connect to.
|
||||
* @return object
|
||||
* The new HeadsUpDisplay instance.
|
||||
*/
|
||||
activateHUDForContext: function HS_activateHUDForContext(aTab, aAnimated)
|
||||
activateHUDForContext:
|
||||
function HS_activateHUDForContext(aTab, aAnimated, aOptions)
|
||||
{
|
||||
let hudId = "hud_" + aTab.linkedPanel;
|
||||
if (hudId in this.hudReferences) {
|
||||
|
@ -132,7 +139,7 @@ HUD_SERVICE.prototype =
|
|||
gBrowser.tabContainer.addEventListener("TabSelect", this.onTabSelect, false);
|
||||
window.addEventListener("unload", this.onWindowUnload, false);
|
||||
|
||||
let hud = new WebConsole(aTab);
|
||||
let hud = new WebConsole(aTab, aOptions);
|
||||
this.hudReferences[hudId] = hud;
|
||||
|
||||
if (!aAnimated || hud.consolePanel) {
|
||||
|
@ -493,13 +500,19 @@ HUD_SERVICE.prototype =
|
|||
*
|
||||
* @param nsIDOMElement aTab
|
||||
* The xul:tab for which you want the WebConsole object.
|
||||
* @param object aOptions
|
||||
* Web Console options: host and port, for the remote Web console.
|
||||
*/
|
||||
function WebConsole(aTab)
|
||||
function WebConsole(aTab, aOptions = {})
|
||||
{
|
||||
this.tab = aTab;
|
||||
this.chromeDocument = this.tab.ownerDocument;
|
||||
this.chromeWindow = this.chromeDocument.defaultView;
|
||||
this.hudId = "hud_" + this.tab.linkedPanel;
|
||||
|
||||
this.remoteHost = aOptions.host;
|
||||
this.remotePort = aOptions.port;
|
||||
|
||||
this._onIframeLoad = this._onIframeLoad.bind(this);
|
||||
this._initUI();
|
||||
}
|
||||
|
@ -1017,7 +1030,8 @@ var HeadsUpDisplayUICommands = {
|
|||
}
|
||||
},
|
||||
|
||||
toggleHUD: function UIC_toggleHUD() {
|
||||
toggleHUD: function UIC_toggleHUD(aOptions)
|
||||
{
|
||||
var window = HUDService.currentContext();
|
||||
var gBrowser = window.gBrowser;
|
||||
var linkedBrowser = gBrowser.selectedTab.linkedBrowser;
|
||||
|
@ -1046,11 +1060,52 @@ var HeadsUpDisplayUICommands = {
|
|||
}
|
||||
}
|
||||
else {
|
||||
HUDService.activateHUDForContext(gBrowser.selectedTab, true);
|
||||
HUDService.activateHUDForContext(gBrowser.selectedTab, true, aOptions);
|
||||
HUDService.animate(hudId, ANIMATE_IN);
|
||||
}
|
||||
},
|
||||
|
||||
toggleRemoteHUD: function UIC_toggleRemoteHUD()
|
||||
{
|
||||
if (this.getOpenHUD()) {
|
||||
this.toggleHUD();
|
||||
return;
|
||||
}
|
||||
|
||||
let host = Services.prefs.getCharPref("devtools.debugger.remote-host");
|
||||
let port = Services.prefs.getIntPref("devtools.debugger.remote-port");
|
||||
|
||||
let check = { value: false };
|
||||
let input = { value: host + ":" + port };
|
||||
|
||||
let result = Services.prompt.prompt(null,
|
||||
l10n.getStr("remoteWebConsolePromptTitle"),
|
||||
l10n.getStr("remoteWebConsolePromptMessage"),
|
||||
input, null, check);
|
||||
|
||||
if (!result) {
|
||||
return;
|
||||
}
|
||||
|
||||
let parts = input.value.split(":");
|
||||
if (parts.length != 2) {
|
||||
return;
|
||||
}
|
||||
|
||||
[host, port] = parts;
|
||||
if (!host.length || !port.length) {
|
||||
return;
|
||||
}
|
||||
|
||||
Services.prefs.setCharPref("devtools.debugger.remote-host", host);
|
||||
Services.prefs.setIntPref("devtools.debugger.remote-port", port);
|
||||
|
||||
this.toggleHUD({
|
||||
host: host,
|
||||
port: port,
|
||||
});
|
||||
},
|
||||
|
||||
/**
|
||||
* Find the hudId for the active chrome window.
|
||||
* @return string|null
|
||||
|
|
|
@ -152,6 +152,7 @@ function testNext() {
|
|||
pos++;
|
||||
if (pos < TESTS.length) {
|
||||
waitForSuccess({
|
||||
timeout: 10000,
|
||||
name: "test #" + pos + " successful finish",
|
||||
validatorFn: function()
|
||||
{
|
||||
|
@ -211,6 +212,8 @@ function onDOMNodeInserted(aEvent) {
|
|||
}
|
||||
|
||||
function test() {
|
||||
requestLongerTimeout(2);
|
||||
|
||||
addTab("data:text/html;charset=utf-8,Web Console test for bug 595934 - message categories coverage.");
|
||||
browser.addEventListener("load", function onLoad() {
|
||||
browser.removeEventListener("load", onLoad, true);
|
||||
|
|
|
@ -21,6 +21,9 @@ XPCOMUtils.defineLazyModuleGetter(this, "DebuggerServer",
|
|||
XPCOMUtils.defineLazyModuleGetter(this, "DebuggerClient",
|
||||
"resource://gre/modules/devtools/dbg-client.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyModuleGetter(this, "debuggerSocketConnect",
|
||||
"resource://gre/modules/devtools/dbg-client.jsm");
|
||||
|
||||
XPCOMUtils.defineLazyServiceGetter(this, "clipboardHelper",
|
||||
"@mozilla.org/widget/clipboardhelper;1",
|
||||
"nsIClipboardHelper");
|
||||
|
@ -360,8 +363,11 @@ WebConsoleFrame.prototype = {
|
|||
*/
|
||||
_initConnection: function WCF__initConnection()
|
||||
{
|
||||
this.proxy = new WebConsoleConnectionProxy(this);
|
||||
this.proxy.initServer();
|
||||
this.proxy = new WebConsoleConnectionProxy(this, {
|
||||
host: this.owner.remoteHost,
|
||||
port: this.owner.remotePort,
|
||||
});
|
||||
|
||||
this.proxy.connect(function() {
|
||||
this.saveRequestAndResponseBodies = this._saveRequestAndResponseBodies;
|
||||
this._onInitComplete();
|
||||
|
@ -959,9 +965,9 @@ WebConsoleFrame.prototype = {
|
|||
|
||||
/**
|
||||
* Filter the console node from the output node if it is a repeat. Console
|
||||
* messages are filtered from the output if and only if they match the
|
||||
* immediately preceding message. The output node's last occurrence should
|
||||
* have its timestamp updated.
|
||||
* messages are filtered from the output if they match the immediately
|
||||
* preceding message that came from the same source. The output node's
|
||||
* last occurrence should have its timestamp updated.
|
||||
*
|
||||
* @param nsIDOMNode aNode
|
||||
* The message node to be filtered or not.
|
||||
|
@ -972,11 +978,31 @@ WebConsoleFrame.prototype = {
|
|||
{
|
||||
let lastMessage = this.outputNode.lastChild;
|
||||
|
||||
// childNodes[2] is the description element
|
||||
if (lastMessage && lastMessage.childNodes[2] &&
|
||||
!aNode.classList.contains("webconsole-msg-inspector") &&
|
||||
aNode.childNodes[2].textContent ==
|
||||
lastMessage.childNodes[2].textContent) {
|
||||
if (!lastMessage) {
|
||||
return false;
|
||||
}
|
||||
|
||||
let body = aNode.querySelector(".webconsole-msg-body");
|
||||
let lastBody = lastMessage.querySelector(".webconsole-msg-body");
|
||||
|
||||
if (aNode.classList.contains("webconsole-msg-inspector")) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!body || !lastBody) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (body.textContent == lastBody.textContent) {
|
||||
let loc = aNode.querySelector(".webconsole-location");
|
||||
let lastLoc = lastMessage.querySelector(".webconsole-location");
|
||||
|
||||
if (loc && lastLoc) {
|
||||
if (loc.getAttribute("value") !== lastLoc.getAttribute("value")) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
this.mergeFilteredMessageNode(lastMessage, aNode);
|
||||
return true;
|
||||
}
|
||||
|
@ -2367,11 +2393,20 @@ WebConsoleFrame.prototype = {
|
|||
let locationNode = this.document.createElementNS(XUL_NS, "label");
|
||||
|
||||
// Create the text, which consists of an abbreviated version of the URL
|
||||
// plus an optional line number.
|
||||
let text = WebConsoleUtils.abbreviateSourceURL(aSourceURL);
|
||||
// plus an optional line number. Scratchpad URLs should not be abbreviated.
|
||||
let text;
|
||||
|
||||
if (/^Scratchpad\/\d+$/.test(aSourceURL)) {
|
||||
text = aSourceURL;
|
||||
}
|
||||
else {
|
||||
text = WebConsoleUtils.abbreviateSourceURL(aSourceURL);
|
||||
}
|
||||
|
||||
if (aSourceLine) {
|
||||
text += ":" + aSourceLine;
|
||||
}
|
||||
|
||||
locationNode.setAttribute("value", text);
|
||||
|
||||
// Style appropriately.
|
||||
|
@ -2383,10 +2418,16 @@ WebConsoleFrame.prototype = {
|
|||
|
||||
// Make the location clickable.
|
||||
locationNode.addEventListener("click", function() {
|
||||
if (aSourceURL == "Scratchpad") {
|
||||
let win = Services.wm.getMostRecentWindow("devtools:scratchpad");
|
||||
if (win) {
|
||||
win.focus();
|
||||
if (/^Scratchpad\/\d+$/.test(aSourceURL)) {
|
||||
let wins = Services.wm.getEnumerator("devtools:scratchpad");
|
||||
|
||||
while (wins.hasMoreElements()) {
|
||||
let win = wins.getNext();
|
||||
|
||||
if (win.Scratchpad.uniqueName === aSourceURL) {
|
||||
win.focus();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (locationNode.parentNode.category == CATEGORY_CSS) {
|
||||
|
@ -3859,10 +3900,14 @@ CommandController.prototype = {
|
|||
* @constructor
|
||||
* @param object aWebConsole
|
||||
* The Web Console instance that owns this connection proxy.
|
||||
* @param object aOptions
|
||||
* Connection options: host and port.
|
||||
*/
|
||||
function WebConsoleConnectionProxy(aWebConsole)
|
||||
function WebConsoleConnectionProxy(aWebConsole, aOptions = {})
|
||||
{
|
||||
this.owner = aWebConsole;
|
||||
this.remoteHost = aOptions.host;
|
||||
this.remotePort = aOptions.port;
|
||||
|
||||
this._onPageError = this._onPageError.bind(this);
|
||||
this._onConsoleAPICall = this._onConsoleAPICall.bind(this);
|
||||
|
@ -3938,7 +3983,15 @@ WebConsoleConnectionProxy.prototype = {
|
|||
*/
|
||||
connect: function WCCP_connect(aCallback)
|
||||
{
|
||||
let transport = DebuggerServer.connectPipe();
|
||||
let transport;
|
||||
if (this.remoteHost) {
|
||||
transport = debuggerSocketConnect(this.remoteHost, this.remotePort);
|
||||
}
|
||||
else {
|
||||
this.initServer();
|
||||
transport = DebuggerServer.connectPipe();
|
||||
}
|
||||
|
||||
let client = this.client = new DebuggerClient(transport);
|
||||
|
||||
client.addListener("pageError", this._onPageError);
|
||||
|
@ -3948,18 +4001,58 @@ WebConsoleConnectionProxy.prototype = {
|
|||
client.addListener("fileActivity", this._onFileActivity);
|
||||
client.addListener("locationChange", this._onLocationChange);
|
||||
|
||||
client.connect(function(aType, aTraits) {
|
||||
client.listTabs(this._onListTabs.bind(this, aCallback));
|
||||
}.bind(this));
|
||||
},
|
||||
|
||||
/**
|
||||
* The "listTabs" response handler.
|
||||
*
|
||||
* @private
|
||||
* @param function [aCallback]
|
||||
* Optional function to invoke once the connection is established.
|
||||
* @param object aResponse
|
||||
* The JSON response object received from the server.
|
||||
*/
|
||||
_onListTabs: function WCCP__onListTabs(aCallback, aResponse)
|
||||
{
|
||||
let selectedTab;
|
||||
|
||||
if (this.remoteHost) {
|
||||
let tabs = [];
|
||||
for (let tab of aResponse.tabs) {
|
||||
tabs.push(tab.title);
|
||||
}
|
||||
|
||||
tabs.push(l10n.getStr("listTabs.globalConsoleActor"));
|
||||
|
||||
let selected = {};
|
||||
let result = Services.prompt.select(null,
|
||||
l10n.getStr("remoteWebConsoleSelectTabTitle"),
|
||||
l10n.getStr("remoteWebConsoleSelectTabMessage"),
|
||||
tabs.length, tabs, selected);
|
||||
|
||||
if (result && selected.value < aResponse.tabs.length) {
|
||||
selectedTab = aResponse.tabs[selected.value];
|
||||
}
|
||||
}
|
||||
else {
|
||||
selectedTab = aResponse.tabs[aResponse.selected];
|
||||
}
|
||||
|
||||
if (selectedTab) {
|
||||
this._consoleActor = selectedTab.consoleActor;
|
||||
this.owner.onLocationChange(selectedTab.url, selectedTab.title);
|
||||
}
|
||||
else {
|
||||
this._consoleActor = aResponse.consoleActor;
|
||||
}
|
||||
|
||||
let listeners = ["PageError", "ConsoleAPI", "NetworkActivity",
|
||||
"FileActivity", "LocationChange"];
|
||||
|
||||
client.connect(function(aType, aTraits) {
|
||||
client.listTabs(function(aResponse) {
|
||||
let tab = aResponse.tabs[aResponse.selected];
|
||||
this._consoleActor = tab.consoleActor;
|
||||
this.owner.onLocationChange(tab.url, tab.title);
|
||||
client.attachConsole(tab.consoleActor, listeners,
|
||||
this._onAttachConsole.bind(this, aCallback));
|
||||
}.bind(this));
|
||||
}.bind(this));
|
||||
this.client.attachConsole(this._consoleActor, listeners,
|
||||
this._onAttachConsole.bind(this, aCallback));
|
||||
},
|
||||
|
||||
/**
|
||||
|
|
|
@ -207,6 +207,7 @@ These should match what Safari and other Apple applications use on OS X Lion. --
|
|||
<!ENTITY webConsoleCmd.label "Web Console">
|
||||
<!ENTITY webConsoleCmd.accesskey "W">
|
||||
<!ENTITY webConsoleCmd.commandkey "k">
|
||||
<!ENTITY remoteWebConsoleCmd.label "Remote Web Console">
|
||||
|
||||
<!ENTITY inspectMenu.label "Inspect">
|
||||
<!ENTITY inspectMenu.accesskey "I">
|
||||
|
|
|
@ -71,6 +71,11 @@ confirmRevert.title=Revert Changes
|
|||
# comment inside /* and */.
|
||||
scratchpadIntro1=/*\n * This is a JavaScript Scratchpad.\n *\n * Enter some JavaScript, then Right Click or choose from the Execute Menu:\n * 1. Run to evaluate the selected text (%1$S),\n * 2. Inspect to bring up an Object Inspector on the result (%2$S), or,\n * 3. Display to insert the result in a comment after the selection. (%3$S)\n */\n\n
|
||||
|
||||
# LOCALIZATION NOTE (scratchpad.noargs): This error message is shown when
|
||||
# Scratchpad instance is created without any arguments. Scratchpad window
|
||||
# expects to receive its unique identifier as the first window argument.
|
||||
scratchpad.noargs=Scratchpad was created without any arguments.
|
||||
|
||||
# LOCALIZATION NOTE (notification.browserContext): This is the message displayed
|
||||
# over the top of the editor when the user has switched to browser context.
|
||||
browserContext.notification=This scratchpad executes in the Browser context.
|
||||
|
|
|
@ -145,3 +145,23 @@ maxTimersExceeded=The maximum allowed number of timers in this page was exceeded
|
|||
# Console and tries the Update button, but the new result no longer returns an
|
||||
# object that can be inspected.
|
||||
JSTerm.updateNotInspectable=After your input has been re-evaluated the result is no longer inspectable.
|
||||
|
||||
# LOCALIZATION NOTE (remoteWebConsolePromptTitle): The title displayed on the
|
||||
# Web Console prompt asking for the remote host and port to connect to.
|
||||
remoteWebConsolePromptTitle=Remote Connection
|
||||
|
||||
# LOCALIZATION NOTE (remoteWebConsolePromptMessage): The message displayed on the
|
||||
# Web Console prompt asking for the remote host and port to connect to.
|
||||
remoteWebConsolePromptMessage=Enter hostname and port number (host:port)
|
||||
|
||||
# LOCALIZATION NOTE (remoteWebConsoleSelectTabTitle): The title displayed on the
|
||||
# Web Console prompt asking the user to pick a tab to attach to.
|
||||
remoteWebConsoleSelectTabTitle=Tab list - Remote Connection
|
||||
|
||||
# LOCALIZATION NOTE (remoteWebConsoleSelectTabMessage): The message displayed on the
|
||||
# Web Console prompt asking the user to pick a tab to attach to.
|
||||
remoteWebConsoleSelectTabMessage=Select one of the tabs you want to attach to, or select the global console.
|
||||
|
||||
# LOCALIZATION NOTE (listTabs.globalConsoleActor): The string displayed for the
|
||||
# global console in the tabs selection.
|
||||
listTabs.globalConsoleActor=*Global Console*
|
||||
|
|
|
@ -1122,6 +1122,26 @@ nsTextEditorState::BindToFrame(nsTextControlFrame* aFrame)
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
struct PreDestroyer
|
||||
{
|
||||
void Init(nsIEditor* aEditor)
|
||||
{
|
||||
mNewEditor = aEditor;
|
||||
}
|
||||
~PreDestroyer()
|
||||
{
|
||||
if (mNewEditor) {
|
||||
mNewEditor->PreDestroy(true);
|
||||
}
|
||||
}
|
||||
void Swap(nsCOMPtr<nsIEditor>& aEditor)
|
||||
{
|
||||
return mNewEditor.swap(aEditor);
|
||||
}
|
||||
private:
|
||||
nsCOMPtr<nsIEditor> mNewEditor;
|
||||
};
|
||||
|
||||
nsresult
|
||||
nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
||||
{
|
||||
|
@ -1168,12 +1188,14 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
|||
bool shouldInitializeEditor = false;
|
||||
nsCOMPtr<nsIEditor> newEditor; // the editor that we might create
|
||||
nsresult rv = NS_OK;
|
||||
PreDestroyer preDestroyer;
|
||||
if (!mEditor) {
|
||||
shouldInitializeEditor = true;
|
||||
|
||||
// Create an editor
|
||||
newEditor = do_CreateInstance(kTextEditorCID, &rv);
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
preDestroyer.Init(newEditor);
|
||||
|
||||
// Make sure we clear out the non-breaking space before we initialize the editor
|
||||
rv = mBoundFrame->UpdateValueDisplay(false, true);
|
||||
|
@ -1302,7 +1324,7 @@ nsTextEditorState::PrepareEditor(const nsAString *aValue)
|
|||
|
||||
if (shouldInitializeEditor) {
|
||||
// Hold on to the newly created editor
|
||||
mEditor = newEditor;
|
||||
preDestroyer.Swap(mEditor);
|
||||
}
|
||||
|
||||
// If we have a default value, insert it under the div we created
|
||||
|
|
|
@ -104,7 +104,7 @@ nsTextEditRules::Init(nsPlaintextEditor *aEditor)
|
|||
mEditor = aEditor; // we hold a non-refcounted reference back to our editor
|
||||
nsCOMPtr<nsISelection> selection;
|
||||
mEditor->GetSelection(getter_AddRefs(selection));
|
||||
NS_ASSERTION(selection, "editor cannot get selection");
|
||||
NS_WARN_IF_FALSE(selection, "editor cannot get selection");
|
||||
|
||||
// Put in a magic br if needed. This method handles null selection,
|
||||
// which should never happen anyway
|
||||
|
|
|
@ -425,6 +425,34 @@ SuspectDOMExpandos(nsPtrHashKey<JSObject> *key, void *arg)
|
|||
return PL_DHASH_NEXT;
|
||||
}
|
||||
|
||||
bool
|
||||
CanSkipWrappedJS(nsXPCWrappedJS *wrappedJS)
|
||||
{
|
||||
JSObject *obj = wrappedJS->GetJSObjectPreserveColor();
|
||||
// If traversing wrappedJS wouldn't release it, nor
|
||||
// cause any other objects to be added to the graph, no
|
||||
// need to add it to the graph at all.
|
||||
if (nsCCUncollectableMarker::sGeneration &&
|
||||
(!obj || !xpc_IsGrayGCThing(obj)) &&
|
||||
!wrappedJS->IsSubjectToFinalization() &&
|
||||
wrappedJS->GetRootWrapper() == wrappedJS) {
|
||||
if (!wrappedJS->IsAggregatedToNative()) {
|
||||
return true;
|
||||
} else {
|
||||
nsISupports* agg = wrappedJS->GetAggregatedNativeObject();
|
||||
nsXPCOMCycleCollectionParticipant* cp = nullptr;
|
||||
CallQueryInterface(agg, &cp);
|
||||
nsISupports* canonical = nullptr;
|
||||
agg->QueryInterface(NS_GET_IID(nsCycleCollectionISupports),
|
||||
reinterpret_cast<void**>(&canonical));
|
||||
if (cp && canonical && cp->CanSkipInCC(canonical)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
XPCJSRuntime::AddXPConnectRoots(nsCycleCollectionTraversalCallback &cb)
|
||||
{
|
||||
|
@ -458,15 +486,8 @@ XPCJSRuntime::AddXPConnectRoots(nsCycleCollectionTraversalCallback &cb)
|
|||
|
||||
for (XPCRootSetElem *e = mWrappedJSRoots; e ; e = e->GetNextRoot()) {
|
||||
nsXPCWrappedJS *wrappedJS = static_cast<nsXPCWrappedJS*>(e);
|
||||
JSObject *obj = wrappedJS->GetJSObjectPreserveColor();
|
||||
// If traversing wrappedJS wouldn't release it, nor
|
||||
// cause any other objects to be added to the graph, no
|
||||
// need to add it to the graph at all.
|
||||
if (nsCCUncollectableMarker::sGeneration &&
|
||||
!cb.WantAllTraces() && (!obj || !xpc_IsGrayGCThing(obj)) &&
|
||||
!wrappedJS->IsSubjectToFinalization() &&
|
||||
wrappedJS->GetRootWrapper() == wrappedJS &&
|
||||
!wrappedJS->IsAggregatedToNative()) {
|
||||
if (!cb.WantAllTraces() &&
|
||||
CanSkipWrappedJS(wrappedJS)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
|
|
|
@ -296,50 +296,53 @@ nsTextControlFrame::EnsureEditorInitialized()
|
|||
|
||||
// Make sure that editor init doesn't do things that would kill us off
|
||||
// (especially off the script blockers it'll create for its DOM mutations).
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
{
|
||||
nsAutoScriptBlocker scriptBlocker;
|
||||
|
||||
// Time to mess with our security context... See comments in GetValue()
|
||||
// for why this is needed.
|
||||
nsCxPusher pusher;
|
||||
pusher.PushNull();
|
||||
// Time to mess with our security context... See comments in GetValue()
|
||||
// for why this is needed.
|
||||
nsCxPusher pusher;
|
||||
pusher.PushNull();
|
||||
|
||||
// Make sure that we try to focus the content even if the method fails
|
||||
class EnsureSetFocus {
|
||||
public:
|
||||
explicit EnsureSetFocus(nsTextControlFrame* aFrame)
|
||||
: mFrame(aFrame) {}
|
||||
~EnsureSetFocus() {
|
||||
if (nsContentUtils::IsFocusedContent(mFrame->GetContent()))
|
||||
mFrame->SetFocus(true, false);
|
||||
}
|
||||
private:
|
||||
nsTextControlFrame *mFrame;
|
||||
};
|
||||
EnsureSetFocus makeSureSetFocusHappens(this);
|
||||
// Make sure that we try to focus the content even if the method fails
|
||||
class EnsureSetFocus {
|
||||
public:
|
||||
explicit EnsureSetFocus(nsTextControlFrame* aFrame)
|
||||
: mFrame(aFrame) {}
|
||||
~EnsureSetFocus() {
|
||||
if (nsContentUtils::IsFocusedContent(mFrame->GetContent()))
|
||||
mFrame->SetFocus(true, false);
|
||||
}
|
||||
private:
|
||||
nsTextControlFrame *mFrame;
|
||||
};
|
||||
EnsureSetFocus makeSureSetFocusHappens(this);
|
||||
|
||||
#ifdef DEBUG
|
||||
// Make sure we are not being called again until we're finished.
|
||||
// If reentrancy happens, just pretend that we don't have an editor.
|
||||
const EditorInitializerEntryTracker tracker(*this);
|
||||
NS_ASSERTION(!tracker.EnteredMoreThanOnce(),
|
||||
"EnsureEditorInitialized has been called while a previous call was in progress");
|
||||
// Make sure we are not being called again until we're finished.
|
||||
// If reentrancy happens, just pretend that we don't have an editor.
|
||||
const EditorInitializerEntryTracker tracker(*this);
|
||||
NS_ASSERTION(!tracker.EnteredMoreThanOnce(),
|
||||
"EnsureEditorInitialized has been called while a previous call was in progress");
|
||||
#endif
|
||||
|
||||
// Create an editor for the frame, if one doesn't already exist
|
||||
nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
|
||||
NS_ASSERTION(txtCtrl, "Content not a text control element");
|
||||
nsresult rv = txtCtrl->CreateEditor();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
// Create an editor for the frame, if one doesn't already exist
|
||||
nsCOMPtr<nsITextControlElement> txtCtrl = do_QueryInterface(GetContent());
|
||||
NS_ASSERTION(txtCtrl, "Content not a text control element");
|
||||
nsresult rv = txtCtrl->CreateEditor();
|
||||
NS_ENSURE_SUCCESS(rv, rv);
|
||||
NS_ENSURE_STATE(weakFrame.IsAlive());
|
||||
|
||||
// Turn on mUseEditor so that subsequent calls will use the
|
||||
// editor.
|
||||
mUseEditor = true;
|
||||
// Turn on mUseEditor so that subsequent calls will use the
|
||||
// editor.
|
||||
mUseEditor = true;
|
||||
|
||||
// Set the selection to the beginning of the text field.
|
||||
if (weakFrame.IsAlive()) {
|
||||
SetSelectionEndPoints(0, 0);
|
||||
// Set the selection to the beginning of the text field.
|
||||
if (weakFrame.IsAlive()) {
|
||||
SetSelectionEndPoints(0, 0);
|
||||
}
|
||||
}
|
||||
|
||||
NS_ENSURE_STATE(weakFrame.IsAlive());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
|
@ -1089,8 +1092,10 @@ nsTextControlFrame::GetSelectionRange(int32_t* aSelectionStart,
|
|||
return NS_OK;
|
||||
}
|
||||
|
||||
nsContentUtils::GetSelectionInTextControl(typedSel,
|
||||
GetRootNodeAndInitializeEditor(), *aSelectionStart, *aSelectionEnd);
|
||||
mozilla::dom::Element* root = GetRootNodeAndInitializeEditor();
|
||||
NS_ENSURE_STATE(root);
|
||||
nsContentUtils::GetSelectionInTextControl(typedSel, root,
|
||||
*aSelectionStart, *aSelectionEnd);
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
|
|
@ -212,10 +212,9 @@ var NetworkHelper =
|
|||
*/
|
||||
getWindowForRequest: function NH_getWindowForRequest(aRequest)
|
||||
{
|
||||
let loadContext = this.getRequestLoadContext(aRequest);
|
||||
if (loadContext) {
|
||||
return loadContext.associatedWindow;
|
||||
}
|
||||
try {
|
||||
return this.getRequestLoadContext(aRequest).associatedWindow;
|
||||
} catch (ex) { }
|
||||
return null;
|
||||
},
|
||||
|
||||
|
@ -227,18 +226,13 @@ var NetworkHelper =
|
|||
*/
|
||||
getRequestLoadContext: function NH_getRequestLoadContext(aRequest)
|
||||
{
|
||||
if (aRequest && aRequest.notificationCallbacks) {
|
||||
try {
|
||||
return aRequest.notificationCallbacks.getInterface(Ci.nsILoadContext);
|
||||
} catch (ex) { }
|
||||
}
|
||||
try {
|
||||
return aRequest.notificationCallbacks.getInterface(Ci.nsILoadContext);
|
||||
} catch (ex) { }
|
||||
|
||||
if (aRequest && aRequest.loadGroup
|
||||
&& aRequest.loadGroup.notificationCallbacks) {
|
||||
try {
|
||||
return aRequest.loadGroup.notificationCallbacks.getInterface(Ci.nsILoadContext);
|
||||
} catch (ex) { }
|
||||
}
|
||||
try {
|
||||
return aRequest.loadGroup.notificationCallbacks.getInterface(Ci.nsILoadContext);
|
||||
} catch (ex) { }
|
||||
|
||||
return null;
|
||||
},
|
||||
|
|
|
@ -2590,16 +2590,16 @@ _global.NetworkResponseListener = NetworkResponseListener;
|
|||
* location changes.
|
||||
*
|
||||
* @constructor
|
||||
* @param object aBrowser
|
||||
* The xul:browser for which we need to track location changes.
|
||||
* @param object aWindow
|
||||
* The window for which we need to track location changes.
|
||||
* @param object aOwner
|
||||
* The listener owner which needs to implement two methods:
|
||||
* - onFileActivity(aFileURI)
|
||||
* - onLocationChange(aState, aTabURI, aPageTitle)
|
||||
*/
|
||||
function ConsoleProgressListener(aBrowser, aOwner)
|
||||
function ConsoleProgressListener(aWindow, aOwner)
|
||||
{
|
||||
this.browser = aBrowser;
|
||||
this.window = aWindow;
|
||||
this.owner = aOwner;
|
||||
}
|
||||
|
||||
|
@ -2637,6 +2637,8 @@ ConsoleProgressListener.prototype = {
|
|||
*/
|
||||
_initialized: false,
|
||||
|
||||
_webProgress: null,
|
||||
|
||||
QueryInterface: XPCOMUtils.generateQI([Ci.nsIWebProgressListener,
|
||||
Ci.nsISupportsWeakReference]),
|
||||
|
||||
|
@ -2650,8 +2652,13 @@ ConsoleProgressListener.prototype = {
|
|||
return;
|
||||
}
|
||||
|
||||
this._webProgress = this.window.QueryInterface(Ci.nsIInterfaceRequestor)
|
||||
.getInterface(Ci.nsIWebNavigation)
|
||||
.QueryInterface(Ci.nsIWebProgress);
|
||||
this._webProgress.addProgressListener(this,
|
||||
Ci.nsIWebProgress.NOTIFY_STATE_ALL);
|
||||
|
||||
this._initialized = true;
|
||||
this.browser.addProgressListener(this, Ci.nsIWebProgress.NOTIFY_STATE_ALL);
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -2768,8 +2775,7 @@ ConsoleProgressListener.prototype = {
|
|||
let isWindow = aState & Ci.nsIWebProgressListener.STATE_IS_WINDOW;
|
||||
|
||||
// Skip non-interesting states.
|
||||
if (!isNetwork || !isWindow ||
|
||||
aProgress.DOMWindow != this.browser.contentWindow) {
|
||||
if (!isNetwork || !isWindow || aProgress.DOMWindow != this.window) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2777,9 +2783,8 @@ ConsoleProgressListener.prototype = {
|
|||
this.owner.onLocationChange("start", aRequest.URI.spec, "");
|
||||
}
|
||||
else if (isStop) {
|
||||
let window = this.browser.contentWindow;
|
||||
this.owner.onLocationChange("stop", window.location.href,
|
||||
window.document.title);
|
||||
this.owner.onLocationChange("stop", this.window.location.href,
|
||||
this.window.document.title);
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -2801,11 +2806,15 @@ ConsoleProgressListener.prototype = {
|
|||
this._fileActivity = false;
|
||||
this._locationChange = false;
|
||||
|
||||
if (this.browser.removeProgressListener) {
|
||||
this.browser.removeProgressListener(this);
|
||||
try {
|
||||
this._webProgress.removeProgressListener(this);
|
||||
}
|
||||
catch (ex) {
|
||||
// This can throw during browser shutdown.
|
||||
}
|
||||
|
||||
this.browser = null;
|
||||
this._webProgress = null;
|
||||
this.window = null;
|
||||
this.owner = null;
|
||||
},
|
||||
};
|
||||
|
|
|
@ -47,15 +47,20 @@ XPCOMUtils.defineLazyModuleGetter(this, "ConsoleAPIStorage",
|
|||
* @constructor
|
||||
* @param object aConnection
|
||||
* The connection to the client, DebuggerServerConnection.
|
||||
* @param object [aTabActor]
|
||||
* Optional, the parent tab actor. This must be an instance of
|
||||
* BrowserTabActor.
|
||||
* @param object [aParentActor]
|
||||
* Optional, the parent actor.
|
||||
*/
|
||||
function WebConsoleActor(aConnection, aTabActor)
|
||||
function WebConsoleActor(aConnection, aParentActor)
|
||||
{
|
||||
this.conn = aConnection;
|
||||
if (aTabActor instanceof BrowserTabActor) {
|
||||
this._browser = aTabActor.browser;
|
||||
|
||||
if (aParentActor instanceof BrowserTabActor &&
|
||||
aParentActor.browser instanceof Ci.nsIDOMWindow) {
|
||||
this._window = aParentActor.browser;
|
||||
}
|
||||
else if (aParentActor instanceof BrowserTabActor &&
|
||||
aParentActor.browser instanceof Ci.nsIDOMElement) {
|
||||
this._window = aParentActor.browser.contentWindow;
|
||||
}
|
||||
else {
|
||||
this._window = Services.wm.getMostRecentWindow("navigator:browser");
|
||||
|
@ -73,14 +78,6 @@ function WebConsoleActor(aConnection, aTabActor)
|
|||
|
||||
WebConsoleActor.prototype =
|
||||
{
|
||||
/**
|
||||
* The xul:browser we work with. This is only available when the Web Console
|
||||
* actor is a tab actor.
|
||||
* @private
|
||||
* @type nsIDOMElement
|
||||
*/
|
||||
_browser: null,
|
||||
|
||||
/**
|
||||
* Tells if this Web Console actor is a global actor or not.
|
||||
* @private
|
||||
|
@ -137,7 +134,7 @@ WebConsoleActor.prototype =
|
|||
* The content window we work with.
|
||||
* @type nsIDOMWindow
|
||||
*/
|
||||
get window() this._browser ? this._browser.contentWindow : this._window,
|
||||
get window() this._window,
|
||||
|
||||
_window: null,
|
||||
|
||||
|
@ -220,7 +217,7 @@ WebConsoleActor.prototype =
|
|||
this._objectActorsPool = null;
|
||||
this._networkEventActorsPool = null;
|
||||
this._sandboxLocation = this.sandbox = null;
|
||||
this.conn = this._browser = this._window = null;
|
||||
this.conn = this._window = null;
|
||||
},
|
||||
|
||||
/**
|
||||
|
@ -332,29 +329,23 @@ WebConsoleActor.prototype =
|
|||
startedListeners.push(listener);
|
||||
break;
|
||||
case "FileActivity":
|
||||
if (this._isGlobalActor) {
|
||||
// The ConsoleProgressListener cannot listen for global events.
|
||||
// See bug 798764.
|
||||
break;
|
||||
}
|
||||
if (!this.consoleProgressListener) {
|
||||
this.consoleProgressListener =
|
||||
new ConsoleProgressListener(this._browser, this);
|
||||
new ConsoleProgressListener(this.window, this);
|
||||
}
|
||||
this.consoleProgressListener.startMonitor(this.consoleProgressListener.
|
||||
MONITOR_FILE_ACTIVITY);
|
||||
startedListeners.push(listener);
|
||||
break;
|
||||
case "LocationChange":
|
||||
if (this._isGlobalActor) {
|
||||
break;
|
||||
}
|
||||
if (!this.consoleProgressListener) {
|
||||
this.consoleProgressListener =
|
||||
new ConsoleProgressListener(this._browser, this);
|
||||
new ConsoleProgressListener(this.window, this);
|
||||
}
|
||||
this.consoleProgressListener.startMonitor(this.consoleProgressListener.
|
||||
MONITOR_LOCATION_CHANGE);
|
||||
startedListeners.push(listener);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return {
|
||||
|
|
|
@ -19,6 +19,7 @@ MOCHITEST_CHROME_FILES = \
|
|||
test_object_actor.html \
|
||||
test_network_get.html \
|
||||
test_network_post.html \
|
||||
test_file_uri.html \
|
||||
network_requests_iframe.html \
|
||||
data.json \
|
||||
common.js \
|
||||
|
|
|
@ -0,0 +1,97 @@
|
|||
<!DOCTYPE HTML>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf8">
|
||||
<title>Test for file activity tracking</title>
|
||||
<script type="text/javascript" src="chrome://mochikit/content/tests/SimpleTest/SimpleTest.js"></script>
|
||||
<script type="text/javascript;version=1.8" src="common.js"></script>
|
||||
<!-- Any copyright is dedicated to the Public Domain.
|
||||
- http://creativecommons.org/publicdomain/zero/1.0/ -->
|
||||
</head>
|
||||
<body>
|
||||
<p>Test for file activity tracking</p>
|
||||
|
||||
<script class="testbody" type="text/javascript;version=1.8">
|
||||
SimpleTest.waitForExplicitFinish();
|
||||
|
||||
Cu.import("resource://gre/modules/NetUtil.jsm");
|
||||
Cu.import("resource://gre/modules/FileUtils.jsm");
|
||||
|
||||
let gState;
|
||||
let gTmpFile;
|
||||
|
||||
function doFileActivity()
|
||||
{
|
||||
info("doFileActivity");
|
||||
let fileContent = "<p>hello world from bug 798764";
|
||||
|
||||
gTmpFile = FileUtils.getFile("TmpD", ["bug798764.html"]);
|
||||
gTmpFile.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, FileUtils.PERMS_FILE);
|
||||
|
||||
let fout = FileUtils.openSafeFileOutputStream(gTmpFile,
|
||||
FileUtils.MODE_WRONLY | FileUtils.MODE_CREATE | FileUtils.MODE_TRUNCATE);
|
||||
|
||||
let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"].
|
||||
createInstance(Ci.nsIScriptableUnicodeConverter);
|
||||
converter.charset = "UTF-8";
|
||||
let fileContentStream = converter.convertToInputStream(fileContent);
|
||||
|
||||
NetUtil.asyncCopy(fileContentStream, fout, addIframe);
|
||||
}
|
||||
|
||||
function addIframe(aStatus)
|
||||
{
|
||||
ok(Components.isSuccessCode(aStatus),
|
||||
"the temporary file was saved successfully");
|
||||
|
||||
let iframe = document.createElement("iframe");
|
||||
iframe.src = NetUtil.newURI(gTmpFile).spec;
|
||||
document.body.appendChild(iframe);
|
||||
}
|
||||
|
||||
function startTest()
|
||||
{
|
||||
removeEventListener("load", startTest);
|
||||
|
||||
attachConsole(["FileActivity"], onAttach);
|
||||
}
|
||||
|
||||
function onAttach(aState, aResponse)
|
||||
{
|
||||
gState = aState;
|
||||
gState.dbgClient.addListener("fileActivity", onFileActivity);
|
||||
doFileActivity();
|
||||
}
|
||||
|
||||
function onFileActivity(aType, aPacket)
|
||||
{
|
||||
is(aPacket.from, gState.actor, "fileActivity actor");
|
||||
|
||||
gState.dbgClient.removeListener("fileActivity", onFileActivity);
|
||||
|
||||
ok(/bug798764\.html$/.test(aPacket.uri), "file URI match");
|
||||
|
||||
testEnd();
|
||||
}
|
||||
|
||||
function testEnd()
|
||||
{
|
||||
if (gTmpFile) {
|
||||
gTmpFile.remove(false);
|
||||
gTmpFile = null;
|
||||
}
|
||||
|
||||
if (gState) {
|
||||
closeDebugger(gState, function() {
|
||||
gState = null;
|
||||
SimpleTest.finish();
|
||||
});
|
||||
} else {
|
||||
SimpleTest.finish();
|
||||
}
|
||||
}
|
||||
|
||||
addEventListener("load", startTest);
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
Загрузка…
Ссылка в новой задаче