Bug 777732 - Remove compose windows recycling (part 1). r=mkmelin a=jorgk SM CLOSED TREE
--HG-- extra : amend_source : ca1429db926ffc959e12cc064f03e6ee4cbffb4b
This commit is contained in:
Родитель
bc3e45281a
Коммит
9af4160c55
|
@ -171,90 +171,6 @@ function updateEditableFields(aDisable)
|
||||||
elements[i].disabled = aDisable;
|
elements[i].disabled = aDisable;
|
||||||
}
|
}
|
||||||
|
|
||||||
var gComposeRecyclingListener = {
|
|
||||||
onClose: function() {
|
|
||||||
//Clear the subject
|
|
||||||
GetMsgSubjectElement().value = "";
|
|
||||||
// be sure to clear the transaction manager for the subject
|
|
||||||
GetMsgSubjectElement().editor.transactionManager.clear();
|
|
||||||
SetComposeWindowTitle();
|
|
||||||
|
|
||||||
//Reset recipients and attachments
|
|
||||||
awResetAllRows();
|
|
||||||
RemoveAllAttachments();
|
|
||||||
|
|
||||||
// We need to clear the identity popup menu in case the user will change them.
|
|
||||||
// It will be rebuilt later in ComposeStartup
|
|
||||||
ClearIdentityListPopup(document.getElementById("msgIdentityPopup"));
|
|
||||||
var identityElement = document.getElementById("msgIdentity");
|
|
||||||
identityElement.editable = false;
|
|
||||||
identityElement.setAttribute("type", "description");
|
|
||||||
var customizeMenuitem = document.getElementById("cmd_customizeFromAddress");
|
|
||||||
customizeMenuitem.removeAttribute("disabled");
|
|
||||||
customizeMenuitem.setAttribute("checked", "false");
|
|
||||||
|
|
||||||
// Do not listen to changes to spell check dictionary.
|
|
||||||
document.removeEventListener("spellcheck-changed", updateDocumentLanguage);
|
|
||||||
|
|
||||||
// Disconnect the observer, we'll attach a new one when recycling the
|
|
||||||
// window.
|
|
||||||
gLanguageObserver.disconnect();
|
|
||||||
|
|
||||||
// Stop observing dictionary removals.
|
|
||||||
dictionaryRemovalObserver.removeObserver();
|
|
||||||
|
|
||||||
// Stop gSpellChecker so personal dictionary is saved.
|
|
||||||
// We need to do this before disabling the editor.
|
|
||||||
enableInlineSpellCheck(false);
|
|
||||||
// clear any suggestions in the context menu
|
|
||||||
gSpellChecker.clearSuggestionsFromMenu();
|
|
||||||
gSpellChecker.clearDictionaryListFromMenu();
|
|
||||||
|
|
||||||
SetContentAndBodyAsUnmodified();
|
|
||||||
updateEditableFields(true);
|
|
||||||
|
|
||||||
// Clear the focus
|
|
||||||
awGetInputElement(1).removeAttribute('focused');
|
|
||||||
|
|
||||||
//Reset Boxes size
|
|
||||||
document.getElementById("headers-box").removeAttribute("height");
|
|
||||||
document.getElementById("appcontent").removeAttribute("height");
|
|
||||||
document.getElementById("addresses-box").removeAttribute("width");
|
|
||||||
|
|
||||||
//Reset menu options
|
|
||||||
document.getElementById("format_auto").setAttribute("checked", "true");
|
|
||||||
document.getElementById("priority_normal").setAttribute("checked", "true");
|
|
||||||
|
|
||||||
// Reset the Customize Toolbars panel/sheet if open.
|
|
||||||
if (getMailToolbox().customizing && gCustomizeSheet)
|
|
||||||
document.getElementById("customizeToolbarSheetIFrame")
|
|
||||||
.contentWindow.finishToolbarCustomization();
|
|
||||||
|
|
||||||
//Reset editor
|
|
||||||
EditorResetFontAndColorAttributes();
|
|
||||||
EditorCleanup();
|
|
||||||
gAttachmentNotifier.redetectKeywords();
|
|
||||||
|
|
||||||
//Release the nsIMsgComposeParams object
|
|
||||||
if (window.arguments && window.arguments[0])
|
|
||||||
window.arguments[0] = null;
|
|
||||||
document.getElementById("msgcomposeWindow").dispatchEvent(
|
|
||||||
new Event("compose-window-close", { bubbles: false , cancelable: true }));
|
|
||||||
if (gAutoSaveTimeout)
|
|
||||||
clearTimeout(gAutoSaveTimeout);
|
|
||||||
ReleaseGlobalVariables(); // This line must be the last in onClose();
|
|
||||||
},
|
|
||||||
|
|
||||||
onReopen: function(params) {
|
|
||||||
InitializeGlobalVariables();
|
|
||||||
ComposeStartup(true, params);
|
|
||||||
|
|
||||||
var event = document.createEvent('Events');
|
|
||||||
event.initEvent('compose-window-reopen', false, true);
|
|
||||||
document.getElementById("msgcomposeWindow").dispatchEvent(event);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var PrintPreviewListener = {
|
var PrintPreviewListener = {
|
||||||
getPrintPreviewBrowser: function() {
|
getPrintPreviewBrowser: function() {
|
||||||
var browser = document.getElementById("cppBrowser");
|
var browser = document.getElementById("cppBrowser");
|
||||||
|
@ -379,7 +295,7 @@ var stateListener = {
|
||||||
if (gMsgCompose)
|
if (gMsgCompose)
|
||||||
gMsgCompose.onSendNotPerformed(null, Components.results.NS_ERROR_ABORT);
|
gMsgCompose.onSendNotPerformed(null, Components.results.NS_ERROR_ABORT);
|
||||||
|
|
||||||
MsgComposeCloseWindow(true);
|
MsgComposeCloseWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// else if we failed to save, and we're autosaving, need to re-mark the editor
|
// else if we failed to save, and we're autosaving, need to re-mark the editor
|
||||||
|
@ -1671,8 +1587,8 @@ function DoCommandClose()
|
||||||
if (gMsgCompose)
|
if (gMsgCompose)
|
||||||
gMsgCompose.onSendNotPerformed(null, Components.results.NS_ERROR_ABORT);
|
gMsgCompose.onSendNotPerformed(null, Components.results.NS_ERROR_ABORT);
|
||||||
|
|
||||||
// note: if we're not caching this window, this destroys it for us
|
// This destroys the window for us.
|
||||||
MsgComposeCloseWindow(true);
|
MsgComposeCloseWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -2102,10 +2018,6 @@ var dictionaryRemovalObserver =
|
||||||
},
|
},
|
||||||
|
|
||||||
removeObserver: function() {
|
removeObserver: function() {
|
||||||
// We need to protect against double removal:
|
|
||||||
// The window can be recycled and later destroyed (at shutdown or when the
|
|
||||||
// composition style changes from HTML to plain text or vice versa) or
|
|
||||||
// only destroyed if it was never recycled before.
|
|
||||||
if (this.isAdded) {
|
if (this.isAdded) {
|
||||||
Services.obs.removeObserver(this, "spellcheck-dictionary-remove");
|
Services.obs.removeObserver(this, "spellcheck-dictionary-remove");
|
||||||
this.isAdded = false;
|
this.isAdded = false;
|
||||||
|
@ -2113,7 +2025,7 @@ var dictionaryRemovalObserver =
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function ComposeStartup(recycled, aParams)
|
function ComposeStartup(aParams)
|
||||||
{
|
{
|
||||||
// Findbar overlay
|
// Findbar overlay
|
||||||
if (!document.getElementById("findbar-replaceButton")) {
|
if (!document.getElementById("findbar-replaceButton")) {
|
||||||
|
@ -2297,11 +2209,7 @@ function ComposeStartup(recycled, aParams)
|
||||||
var editorElement = GetCurrentEditorElement();
|
var editorElement = GetCurrentEditorElement();
|
||||||
gMsgCompose = MailServices.compose.initCompose(params, window, editorElement.docShell);
|
gMsgCompose = MailServices.compose.initCompose(params, window, editorElement.docShell);
|
||||||
|
|
||||||
// Set the close listener.
|
|
||||||
gMsgCompose.recyclingListener = gComposeRecyclingListener;
|
|
||||||
gMsgCompose.addMsgSendListener(gSendListener);
|
gMsgCompose.addMsgSendListener(gSendListener);
|
||||||
// Lets the compose object know that we are dealing with a recycled window.
|
|
||||||
gMsgCompose.recycledWindow = recycled;
|
|
||||||
|
|
||||||
document.getElementById("returnReceiptMenu")
|
document.getElementById("returnReceiptMenu")
|
||||||
.setAttribute('checked', gMsgCompose.compFields.returnReceipt);
|
.setAttribute('checked', gMsgCompose.compFields.returnReceipt);
|
||||||
|
@ -2314,32 +2222,25 @@ function ComposeStartup(recycled, aParams)
|
||||||
SetCompositionAsPerDeliveryFormat(gSendFormat);
|
SetCompositionAsPerDeliveryFormat(gSendFormat);
|
||||||
SelectDeliveryFormatMenuOption(gSendFormat);
|
SelectDeliveryFormatMenuOption(gSendFormat);
|
||||||
|
|
||||||
// If recycle, editor is already created.
|
let editortype = gMsgCompose.composeHTML ? "htmlmail" : "textmail";
|
||||||
if (!recycled)
|
editorElement.makeEditable(editortype, true);
|
||||||
|
|
||||||
|
// setEditorType MUST be called before setContentWindow
|
||||||
|
if (gMsgCompose.composeHTML)
|
||||||
{
|
{
|
||||||
let editortype = gMsgCompose.composeHTML ? "htmlmail" : "textmail";
|
initLocalFontFaceMenu(document.getElementById("FontFacePopup"));
|
||||||
editorElement.makeEditable(editortype, true);
|
|
||||||
|
|
||||||
// setEditorType MUST be called before setContentWindow
|
|
||||||
if (gMsgCompose.composeHTML)
|
|
||||||
{
|
|
||||||
initLocalFontFaceMenu(document.getElementById("FontFacePopup"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// We are editing in plain text mode.
|
|
||||||
// The SetCompositionAsPerDeliveryFormat call above already hid
|
|
||||||
// the HTML toolbar, format and insert menus.
|
|
||||||
// Also remove the delivery format from the options menu.
|
|
||||||
// We only do that when the window is first created ("!recycled")
|
|
||||||
// as we will never need to restore it since a plain text window will
|
|
||||||
// never be used for a HTML composition.
|
|
||||||
document.getElementById("outputFormatMenu").setAttribute("hidden", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do setup common to Message Composer and Web Composer.
|
|
||||||
EditorSharedStartup();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// We are editing in plain text mode.
|
||||||
|
// The SetCompositionAsPerDeliveryFormat call above already hid
|
||||||
|
// the HTML toolbar, format and insert menus.
|
||||||
|
// Also remove the delivery format from the options menu.
|
||||||
|
document.getElementById("outputFormatMenu").setAttribute("hidden", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do setup common to Message Composer and Web Composer.
|
||||||
|
EditorSharedStartup();
|
||||||
|
|
||||||
if (params.bodyIsLink)
|
if (params.bodyIsLink)
|
||||||
{
|
{
|
||||||
|
@ -2370,33 +2271,16 @@ function ComposeStartup(recycled, aParams)
|
||||||
|
|
||||||
gMsgCompose.RegisterStateListener(stateListener);
|
gMsgCompose.RegisterStateListener(stateListener);
|
||||||
|
|
||||||
if (recycled)
|
// Add an observer to be called when document is done loading,
|
||||||
{
|
// which creates the editor.
|
||||||
InitEditor();
|
try {
|
||||||
|
GetCurrentCommandManager().
|
||||||
|
addCommandObserver(gMsgEditorCreationObserver, "obs_documentCreated");
|
||||||
|
|
||||||
if (gMsgCompose.composeHTML)
|
// Load empty page to create the editor.
|
||||||
{
|
editorElement.webNavigation.loadURI("about:blank", 0, null, null, null);
|
||||||
// Force color picker on toolbar to show document colors.
|
} catch (e) {
|
||||||
onFontColorChange();
|
Components.utils.reportError(e);
|
||||||
onBackgroundColorChange();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset the priority field for recycled windows.
|
|
||||||
updatePriorityToolbarButton("Normal");
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// Add an observer to be called when document is done loading,
|
|
||||||
// which creates the editor.
|
|
||||||
try {
|
|
||||||
GetCurrentCommandManager().
|
|
||||||
addCommandObserver(gMsgEditorCreationObserver, "obs_documentCreated");
|
|
||||||
|
|
||||||
// Load empty page to create the editor.
|
|
||||||
editorElement.webNavigation.loadURI("about:blank", 0, null, null, null);
|
|
||||||
} catch (e) {
|
|
||||||
Components.utils.reportError(e);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
gEditingDraft = gMsgCompose.compFields.draftId;
|
gEditingDraft = gMsgCompose.compFields.draftId;
|
||||||
|
@ -2456,7 +2340,7 @@ function WizCallback(state)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The account wizard is still closing so we can't close just yet
|
// The account wizard is still closing so we can't close just yet
|
||||||
setTimeout(MsgComposeCloseWindow, 0, false); // Don't recycle a bogus window
|
setTimeout(MsgComposeCloseWindow, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2495,14 +2379,14 @@ function ComposeLoad()
|
||||||
selectNode.appendItem(other_headers_Array[i] + ":", "addr_other");
|
selectNode.appendItem(other_headers_Array[i] + ":", "addr_other");
|
||||||
}
|
}
|
||||||
if (state)
|
if (state)
|
||||||
ComposeStartup(false, null);
|
ComposeStartup(null);
|
||||||
}
|
}
|
||||||
catch (ex) {
|
catch (ex) {
|
||||||
Components.utils.reportError(ex);
|
Components.utils.reportError(ex);
|
||||||
Services.prompt.alert(window, getComposeBundle().getString("initErrorDlogTitle"),
|
Services.prompt.alert(window, getComposeBundle().getString("initErrorDlogTitle"),
|
||||||
getComposeBundle().getString("initErrorDlgMessage"));
|
getComposeBundle().getString("initErrorDlgMessage"));
|
||||||
|
|
||||||
MsgComposeCloseWindow(false); // Don't try to recycle a bogus window
|
MsgComposeCloseWindow();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3664,10 +3548,10 @@ function SetContentAndBodyAsUnmodified()
|
||||||
gContentChanged = false;
|
gContentChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function MsgComposeCloseWindow(recycleIt)
|
function MsgComposeCloseWindow()
|
||||||
{
|
{
|
||||||
if (gMsgCompose)
|
if (gMsgCompose)
|
||||||
gMsgCompose.CloseWindow(recycleIt);
|
gMsgCompose.CloseWindow();
|
||||||
else
|
else
|
||||||
window.close();
|
window.close();
|
||||||
}
|
}
|
||||||
|
@ -4993,9 +4877,8 @@ function InitEditor()
|
||||||
editor.addOverrideStyleSheet("chrome://messenger/content/composerOverlay.css");
|
editor.addOverrideStyleSheet("chrome://messenger/content/composerOverlay.css");
|
||||||
gMsgCompose.initEditor(editor, window.content);
|
gMsgCompose.initEditor(editor, window.content);
|
||||||
|
|
||||||
// We always go through this function everytime we init an editor, be it a
|
// We always go through this function everytime we init an editor.
|
||||||
// recycled editor, or a fresh one. First step is making sure we can spell
|
// First step is making sure we can spell check.
|
||||||
// check.
|
|
||||||
gSpellChecker.init(editor);
|
gSpellChecker.init(editor);
|
||||||
document.getElementById('menu_inlineSpellCheck')
|
document.getElementById('menu_inlineSpellCheck')
|
||||||
.setAttribute('disabled', !gSpellChecker.canSpellCheck);
|
.setAttribute('disabled', !gSpellChecker.canSpellCheck);
|
||||||
|
|
|
@ -73,8 +73,7 @@ function onComposerReOpen()
|
||||||
|
|
||||||
addEventListener("load", smimeComposeOnLoad, false);
|
addEventListener("load", smimeComposeOnLoad, false);
|
||||||
|
|
||||||
// this function gets called multiple times,
|
// this function gets called multiple times.
|
||||||
// but only on first open, not on composer recycling
|
|
||||||
function smimeComposeOnLoad()
|
function smimeComposeOnLoad()
|
||||||
{
|
{
|
||||||
removeEventListener("load", smimeComposeOnLoad, false);
|
removeEventListener("load", smimeComposeOnLoad, false);
|
||||||
|
|
|
@ -554,42 +554,6 @@ function test_disabled_attachment_reminder() {
|
||||||
Services.prefs.setBoolPref(kReminderPref, true);
|
Services.prefs.setBoolPref(kReminderPref, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Bug 1099866
|
|
||||||
* Check if reminder does not stay open on compose window reopen
|
|
||||||
* due to window recycling.
|
|
||||||
*/
|
|
||||||
function test_recycling_attachment_reminder() {
|
|
||||||
let recycledWindows = Services.prefs.getIntPref("mail.compose.max_recycled_windows");
|
|
||||||
assert_true(recycledWindows > 0);
|
|
||||||
// Open a sample message with no attachment keywords.
|
|
||||||
let cwc = open_compose_new_mail();
|
|
||||||
setupComposeWin(cwc, "test@example.invalid", "Testing recycling a reminder!",
|
|
||||||
"Some body...");
|
|
||||||
|
|
||||||
// There should be no attachment notification.
|
|
||||||
assert_automatic_reminder_state(cwc, false);
|
|
||||||
|
|
||||||
// Add some keyword so the automatic notification
|
|
||||||
// could potentially show up.
|
|
||||||
setupComposeWin(cwc, "", "", " and look for your attachment!");
|
|
||||||
// Give the notification time to appear. It should.
|
|
||||||
wait_for_reminder_state(cwc, true);
|
|
||||||
|
|
||||||
close_compose_window(cwc, true);
|
|
||||||
|
|
||||||
// Another compose window without any keywords.
|
|
||||||
cwc = open_compose_new_mail();
|
|
||||||
setupComposeWin(cwc, "test@example.invalid", "Testing reminder after recycling!",
|
|
||||||
"Some body...");
|
|
||||||
|
|
||||||
// There should be no attachment notification.
|
|
||||||
assert_automatic_reminder_state(cwc, false);
|
|
||||||
|
|
||||||
close_compose_window(cwc);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Click the send button and handle the send error dialog popping up.
|
* Click the send button and handle the send error dialog popping up.
|
||||||
* It will return us back to the compose window.
|
* It will return us back to the compose window.
|
||||||
|
|
|
@ -159,8 +159,10 @@ function test_encoding_upgrade_html_compose() {
|
||||||
throw new Error("Chinese text not in msg; CHINESE=" + CHINESE +
|
throw new Error("Chinese text not in msg; CHINESE=" + CHINESE +
|
||||||
", draftMsg2Content=" + draftMsg2Content);
|
", draftMsg2Content=" + draftMsg2Content);
|
||||||
|
|
||||||
// Ctrl+Shift+Return = Send Later
|
compWin.window.setTimeout(function() {
|
||||||
compWin.keypress(null, "VK_RETURN", {shiftKey: true, accelKey: true});
|
// Ctrl+Shift+Return = Send Later
|
||||||
|
compWin.keypress(null, "VK_RETURN", {shiftKey: true, accelKey: true});
|
||||||
|
}, 0);
|
||||||
|
|
||||||
be_in_folder(outboxFolder);
|
be_in_folder(outboxFolder);
|
||||||
let outMsg = select_click_row(0);
|
let outMsg = select_click_row(0);
|
||||||
|
@ -232,8 +234,10 @@ function test_encoding_upgrade_plaintext_compose() {
|
||||||
throw new Error("Chinese text not in msg; CHINESE=" + CHINESE +
|
throw new Error("Chinese text not in msg; CHINESE=" + CHINESE +
|
||||||
", draftMsg2Content=" + draftMsg2Content);
|
", draftMsg2Content=" + draftMsg2Content);
|
||||||
|
|
||||||
// Ctrl+Shift+Return = Send Later.
|
compWin.window.setTimeout(function() {
|
||||||
compWin.keypress(null, "VK_RETURN", {shiftKey: true, accelKey: true});
|
// Ctrl+Shift+Return = Send Later.
|
||||||
|
compWin.keypress(null, "VK_RETURN", {shiftKey: true, accelKey: true});
|
||||||
|
}, 0);
|
||||||
|
|
||||||
be_in_folder(outboxFolder);
|
be_in_folder(outboxFolder);
|
||||||
let outMsg = select_click_row(0);
|
let outMsg = select_click_row(0);
|
||||||
|
|
|
@ -143,7 +143,7 @@ function test_save_delivery_format() {
|
||||||
close_compose_window(cwc);
|
close_compose_window(cwc);
|
||||||
|
|
||||||
// Open a new composition see if the menu is again at default value, not the one
|
// Open a new composition see if the menu is again at default value, not the one
|
||||||
// chosen above, even in a recycled compose window.
|
// chosen above.
|
||||||
cwc = open_compose_new_mail();
|
cwc = open_compose_new_mail();
|
||||||
|
|
||||||
assert_format_value("format_auto", Ci.nsIMsgCompSendFormat.AskUser);
|
assert_format_value("format_auto", Ci.nsIMsgCompSendFormat.AskUser);
|
||||||
|
|
|
@ -91,13 +91,6 @@ interface nsIMsgComposeNotificationType
|
||||||
native nsString(nsString);
|
native nsString(nsString);
|
||||||
[ref] native nsStringRef(nsString);
|
[ref] native nsStringRef(nsString);
|
||||||
|
|
||||||
/* recycling listener interface */
|
|
||||||
[scriptable, uuid(0b28cc56-1dd2-11b2-bbe4-99e6a314f8ba)]
|
|
||||||
interface nsIMsgComposeRecyclingListener : nsISupports {
|
|
||||||
void onClose();
|
|
||||||
void onReopen(in nsIMsgComposeParams params);
|
|
||||||
};
|
|
||||||
|
|
||||||
[scriptable, uuid(c6544b6b-06dd-43ac-89b5-949d7c81bb7b)]
|
[scriptable, uuid(c6544b6b-06dd-43ac-89b5-949d7c81bb7b)]
|
||||||
interface nsIMsgCompose : nsIMsgSendListener {
|
interface nsIMsgCompose : nsIMsgSendListener {
|
||||||
|
|
||||||
|
@ -140,7 +133,7 @@ interface nsIMsgCompose : nsIMsgSendListener {
|
||||||
in string accountKey);
|
in string accountKey);
|
||||||
|
|
||||||
/* ... */
|
/* ... */
|
||||||
void CloseWindow(in boolean reclycleIt);
|
void CloseWindow();
|
||||||
|
|
||||||
/* ... */
|
/* ... */
|
||||||
void abort();
|
void abort();
|
||||||
|
@ -284,12 +277,6 @@ interface nsIMsgCompose : nsIMsgSendListener {
|
||||||
/* ... */
|
/* ... */
|
||||||
[noscript] void getQuotingToFollow(out boolean quotingToFollow);
|
[noscript] void getQuotingToFollow(out boolean quotingToFollow);
|
||||||
|
|
||||||
/* ... */
|
|
||||||
attribute nsIMsgComposeRecyclingListener recyclingListener;
|
|
||||||
|
|
||||||
/* ... */
|
|
||||||
attribute boolean recycledWindow;
|
|
||||||
|
|
||||||
readonly attribute string originalMsgURI;
|
readonly attribute string originalMsgURI;
|
||||||
|
|
||||||
attribute boolean deleteDraft;
|
attribute boolean deleteDraft;
|
||||||
|
|
|
@ -46,8 +46,7 @@ interface nsIMsgComposeService : nsISupports {
|
||||||
void OpenComposeWindowWithParams(in string msgComposeWindowURL, in nsIMsgComposeParams params);
|
void OpenComposeWindowWithParams(in string msgComposeWindowURL, in nsIMsgComposeParams params);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an nsIMsgCompose instance, initalizes it, and manages the window
|
* Creates an nsIMsgCompose instance and initalizes it.
|
||||||
* recycling cache.
|
|
||||||
*
|
*
|
||||||
* @param aParams An nsIMsgComposeParams object containing the initial
|
* @param aParams An nsIMsgComposeParams object containing the initial
|
||||||
* details for the compose.
|
* details for the compose.
|
||||||
|
@ -73,8 +72,6 @@ interface nsIMsgComposeService : nsISupports {
|
||||||
readonly attribute boolean logComposePerformance;
|
readonly attribute boolean logComposePerformance;
|
||||||
|
|
||||||
[noscript] boolean determineComposeHTML(in nsIMsgIdentity aIdentity, in MSG_ComposeFormat aFormat);
|
[noscript] boolean determineComposeHTML(in nsIMsgIdentity aIdentity, in MSG_ComposeFormat aFormat);
|
||||||
[noscript] void cacheWindow(in mozIDOMWindowProxy aWindow, in boolean aComposeHTML, in nsIMsgComposeRecyclingListener listener);
|
|
||||||
boolean isCachedWindow(in mozIDOMWindowProxy aWindow);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* given a mailto url, parse the attributes and turn them into a nsIMsgComposeParams object
|
* given a mailto url, parse the attributes and turn them into a nsIMsgComposeParams object
|
||||||
|
@ -130,7 +127,7 @@ interface nsIMsgComposeService : nsISupports {
|
||||||
in nsIMsgCompose aMsgCompose);
|
in nsIMsgCompose aMsgCompose);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When an editor docShell is being closed (or recycled), you should
|
* When an editor docShell is being closed, you should
|
||||||
* unregister it from this service. nsIMsgCompose normally calls this
|
* unregister it from this service. nsIMsgCompose normally calls this
|
||||||
* automatically for items passed to initCompose.
|
* automatically for items passed to initCompose.
|
||||||
*
|
*
|
||||||
|
|
|
@ -187,7 +187,6 @@ nsMsgCompose::nsMsgCompose()
|
||||||
prefBranch->GetBoolPref("converter.html2txt.structs", &mConvertStructs);
|
prefBranch->GetBoolPref("converter.html2txt.structs", &mConvertStructs);
|
||||||
|
|
||||||
m_composeHTML = false;
|
m_composeHTML = false;
|
||||||
mRecycledWindow = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -610,17 +609,6 @@ nsMsgCompose::ConvertAndLoadComposeWindow(nsString& aPrefix,
|
||||||
TranslateLineEnding(aBuf);
|
TranslateLineEnding(aBuf);
|
||||||
TranslateLineEnding(aSignature);
|
TranslateLineEnding(aSignature);
|
||||||
|
|
||||||
// We're going to be inserting stuff, and MsgComposeCommands
|
|
||||||
// may have set the editor to readonly in the recycled case.
|
|
||||||
// So set it back to writable.
|
|
||||||
// Note! enableEditableFields in gComposeRecyclingListener::onReopen
|
|
||||||
// will redundantly set this flag to writable, but it gets there
|
|
||||||
// too late.
|
|
||||||
uint32_t flags = 0;
|
|
||||||
m_editor->GetFlags(&flags);
|
|
||||||
flags &= ~nsIPlaintextEditor::eEditorReadonlyMask;
|
|
||||||
m_editor->SetFlags(flags);
|
|
||||||
|
|
||||||
m_editor->EnableUndo(false);
|
m_editor->EnableUndo(false);
|
||||||
|
|
||||||
// Ok - now we need to figure out the charset of the aBuf we are going to send
|
// Ok - now we need to figure out the charset of the aBuf we are going to send
|
||||||
|
@ -1488,34 +1476,6 @@ NS_IMETHODIMP nsMsgCompose::SendMsg(MSG_DeliverMode deliverMode, nsIMsgIdentity
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
// XXX when do we break this ref to the listener?
|
|
||||||
NS_IMETHODIMP nsMsgCompose::SetRecyclingListener(nsIMsgComposeRecyclingListener *aRecyclingListener)
|
|
||||||
{
|
|
||||||
mRecyclingListener = aRecyclingListener;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP nsMsgCompose::GetRecyclingListener(nsIMsgComposeRecyclingListener **aRecyclingListener)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aRecyclingListener);
|
|
||||||
*aRecyclingListener = mRecyclingListener;
|
|
||||||
NS_IF_ADDREF(*aRecyclingListener);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* attribute boolean recycledWindow; */
|
|
||||||
NS_IMETHODIMP nsMsgCompose::GetRecycledWindow(bool *aRecycledWindow)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aRecycledWindow);
|
|
||||||
*aRecycledWindow = mRecycledWindow;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
NS_IMETHODIMP nsMsgCompose::SetRecycledWindow(bool aRecycledWindow)
|
|
||||||
{
|
|
||||||
mRecycledWindow = aRecycledWindow;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* attribute boolean deleteDraft */
|
/* attribute boolean deleteDraft */
|
||||||
NS_IMETHODIMP nsMsgCompose::GetDeleteDraft(bool *aDeleteDraft)
|
NS_IMETHODIMP nsMsgCompose::GetDeleteDraft(bool *aDeleteDraft)
|
||||||
{
|
{
|
||||||
|
@ -1553,7 +1513,7 @@ bool nsMsgCompose::IsLastWindow()
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP nsMsgCompose::CloseWindow(bool recycleIt)
|
NS_IMETHODIMP nsMsgCompose::CloseWindow(void)
|
||||||
{
|
{
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
|
@ -1569,55 +1529,13 @@ NS_IMETHODIMP nsMsgCompose::CloseWindow(bool recycleIt)
|
||||||
// temporary files.
|
// temporary files.
|
||||||
mMsgSend = nullptr;
|
mMsgSend = nullptr;
|
||||||
|
|
||||||
recycleIt = recycleIt && !IsLastWindow();
|
|
||||||
if (recycleIt)
|
|
||||||
{
|
|
||||||
rv = composeService->CacheWindow(m_window, m_composeHTML, mRecyclingListener);
|
|
||||||
if (NS_SUCCEEDED(rv))
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIHTMLEditor> htmlEditor (do_QueryInterface(m_editor));
|
|
||||||
NS_ASSERTION(htmlEditor, "no editor");
|
|
||||||
if (htmlEditor)
|
|
||||||
{
|
|
||||||
// XXX clear undo txn manager?
|
|
||||||
|
|
||||||
rv = m_editor->EnableUndo(false);
|
|
||||||
NS_ENSURE_SUCCESS(rv,rv);
|
|
||||||
|
|
||||||
rv = htmlEditor->RebuildDocumentFromSource(EmptyString());
|
|
||||||
NS_ENSURE_SUCCESS(rv,rv);
|
|
||||||
|
|
||||||
rv = m_editor->EnableUndo(true);
|
|
||||||
NS_ENSURE_SUCCESS(rv,rv);
|
|
||||||
|
|
||||||
SetBodyModified(false);
|
|
||||||
}
|
|
||||||
if (mRecyclingListener)
|
|
||||||
{
|
|
||||||
mRecyclingListener->OnClose();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* In order to really free the memory, we need to call the JS garbage collector for our window.
|
|
||||||
* If we don't call GC, the nsIMsgCompose object held by JS will not be released despite we set
|
|
||||||
* the JS global that held it to null. Each time we reopen a recycled window, we allocate a new
|
|
||||||
* nsIMsgCompose that we really need to be released when we recycle the window. In fact despite
|
|
||||||
* we call GC here, the release won't occur right away. But if we don't call it, the release
|
|
||||||
* will happen only when we physically close the window which will happen only on quit.
|
|
||||||
*/
|
|
||||||
nsJSContext::PokeGC(JS::gcreason::NSJSCONTEXT_DESTROY);
|
|
||||||
}
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//We are going away for real, we need to do some clean up first
|
//We are going away for real, we need to do some clean up first
|
||||||
if (m_baseWindow)
|
if (m_baseWindow)
|
||||||
{
|
{
|
||||||
if (m_editor)
|
if (m_editor)
|
||||||
{
|
{
|
||||||
/* The editor will be destroyed during yje close window.
|
// The editor will be destroyed during the close window.
|
||||||
* Set it to null to be sure we won't use it anymore
|
// Set it to null to be sure we won't use it anymore.
|
||||||
*/
|
|
||||||
m_editor = nullptr;
|
m_editor = nullptr;
|
||||||
}
|
}
|
||||||
nsIBaseWindow * window = m_baseWindow;
|
nsIBaseWindow * window = m_baseWindow;
|
||||||
|
@ -1625,6 +1543,7 @@ NS_IMETHODIMP nsMsgCompose::CloseWindow(bool recycleIt)
|
||||||
rv = window->Destroy();
|
rv = window->Destroy();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
m_window = nullptr;
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -3759,7 +3678,7 @@ nsresult nsMsgComposeSendListener::OnStopSending(const char *aMsgID, nsresult aS
|
||||||
progress->CloseProgressDialog(false);
|
progress->CloseProgressDialog(false);
|
||||||
}
|
}
|
||||||
if (hasDomWindow)
|
if (hasDomWindow)
|
||||||
msgCompose->CloseWindow(true);
|
msgCompose->CloseWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -3772,8 +3691,8 @@ nsresult nsMsgComposeSendListener::OnStopSending(const char *aMsgID, nsresult aS
|
||||||
progress->CloseProgressDialog(false);
|
progress->CloseProgressDialog(false);
|
||||||
}
|
}
|
||||||
if (hasDomWindow)
|
if (hasDomWindow)
|
||||||
msgCompose->CloseWindow(true); // if we fail on the simple GetFcc call, close the window to be safe and avoid
|
msgCompose->CloseWindow(); // if we fail on the simple GetFcc call, close the window to be safe and avoid
|
||||||
// windows hanging around to prevent the app from exiting.
|
// windows hanging around to prevent the app from exiting.
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove the current draft msg when sending draft is done.
|
// Remove the current draft msg when sending draft is done.
|
||||||
|
@ -3875,7 +3794,7 @@ nsMsgComposeSendListener::OnStopCopy(nsresult aStatus)
|
||||||
msgCompose->SetDeleteDraft(true);
|
msgCompose->SetDeleteDraft(true);
|
||||||
RemoveCurrentDraftMessage(msgCompose, true);
|
RemoveCurrentDraftMessage(msgCompose, true);
|
||||||
}
|
}
|
||||||
msgCompose->CloseWindow(true);
|
msgCompose->CloseWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
msgCompose->ClearMessageSend();
|
msgCompose->ClearMessageSend();
|
||||||
|
|
|
@ -113,8 +113,6 @@ protected:
|
||||||
QuotingOutputStreamListener *mQuoteStreamListener;
|
QuotingOutputStreamListener *mQuoteStreamListener;
|
||||||
nsCOMPtr<nsIOutputStream> mBaseStream;
|
nsCOMPtr<nsIOutputStream> mBaseStream;
|
||||||
|
|
||||||
nsCOMPtr<nsIMsgComposeRecyclingListener> mRecyclingListener;
|
|
||||||
bool mRecycledWindow;
|
|
||||||
nsCOMPtr<nsIMsgSend> mMsgSend; // for composition back end
|
nsCOMPtr<nsIMsgSend> mMsgSend; // for composition back end
|
||||||
nsCOMPtr<nsIMsgProgress> mProgress; // use by the back end to report progress to the front end
|
nsCOMPtr<nsIMsgProgress> mProgress; // use by the back end to report progress to the front end
|
||||||
|
|
||||||
|
|
|
@ -72,8 +72,6 @@
|
||||||
|
|
||||||
#define DEFAULT_CHROME "chrome://messenger/content/messengercompose/messengercompose.xul"
|
#define DEFAULT_CHROME "chrome://messenger/content/messengercompose/messengercompose.xul"
|
||||||
|
|
||||||
#define PREF_MAIL_COMPOSE_MAXRECYCLEDWINDOWS "mail.compose.max_recycled_windows"
|
|
||||||
|
|
||||||
#define PREF_MAILNEWS_REPLY_QUOTING_SELECTION "mailnews.reply_quoting_selection"
|
#define PREF_MAILNEWS_REPLY_QUOTING_SELECTION "mailnews.reply_quoting_selection"
|
||||||
#define PREF_MAILNEWS_REPLY_QUOTING_SELECTION_MULTI_WORD "mailnews.reply_quoting_selection.multi_word"
|
#define PREF_MAILNEWS_REPLY_QUOTING_SELECTION_MULTI_WORD "mailnews.reply_quoting_selection.multi_word"
|
||||||
#define PREF_MAILNEWS_REPLY_QUOTING_SELECTION_ONLY_IF "mailnews.reply_quoting_selection.only_if_chars"
|
#define PREF_MAILNEWS_REPLY_QUOTING_SELECTION_ONLY_IF "mailnews.reply_quoting_selection.only_if_chars"
|
||||||
|
@ -118,45 +116,21 @@ nsMsgComposeService::nsMsgComposeService()
|
||||||
mPreviousTime = mStartTime;
|
mPreviousTime = mStartTime;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
mMaxRecycledWindows = 0;
|
|
||||||
mCachedWindows = nullptr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMPL_ISUPPORTS(nsMsgComposeService,
|
NS_IMPL_ISUPPORTS(nsMsgComposeService,
|
||||||
nsIMsgComposeService,
|
nsIMsgComposeService,
|
||||||
nsIObserver,
|
|
||||||
ICOMMANDLINEHANDLER,
|
ICOMMANDLINEHANDLER,
|
||||||
nsISupportsWeakReference)
|
nsISupportsWeakReference)
|
||||||
|
|
||||||
nsMsgComposeService::~nsMsgComposeService()
|
nsMsgComposeService::~nsMsgComposeService()
|
||||||
{
|
{
|
||||||
if (mCachedWindows)
|
|
||||||
{
|
|
||||||
DeleteCachedWindows();
|
|
||||||
delete [] mCachedWindows;
|
|
||||||
}
|
|
||||||
|
|
||||||
mOpenComposeWindows.Clear();
|
mOpenComposeWindows.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsMsgComposeService::Init()
|
nsresult nsMsgComposeService::Init()
|
||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
nsresult rv = NS_OK;
|
||||||
// Register observers
|
|
||||||
|
|
||||||
// Register for quit application and profile change, we will need to clear the cache.
|
|
||||||
nsCOMPtr<nsIObserverService> observerService =
|
|
||||||
mozilla::services::GetObserverService();
|
|
||||||
if (observerService)
|
|
||||||
{
|
|
||||||
rv = observerService->AddObserver(this, "quit-application", true);
|
|
||||||
rv = observerService->AddObserver(this, "profile-do-change", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Register some pref observer
|
|
||||||
nsCOMPtr<nsIPrefBranch> pbi = do_GetService(NS_PREFSERVICE_CONTRACTID);
|
|
||||||
if (pbi)
|
|
||||||
rv = pbi->AddObserver(PREF_MAIL_COMPOSE_MAXRECYCLEDWINDOWS, this, true);
|
|
||||||
|
|
||||||
Reset();
|
Reset();
|
||||||
|
|
||||||
|
@ -171,41 +145,11 @@ nsresult nsMsgComposeService::Init()
|
||||||
|
|
||||||
void nsMsgComposeService::Reset()
|
void nsMsgComposeService::Reset()
|
||||||
{
|
{
|
||||||
nsresult rv = NS_OK;
|
|
||||||
|
|
||||||
if (mCachedWindows)
|
|
||||||
{
|
|
||||||
DeleteCachedWindows();
|
|
||||||
delete [] mCachedWindows;
|
|
||||||
mCachedWindows = nullptr;
|
|
||||||
mMaxRecycledWindows = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
mOpenComposeWindows.Clear();
|
mOpenComposeWindows.Clear();
|
||||||
|
|
||||||
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
nsCOMPtr<nsIPrefBranch> prefs(do_GetService(NS_PREFSERVICE_CONTRACTID));
|
||||||
if(prefs)
|
if (prefs)
|
||||||
rv = prefs->GetIntPref(PREF_MAIL_COMPOSE_MAXRECYCLEDWINDOWS, &mMaxRecycledWindows);
|
prefs->GetBoolPref("mailnews.logComposePerformance", &mLogComposePerformance);
|
||||||
if (NS_SUCCEEDED(rv) && mMaxRecycledWindows > 0)
|
|
||||||
{
|
|
||||||
mCachedWindows = new nsMsgCachedWindowInfo[mMaxRecycledWindows];
|
|
||||||
if (!mCachedWindows)
|
|
||||||
mMaxRecycledWindows = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
rv = prefs->GetBoolPref("mailnews.logComposePerformance", &mLogComposePerformance);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
void nsMsgComposeService::DeleteCachedWindows()
|
|
||||||
{
|
|
||||||
int32_t i;
|
|
||||||
for (i = 0; i < mMaxRecycledWindows; i ++)
|
|
||||||
{
|
|
||||||
CloseHiddenCachedWindow(mCachedWindows[i].window);
|
|
||||||
mCachedWindows[i].Clear();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Function to open a message compose window and pass an nsIMsgComposeParams
|
// Function to open a message compose window and pass an nsIMsgComposeParams
|
||||||
|
@ -235,38 +179,7 @@ nsMsgComposeService::OpenComposeWindowWithParams(const char *chrome,
|
||||||
params->SetIdentity(identity);
|
params->SetIdentity(identity);
|
||||||
}
|
}
|
||||||
|
|
||||||
//if we have a cached window for the default chrome, try to reuse it...
|
// Create a new window.
|
||||||
if (!chrome || PL_strcasecmp(chrome, DEFAULT_CHROME) == 0)
|
|
||||||
{
|
|
||||||
MSG_ComposeFormat format;
|
|
||||||
params->GetFormat(&format);
|
|
||||||
|
|
||||||
bool composeHTML = true;
|
|
||||||
rv = DetermineComposeHTML(identity, format, &composeHTML);
|
|
||||||
if (NS_SUCCEEDED(rv))
|
|
||||||
{
|
|
||||||
int32_t i;
|
|
||||||
for (i = 0; i < mMaxRecycledWindows; i ++)
|
|
||||||
{
|
|
||||||
if (mCachedWindows[i].window && (mCachedWindows[i].htmlCompose == composeHTML) && mCachedWindows[i].listener)
|
|
||||||
{
|
|
||||||
/* We need to save the window pointer as OnReopen will call nsMsgComposeService::InitCompose which will
|
|
||||||
clear the cache entry if everything goes well
|
|
||||||
*/
|
|
||||||
nsCOMPtr<mozIDOMWindowProxy> domWindow(mCachedWindows[i].window);
|
|
||||||
nsCOMPtr<nsIXULWindow> xulWindow(mCachedWindows[i].xulWindow);
|
|
||||||
rv = ShowCachedComposeWindow(domWindow, xulWindow, true);
|
|
||||||
if (NS_SUCCEEDED(rv))
|
|
||||||
{
|
|
||||||
mCachedWindows[i].listener->OnReopen(params);
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//Else, create a new one...
|
|
||||||
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
|
nsCOMPtr<nsIWindowWatcher> wwatch(do_GetService(NS_WINDOWWATCHER_CONTRACTID));
|
||||||
if (!wwatch)
|
if (!wwatch)
|
||||||
return NS_ERROR_FAILURE;
|
return NS_ERROR_FAILURE;
|
||||||
|
@ -286,63 +199,6 @@ nsMsgComposeService::OpenComposeWindowWithParams(const char *chrome,
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
||||||
void nsMsgComposeService::CloseHiddenCachedWindow(mozIDOMWindowProxy *domWindow)
|
|
||||||
{
|
|
||||||
if (domWindow)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDocShell> docshell;
|
|
||||||
if (domWindow)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(domWindow);
|
|
||||||
nsCOMPtr<nsIDocShellTreeItem> treeItem =
|
|
||||||
do_QueryInterface(window->GetDocShell());
|
|
||||||
|
|
||||||
if (treeItem)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIDocShellTreeOwner> treeOwner;
|
|
||||||
treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
|
|
||||||
if (treeOwner)
|
|
||||||
{
|
|
||||||
nsCOMPtr<nsIBaseWindow> baseWindow;
|
|
||||||
baseWindow = do_QueryInterface(treeOwner);
|
|
||||||
if (baseWindow) {
|
|
||||||
// HACK ALERT: when we hid this window we fired the "xul-window-destroyed"
|
|
||||||
// notification for it. Now that it's being really-destroyed it will fire that
|
|
||||||
// notification *again* for itself. The appstartup code maintains an internal
|
|
||||||
// reference count of windows that block app shutdown: we want to increment that
|
|
||||||
// count without cancelling app shutdown (so don't use "xul-window-registered").
|
|
||||||
nsCOMPtr<nsIAppStartup> appStartup(do_GetService(NS_APPSTARTUP_CONTRACTID));
|
|
||||||
if (appStartup)
|
|
||||||
appStartup->EnterLastWindowClosingSurvivalArea();
|
|
||||||
|
|
||||||
baseWindow->Destroy();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsMsgComposeService::Observe(nsISupports *aSubject, const char *aTopic, const char16_t *someData)
|
|
||||||
{
|
|
||||||
if (!strcmp(aTopic, "profile-do-change") || !strcmp(aTopic, "quit-application"))
|
|
||||||
{
|
|
||||||
DeleteCachedWindows();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!strcmp(aTopic, NS_PREFBRANCH_PREFCHANGE_TOPIC_ID))
|
|
||||||
{
|
|
||||||
nsDependentString prefName(someData);
|
|
||||||
if (prefName.EqualsLiteral(PREF_MAIL_COMPOSE_MAXRECYCLEDWINDOWS))
|
|
||||||
Reset();
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsMsgComposeService::DetermineComposeHTML(nsIMsgIdentity *aIdentity, MSG_ComposeFormat aFormat, bool *aComposeHTML)
|
nsMsgComposeService::DetermineComposeHTML(nsIMsgIdentity *aIdentity, MSG_ComposeFormat aFormat, bool *aComposeHTML)
|
||||||
{
|
{
|
||||||
|
@ -714,15 +570,6 @@ NS_IMETHODIMP nsMsgComposeService::InitCompose(nsIMsgComposeParams *aParams,
|
||||||
nsIDocShell *aDocShell,
|
nsIDocShell *aDocShell,
|
||||||
nsIMsgCompose **_retval)
|
nsIMsgCompose **_retval)
|
||||||
{
|
{
|
||||||
// We need to remove the window from the cache.
|
|
||||||
int32_t i;
|
|
||||||
for (i = 0; i < mMaxRecycledWindows; i ++)
|
|
||||||
if (mCachedWindows[i].window == aWindow)
|
|
||||||
{
|
|
||||||
mCachedWindows[i].Clear();
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
nsCOMPtr<nsIMsgCompose> msgCompose =
|
nsCOMPtr<nsIMsgCompose> msgCompose =
|
||||||
do_CreateInstance(NS_MSGCOMPOSE_CONTRACTID, &rv);
|
do_CreateInstance(NS_MSGCOMPOSE_CONTRACTID, &rv);
|
||||||
|
@ -790,89 +637,6 @@ NS_IMETHODIMP nsMsgComposeService::TimeStamp(const char * label, bool resetTime)
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsMsgComposeService::IsCachedWindow(mozIDOMWindowProxy *aCachedWindow, bool *aIsCachedWindow)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aCachedWindow);
|
|
||||||
NS_ENSURE_ARG_POINTER(aIsCachedWindow);
|
|
||||||
|
|
||||||
int32_t i;
|
|
||||||
for (i = 0; i < mMaxRecycledWindows; i ++)
|
|
||||||
if (mCachedWindows[i].window.get() == aCachedWindow)
|
|
||||||
{
|
|
||||||
*aIsCachedWindow = true;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
*aIsCachedWindow = false;
|
|
||||||
return NS_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
NS_IMETHODIMP
|
|
||||||
nsMsgComposeService::CacheWindow(mozIDOMWindowProxy *aWindow, bool aComposeHTML, nsIMsgComposeRecyclingListener * aListener)
|
|
||||||
{
|
|
||||||
NS_ENSURE_ARG_POINTER(aWindow);
|
|
||||||
NS_ENSURE_ARG_POINTER(aListener);
|
|
||||||
|
|
||||||
nsresult rv;
|
|
||||||
nsCOMPtr<nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aWindow);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIDocShellTreeItem> treeItem(do_QueryInterface(window->GetDocShell(), &rv));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
nsCOMPtr <nsIDocShellTreeOwner> treeOwner;
|
|
||||||
rv = treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
|
|
||||||
NS_ENSURE_SUCCESS(rv,rv);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIXULWindow> xulWindow(do_GetInterface(treeOwner, &rv));
|
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
|
||||||
|
|
||||||
int32_t i;
|
|
||||||
int32_t sameTypeId = -1;
|
|
||||||
int32_t oppositeTypeId = -1;
|
|
||||||
|
|
||||||
for (i = 0; i < mMaxRecycledWindows; i ++)
|
|
||||||
{
|
|
||||||
if (!mCachedWindows[i].window)
|
|
||||||
{
|
|
||||||
rv = ShowCachedComposeWindow(aWindow, xulWindow, false);
|
|
||||||
if (NS_SUCCEEDED(rv))
|
|
||||||
mCachedWindows[i].Initialize(aWindow, xulWindow, aListener, aComposeHTML);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
if (mCachedWindows[i].htmlCompose == aComposeHTML)
|
|
||||||
{
|
|
||||||
if (sameTypeId == -1)
|
|
||||||
sameTypeId = i;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (oppositeTypeId == -1)
|
|
||||||
oppositeTypeId = i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Looks like the cache is full. In the case we try to cache a type (html or plain text) of compose window which is not
|
|
||||||
already cached, we should replace an opposite one with this new one. That would allow users to be able to take advantage
|
|
||||||
of the cached compose window when they switch from one type to another one
|
|
||||||
*/
|
|
||||||
if (sameTypeId == -1 && oppositeTypeId != -1)
|
|
||||||
{
|
|
||||||
CloseHiddenCachedWindow(mCachedWindows[oppositeTypeId].window);
|
|
||||||
mCachedWindows[oppositeTypeId].Clear();
|
|
||||||
|
|
||||||
rv = ShowCachedComposeWindow(aWindow, xulWindow, false);
|
|
||||||
if (NS_SUCCEEDED(rv))
|
|
||||||
mCachedWindows[oppositeTypeId].Initialize(aWindow, xulWindow, aListener, aComposeHTML);
|
|
||||||
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
return NS_ERROR_NOT_AVAILABLE;
|
|
||||||
}
|
|
||||||
|
|
||||||
class nsMsgTemplateReplyHelper final: public nsIStreamListener,
|
class nsMsgTemplateReplyHelper final: public nsIStreamListener,
|
||||||
public nsIUrlListener
|
public nsIUrlListener
|
||||||
{
|
{
|
||||||
|
@ -1295,74 +1059,6 @@ nsMsgComposeService::ForwardMessage(const nsAString &forwardTo,
|
||||||
return folder->AddMessageDispositionState(aMsgHdr, nsIMsgFolder::nsMsgDispositionState_Forwarded);
|
return folder->AddMessageDispositionState(aMsgHdr, nsIMsgFolder::nsMsgDispositionState_Forwarded);
|
||||||
}
|
}
|
||||||
|
|
||||||
nsresult nsMsgComposeService::ShowCachedComposeWindow(mozIDOMWindowProxy *aComposeWindow, nsIXULWindow *aXULWindow, bool aShow)
|
|
||||||
{
|
|
||||||
nsresult rv = NS_OK;
|
|
||||||
|
|
||||||
nsCOMPtr<nsIObserverService> obs =
|
|
||||||
mozilla::services::GetObserverService();
|
|
||||||
NS_ENSURE_TRUE(obs, NS_ERROR_UNEXPECTED);
|
|
||||||
|
|
||||||
NS_ENSURE_TRUE(aComposeWindow, NS_ERROR_FAILURE);
|
|
||||||
nsCOMPtr <nsPIDOMWindowOuter> window = nsPIDOMWindowOuter::From(aComposeWindow);
|
|
||||||
|
|
||||||
nsIDocShell *docShell = window->GetDocShell();
|
|
||||||
|
|
||||||
nsCOMPtr <nsIDocShellTreeItem> treeItem = do_QueryInterface(docShell, &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv,rv);
|
|
||||||
|
|
||||||
nsCOMPtr <nsIDocShellTreeOwner> treeOwner;
|
|
||||||
rv = treeItem->GetTreeOwner(getter_AddRefs(treeOwner));
|
|
||||||
NS_ENSURE_SUCCESS(rv,rv);
|
|
||||||
|
|
||||||
if (treeOwner) {
|
|
||||||
// the window need to be sticky before we hide it.
|
|
||||||
nsCOMPtr<nsIContentViewer> contentViewer;
|
|
||||||
rv = docShell->GetContentViewer(getter_AddRefs(contentViewer));
|
|
||||||
NS_ENSURE_SUCCESS(rv,rv);
|
|
||||||
|
|
||||||
rv = contentViewer->SetSticky(!aShow);
|
|
||||||
NS_ENSURE_SUCCESS(rv,rv);
|
|
||||||
|
|
||||||
// disable (enable) the cached window
|
|
||||||
nsCOMPtr<nsIBaseWindow> baseWindow;
|
|
||||||
baseWindow = do_QueryInterface(treeOwner, &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv,rv);
|
|
||||||
|
|
||||||
baseWindow->SetEnabled(aShow);
|
|
||||||
NS_ENSURE_SUCCESS(rv,rv);
|
|
||||||
|
|
||||||
nsCOMPtr<nsIWindowMediator> windowMediator =
|
|
||||||
do_GetService(NS_WINDOWMEDIATOR_CONTRACTID, &rv);
|
|
||||||
NS_ENSURE_SUCCESS(rv,rv);
|
|
||||||
|
|
||||||
// if showing, reinstate the window with the mediator
|
|
||||||
if (aShow) {
|
|
||||||
rv = windowMediator->RegisterWindow(aXULWindow);
|
|
||||||
NS_ENSURE_SUCCESS(rv,rv);
|
|
||||||
|
|
||||||
obs->NotifyObservers(aXULWindow, "xul-window-registered", nullptr);
|
|
||||||
}
|
|
||||||
|
|
||||||
// hide (show) the cached window
|
|
||||||
rv = baseWindow->SetVisibility(aShow);
|
|
||||||
NS_ENSURE_SUCCESS(rv,rv);
|
|
||||||
|
|
||||||
// if hiding, remove the window from the mediator,
|
|
||||||
// so that it will be removed from the task list
|
|
||||||
if (!aShow) {
|
|
||||||
rv = windowMediator->UnregisterWindow(aXULWindow);
|
|
||||||
NS_ENSURE_SUCCESS(rv,rv);
|
|
||||||
|
|
||||||
obs->NotifyObservers(aXULWindow, "xul-window-destroyed", nullptr);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
rv = NS_ERROR_FAILURE;
|
|
||||||
}
|
|
||||||
return rv;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsresult nsMsgComposeService::AddGlobalHtmlDomains()
|
nsresult nsMsgComposeService::AddGlobalHtmlDomains()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
|
|
@ -17,32 +17,8 @@
|
||||||
#include "nsICommandLineHandler.h"
|
#include "nsICommandLineHandler.h"
|
||||||
#define ICOMMANDLINEHANDLER nsICommandLineHandler
|
#define ICOMMANDLINEHANDLER nsICommandLineHandler
|
||||||
|
|
||||||
class nsMsgCachedWindowInfo
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
void Initialize(mozIDOMWindowProxy *aWindow, nsIXULWindow *aXULWindow, nsIMsgComposeRecyclingListener *aListener, bool aHtmlCompose)
|
|
||||||
{
|
|
||||||
window = aWindow;
|
|
||||||
xulWindow = aXULWindow;
|
|
||||||
listener = aListener;
|
|
||||||
htmlCompose = aHtmlCompose;
|
|
||||||
}
|
|
||||||
|
|
||||||
void Clear()
|
|
||||||
{
|
|
||||||
window = nullptr;
|
|
||||||
listener = nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
nsCOMPtr<mozIDOMWindowProxy> window;
|
|
||||||
nsCOMPtr<nsIXULWindow> xulWindow;
|
|
||||||
nsCOMPtr<nsIMsgComposeRecyclingListener> listener;
|
|
||||||
bool htmlCompose;
|
|
||||||
};
|
|
||||||
|
|
||||||
class nsMsgComposeService :
|
class nsMsgComposeService :
|
||||||
public nsIMsgComposeService,
|
public nsIMsgComposeService,
|
||||||
public nsIObserver,
|
|
||||||
public ICOMMANDLINEHANDLER,
|
public ICOMMANDLINEHANDLER,
|
||||||
public nsSupportsWeakReference
|
public nsSupportsWeakReference
|
||||||
{
|
{
|
||||||
|
@ -51,7 +27,6 @@ public:
|
||||||
|
|
||||||
NS_DECL_ISUPPORTS
|
NS_DECL_ISUPPORTS
|
||||||
NS_DECL_NSIMSGCOMPOSESERVICE
|
NS_DECL_NSIMSGCOMPOSESERVICE
|
||||||
NS_DECL_NSIOBSERVER
|
|
||||||
NS_DECL_NSICOMMANDLINEHANDLER
|
NS_DECL_NSICOMMANDLINEHANDLER
|
||||||
|
|
||||||
nsresult Init();
|
nsresult Init();
|
||||||
|
@ -63,11 +38,6 @@ private:
|
||||||
virtual ~nsMsgComposeService();
|
virtual ~nsMsgComposeService();
|
||||||
bool mLogComposePerformance;
|
bool mLogComposePerformance;
|
||||||
|
|
||||||
int32_t mMaxRecycledWindows;
|
|
||||||
nsMsgCachedWindowInfo *mCachedWindows;
|
|
||||||
|
|
||||||
void CloseHiddenCachedWindow(mozIDOMWindowProxy *domWindow);
|
|
||||||
|
|
||||||
nsresult LoadDraftOrTemplate(const nsACString& aMsgURI, nsMimeOutputType aOutType,
|
nsresult LoadDraftOrTemplate(const nsACString& aMsgURI, nsMimeOutputType aOutType,
|
||||||
nsIMsgIdentity * aIdentity, const char * aOriginalMsgURI,
|
nsIMsgIdentity * aIdentity, const char * aOriginalMsgURI,
|
||||||
nsIMsgDBHdr * aOrigMsgHdr, bool aForwardInline,
|
nsIMsgDBHdr * aOrigMsgHdr, bool aForwardInline,
|
||||||
|
@ -84,8 +54,6 @@ private:
|
||||||
bool overrideComposeFormat,
|
bool overrideComposeFormat,
|
||||||
nsIMsgWindow *aMsgWindow);
|
nsIMsgWindow *aMsgWindow);
|
||||||
|
|
||||||
nsresult ShowCachedComposeWindow(mozIDOMWindowProxy *aComposeWindow, nsIXULWindow *aXULWindow, bool aShow);
|
|
||||||
|
|
||||||
// hash table mapping dom windows to nsIMsgCompose objects
|
// hash table mapping dom windows to nsIMsgCompose objects
|
||||||
nsInterfaceHashtable<nsISupportsHashKey, nsIWeakReference> mOpenComposeWindows;
|
nsInterfaceHashtable<nsISupportsHashKey, nsIWeakReference> mOpenComposeWindows;
|
||||||
|
|
||||||
|
|
|
@ -71,8 +71,7 @@ function onComposerReOpen()
|
||||||
|
|
||||||
addEventListener("load", smimeComposeOnLoad, false);
|
addEventListener("load", smimeComposeOnLoad, false);
|
||||||
|
|
||||||
// this function gets called multiple times,
|
// this function gets called multiple times
|
||||||
// but only on first open, not on composer recycling
|
|
||||||
function smimeComposeOnLoad()
|
function smimeComposeOnLoad()
|
||||||
{
|
{
|
||||||
removeEventListener("load", smimeComposeOnLoad, false);
|
removeEventListener("load", smimeComposeOnLoad, false);
|
||||||
|
|
|
@ -732,8 +732,6 @@ pref("mailnews.ui.select_addresses_results.version", 1);
|
||||||
// to hide the non default columns in the advanced directory search dialog
|
// to hide the non default columns in the advanced directory search dialog
|
||||||
// see abCommon.js and ABSearchDialog.js
|
// see abCommon.js and ABSearchDialog.js
|
||||||
pref("mailnews.ui.advanced_directory_search_results.version", 1);
|
pref("mailnews.ui.advanced_directory_search_results.version", 1);
|
||||||
//If set to a number greater than 0, msg compose windows will be recycled in order to open them quickly
|
|
||||||
pref("mail.compose.max_recycled_windows", 1);
|
|
||||||
|
|
||||||
// from/recipient columns will be replaced with correspondents column
|
// from/recipient columns will be replaced with correspondents column
|
||||||
pref("mailnews.ui.upgrade.correspondents", true);
|
pref("mailnews.ui.upgrade.correspondents", true);
|
||||||
|
|
|
@ -143,87 +143,6 @@ function enableEditableFields()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var gComposeRecyclingListener = {
|
|
||||||
onClose: function() {
|
|
||||||
//Reset recipients and attachments
|
|
||||||
awResetAllRows();
|
|
||||||
RemoveAllAttachments();
|
|
||||||
|
|
||||||
// We need to clear the identity popup menu in case the user will change them. It will be rebuilded later in ComposeStartup
|
|
||||||
ClearIdentityListPopup(document.getElementById("msgIdentityPopup"));
|
|
||||||
|
|
||||||
// Stop listening to changes in the spell check dictionary.
|
|
||||||
document.removeEventListener("spellcheck-changed", updateDocumentLanguage);
|
|
||||||
|
|
||||||
// Stop InlineSpellCheckerUI so personal dictionary is saved.
|
|
||||||
// We need to do this before disabling the editor.
|
|
||||||
EnableInlineSpellCheck(false);
|
|
||||||
// clear any suggestions in the context menu
|
|
||||||
InlineSpellCheckerUI.clearSuggestionsFromMenu();
|
|
||||||
InlineSpellCheckerUI.clearDictionaryListFromMenu();
|
|
||||||
|
|
||||||
//Clear the subject
|
|
||||||
GetMsgSubjectElement().value = "";
|
|
||||||
SetComposeWindowTitle();
|
|
||||||
|
|
||||||
SetContentAndBodyAsUnmodified();
|
|
||||||
disableEditableFields();
|
|
||||||
ReleaseGlobalVariables();
|
|
||||||
|
|
||||||
// Clear the focus
|
|
||||||
awGetInputElement(1).removeAttribute('focused');
|
|
||||||
|
|
||||||
//Reset Boxes size
|
|
||||||
document.getElementById("compose-toolbox").removeAttribute("height");
|
|
||||||
document.getElementById("appcontent").removeAttribute("height");
|
|
||||||
document.getElementById("addresses-box").removeAttribute("width");
|
|
||||||
document.getElementById("attachments-box").removeAttribute("width");
|
|
||||||
|
|
||||||
//Reset menu options
|
|
||||||
document.getElementById("format_auto").setAttribute("checked", "true");
|
|
||||||
|
|
||||||
//Reset toolbars that could be hidden
|
|
||||||
if (gHideMenus) {
|
|
||||||
document.getElementById("formatMenu").hidden = false;
|
|
||||||
document.getElementById("insertMenu").hidden = false;
|
|
||||||
var showFormat = document.getElementById("menu_showFormatToolbar")
|
|
||||||
showFormat.hidden = false;
|
|
||||||
if (showFormat.getAttribute("checked") == "true")
|
|
||||||
document.getElementById("FormatToolbar").hidden = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Reset the Customize Toolbars panel/sheet if open.
|
|
||||||
if (getMailToolbox().customizing && gCustomizeSheet)
|
|
||||||
document.getElementById("customizeToolbarSheetIFrame")
|
|
||||||
.contentWindow.finishToolbarCustomization();
|
|
||||||
|
|
||||||
//Reset editor
|
|
||||||
EditorResetFontAndColorAttributes();
|
|
||||||
EditorCleanup();
|
|
||||||
|
|
||||||
//Release the nsIMsgComposeParams object
|
|
||||||
if (window.arguments && window.arguments[0])
|
|
||||||
window.arguments[0] = null;
|
|
||||||
|
|
||||||
var event = document.createEvent('Events');
|
|
||||||
event.initEvent('compose-window-close', false, true);
|
|
||||||
document.getElementById("msgcomposeWindow").dispatchEvent(event);
|
|
||||||
if (gAutoSaveTimeout)
|
|
||||||
clearTimeout(gAutoSaveTimeout);
|
|
||||||
},
|
|
||||||
|
|
||||||
onReopen: function(params) {
|
|
||||||
// Reset focus to avoid undesirable visual effect when reopening the window
|
|
||||||
|
|
||||||
InitializeGlobalVariables();
|
|
||||||
ComposeStartup(true, params);
|
|
||||||
|
|
||||||
var event = document.createEvent('Events');
|
|
||||||
event.initEvent('compose-window-reopen', false, true);
|
|
||||||
document.getElementById("msgcomposeWindow").dispatchEvent(event);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
var stateListener = {
|
var stateListener = {
|
||||||
NotifyComposeFieldsReady: function() {
|
NotifyComposeFieldsReady: function() {
|
||||||
ComposeFieldsReady();
|
ComposeFieldsReady();
|
||||||
|
@ -251,7 +170,7 @@ var stateListener = {
|
||||||
if (gMsgCompose)
|
if (gMsgCompose)
|
||||||
gMsgCompose.onSendNotPerformed(null, Components.results.NS_ERROR_ABORT);
|
gMsgCompose.onSendNotPerformed(null, Components.results.NS_ERROR_ABORT);
|
||||||
|
|
||||||
MsgComposeCloseWindow(true);
|
MsgComposeCloseWindow();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// else if we failed to save, and we're autosaving, need to re-mark the editor
|
// else if we failed to save, and we're autosaving, need to re-mark the editor
|
||||||
|
@ -734,7 +653,7 @@ function DoCommandClose()
|
||||||
gMsgCompose.onSendNotPerformed(null, Components.results.NS_ERROR_ABORT);
|
gMsgCompose.onSendNotPerformed(null, Components.results.NS_ERROR_ABORT);
|
||||||
|
|
||||||
// note: if we're not caching this window, this destroys it for us
|
// note: if we're not caching this window, this destroys it for us
|
||||||
MsgComposeCloseWindow(true);
|
MsgComposeCloseWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
|
@ -930,7 +849,7 @@ function handleMailtoArgs(mailtoUrl)
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
function ComposeStartup(recycled, aParams)
|
function ComposeStartup(aParams)
|
||||||
{
|
{
|
||||||
var params = null; // New way to pass parameters to the compose window as a nsIMsgComposeParameters object
|
var params = null; // New way to pass parameters to the compose window as a nsIMsgComposeParameters object
|
||||||
var args = null; // old way, parameters are passed as a string
|
var args = null; // old way, parameters are passed as a string
|
||||||
|
@ -1055,12 +974,6 @@ function ComposeStartup(recycled, aParams)
|
||||||
editorElement.docShell);
|
editorElement.docShell);
|
||||||
if (gMsgCompose)
|
if (gMsgCompose)
|
||||||
{
|
{
|
||||||
// set the close listener
|
|
||||||
gMsgCompose.recyclingListener = gComposeRecyclingListener;
|
|
||||||
|
|
||||||
//Lets the compose object knows that we are dealing with a recycled window
|
|
||||||
gMsgCompose.recycledWindow = recycled;
|
|
||||||
|
|
||||||
if (!editorElement)
|
if (!editorElement)
|
||||||
{
|
{
|
||||||
dump("Failed to get editor element!\n");
|
dump("Failed to get editor element!\n");
|
||||||
|
@ -1076,32 +989,28 @@ function ComposeStartup(recycled, aParams)
|
||||||
document.getElementById("menu_inlineSpellCheck")
|
document.getElementById("menu_inlineSpellCheck")
|
||||||
.setAttribute("checked", getPref("mail.spellcheck.inline"));
|
.setAttribute("checked", getPref("mail.spellcheck.inline"));
|
||||||
|
|
||||||
// If recycle, editor is already created
|
try {
|
||||||
if (!recycled)
|
var editortype = gMsgCompose.composeHTML ? "htmlmail" : "textmail";
|
||||||
|
editorElement.makeEditable(editortype, true);
|
||||||
|
} catch (e) { dump(" FAILED TO START EDITOR: "+e+"\n"); }
|
||||||
|
|
||||||
|
// setEditorType MUST be call before setContentWindow
|
||||||
|
if (gMsgCompose.composeHTML)
|
||||||
{
|
{
|
||||||
try {
|
initLocalFontFaceMenu(document.getElementById("FontFacePopup"));
|
||||||
var editortype = gMsgCompose.composeHTML ? "htmlmail" : "textmail";
|
|
||||||
editorElement.makeEditable(editortype, true);
|
|
||||||
} catch (e) { dump(" FAILED TO START EDITOR: "+e+"\n"); }
|
|
||||||
|
|
||||||
// setEditorType MUST be call before setContentWindow
|
|
||||||
if (gMsgCompose.composeHTML)
|
|
||||||
{
|
|
||||||
initLocalFontFaceMenu(document.getElementById("FontFacePopup"));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Remove HTML toolbar, format and insert menus as we are editing in plain text mode
|
|
||||||
document.getElementById("outputFormatMenu").setAttribute("hidden", true);
|
|
||||||
document.getElementById("FormatToolbar").setAttribute("hidden", true);
|
|
||||||
document.getElementById("formatMenu").setAttribute("hidden", true);
|
|
||||||
document.getElementById("insertMenu").setAttribute("hidden", true);
|
|
||||||
document.getElementById("menu_showFormatToolbar").setAttribute("hidden", true);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Do setup common to Message Composer and Web Composer
|
|
||||||
EditorSharedStartup();
|
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//Remove HTML toolbar, format and insert menus as we are editing in plain text mode
|
||||||
|
document.getElementById("outputFormatMenu").setAttribute("hidden", true);
|
||||||
|
document.getElementById("FormatToolbar").setAttribute("hidden", true);
|
||||||
|
document.getElementById("formatMenu").setAttribute("hidden", true);
|
||||||
|
document.getElementById("insertMenu").setAttribute("hidden", true);
|
||||||
|
document.getElementById("menu_showFormatToolbar").setAttribute("hidden", true);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Do setup common to Message Composer and Web Composer
|
||||||
|
EditorSharedStartup();
|
||||||
|
|
||||||
var msgCompFields = gMsgCompose.compFields;
|
var msgCompFields = gMsgCompose.compFields;
|
||||||
if (msgCompFields)
|
if (msgCompFields)
|
||||||
|
@ -1138,35 +1047,20 @@ function ComposeStartup(recycled, aParams)
|
||||||
|
|
||||||
gMsgCompose.RegisterStateListener(stateListener);
|
gMsgCompose.RegisterStateListener(stateListener);
|
||||||
|
|
||||||
if (recycled)
|
// Add an observer to be called when document is done loading,
|
||||||
{
|
// which creates the editor
|
||||||
InitEditor(GetCurrentEditor());
|
try {
|
||||||
|
GetCurrentCommandManager().
|
||||||
|
addCommandObserver(gMsgEditorCreationObserver, "obs_documentCreated");
|
||||||
|
|
||||||
if (gMsgCompose.composeHTML)
|
// Load empty page to create the editor
|
||||||
{
|
editorElement.webNavigation.loadURI("about:blank", // uri string
|
||||||
// Force color picker on toolbar to show document colors
|
0, // load flags
|
||||||
onFontColorChange();
|
null, // referrer
|
||||||
onBackgroundColorChange();
|
null, // post-data stream
|
||||||
// XXX todo: reset paragraph select to "Body Text"
|
null);
|
||||||
}
|
} catch (e) {
|
||||||
}
|
dump(" Failed to startup editor: "+e+"\n");
|
||||||
else
|
|
||||||
{
|
|
||||||
// Add an observer to be called when document is done loading,
|
|
||||||
// which creates the editor
|
|
||||||
try {
|
|
||||||
GetCurrentCommandManager().
|
|
||||||
addCommandObserver(gMsgEditorCreationObserver, "obs_documentCreated");
|
|
||||||
|
|
||||||
// Load empty page to create the editor
|
|
||||||
editorElement.webNavigation.loadURI("about:blank", // uri string
|
|
||||||
0, // load flags
|
|
||||||
null, // referrer
|
|
||||||
null, // post-data stream
|
|
||||||
null);
|
|
||||||
} catch (e) {
|
|
||||||
dump(" Failed to startup editor: "+e+"\n");
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1228,7 +1122,7 @@ function WizCallback(state)
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
// The account wizard is still closing so we can't close just yet
|
// The account wizard is still closing so we can't close just yet
|
||||||
setTimeout(MsgComposeCloseWindow, 0, false); // Don't recycle a bogus window
|
setTimeout(MsgComposeCloseWindow, 0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1269,7 +1163,7 @@ function ComposeLoad()
|
||||||
var errorMsg = sComposeMsgsBundle.getString("initErrorDlgMessage");
|
var errorMsg = sComposeMsgsBundle.getString("initErrorDlgMessage");
|
||||||
Services.prompt.alert(window, errorTitle, errorMsg);
|
Services.prompt.alert(window, errorTitle, errorMsg);
|
||||||
|
|
||||||
MsgComposeCloseWindow(false); // Don't try to recycle a bogus window
|
MsgComposeCloseWindow();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (gLogComposePerformance)
|
if (gLogComposePerformance)
|
||||||
|
@ -2162,10 +2056,10 @@ function SetContentAndBodyAsUnmodified()
|
||||||
gContentChanged = false;
|
gContentChanged = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
function MsgComposeCloseWindow(recycleIt)
|
function MsgComposeCloseWindow()
|
||||||
{
|
{
|
||||||
if (gMsgCompose)
|
if (gMsgCompose)
|
||||||
gMsgCompose.CloseWindow(recycleIt);
|
gMsgCompose.CloseWindow();
|
||||||
else
|
else
|
||||||
window.close();
|
window.close();
|
||||||
}
|
}
|
||||||
|
|
|
@ -283,7 +283,6 @@ nsThunderbirdProfileMigrator::PrefTransform gTransforms[] = {
|
||||||
MAKESAMETYPEPREFTRANSFORM("mail.compose.autosaveinterval", Int),
|
MAKESAMETYPEPREFTRANSFORM("mail.compose.autosaveinterval", Int),
|
||||||
MAKESAMETYPEPREFTRANSFORM("mail.compose.dont_attach_source_of_local_network_links", Bool),
|
MAKESAMETYPEPREFTRANSFORM("mail.compose.dont_attach_source_of_local_network_links", Bool),
|
||||||
MAKESAMETYPEPREFTRANSFORM("mail.compose.dontWarnMail2Newsgroup", Bool),
|
MAKESAMETYPEPREFTRANSFORM("mail.compose.dontWarnMail2Newsgroup", Bool),
|
||||||
MAKESAMETYPEPREFTRANSFORM("mail.compose.max_recycled_windows", Int),
|
|
||||||
MAKESAMETYPEPREFTRANSFORM("mail.compose.other.header", String),
|
MAKESAMETYPEPREFTRANSFORM("mail.compose.other.header", String),
|
||||||
MAKESAMETYPEPREFTRANSFORM("mail.compose.wrap_to_window_width", Bool),
|
MAKESAMETYPEPREFTRANSFORM("mail.compose.wrap_to_window_width", Bool),
|
||||||
MAKESAMETYPEPREFTRANSFORM("mail.content_disposition_type", Int),
|
MAKESAMETYPEPREFTRANSFORM("mail.content_disposition_type", Int),
|
||||||
|
|
Загрузка…
Ссылка в новой задаче