Bug 1629669 - Rework nsImapProtocol::GetPassword to avoid deadlock, and better protect m_passwordObtained/m_passwordStatus. r=benc,mkmelin
Differential Revision: https://phabricator.services.mozilla.com/D154019 --HG-- extra : amend_source : e2bd2d6e89ca13e20a20e66567fc161ed060b4ce
This commit is contained in:
Родитель
eaf331b7a4
Коммит
9a93867602
|
@ -8355,27 +8355,54 @@ nsresult nsImapProtocol::GetPassword(nsString& password,
|
||||||
NS_ENSURE_TRUE(m_server, NS_ERROR_NULL_POINTER);
|
NS_ENSURE_TRUE(m_server, NS_ERROR_NULL_POINTER);
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
|
|
||||||
|
password = nsString();
|
||||||
// Get the password already stored in mem
|
// Get the password already stored in mem
|
||||||
rv = m_imapServerSink->GetServerPassword(password);
|
rv = m_imapServerSink->GetServerPassword(password);
|
||||||
if (NS_FAILED(rv) || password.IsEmpty()) {
|
if (NS_FAILED(rv) || password.IsEmpty()) {
|
||||||
AutoProxyReleaseMsgWindow msgWindow;
|
AutoProxyReleaseMsgWindow msgWindow;
|
||||||
GetMsgWindow(getter_AddRefs(msgWindow));
|
GetMsgWindow(getter_AddRefs(msgWindow));
|
||||||
NS_ENSURE_TRUE(msgWindow, NS_ERROR_NOT_AVAILABLE); // biff case
|
NS_ENSURE_TRUE(msgWindow, NS_ERROR_NOT_AVAILABLE); // biff case
|
||||||
|
m_passwordStatus = NS_OK;
|
||||||
|
m_passwordObtained = false;
|
||||||
|
|
||||||
// Get the password from pw manager (harddisk) or user (dialog)
|
// Get the password from pw manager (harddisk) or user (dialog)
|
||||||
m_passwordObtained = false;
|
|
||||||
rv = m_imapServerSink->AsyncGetPassword(this, newPasswordRequested,
|
rv = m_imapServerSink->AsyncGetPassword(this, newPasswordRequested,
|
||||||
password);
|
password);
|
||||||
if (password.IsEmpty()) {
|
|
||||||
PRIntervalTime sleepTime = kImapSleepTime;
|
if (NS_SUCCEEDED(rv)) {
|
||||||
m_passwordStatus = NS_OK;
|
while (password.IsEmpty()) {
|
||||||
ReentrantMonitorAutoEnter mon(m_passwordReadyMonitor);
|
bool shuttingDown = false;
|
||||||
while (!m_passwordObtained && !NS_FAILED(m_passwordStatus) &&
|
(void)m_imapServerSink->GetServerShuttingDown(&shuttingDown);
|
||||||
m_passwordStatus != NS_MSG_PASSWORD_PROMPT_CANCELLED &&
|
if (shuttingDown) {
|
||||||
!DeathSignalReceived())
|
// Note: If we fix bug 1783573 this check could be ditched.
|
||||||
mon.Wait(sleepTime);
|
rv = NS_ERROR_FAILURE;
|
||||||
rv = m_passwordStatus;
|
break;
|
||||||
password = m_password;
|
}
|
||||||
|
|
||||||
|
ReentrantMonitorAutoEnter mon(m_passwordReadyMonitor);
|
||||||
|
if (!m_passwordObtained && !NS_FAILED(m_passwordStatus) &&
|
||||||
|
m_passwordStatus != NS_MSG_PASSWORD_PROMPT_CANCELLED &&
|
||||||
|
!DeathSignalReceived()) {
|
||||||
|
mon.Wait(PR_MillisecondsToInterval(1000));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (NS_FAILED(m_passwordStatus) ||
|
||||||
|
m_passwordStatus == NS_MSG_PASSWORD_PROMPT_CANCELLED) {
|
||||||
|
rv = m_passwordStatus;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (DeathSignalReceived()) {
|
||||||
|
rv = NS_ERROR_FAILURE;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (m_passwordObtained) {
|
||||||
|
rv = m_passwordStatus;
|
||||||
|
password = m_password;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!password.IsEmpty()) m_lastPasswordSent = password;
|
if (!password.IsEmpty()) m_lastPasswordSent = password;
|
||||||
|
@ -8401,13 +8428,15 @@ nsImapProtocol::OnPromptStart(bool* aResult) {
|
||||||
GetMsgWindow(getter_AddRefs(msgWindow));
|
GetMsgWindow(getter_AddRefs(msgWindow));
|
||||||
nsString password = m_lastPasswordSent;
|
nsString password = m_lastPasswordSent;
|
||||||
rv = imapServer->PromptPassword(msgWindow, password);
|
rv = imapServer->PromptPassword(msgWindow, password);
|
||||||
|
|
||||||
|
ReentrantMonitorAutoEnter passwordMon(m_passwordReadyMonitor);
|
||||||
|
|
||||||
m_password = password;
|
m_password = password;
|
||||||
m_passwordStatus = rv;
|
m_passwordStatus = rv;
|
||||||
if (!m_password.IsEmpty()) *aResult = true;
|
if (!m_password.IsEmpty()) *aResult = true;
|
||||||
|
|
||||||
// Notify the imap thread that we have a password.
|
// Notify the imap thread that we have a password.
|
||||||
m_passwordObtained = true;
|
m_passwordObtained = true;
|
||||||
ReentrantMonitorAutoEnter passwordMon(m_passwordReadyMonitor);
|
|
||||||
passwordMon.Notify();
|
passwordMon.Notify();
|
||||||
return rv;
|
return rv;
|
||||||
}
|
}
|
||||||
|
@ -8417,10 +8446,14 @@ nsImapProtocol::OnPromptAuthAvailable() {
|
||||||
nsresult rv;
|
nsresult rv;
|
||||||
nsCOMPtr<nsIMsgIncomingServer> imapServer = do_QueryReferent(m_server, &rv);
|
nsCOMPtr<nsIMsgIncomingServer> imapServer = do_QueryReferent(m_server, &rv);
|
||||||
NS_ENSURE_SUCCESS(rv, rv);
|
NS_ENSURE_SUCCESS(rv, rv);
|
||||||
m_passwordStatus = imapServer->GetPassword(m_password);
|
|
||||||
|
nsresult status = imapServer->GetPassword(m_password);
|
||||||
|
|
||||||
|
ReentrantMonitorAutoEnter passwordMon(m_passwordReadyMonitor);
|
||||||
|
|
||||||
|
m_passwordStatus = status;
|
||||||
// Notify the imap thread that we have a password.
|
// Notify the imap thread that we have a password.
|
||||||
m_passwordObtained = true;
|
m_passwordObtained = true;
|
||||||
ReentrantMonitorAutoEnter passwordMon(m_passwordReadyMonitor);
|
|
||||||
passwordMon.Notify();
|
passwordMon.Notify();
|
||||||
return m_passwordStatus;
|
return m_passwordStatus;
|
||||||
}
|
}
|
||||||
|
@ -8428,8 +8461,8 @@ nsImapProtocol::OnPromptAuthAvailable() {
|
||||||
NS_IMETHODIMP
|
NS_IMETHODIMP
|
||||||
nsImapProtocol::OnPromptCanceled() {
|
nsImapProtocol::OnPromptCanceled() {
|
||||||
// A prompt was cancelled, so notify the imap thread.
|
// A prompt was cancelled, so notify the imap thread.
|
||||||
m_passwordStatus = NS_MSG_PASSWORD_PROMPT_CANCELLED;
|
|
||||||
ReentrantMonitorAutoEnter passwordMon(m_passwordReadyMonitor);
|
ReentrantMonitorAutoEnter passwordMon(m_passwordReadyMonitor);
|
||||||
|
m_passwordStatus = NS_MSG_PASSWORD_PROMPT_CANCELLED;
|
||||||
passwordMon.Notify();
|
passwordMon.Notify();
|
||||||
return NS_OK;
|
return NS_OK;
|
||||||
}
|
}
|
||||||
|
|
Загрузка…
Ссылка в новой задаче