这个系列的前两篇文章主要是根据自己的需求,对Thunderbird的源代码进行修改,改进了Thunderbird的现有功能,关注点都在Thunderbird的老本行---邮件客户端的实现上,那是否Thunderbird就仅仅是一个邮件客户端呢?在我看来,并非如此,它源自Mozilla内核,就继承了Mozilla平台的光荣传统,应该视为一个优秀的可扩展的开发平台,更进一步来看,Mozilla的文化深入其骨髓,可以看到后来Adobe的Flex,MicroSoft的WPF都吸收了Mozilla平台界面与逻辑相分离的思想,所以接下来几篇文章我想写一个比较有意思的方面----进程间通信。
进程间通信的概念在操作系统中有过详细的介绍,方法很多,我主要关注其中两种:socket通信,Pipe(管道)通信。
本文的目的就是开发一个扩展,展示TCP/IP socket技术在Mozilla扩展开发中的应用。
服务器端主代码:
const tBirdBiffServerUi =

{
tBirdBiffServerOnLoad: function()

{//启动服务器
// remove to avoid duplicate initialization
removeEventListener("load", tBirdBiffServerUi.tBirdBiffServerOnLoad, true);
tBirdBiffCommon.setIconPosition();//设置图标位置
//创建服务器对象并初始化
var server = Components.classes["@phinecos.cnblogs.com/TBbiff/server;1"].getService(Components.interfaces.nsISupports).wrappedJSObject;
server.initialize();
server.addWindow(window);//保存当前窗口
server = null;
},
tBirdBiffServerOnClose: function()

{//关闭服务器
// remove to avoid duplicate initialization
removeEventListener("close", tBirdBiffServerUi.tBirdBiffServerOnClose, true);

//移除当前窗口
var server = Components.classes["@dpwhite.com/thunderbirdbiff/server;1"].getService(Components.interfaces.nsISupports).wrappedJSObject;
server.removeWindow(window);
server = null;
}
}

addEventListener("load", tBirdBiffServerUi.tBirdBiffServerOnLoad, true);
addEventListener("close", tBirdBiffServerUi.tBirdBiffServerOnClose, true);

服务器类,负责创建服务器端socket,并异步监听来自客户端的请求,管理邮箱状态的变化和来自客户端的连接。

服务器类
const CI = Components.interfaces, CC = Components.classes, CR = Components.results;
const newMail= "1";
const noMail = "0";
const serverError = "9";

tBirdBiffServer.classID = Components.ID("{d2c9b4c6-2851-4d25-8cb6-3d3b037f8e1e}");//组件ID
tBirdBiffServer.contractID = "@phinecos.cnblogs.com/TBbiff/server;1";
tBirdBiffServer.classDescription = "TBbiff Server Service";

function tBirdBiffServer()


{
this.utility = CC[utilityContractID].getService(CI.nsISupports).wrappedJSObject;//工具类对象
this.prefs = CC["@mozilla.org/preferences-service;1"].getService(CI.nsIPrefBranch);
this.connections = CC["@mozilla.org/supports-array;1"].createInstance(CI.nsICollection);//客户端连接集合
this.useAnimation = null;//是否使用动画效果
this.mailStatus = noMail;//邮箱状态
this.serverSocket = null;//服务器端socket
this.port = null;//服务器端口
this.windowCollection = CC["@mozilla.org/supports-array;1"].createInstance(CI.nsICollection);//保存的窗口集合
this.initialized = false;//是否已经初始化
}

broadcast: function()

{//向客户端发送数据
var deadConnections = new Array();//已断开的连接
var status = this.mailStatus;//获取当前邮箱状态
var count = this.connections.Count();//来自客户端的连接数目

//依次向各个客户端发送服务器的邮箱状态
for(var i = 0; i < count; i++)

{
var connection = this.connections.GetElementAt(i);//来自客户端的连接
connection = connection.wrappedJSObject;
//发送数据给客户端
if(!connection.broadcast(status))

{
connection.closeSocket();//关闭此断开的连接
deadConnections[i] = connection;
}
else

{
deadConnections[i] = null;
}

connection = null;
}

for(var i = 0; i < deadConnections.length; i++)

{//移除已经断开的连接
if(deadConnections[i] != null)

{
this.removeConnection(deadConnections[i]);
}
}

deadConnections = null;
count = null;
},

addConnection: function(value)

{//加入新的来自客户端的连接
this.connections.AppendElement(value);
},

removeConnection: function(value)

{//移除连接
this.connections.RemoveElement(value);
},
getServerSocket: function()

{//创建服务器端socket,并开始异步监听来自客户端的request
this.serverSocket = CC["@mozilla.org/network/server-socket;1"].createInstance(CI.nsIServerSocket);
if(!this.serverSocket)

{
alert("Unable to get a server socket");
}
else

{
try

{
this.serverSocket.init(this.port, false, -1);//初始化服务器端socket,绑定到端口号port
this.serverSocket.asyncListen(tBirdBiffServerSocketListener);//开始异步监听来自客户端的请求
}
catch(e)

{
this.serverSocket = null;
}
}
},
closeServerSocket: function()

{//关闭服务器端socket
if(!this.serverSocket)

{
this.serverSocket.close(null);
this.serverSocket = null;
}
},
initialize: function()

{//初始化服务器
if(this.initialized)

{//已经初始化过了
return;
}
this.port = 25501;//设置服务器监听端口
this.useAnimation = true;
this.getServerSocket();//创建服务器端socket并开始监听
this.monitorBiff(true);//监控状态变化
this.initialized = true;
},
monitorBiff: function(isStarting)

{//监控邮箱状态变化
var sessionService = CC["@mozilla.org/messenger/services/session;1"].getService(CI.nsIMsgMailSession);
if(isStarting)

{
sessionService.AddFolderListener(tBirdBiffServerBiffStateListener, CI.nsIFolderListener.intPropertyChanged);//增加监听者
}
else

{
sessionService.RemoveFolderListener(tBirdBiffServerBiffStateListener, CI.nsIFolderListener.intPropertyChanged);//移除监听者
}

sessionService = null;
},

closeAllConnections: function()

{//关闭所有来自客户端的连接
var count = this.connections.Count();
for(var i = 0; i < count; i++)

{
var connection = this.connections.GetElementAt(i);
connection = connection.wrappedJSObject;
connection.closeSocket();
connection = null;
}

count = null;
this.connections.Clear();
},
finalize: function()

{//析构函数
if(!this.initialized)

{
return;
}

this.closeServerSocket();//关闭服务器端socket
this.monitorBiff(false);//移除监听邮箱状态的监听者
this.closeAllConnections();//关闭所有来自客户端的连接
},

updateUi: function(window)

{//刷新界面状态
var state;
var tip = "T-Bird Biff: ";
var status = window.document.getElementById("thunderbird-biff");

switch(this.mailStatus)

{
case noMail:

{//没有新邮件
tip += this.getLocalizedString("noNewMail");
state = "noMail";
break;
}

case newMail:

{//有新邮件
tip += this.getLocalizedString("newMail");
if(this.useAnimation)

{
state = "newMailAni"; // using gif here due to animation
}
else

{
state = "newMail";
}

break;
}

default:

{//error
this.utility.logError("Unexpected result: " + this.mailStatus);
tip = this.getLocalizedString("weirdness");
state = "weirdness";
break;
}
}

status.setAttribute("tooltiptext", tip);
status.setAttribute("biffState", state);
tip = null;
state = null;
status = null;
},

setMailStatus: function(value)

{//设置邮箱状态
if(this.MailStatus == value)

{//没有变化
return;
}
this.mailStatus = value;
//邮箱状态发生改变,逐个窗口通知其更新状态,这些窗口都是服务器端的Observer
var server = CC[tBirdBiffServer.contractID].getService(CI.nsISupports).wrappedJSObject;
var windowCollection = server.getWindowCollection();
var count = windowCollection.Count();
for(var i = 0; i < count; i++)

{
var window = windowCollection.GetElementAt(i);
this.updateUi(window);//更新此窗口状态
window = null;
}

this.broadcast();//将服务器的邮箱状态通知给各个客户端

windowCollection = null;
count = null;
server = null;
},

check: function()

{//检查服务器邮箱状态
tBirdBiffServerBiffStateListener.clearIntervalTimeout();//清除此前的定时器
this.setMailStatus(this.checkServers());//实际的检查动作
},

checkServers: function()

{
try

{
const biffShowsMailReady = 0;
//帐户管理器
var accountManager = CC["@mozilla.org/messenger/account-manager;1"].getService(CI.nsIMsgAccountManager);
if(accountManager)

{
