michael@0: /* vim: set ts=2 et sw=2 tw=80: */ michael@0: /* Any copyright is dedicated to the Public Domain. michael@0: http://creativecommons.org/publicdomain/zero/1.0/ */ michael@0: /* Bug 653427 */ michael@0: michael@0: let tempScope = {}; michael@0: Cu.import("resource://gre/modules/NetUtil.jsm", tempScope); michael@0: Cu.import("resource://gre/modules/FileUtils.jsm", tempScope); michael@0: let NetUtil = tempScope.NetUtil; michael@0: let FileUtils = tempScope.FileUtils; michael@0: michael@0: // only finish() when correct number of tests are done michael@0: const expected = 9; michael@0: var count = 0; michael@0: function done() michael@0: { michael@0: if (++count == expected) { michael@0: cleanup(); michael@0: finish(); michael@0: } michael@0: } michael@0: michael@0: var gFile; michael@0: michael@0: var oldPrompt = Services.prompt; michael@0: var promptButton = -1; michael@0: michael@0: function test() michael@0: { michael@0: waitForExplicitFinish(); michael@0: michael@0: gFile = createTempFile("fileForBug653427.tmp"); michael@0: writeFile(gFile, "text", testUnsaved.call(this)); michael@0: michael@0: Services.prompt = { michael@0: confirmEx: function() { michael@0: return promptButton; michael@0: } michael@0: }; michael@0: michael@0: testNew(); michael@0: testSavedFile(); michael@0: michael@0: gBrowser.selectedTab = gBrowser.addTab(); michael@0: content.location = "data:text/html,

test scratchpad save file prompt on closing"; michael@0: } michael@0: michael@0: function testNew() michael@0: { michael@0: openScratchpad(function(win) { michael@0: win.Scratchpad.close(function() { michael@0: ok(win.closed, "new scratchpad window should close without prompting") michael@0: done(); michael@0: }); michael@0: }, {noFocus: true}); michael@0: } michael@0: michael@0: function testSavedFile() michael@0: { michael@0: openScratchpad(function(win) { michael@0: win.Scratchpad.filename = "test.js"; michael@0: win.Scratchpad.editor.dirty = false; michael@0: win.Scratchpad.close(function() { michael@0: ok(win.closed, "scratchpad from file with no changes should close") michael@0: done(); michael@0: }); michael@0: }, {noFocus: true}); michael@0: } michael@0: michael@0: function testUnsaved() michael@0: { michael@0: function setFilename(aScratchpad, aFile) { michael@0: aScratchpad.setFilename(aFile); michael@0: } michael@0: michael@0: testUnsavedFileCancel(setFilename); michael@0: testUnsavedFileSave(setFilename); michael@0: testUnsavedFileDontSave(setFilename); michael@0: testCancelAfterLoad(); michael@0: michael@0: function mockSaveFile(aScratchpad) { michael@0: let SaveFileStub = function (aCallback) { michael@0: /* michael@0: * An argument for aCallback must pass Components.isSuccessCode michael@0: * michael@0: * A version of isSuccessCode in JavaScript: michael@0: * function isSuccessCode(returnCode) { michael@0: * return (returnCode & 0x80000000) == 0; michael@0: * } michael@0: */ michael@0: aCallback(1); michael@0: }; michael@0: michael@0: aScratchpad.saveFile = SaveFileStub; michael@0: } michael@0: michael@0: // Run these tests again but this time without setting a filename to michael@0: // test that Scratchpad always asks for confirmation on dirty editor. michael@0: testUnsavedFileCancel(mockSaveFile); michael@0: testUnsavedFileSave(mockSaveFile); michael@0: testUnsavedFileDontSave(); michael@0: } michael@0: michael@0: function testUnsavedFileCancel(aCallback=function () {}) michael@0: { michael@0: openScratchpad(function(win) { michael@0: aCallback(win.Scratchpad, "test.js"); michael@0: win.Scratchpad.editor.dirty = true; michael@0: michael@0: promptButton = win.BUTTON_POSITION_CANCEL; michael@0: michael@0: win.Scratchpad.close(function() { michael@0: ok(!win.closed, "cancelling dialog shouldn't close scratchpad"); michael@0: win.close(); michael@0: done(); michael@0: }); michael@0: }, {noFocus: true}); michael@0: } michael@0: michael@0: // Test a regression where our confirmation dialog wasn't appearing michael@0: // after openFile calls. See bug 801982. michael@0: function testCancelAfterLoad() michael@0: { michael@0: openScratchpad(function(win) { michael@0: win.Scratchpad.setRecentFile(gFile); michael@0: win.Scratchpad.openFile(0); michael@0: win.Scratchpad.editor.dirty = true; michael@0: promptButton = win.BUTTON_POSITION_CANCEL; michael@0: michael@0: let EventStub = { michael@0: called: false, michael@0: preventDefault: function() { michael@0: EventStub.called = true; michael@0: } michael@0: }; michael@0: michael@0: win.Scratchpad.onClose(EventStub, function() { michael@0: ok(!win.closed, "cancelling dialog shouldn't close scratchpad"); michael@0: ok(EventStub.called, "aEvent.preventDefault was called"); michael@0: michael@0: win.Scratchpad.editor.dirty = false; michael@0: win.close(); michael@0: done(); michael@0: }); michael@0: }, {noFocus: true}); michael@0: } michael@0: michael@0: function testUnsavedFileSave(aCallback=function () {}) michael@0: { michael@0: openScratchpad(function(win) { michael@0: win.Scratchpad.importFromFile(gFile, true, function(status, content) { michael@0: aCallback(win.Scratchpad, gFile.path); michael@0: michael@0: let text = "new text"; michael@0: win.Scratchpad.setText(text); michael@0: michael@0: promptButton = win.BUTTON_POSITION_SAVE; michael@0: michael@0: win.Scratchpad.close(function() { michael@0: ok(win.closed, 'pressing "Save" in dialog should close scratchpad'); michael@0: readFile(gFile, function(savedContent) { michael@0: is(savedContent, text, 'prompted "Save" worked when closing scratchpad'); michael@0: done(); michael@0: }); michael@0: }); michael@0: }); michael@0: }, {noFocus: true}); michael@0: } michael@0: michael@0: function testUnsavedFileDontSave(aCallback=function () {}) michael@0: { michael@0: openScratchpad(function(win) { michael@0: aCallback(win.Scratchpad, gFile.path); michael@0: win.Scratchpad.editor.dirty = true; michael@0: michael@0: promptButton = win.BUTTON_POSITION_DONT_SAVE; michael@0: michael@0: win.Scratchpad.close(function() { michael@0: ok(win.closed, 'pressing "Don\'t Save" in dialog should close scratchpad'); michael@0: done(); michael@0: }); michael@0: }, {noFocus: true}); michael@0: } michael@0: michael@0: function cleanup() michael@0: { michael@0: Services.prompt = oldPrompt; michael@0: gFile.remove(false); michael@0: gFile = null; michael@0: } michael@0: michael@0: function createTempFile(name) michael@0: { michael@0: let file = FileUtils.getFile("TmpD", [name]); michael@0: file.createUnique(Ci.nsIFile.NORMAL_FILE_TYPE, 0666); michael@0: file.QueryInterface(Ci.nsILocalFile) michael@0: return file; michael@0: } michael@0: michael@0: function writeFile(file, content, callback) michael@0: { michael@0: let fout = Cc["@mozilla.org/network/file-output-stream;1"]. michael@0: createInstance(Ci.nsIFileOutputStream); michael@0: fout.init(file.QueryInterface(Ci.nsILocalFile), 0x02 | 0x08 | 0x20, michael@0: 0644, fout.DEFER_OPEN); michael@0: michael@0: let converter = Cc["@mozilla.org/intl/scriptableunicodeconverter"]. michael@0: createInstance(Ci.nsIScriptableUnicodeConverter); michael@0: converter.charset = "UTF-8"; michael@0: let fileContentStream = converter.convertToInputStream(content); michael@0: michael@0: NetUtil.asyncCopy(fileContentStream, fout, callback); michael@0: } michael@0: michael@0: function readFile(file, callback) michael@0: { michael@0: let channel = NetUtil.newChannel(file); michael@0: channel.contentType = "application/javascript"; michael@0: michael@0: NetUtil.asyncFetch(channel, function(inputStream, status) { michael@0: ok(Components.isSuccessCode(status), michael@0: "file was read successfully"); michael@0: michael@0: let content = NetUtil.readInputStreamToString(inputStream, michael@0: inputStream.available()); michael@0: callback(content); michael@0: }); michael@0: }