Discuz! Board

 找回密码
 立即注册
搜索
热搜: 活动 交友 discuz
查看: 2614|回复: 7
打印 上一主题 下一主题

pop流程跟踪

[复制链接]

388

主题

602

帖子

2218

积分

金牌会员

Rank: 6Rank: 6

积分
2218
跳转到指定楼层
楼主
发表于 2016-3-27 23:24:23 | 只看该作者 |只看大图 回帖奖励 |倒序浏览 |阅读模式
-----向导窗口 emailWizard.xul  检测配置--------

接收方式选择pop3 。 重新测试:
onHalfManualTest

涉及到文件
emailWizard.js  
guessConfig成功后设置界面输入输出服务器配置
guessConfig.js  
guessConfig
1.创建AccountConfig对象 accountConfig.js   含有收发服务器参数
resultConfig = new AccountConfig();
2.如果离线,自动配置好resultConfig 的收发信服务器参数返回
if (Services.io.offline)

3.其它情况创建收发服务器探测对象
incomingHostDetector = new IncomingHostDetector(progress, incomingSuccess,
                                                  incomingError);
  outgoingHostDetector = new OutgoingHostDetector(progress, outgoingSuccess,
                                                  outgoingError);

根据设置好的服务器可能域名地址及对应端口号进行测试
"imap." +  domain  "pop3." +  domain等
incomingHostDetector.start
start : function(domain, hostIsPrecise, type, port, socketType)
_tryAll : function()
  thisTry.abortable = SocketUtil(

var transportService = Cc["@mozilla.org/network/socket-transport-service;1"]
                         .getService(Ci.nsISocketTransportService);
var transport = transportService.createTransport
var outstream = transport.openOutputStream(0, 0, 0);  --输出流
  var stream = transport.openInputStream(0, 0, 0);
  var instream = Cc["@mozilla.org/scriptableinputstream;1"]
      .createInstance(Ci.nsIScriptableInputStream);
  instream.init(stream);  ---输入流
var pump = Cc["@mozilla.org/network/input-stream-pump;1"]
        .createInstance(Ci.nsIInputStreamPump);
    pump.init(stream, -1, -1, 0, 0, false);----输入流
    pump.asyncRead(dataListener, null);   --异步读
    return new SocketAbortable(transport);
  } catch (e) { _error(e); }


-----向导窗口 emailWizard.xul  完成操作--------
emailWizard.js  
onCreate
{
  validateAndFinish(configFilledIn) //根据上一步检测出的配置参数进行验证
}
validateAndFinish
{
checkIncomingServerAlreadyExists//检测接收服务器是否已经存在  createInBackend.js 这四个条件相同即存在(username\hostname\type[imap、pop、nntp]\port)
checkOutgoingServerAlreadyExists//检测发送服务器是否已经存在 createInBackend.js 这三个条件相同即存在(username\hostname\port)
verifyConfig //登录验证 verifyConfig.js

}

verifyConfig{
//从账号管理组件入手
var accountManager = Cc["@mozilla.org/messenger/account-manager;1"]
                       .getService(Ci.nsIMsgAccountManager);
1.检测账号中是否有此收信服务器  accountManager.findRealServer
2. 不存在则创建  nsMsgAccountManager.cpp
var inServer =   accountManager.createIncomingServer(config.incoming.username,
                                        config.incoming.hostname,
                                        sanitize.enum(config.incoming.type,
                                                    ["pop3", "imap", "nntp"]));
并初始化负值其它相关参数
inServer.port = config.incoming.port;
  inServer.password = config.incoming.password;
    inServer.socketType = Ci.nsMsgSocketType.plain;
  inServer.authMethod = config.incoming.auth;

3.登录验证
verifyLogon(config, inServer, alter, msgWindow,
                  successCallback, errorCallback);
}

verifyLogon
{
// 设置验证用户登录的回调,verifyLogon 将同步创建 transport并利用通知(notification )回调 此侦听器同时侦听此url和证书错误,故实现 nsIUrlListener和nsIBadCertListener2 这两个接口 另外还实现了nsIInterfaceRequestor和nsISupports接口
  let listener = new urlListener(config, inServer, alter, msgWindow, successCallback, errorCallback);
let uri = inServer.verifyLogon(listener, msgWindow);

验证成功后调用 emailWizard.js 中的 finish : function()
}

urlListener.prototype =
{
//nsIUrlListener
OnStartRunningUrl: function(aUrl)
OnStopRunningUrl: function(aUrl, aExitCode)
//nsIBadCertListener2.idl
  notifyCertProblem: function(socketInfo, status, targetSite)
// nsIInterfaceRequestor
  getInterface: function(iid)
// nsISupports
  QueryInterface: function(iid)
}

inServer.verifyLogon
imap

pop



回复

使用道具 举报

388

主题

602

帖子

2218

积分

金牌会员

Rank: 6Rank: 6

积分
2218
沙发
 楼主| 发表于 2016-3-27 23:24:39 | 只看该作者
  1. --------pop3验证底层实现-------
  2. nsPop3IncomingServer.cpp
  3. NS_IMETHODIMP nsPop3IncomingServer::VerifyLogon(nsIUrlListener *aUrlListener,nsIMsgWindow *aMsgWindow, nsIURI **aURL)
  4. {
  5.   nsresult rv;
  6.   nsCOMPtr<nsIPop3Service> pop3Service = do_GetService(kCPop3ServiceCID, &rv);
  7.   NS_ENSURE_SUCCESS(rv,rv);
  8.   return pop3Service->VerifyLogon(this, aUrlListener, aMsgWindow, aURL);
  9. }

  10. nsPop3Service.cpp
  11. NS_IMETHODIMP nsPop3Service::VerifyLogon(nsIMsgIncomingServer *aServer,...
  12. {
  13. //根据pop3收信服务器的前端设置(用户名[进行编码防止含有 / % @]、主机名、端口)构造url
  14. char *urlSpec = PR_smprintf("pop3://%s@%s:%d/?verifyLogon", escapedUsername.get(), popHost.get(), popPort);
  15. ////pop3://13342978053@pop3.139.com:110/?verifyLogon
  16. //构造url接口智能指针 nsIURI
  17. nsCOMPtr<nsIURI> url;   //参考下面 url构建做了什么
  18.   rv = BuildPop3Url(urlSpec, nullptr, popServer, aUrlListener,  getter_AddRefs(url), aMsgWindow);
  19. //运行url
  20. rv = RunPopUrl(aServer, url);

  21. }

  22. RunPopUrl
  23. {
  24. 1.获取pop收信服务器配置的用户名
  25. nsresult rv = aServer->GetRealUsername(userName);

  26. 2.判断收信服务是否在忙
  27. rv = aServer->GetServerBusy(&serverBusy);  //参考下面 服务是否在忙做了什么
  28. a.忙,弹出提示
  29. nsCOMPtr<nsIMsgMailNewsUrl> url = do_QueryInterface(aUrlToRun);
  30.     if (url)
  31.       AlertServerBusy(url);
  32. b.不忙进行如下执行
  33. nsRefPtr<nsPop3Protocol> protocol = new nsPop3Protocol(aUrlToRun); //参看下面的关于nsPop3Protocol类
  34. //设置用户名
  35. protocol->SetUsername(userName.get());
  36. //加载url //参看下面的关于nsPop3Protocol类中加载Url
  37. rv = protocol->LoadUrl(aUrlToRun);
  38. //设置收取邮件数
  39. protocol->SetNumForRETR(aNumForRETR);
  40. }


  41. ****url构建做了什么*************
  42. url中有一个指向pop3sink的指针m_pop3Sink
  43. nsresult nsPop3Service::BuildPop3Url()
  44. {
  45. nsPop3Sink *pop3Sink = new nsPop3Sink(); //nsIPop3Sink
  46. pop3Sink->SetPopServer(server);
  47.   pop3Sink->SetFolder(inbox);
  48. //创建pop3Url
  49. nsCOMPtr<nsIPop3URL> pop3Url = do_CreateInstance(kPop3UrlCID, &rv);
  50. pop3Url->SetPop3Sink(pop3Sink);  //m_pop3Sink = aPop3Sink;

  51. nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(pop3Url);
  52. //前端传入的侦听器在这里注册  
  53. mailnewsurl->RegisterListener(aUrlListener);
  54. {
  55. nsMsgMailNewsUrl::RegisterListener    mUrlListeners.AppendElement(aUrlListener);
  56. nsMsgMailNewsUrl.cpp文件中使用 NOTIFY_URL_LISTENERS(propertyfunc_, params_) 发出侦听通知

  57. }
  58. ****************

  59. ****服务是否在忙做了什么******
  60. NS_IMETHODIMP nsMsgIncomingServer::GetServerBusy(bool * aServerBusy)
  61. {
  62.   NS_ENSURE_ARG_POINTER(aServerBusy);
  63.   *aServerBusy = m_serverBusy;
  64.   return NS_OK;

  65. //主要看什么时候设置了忙状态
  66. NS_IMETHODIMP nsMsgIncomingServer::SetServerBusy(bool aServerBusy)
  67. {
  68.   m_serverBusy = aServerBusy;
  69.   return NS_OK;
  70. }


  71. ***************************

  72. ************关于nsPop3Protocol类******nsPop3Protocol.cpp
  73. class nsPop3Protocol : public nsMsgProtocol,
  74.                        public nsIPop3Protocol,
  75.                        public nsIMsgAsyncPromptListener
  76. { ...}
  77. nsresult nsPop3Protocol:oadUrl(nsIURI* aURL..)
  78. {
  79. //1.初始化url  完成功能
  80. *a.日志初始化  b.创建pop3连接数据结构 m_pop3ConData  c.设置关于下载的其它参数初始值  d.从url中获取状态信息m_statusFeedback
  81. *e.从url中获取收信服务器,及其相关参数m_socketType  authMethod 用于连接设置 f.记录此url于m_url变量  g.预留接收弹出窗口方法 ir
  82. *h.初始化代理信息详细参考下面代理信息 usePAC=false    i.过滤器列表应用 可优化点,以提高性能? j.连接类型设置  connectionType = "ssl";
  83. *k.打开网络Socket 参考 打开网络Socket  l.创建命令输出流 参考 创建命令输出流  m.初始化后端访问的语言资源方法 mLocalBundle
  84.   nsresult rv = Initialize(aURL);

  85. //2.记录url
  86. m_url = do_QueryInterface(aURL);

  87. //3.参考 检测端口安全
  88. rv = NS_CheckPortSafety(port, "pop");

  89. //4.获取url的Query段mQuery,用来判决进行的查询操作上面url最后传入的字符串参数 参考 获取url的Query段
  90. nsCAutoString queryPart;
  91.   rv = url->GetQuery(queryPart);  //如: "verifyLogon"

  92. //5.根据上面的返回设置连接结构中对应的标志值
  93. m_pop3ConData->only_check_for_new_mail = (PL_strcasestr(queryPart.get(), "check") != nullptr);
  94.   m_pop3ConData->verify_logon = (PL_strcasestr(queryPart.get(), "verifyLogon") != nullptr);
  95.   m_pop3ConData->get_url = (PL_strcasestr(queryPart.get(), "gurl") != nullptr);

  96. //6.非登录情况下执行
  97. if (!m_pop3ConData->verify_logon)
  98. {
  99. m_pop3Server->GetLeaveMessagesOnServer(&m_pop3ConData->leave_on_server); // 会根据不同的邮件夹的设置获取
  100. m_pop3Server->GetHeadersOnly(&m_pop3ConData->headers_only);  //根据收信服务器的设置获取
  101. //关于消息大小的限制,并设置相关变量的值
  102. server->GetLimitOfflineMessageSize(&limitMessageSize);  ----"limit_offline_message_size"
  103. m_pop3ConData->size_limit = (max_size) ? max_size * 1024 : 50 * 1024;
  104. //关于在服务器上留取邮件数量的设置
  105. m_pop3Server->GetDeleteByAgeFromServer(&deleteByAgeFromServer);  //根据收信服务器的设置获取
  106. deleteByAgeFromServer
  107. ;

  108.       if (deleteByAgeFromServer)
  109.         m_pop3Server->GetNumDaysToLeaveOnServer(&numDaysToLeaveOnServer);  //根据收信服务器的设置获取
  110. numDaysToLeaveOnServer

  111. }

  112. //7.记录sink  // UIDL stuff  UIDL的东西???
  113. nsCOMPtr<nsIPop3URL> pop3Url = do_QueryInterface(m_url);
  114.   if (pop3Url)
  115.     pop3Url->GetPop3Sink(getter_AddRefs(m_nsIPop3Sink));

  116. //8.关于邮件目录的设置
  117. nsCOMPtr<nsIFile> mailDirectory;
  118. //根据收信服务获取邮件目录 详细参考 收信服务获取本地目录
  119. rv = server->GetLocalPath(getter_AddRefs(mailDirectory));   如创建的子目录名为“pop3.139.com”
  120. 9.设置服务器为忙
  121. server->SetServerBusy(true); // the server is now busy

  122. 10.非登录状态下设置Pop3UidlHost链表结构  维护每个账号的哈希表?
  123. if (!m_pop3ConData->verify_logon)
  124.     m_pop3ConData->uidlinfo = net_pop3_load_state(hostName.get(), userName.get(), mailDirectory);

  125. 11. 设置为无新邮件状态
  126. m_pop3ConData->biffstate = nsIMsgFolder::nsMsgBiffState_NoMail;

  127. 12.邮件删除逻辑处理  _____
  128. if (m_pop3ConData->uidlinfo && numDaysToLeaveOnServer > 0)
  129. ....
  130. 13.uidl逻辑处理___
  131. const char* uidl = PL_strcasestr(queryPart.get(), "uidl=");
  132. .....
  133. 14.连接状态设置
  134. m_pop3ConData->next_state = POP3_START_CONNECT;
  135.   m_pop3ConData->next_state_after_response = POP3_FINISH_CONNECT;

  136. 15.运行当前url
  137. m_pop3Server->SetRunningProtocol(this);
  138.     return nsMsgProtocol:oadUrl(aURL);







  139. }


  140. ******************
  141. ***** 收信服务获取本地目录*****
  142. nsMsgIncomingServer.cpp
  143. nsMsgIncomingServer::GetLocalPath(nsIFile **aLocalPath)
  144. {
  145. rv = GetFileValue("directory-rel", "directory", aLocalPath);
  146. //根据当前收信服务器的相关信息创建对应目录
  147. nsCOMPtr<nsIMsgProtocolInfo> protocolInfo;
  148.   rv = getProtocolInfo(getter_AddRefs(protocolInfo));
  149. nsCOMPtr<nsIFile> localPath;
  150.   rv = protocolInfo->GetDefaultLocalPath(getter_AddRefs(localPath));
  151. localPath->Create(nsIFile:IRECTORY_TYPE, 0755);

  152. }

  153. *****************************


  154. ***代理信息********
  155. PAC可能是代理访问控制的意思
  156. nsProtocolProxyService.cpp
  157. nsProtocolProxyService::Resolve(nsIURI *uri, uint32_t flags,
  158. pop://pop3.139.com:110  ----代理url含有的相关信息
  159. DIRECT  直接
  160. class nsProxyInfo MOZ_FINAL : public nsIProxyInfo
  161. **********************

  162. *******打开网络Socket *********
  163. rv = OpenNetworkSocketWithInfo(hostName.get(), port, connectionType, proxyInfo, ir);
  164. {
  165. //1. 获取 SocketTransportService
  166. nsCOMPtr<nsISocketTransportService> socketService (do_GetService(NS_SOCKETTRANSPORTSERVICE_CONTRACTID));
  167. //2.创建Transport  详细参见创建Transport
  168. nsCOMPtr<nsISocketTransport> strans;
  169.   rv = socketService->CreateTransport(&connectionType, connectionType != nullptr,
  170.                                       nsDependentCString(aHostName),
  171.                                       aGetPort, aProxyInfo,
  172.                                       getter_AddRefs(strans));
  173. //3.设置安全回调,即指向上面的ir用于后端弹出窗口
  174. strans->SetSecurityCallbacks(callbacks);

  175. //4.创建循环引用,可能用来防止线程阻塞???  是在主线程吗?线程ID是哪个?
  176. // creates cyclic reference!
  177.   nsCOMPtr<nsIThread> currentThread(do_GetCurrentThread());
  178.   strans->SetEventSink(this, currentThread);

  179. //5.记录当前传输连接
  180. m_transport = strans;

  181. //6.获取tcp连接超时设置,并进行相关设置
  182. prefBranch->GetIntPref("mailnews.tcptimeout", &gSocketTimeout);
  183. strans->SetTimeout(nsISocketTransport::TIMEOUT_CONNECT, gSocketTimeout + 60);
  184.   strans->SetTimeout(nsISocketTransport::TIMEOUT_READ_WRITE, gSocketTimeout);

  185. //7.设置QoS
  186. (Quality of Service) "服务质量"  详细参看下面 关于Qos的获取

  187. uint8_t qos;
  188.   rv = GetQoSBits(&qos);
  189.   if (NS_SUCCEEDED(rv))
  190.     strans->SetQoSBits(qos);


  191. //8.设置传输状态  详见下面  设置传输状态
  192. return SetupTransportState();

  193. }
  194. ****************************

  195. ***创建Transport*************
  196. .\mozilla\netwerk\base\src\nsSocketTransportService2.cpp
  197. nsSocketTransportService::CreateTransport(const char **types,
  198. {
  199. nsSocketTransport *trans = new nsSocketTransport();
  200. nsresult rv = trans->Init(types, typeCount, host, port, proxyInfo);
  201. }
  202. ***************************


  203. *******关于Qos的获取*************
  204. nsCAutoString prefName("mail.");
  205.   prefName.Append(protocol);
  206.   prefName.Append(".qos");
  207.   nsresult rv;
  208.   nsCOMPtr<nsIPrefBranch> prefBranch = do_GetService(NS_PREFSERVICE_CONTRACTID, &rv);
  209.   NS_ENSURE_SUCCESS(rv,rv);
  210.   int32_t val;
  211.   rv = prefBranch->GetIntPref(prefName.get(), &val);
  212.   NS_ENSURE_SUCCESS(rv, rv);
  213. *****************************************

  214. ************设置传输状态*************
  215. if (!m_socketIsOpen && m_transport)
  216.   // open buffered, blocking output stream  输出流m_outputStream 用于发送数据 nsMsgProtocol::SendData  m_outputStream->Write(dataBuffer, PL_strlen(dataBuffer), &writeCount);
  217.     rv = m_transport->OpenOutputStream(nsITransport::OPEN_BLOCKING, 0, 0, getter_AddRefs(m_outputStream));
  218. ****************************

  219. *********创建命令输出流***************
  220. m_lineStreamBuffer = new nsMsgLineStreamBuffer(OUTPUT_BUFFER_SIZE, true);

  221. ************************************

  222. ***********检测端口安全*********************
  223. NS_CheckPortSafety(int32_t       port,
  224.                    const char   *scheme,
  225.                    nsIIOService *ioService = nullptr)
  226. {
  227.     nsresult rv;
  228.     nsCOMPtr<nsIIOService> grip;
  229.     rv = net_EnsureIOService(&ioService, grip);
  230.     if (ioService) {
  231.         bool allow;
  232.         rv = ioService->AllowPort(port, scheme, &allow);
  233.         if (NS_SUCCEEDED(rv) && !allow) {
  234.             NS_WARNING("port blocked");
  235.             rv = NS_ERROR_PORT_ACCESS_NOT_ALLOWED;
  236.         }
  237.     }
  238.     return rv;
  239. }
  240. *******************************************


  241. *****获取url的Query段*************
  242.   const nsDependentCSubstring Query()     { return Segment(mQuery); }
  243. // url parts (relative to mSpec)
  244.     URLSegment mScheme;
  245.     URLSegment mAuthority;
  246.     URLSegment mUsername;
  247.     URLSegment mPassword;
  248.     URLSegment mHost;
  249.     URLSegment mPath;
  250.     URLSegment mFilepath;
  251.     URLSegment mDirectory;
  252.     URLSegment mBasename;
  253.     URLSegment mExtension;
  254.     URLSegment mQuery;
  255.     URLSegment mRef;
  256. ********************************
复制代码
回复 支持 反对

使用道具 举报

388

主题

602

帖子

2218

积分

金牌会员

Rank: 6Rank: 6

积分
2218
板凳
 楼主| 发表于 2016-3-27 23:24:56 | 只看该作者
15.运行当前协议
m_pop3Server->SetRunningProtocol(this);
{
m_runningProtocol = aProtocol;
}

16.调用父类执行

return nsMsgProtocol:: LoadUrl(aURL);

// Ouput stream for writing commands to the socket  
  nsCOMPtr<nsIOutputStream>   m_outputStream;   // this will be obtained from the transport interface
  nsCOMPtr<nsIInputStream>    m_inputStream;
  // Ouput stream for writing commands to the socket
  nsCOMPtr<nsITransport>  m_transport;
  nsCOMPtr<nsIRequest>    m_request;

nsresult nsMsgProtocol:: LoadUrl(nsIURI * aURL, nsISupports * aConsumer)

//从transport获取输入流 nsCOMPtr<nsIInputStream>    m_inputStream;
rv = m_transport->OpenInputStream(0, 0, 0, getter_AddRefs(m_inputStream));
///inputStream关联 pump 提供异步方法
nsCOMPtr<nsIInputStreamPump> pump;
        rv = NS_NewInputStreamPump(getter_AddRefs(pump),
          m_inputStream, -1, m_readCount);
m_request = pump; // keep a reference to the pump so we can cancel it
//注册有数据的通知 // put us in a state where we are always notified of incoming data
        rv = pump->AsyncRead(this, urlSupports);


回复 支持 反对

使用道具 举报

388

主题

602

帖子

2218

积分

金牌会员

Rank: 6Rank: 6

积分
2218
地板
 楼主| 发表于 2016-3-27 23:27:09 | 只看该作者
触发的状态机的跟踪  nsPop3Protocol:: ProcessProtocolState(nsIURI * url, nsIInputStream * aInputStream, uint32_t sourceOffset, uint32_t aLength)
  1. xul.dll!nsPop3Protocol::ProcessProtocolState(nsIURI * url, nsIInputStream * aInputStream, unsigned int sourceOffset, unsigned int aLength) 行 3868 C++
  2. > xul.dll!nsMsgProtocol::OnDataAvailable(nsIRequest * request, nsISupports * ctxt, nsIInputStream * inStr, unsigned int sourceOffset, unsigned int count) 行 357 + 0x14 字节 C++
  3. xul.dll!nsInputStreamPump::OnStateTransfer() 行 490 + 0x16 字节 C++
  4. xul.dll!nsInputStreamPump::OnInputStreamReady(nsIAsyncInputStream * stream) 行 372 C++
  5. xul.dll!nsOutputStreamReadyEvent::Run() 行 83 C++
  6. xul.dll!nsThread::ProcessNextEvent(bool mayWait, bool * result) 行 624 + 0x6 字节 C++
  7. xul.dll!NS_ProcessNextEvent_P(nsIThread * thread, bool mayWait) 行 220 + 0xd 字节 C++
  8. xul.dll!nsThread::Shutdown() 行 466 + 0xa 字节 C++
  9. xul.dll!nsRunnableMethodImpl<unsigned int (__stdcall nsIThread::*)(void),1>::Run() 行 350 C++
  10. xul.dll!nsThread::ProcessNextEvent(bool mayWait, bool * result) 行 624 + 0x6 字节 C++
  11. xul.dll!NS_ProcessNextEvent_P(nsIThread * thread, bool mayWait) 行 220 + 0xd 字节 C++
  12. xul.dll!mozilla::ipc::MessagePump::Run(base::MessagePump::Delegate * aDelegate) 行 82 + 0xa 字节 C++
  13. xul.dll!MessageLoop::RunHandler() 行 202 C++
  14. xul.dll!MessageLoop::Run() 行 176 C++
  15. xul.dll!nsBaseAppShell::Run() 行 165 C++
  16. xul.dll!nsAppShell::Run() 行 232 + 0x6 字节 C++
  17. xul.dll!nsAppStartup::Run() 行 274 C++
  18. xul.dll!XREMain::XRE_mainRun() 行 3856 + 0x9 字节 C++
  19. xul.dll!XREMain::XRE_main(int argc, char * * argv, const nsXREAppData * aAppData) 行 3933 + 0x7 字节 C++
  20. xul.dll!XRE_main(int argc, char * * argv, const nsXREAppData * aAppData, unsigned int aFlags) 行 4009 + 0x12 字节 C++
  21. 139Mail.exe!do_main(const char * exePath, int argc, char * * argv) 行 112 C++
  22. 139Mail.exe!NS_internal_main(int argc, char * * argv) 行 200 + 0x12 字节 C++
  23. 139Mail.exe!wmain(int argc, wchar_t * * argv) 行 102 C++
  24. 139Mail.exe!__tmainCRTStartup() 行 552 + 0x17 字节 C
复制代码
即连接的缓存中有可用数据时,会触发OnDataAvailable调用,抓包如下:



创建url后的状态更新过程:
1.POP3_START_CONNECT
2.POP3_FINISH_CONNECT
3.POP3_WAIT_FOR_START_OF_CONNECTION_RESPONSE
根据服务端的返回设置服务器相关信息
然后再根据连接类型发送用户名密码登录。
如:
int32_t nsPop3Protocol::SendAuth()
{
  if(!m_pop3ConData->command_succeeded)
    return(Error(POP3_SERVER_ERROR));

  nsCAutoString command("AUTH" CRLF);

  m_pop3ConData->next_state_after_response = POP3_AUTH_RESPONSE;
  return SendData(command.get());
}

回复 支持 反对

使用道具 举报

388

主题

602

帖子

2218

积分

金牌会员

Rank: 6Rank: 6

积分
2218
5#
 楼主| 发表于 2016-3-27 23:27:25 | 只看该作者
+OK richmail system v10(32d255323e8d829-c3ed4)
AUTH
-ERR Bad sequence of commands
CAPA
-ERR Bad sequence of commands
USER 13342978053@139.com
+OK
PASS cccccpassword
+OK login success
STAT
+OK 3 140231
QUIT
+OK dewey POP3 server signing off

前端createAccountInBackend
进行上面几个命令后,
前端js文件 createInBackend.js
function createAccountInBackend(config, isPublicEmailAddr, curEmailAddr)
  account.incomingServer = inServer; // will create folder  调用下面c++代码
会进入邮件夹创建
nsMsgAccount::SetIncomingServer(nsIMsgIncomingServer *aIncomingServer)
回复 支持 反对

使用道具 举报

388

主题

602

帖子

2218

积分

金牌会员

Rank: 6Rank: 6

积分
2218
6#
 楼主| 发表于 2016-3-27 23:27:41 | 只看该作者
第一阶段总结:

验证接收成功失败的回调函数
function verifyLogon(config, inServer, alter, msgWindow, successCallback, errorCallback)
回调函数在verifyConfig.js验证函数内部转换成js对象 listener
let listener = new urlListener(config, inServer, alter, msgWindow,
                                  successCallback, errorCallback);
listener对象实现 nsIUrlListener 接口
//nsIUrlListener
OnStartRunningUrl: function(aUrl)
OnStopRunningUrl: function(aUrl, aExitCode)
{
  this._log.info("Finished verifyConfig resulted in " + aExitCode);
    if (Components.isSuccessCode(aExitCode))//判断返回的退出码
     {
       this._cleanup();
       this.mSuccessCallback(this.mConfig);  //登录成功,完成成功函数的回调
     }
}
--------C++后端关于listener对象的传递与处理机制-------------
js:
let listener = new urlListener(config, inServer, alter, msgWindow,
                                  successCallback, errorCallback);
msgWindow.notificationCallbacks = listener;//注意这里有一个回调通知的保存和恢复
let uri = inServer.verifyLogon(listener, msgWindow);
c++:    //aUrlListener对应js中的listener
nsPop3IncomingServer::VerifyLogon(nsIUrlListener *aUrlListener,nsIMsgWindow *aMsgWindow, nsIURI **aURL)
{
nsCOMPtr<nsIPop3Service> pop3Service = do_GetService(kCPop3ServiceCID, &rv);
return pop3Service->VerifyLogon(this, aUrlListener, aMsgWindow, aURL);
}
nsPop3Service::VerifyLogon(nsIMsgIncomingServer *aServer,nsIUrlListener *aUrlListener,nsIMsgWindow *aMsgWindow,
nsIURI **aURL)
{
//组建url并把listener对象封装进去
char *urlSpec = PR_smprintf("pop3://%s@%s:%d/?verifyLogon",escapedUsername.get(), popHost.get(), popPort);
//构造结果示例:pop3://13342978053@pop3.139.com:110/?verifyLogon
  nsCOMPtr<nsIURI> url;
  
  rv = BuildPop3Url(urlSpec, nullptr, popServer, aUrlListener,
getter_AddRefs(url), aMsgWindow);
}
nsPop3Service::BuildPop3Url(const char *urlSpec,
nsIMsgFolder *inbox,
nsIPop3IncomingServer *server,
nsIUrlListener *aUrlListener,nsIURI **aUrl,nsIMsgWindow *aMsgWindow)
{
nsCOMPtr<nsIPop3URL> pop3Url = do_CreateInstance(kPop3UrlCID, &rv);
rv = CallQueryInterface(pop3Url, aUrl);
nsCOMPtr<nsIMsgMailNewsUrl> mailnewsurl = do_QueryInterface(pop3Url);
//上面接口的获取参看nsIPop3URL的继承关系 class nsPop3URL : public nsIPop3URL, public nsMsgMailNewsUrl
mailnewsurl->RegisterListener(aUrlListener);  
}
//注册后查看后面是处理的
\mailnews\base\util\nsMsgMailNewsUrl.cpp
nsMsgMailNewsUrl::RegisterListener(nsIUrlListener *aUrlListener)
{
mUrlListeners.AppendElement(aUrlListener);
}
//发送通知的宏
#define NOTIFY_URL_LISTENERS(propertyfunc_, params_)                   \
  PR_BEGIN_MACRO                                                       \
  nsTObserverArray<nsCOMPtr<nsIUrlListener> >::ForwardIterator iter(mUrlListeners); \
  while (iter.HasMore()) {                                             \
    nsCOMPtr<nsIUrlListener> listener = iter.GetNext();                \
    listener->propertyfunc_ params_;                                   \
  }                                                                    \
  PR_END_MACRO
//跟踪何时调用这个宏
nsresult nsMsgMailNewsUrl::SetUrlState(bool aRunningUrl, nsresult aExitCode)
{
{
if (m_runningUrl)
  {
    NOTIFY_URL_LISTENERS(OnStartRunningUrl, (this));
  }
  else
  {
    NOTIFY_URL_LISTENERS(OnStopRunningUrl, (this, aExitCode));
    mUrlListeners.Clear();
  }
}
//协议中何时调用
nsPop3Protocol.cpp#4119
case POP3_FREE:
mailnewsurl->SetUrlState(false, m_pop3ConData->urlStatus);
回复 支持 反对

使用道具 举报

388

主题

602

帖子

2218

积分

金牌会员

Rank: 6Rank: 6

积分
2218
7#
 楼主| 发表于 2016-3-27 23:28:06 | 只看该作者
emailWizard.js
validateAndFinish
self.finish();
finish : function()
{
curAccount =createAccountInBackend(this.getConcreteConfig(), true, this._email);
let folder = curAccount.incomingServer.rootMsgFolder;
    let server = curAccount.incomingServer;
if ("imap" == server.type) {
else if ("pop3" == server.type) {
this.startPop3FetchMsg(server, folder);{ server.getNewMessages(folder, null, null);}
}
createInBackend.js
createAccountInBackend
{
//创建收信服务
var accountManager = Cc["@mozilla.org/messenger/account-manager;1"]
                       .getService(Ci.nsIMsgAccountManager);
var inServer = accountManager.createIncomingServer
//创建发信服务
outServer = smtpManager.createSmtpServer();
//创建identity
var identity = accountManager.createIdentity();
//创建账号并记录收信服务器不同于验证过程,验证过程没有这步
var account = accountManager.createAccount();
account.incomingServer = inServer; // will create folder
//设置账号的identity
account.addIdentity(identity);

setFolders(identity, inServer);
//保存账号信息
accountManager.saveAccountInfo();

return account;

}
回复 支持 反对

使用道具 举报

388

主题

602

帖子

2218

积分

金牌会员

Rank: 6Rank: 6

积分
2218
8#
 楼主| 发表于 2016-3-27 23:28:26 | 只看该作者
  1. var inServer = accountManager.createIncomingServer
  2. nsMsgAccountManager.cpp  //创建后台C++中的内存对象与js对应
  3. nsMsgAccountManager::CreateIncomingServer(const nsACString&  username,
  4.                                           const nsACString& hostname,
  5.                                           const nsACString& type,
  6.                                           nsIMsgIncomingServer **_retval)
  7. {
  8. nsresult rv = LoadAccounts();
  9. }

  10. nsMsgAccountManager:oadAccounts()
  11. {
  12. //1.mailSession的作用
  13. nsCOMPtr<nsIMsgMailSession> mailSession = do_GetService(NS_MSGMAILSESSION_CONTRACTID, &rv);
  14.     mailSession->AddFolderListener(this, nsIFolderListener::added |
  15.                                          nsIFolderListener::removed |
  16.                                          nsIFolderListener::intPropertyChanged);
  17. //2.biff service 的作用
  18. nsCOMPtr<nsIMsgBiffManager> biffService =
  19.            do_GetService(NS_MSGBIFFMANAGER_CONTRACTID, &rv);
  20. biffService->Init();

  21. //3.purge service的作用
  22. nsCOMPtr<nsIMsgPurgeService> purgeService =
  23.            do_GetService(NS_MSGPURGESERVICE_CONTRACTID, &rv);
  24. purgeService->Init();

  25. //4.integration service 的作用
  26. nsCOMPtr<nsIMessengerOSIntegration> integrationService =
  27.            do_GetService(NS_MESSENGEROSINTEGRATION_CONTRACTID, &rv);
  28. //5.通过mail.accountmanager.accounts配置中存储的所有账号信息获取账号进入点
  29. nsCString accountList;
  30. rv = m_prefs->GetCharPref(PREF_MAIL_ACCOUNTMANAGER_ACCOUNTS, getter_Copies(accountList));
  31. //6.关于预加载账号
  32. mailnews.js
  33. pref("mailnews.append_preconfig_accounts.version", 1); //预加载账号的版本号配置
  34. mail.accountmanager.appendaccounts  //预加载账号 逗号分隔的帐户列表  参考mail.accountmanager.accounts里的配置
  35. 判断默认配置mailnews.js和当前配置prefs.js的不同,以确认预加载账号的更新
  36. //7.解析账号列表(字符串转为数组),加载每个账号
  37. nsTArray<nsCString> accountsArray;
  38.   ParseString(accountList, ACCOUNT_DELIMITER, accountsArray);
  39. 去重复及判断是否存在m_accounts中
  40. nsCOMPtr<nsISupportsArray> m_accounts;

  41. //8.创建账号
  42. createKeyedAccount(accountsArray, getter_AddRefs(account))) || !account)    // nsCOMPtr<nsIMsgAccount> account = do_CreateInstance(kMsgAccountCID, &rv);

  43. //9. secondsToLeaveUnavailable 和 timeFoundUnavailable 配置

  44. //10.identities加载
  45. nsCOMPtr<nsISupportsArray> identities;
  46.     account->GetIdentities(getter_AddRefs(identities));

  47. //创建账号服务
  48. rv = account->CreateServer();

  49. //即通过AccountManager服务获取到之前创建的服务,然后与账号的m_incomingServer变量关联,并通知NotifyServerLoaded
  50. nsCOMPtr<nsIMsgAccountManager> accountManager =
  51.            do_GetService(NS_MSGACCOUNTMANAGER_CONTRACTID, &rv);
  52.   NS_ENSURE_SUCCESS(rv, rv);
  53.   nsCOMPtr<nsIMsgIncomingServer> server;
  54.   rv = accountManager->GetIncomingServer(serverKey, getter_AddRefs(server));
  55.   NS_ENSURE_SUCCESS(rv, rv);
  56.   // store the server in this structure
  57.   m_incomingServer = server;
  58.   accountManager->NotifyServerLoaded(server);


  59. }
复制代码
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|Archiver|手机版|小黑屋|firemail ( 粤ICP备15085507号-1 )

GMT+8, 2024-11-26 15:54 , Processed in 0.069782 second(s), 21 queries .

Powered by Discuz! X3

© 2001-2013 Comsenz Inc.

快速回复 返回顶部 返回列表