!import
1 //@line 40 "/home/visbrero/mnt/roisin/rev_control/hg/mozilla/mail/base/content/mailWindow.js"
2
3 //This file stores variables common to mail windows
4 var mailSessionContractID = "@mozilla.org/messenger/services/session;1";
5
6 var messenger;
7 var pref;
8 var statusFeedback;
9 var msgWindow;
10
11 var msgComposeService;
12 var accountManager;
13 var RDF;
14
15 var mailSession;
16
17 var gMessengerBundle;
18 var gBrandBundle;
19
20 var gContextMenu;
21
22 var accountManagerDataSource;
23 var folderDataSource;
24 var unreadFolderDataSource;
25 var favoriteFoldersDataSource;
26 var recentFoldersDataSource;
27
28 var gAccountCentralLoaded = true;
29
OnMailWindowUnload
30 function OnMailWindowUnload()
31 {
32 MailOfflineMgr.uninit();
33 ClearPendingReadTimer();
34
35 var searchSession = GetSearchSession();
36 if (searchSession)
37 {
38 removeGlobalListeners();
39 if (gPreQuickSearchView) //close the cached pre quick search view
40 gPreQuickSearchView.close();
41 }
42
43 var dbview = GetDBView();
44 if (dbview) {
45 dbview.close();
46 }
47
48 var mailSession = Components.classes[mailSessionContractID].getService();
49 if(mailSession)
50 {
51 mailSession = mailSession.QueryInterface(Components.interfaces.nsIMsgMailSession);
52 if(mailSession)
53 mailSession.RemoveFolderListener(folderListener);
54 }
55
56 mailSession.RemoveMsgWindow(msgWindow);
57 messenger.setWindow(null, null);
58
59 var msgDS;
60 var viewDataSources = [accountManagerDataSource, folderDataSource,
61 unreadFolderDataSource, favoriteFoldersDataSource,
62 recentFoldersDataSource];
63
64 for (index in viewDataSources)
65 {
66 msgDS = viewDataSources[index].QueryInterface(Components.interfaces.nsIMsgRDFDataSource);
67 msgDS.window = null;
68 msgDS = null;
69 }
70
71 msgWindow.closeWindow();
72 }
73
CreateMessenger
74 function CreateMessenger()
75 {
76 messenger = Components.classes["@mozilla.org/messenger;1"]
77 .createInstance(Components.interfaces.nsIMessenger);
78 }
79
CreateMailWindowGlobals
80 function CreateMailWindowGlobals()
81 {
82 // get the messenger instance
83 CreateMessenger();
84
85 pref = Components.classes["@mozilla.org/preferences-service;1"]
86 .getService(Components.interfaces.nsIPrefBranch2);
87
88 //Create windows status feedback
89 // set the JS implementation of status feedback before creating the c++ one..
90 window.MsgStatusFeedback = new nsMsgStatusFeedback();
91 // double register the status feedback object as the xul browser window implementation
92 window.QueryInterface(Components.interfaces.nsIInterfaceRequestor)
93 .getInterface(Components.interfaces.nsIWebNavigation)
94 .QueryInterface(Components.interfaces.nsIDocShellTreeItem).treeOwner
95 .QueryInterface(Components.interfaces.nsIInterfaceRequestor)
96 .getInterface(Components.interfaces.nsIXULWindow)
97 .XULBrowserWindow = window.MsgStatusFeedback;
98
99 statusFeedback = Components.classes["@mozilla.org/messenger/statusfeedback;1"]
100 .createInstance(Components.interfaces.nsIMsgStatusFeedback);
101 statusFeedback.setWrappedStatusFeedback(window.MsgStatusFeedback);
102
103 //Create message window object
104 msgWindow = Components.classes["@mozilla.org/messenger/msgwindow;1"]
105 .createInstance(Components.interfaces.nsIMsgWindow);
106
107 msgComposeService = Components.classes['@mozilla.org/messengercompose;1']
108 .getService(Components.interfaces.nsIMsgComposeService);
109
110 mailSession = Components.classes["@mozilla.org/messenger/services/session;1"].getService(Components.interfaces.nsIMsgMailSession);
111
112 accountManager = Components.classes["@mozilla.org/messenger/account-manager;1"].getService(Components.interfaces.nsIMsgAccountManager);
113
114 RDF = Components.classes['@mozilla.org/rdf/rdf-service;1'].getService();
115 RDF = RDF.QueryInterface(Components.interfaces.nsIRDFService);
116
117 gMessengerBundle = document.getElementById("bundle_messenger");
118 gBrandBundle = document.getElementById("bundle_brand");
119
120 //Create datasources
121 var prefix = "@mozilla.org/rdf/datasource;1?name=";
122 accountManagerDataSource = Components.classes[prefix + "msgaccountmanager"]
123 .getService();
124 folderDataSource = Components.classes[prefix + "mailnewsfolders"]
125 .getService();
126 unreadFolderDataSource = Components.classes[prefix + "mailnewsunreadfolders"]
127 .getService();
128 favoriteFoldersDataSource = Components.classes[prefix + "mailnewsfavefolders"]
129 .getService();
130 recentFoldersDataSource = Components.classes[prefix + "mailnewsrecentfolders"]
131 .getService();
132 }
133
InitMsgWindow
134 function InitMsgWindow()
135 {
136 msgWindow.windowCommands = new nsMsgWindowCommands();
137 // set the domWindow before setting the status feedback and header sink objects
138 msgWindow.domWindow = window;
139 msgWindow.statusFeedback = statusFeedback;
140 msgWindow.msgHeaderSink = messageHeaderSink;
141 mailSession.AddMsgWindow(msgWindow);
142 getBrowser().docShell.allowAuth = false;
143 msgWindow.rootDocShell.allowAuth = true;
144 msgWindow.rootDocShell.appType = Components.interfaces.nsIDocShell.APP_TYPE_MAIL;
145 }
146
AddDataSources
147 function AddDataSources()
148 {
149 accountManagerDataSource = accountManagerDataSource.QueryInterface(Components.interfaces.nsIRDFDataSource);
150 folderDataSource = folderDataSource.QueryInterface(Components.interfaces.nsIRDFDataSource);
151
152 //Add statusFeedback
153
154 var msgDS;
155 var viewDataSources = [accountManagerDataSource, folderDataSource,
156 unreadFolderDataSource, favoriteFoldersDataSource,
157 recentFoldersDataSource];
158 for (index in viewDataSources)
159 {
160 msgDS = viewDataSources[index].QueryInterface(Components.interfaces.nsIMsgRDFDataSource);
161 msgDS.window = msgWindow;
162 }
163 }
164
165 // We're going to implement our status feedback for the mail window in JS now.
166 // the following contains the implementation of our status feedback object
167
nsMsgStatusFeedback
168 function nsMsgStatusFeedback()
169 {
170 }
171
172 nsMsgStatusFeedback.prototype =
173 {
174 // global variables for status / feedback information....
175 statusTextFld : null,
176 statusBar : null,
177 throbber : null,
178 stopCmd : null,
179 startTimeoutID : null,
180 stopTimeoutID : null,
181 progressMeterContainer : null,
182 pendingStartRequests : 0,
183 meteorsSpinning : false,
184 myDefaultStatus : null,
185 progressMeterVisible : false,
186
ensureStatusFields
Called By: mailWindow.js:_startMeteors (1 calls, 9 v-uS)
187 ensureStatusFields : function()
188 {
189 if (!this.statusTextFld ) this.statusTextFld = document.getElementById("statusText");
190 if (!this.statusBar) this.statusBar = document.getElementById("statusbar-icon");
191 if(!this.throbber) this.throbber = document.getElementById("navigator-throbber");
192 if(!this.stopCmd) this.stopCmd = document.getElementById("cmd_stop");
193 if (!this.progressMeterContainer) this.progressMeterContainer = document.getElementById("statusbar-progresspanel");
194 },
195
196 // nsIXULBrowserWindow implementation
setJSStatus
197 setJSStatus : function(status)
198 {
199 if (status.length > 0)
200 this.showStatusString(status);
201 },
setJSDefaultStatus
202 setJSDefaultStatus : function(status)
203 {
204 if (status.length > 0)
205 {
206 this.myDefaultStatus = status;
207 this.statusTextFld.label = status;
208 }
209 },
setOverLink
210 setOverLink : function(link, context)
211 {
212 this.ensureStatusFields();
213 this.statusTextFld.label = link;
214 },
QueryInterface
215 QueryInterface : function(iid)
216 {
217 if (iid.equals(Components.interfaces.nsIMsgStatusFeedback) ||
218 iid.equals(Components.interfaces.nsIXULBrowserWindow) ||
219 iid.equals(Components.interfaces.nsISupportsWeakReference) ||
220 iid.equals(Components.interfaces.nsISupports))
221 return this;
222 throw Components.results.NS_NOINTERFACE;
223 },
224
225 // nsIMsgStatusFeedback implementation.
showStatusString
226 showStatusString : function(statusText)
227 {
228 this.ensureStatusFields();
229 if ( !statusText.length )
230 statusText = this.myDefaultStatus;
231 else
232 this.myDefaultStatus = "";
233 this.statusTextFld.label = statusText;
234 },
_startMeteors
Called: Object:removeAttribute (2 calls, 97 v-uS)
Object:setAttribute (2 calls, 115 v-uS)
mailWindow.js:ensureStatusFields (1 calls, 9 v-uS)
235 _startMeteors : function()
236 {
237 this.ensureStatusFields();
238
239 this.meteorsSpinning = true;
240 this.startTimeoutID = null;
241
242 if (!this.progressMeterVisible)
243 {
244 this.progressMeterContainer.removeAttribute('collapsed');
245 this.progressMeterVisible = true;
246 }
247
248 // Turn progress meter on.
249 this.statusBar.setAttribute("mode","undetermined");
250
251 // start the throbber
252 if (this.throbber)
253 this.throbber.setAttribute("busy", true);
254
255 //turn on stop button and menu
256 if (this.stopCmd)
257 this.stopCmd.removeAttribute("disabled");
258 },
startMeteors
259 startMeteors : function()
260 {
261 this.pendingStartRequests++;
262 // if we don't already have a start meteor timeout pending
263 // and the meteors aren't spinning, then kick off a start
264 if (!this.startTimeoutID && !this.meteorsSpinning && window.MsgStatusFeedback)
265 this.startTimeoutID = setTimeout('window.MsgStatusFeedback._startMeteors();', 500);
266
267 // since we are going to start up the throbber no sense in processing
268 // a stop timeout...
269 if (this.stopTimeoutID)
270 {
271 clearTimeout(this.stopTimeoutID);
272 this.stopTimeoutID = null;
273 }
274 },
_stopMeteors
275 _stopMeteors : function()
276 {
277 this.ensureStatusFields();
278 this.showStatusString(defaultStatus);
279
280 // stop the throbber
281 if (this.throbber)
282 this.throbber.setAttribute("busy", false);
283
284 // Turn progress meter off.
285 this.statusBar.setAttribute("mode","normal");
286 this.statusBar.value = 0; // be sure to clear the progress bar
287 this.statusBar.label = "";
288
289 if (this.progressMeterVisible)
290 {
291 this.progressMeterContainer.collapsed = true;
292 this.progressMeterVisible = false;
293 }
294
295 if (this.stopCmd)
296 this.stopCmd.setAttribute("disabled", "true");
297
298 this.meteorsSpinning = false;
299 this.stopTimeoutID = null;
300 },
stopMeteors
301 stopMeteors : function()
302 {
303 if (this.pendingStartRequests > 0)
304 this.pendingStartRequests--;
305
306 // if we are going to be starting the meteors, cancel the start
307 if (this.pendingStartRequests == 0 && this.startTimeoutID)
308 {
309 clearTimeout(this.startTimeoutID);
310 this.startTimeoutID = null;
311 }
312
313 // if we have no more pending starts and we don't have a stop timeout already in progress
314 // AND the meteors are currently running then fire a stop timeout to shut them down.
315 if (this.pendingStartRequests == 0 && !this.stopTimeoutID)
316 {
317 if (this.meteorsSpinning && window.MsgStatusFeedback)
318 this.stopTimeoutID = setTimeout('window.MsgStatusFeedback._stopMeteors();', 500);
319 }
320 },
showProgress
321 showProgress : function(percentage)
322 {
323 this.ensureStatusFields();
324 if (percentage >= 0)
325 {
326 this.statusBar.setAttribute("mode", "normal");
327 this.statusBar.value = percentage;
328 this.statusBar.label = Math.round(percentage) + "%";
329 }
330 }
331 }
332
333
nsMsgWindowCommands
334 function nsMsgWindowCommands()
335 {
336 }
337
338 nsMsgWindowCommands.prototype =
339 {
QueryInterface
340 QueryInterface : function(iid)
341 {
342 if (iid.equals(Components.interfaces.nsIMsgWindowCommands) ||
343 iid.equals(Components.interfaces.nsISupports))
344 return this;
345 throw Components.results.NS_NOINTERFACE;
346 },
347
selectFolder
348 selectFolder: function(folderUri)
349 {
350 SelectFolder(folderUri);
351 },
352
selectMessage
353 selectMessage: function(messageUri)
354 {
355 SelectMessage(messageUri);
356 },
357
clearMsgPane
358 clearMsgPane: function()
359 {
360 if (gDBView)
361 setTitleFromFolder(gDBView.msgFolder,null);
362 else
363 setTitleFromFolder(null,null);
364 ClearMessagePane();
365 }
366 }
367
StopUrls
368 function StopUrls()
369 {
370 msgWindow.StopUrls();
371 }
372
373 /**
374 * @returns the pref name to use for fetching the start page url. Every time the application version changes,
375 * return "mailnews.start_page.override_url". If this is the first time the application has been
376 * launched, return "mailnews.start_page.welcome_url". Otherwise return "mailnews.start_page.url".
377 */
startPageUrlPref
378 function startPageUrlPref()
379 {
380 var prefForStartPageUrl = "mailnews.start_page.url";
381 var savedVersion = null;
382 try {
383 savedVersion = pref.getCharPref("mailnews.start_page_override.mstone");
384 } catch (ex) {}
385
386 if (savedVersion != "ignore")
387 {
388 var currentPlatformVersion = Components.classes["@mozilla.org/xre/app-info;1"].
389 getService(Components.interfaces.nsIXULAppInfo).platformVersion;
390 pref.setCharPref("mailnews.start_page_override.mstone", currentPlatformVersion);
391 // Use the welcome URL the first time we run
392 if (!savedVersion)
393 prefForStartPageUrl = "mailnews.start_page.welcome_url";
394 else if (currentPlatformVersion != savedVersion)
395 prefForStartPageUrl = "mailnews.start_page.override_url";
396 }
397
398 return prefForStartPageUrl;
399 }
400
loadStartPage
401 function loadStartPage()
402 {
403 try
404 {
405 gMessageNotificationBar.clearMsgNotifications();
406 var startpageenabled = pref.getBoolPref("mailnews.start_page.enabled");
407 // only load the start page if we are online
408 var startpage = getFormattedURL(startPageUrlPref());
409 // load about:blank as the start page if we are offline or we don't have a start page url...
410 GetMessagePaneFrame().location.href = startpageenabled && startpage && MailOfflineMgr.isOnline() ? startpage : "about:blank";
411 ClearMessageSelection();
412 }
413 catch (ex)
414 {
415 dump("Error loading start page.\n");
416 return;
417 }
418 }
419
420 // When the ThreadPane is hidden via the displayDeck, we should collapse the
421 // elements that are only meaningful to the thread pane. When AccountCentral is
422 // shown via the displayDeck, we need to switch the displayDeck to show the
423 // accountCentralBox, and load the iframe in the AccountCentral box with
424 // corresponding page.
ShowAccountCentral
425 function ShowAccountCentral()
426 {
427 var accountBox = document.getElementById("accountCentralBox");
428 document.getElementById("displayDeck").selectedPanel = accountBox;
429 var prefName = "mailnews.account_central_page.url";
430 var acctCentralPage = pref.getComplexValue(prefName,
431 Components.interfaces.nsIPrefLocalizedString).data;
432 window.frames["accountCentralPane"].location.href = acctCentralPage;
433 }
434
ShowingAccountCentral
435 function ShowingAccountCentral()
436 {
437 if (!IsFolderPaneCollapsed())
438 GetFolderTree().focus();
439
440 gAccountCentralLoaded = true;
441 }
442
HidingAccountCentral
443 function HidingAccountCentral()
444 {
445 gAccountCentralLoaded = false;
446 }
447
ShowThreadPane
448 function ShowThreadPane()
449 {
450 document.getElementById("displayDeck").selectedPanel =
451 document.getElementById("threadPaneBox");
452 }
453
ShowingThreadPane
454 function ShowingThreadPane()
455 {
456 var threadPaneSplitter = document.getElementById("threadpane-splitter");
457 threadPaneSplitter.collapsed = false;
458 GetMessagePane().collapsed = (threadPaneSplitter.getAttribute("state") == "collapsed");
459 // XXX We need to force the tree to refresh its new height
460 // so that it will correctly scroll to the newest message
461 GetThreadTree().boxObject.height;
462 document.getElementById("key_toggleMessagePane").removeAttribute("disabled");
463 }
464
HidingThreadPane
465 function HidingThreadPane()
466 {
467 ClearThreadPane();
468 GetUnreadCountElement().hidden = true;
469 GetTotalCountElement().hidden = true;
470 GetMessagePane().collapsed = true;
471 document.getElementById("threadpane-splitter").collapsed = true;
472 document.getElementById("key_toggleMessagePane").setAttribute("disabled", "true");
473 }
474
475 // the find toolbar needs a method called getBrowser
getBrowser
476 function getBrowser()
477 {
478 return getMessageBrowser();
479 }
480
481 var gCurrentDisplayDeckId = "";
ObserveDisplayDeckChange
Called: ChromeWindow:getElementById (21 calls, 316 v-uS)
XULElement:getAttribute (21 calls, 283 v-uS)
Called By: ChromeWindow:onDeleteCompleted (20 calls, 1495 v-uS)
ChromeWindow:clearSelection (1 calls, 79 v-uS)
482 function ObserveDisplayDeckChange(event)
483 {
484 var selectedPanel = document.getElementById("displayDeck").selectedPanel;
485 var nowSelected = selectedPanel ? selectedPanel.id : null;
486 // onselect fires for every mouse click inside the deck, so ObserveDisplayDeckChange is getting called every time we click
487 // on a message in the thread pane. Only show / Hide elements if the selected deck is actually changing.
488 if (nowSelected != gCurrentDisplayDeckId)
489 {
490 if (nowSelected == "threadPaneBox")
491 ShowingThreadPane();
492 else
493 HidingThreadPane();
494
495 if (nowSelected == "accountCentralBox")
496 ShowingAccountCentral();
497 else
498 HidingAccountCentral();
499 gCurrentDisplayDeckId = nowSelected;
500 }
501 }
502
503 // Given the server, open the twisty and the set the selection
504 // on inbox of that server.
505 // prompt if offline.
OpenInboxForServer
506 function OpenInboxForServer(server)
507 {
508 try {
509 ShowThreadPane();
510 var inboxFolder = GetInboxFolder(server);
511 SelectFolder(inboxFolder.URI);
512
513 if (MailOfflineMgr.isOnline() || MailOfflineMgr.getNewMail()) {
514 if (server.type != "imap")
515 GetMessagesForInboxOnServer(server);
516 }
517 }
518 catch (ex) {
519 dump("Error opening inbox for server -> " + ex + "\n");
520 return;
521 }
522 }
523
GetSearchSession
524 function GetSearchSession()
525 {
526 if (("gSearchSession" in top) && gSearchSession)
527 return gSearchSession;
528 else
529 return null;
530 }