cbui: simplify CredentialLeakDialog lifetime
Dramatis personae: CredentialLeakDialogView (CLDV): a DialogDelegateView, owned by Views CredentialLeakDialogController (CLDC): an abstract interface used by CLDV. CredentialLeakDialogControllerImpl (CLDCI): a CLDC instance - actually the only one used in production ManagePasswordsUIController (MPUIC): a WebContentsUserData that controls any password-related UI showing for a given WebContents. Owns at most one CLDC instance. Right now, there are two ways that a CLDV can be closed: in response to something that happens in the browser, or in response to the user clicking one of the buttons on the CLDV. The former case looks like, e.g.: MPUIC::OnChooseCredentials calls CLDCI::~CLDCI calls CLDV::ControllerGone calls Widget::Close calls NonClientView::CanClose calls DialogClientView::CanClose calls CLDV::Close calls CLDCI::OnCloseDialog calls MPUIC::OnLeakDialogHidden and in MUPIC::OnLeakDialogHidden, dialog_controller_ is already null, so the stack unwinds. The *latter* case looks like this though: DialogClientView::ButtonPressed calls DialogClientView::AcceptWindow calls DialogDelegate::Accept [aka CLDV::Accept] calls CLDCI::OnAcceptDialog calls MPUIC::OnLeakDialogHidden calls CLDCI::~CLDCI calls CLDCI::ResetDialog calls CLDV::ControllerGone calls Widget::Close (!) calls NonClientView::CanClose calls DialogClientView::CanClose calls CLDV::Close calls CLDCI::OnCloseDialog calls MPUIC::OnLeakDialogHidden at that point in MPUIC::OnLeakDialogHidden, dialog_controller_ is null because of the previous call on the stack, so the stack unwinds. However, note that the controller got notified of the closure twice - once via OnAcceptDialog and once via OnCloseDialog. To avoid that double notification in case 2, CredentialLeakDialogView nulls out its own controller in {Accept,Cancel,Close}, with a scary block comment about why this is done. The actual issue, though, is the CLDCI::~CLDCI -> CLDV::ControllerGone -> Widget::Close steps - in case 2, the Widget is *already* in the process of closing, as soon as {Accept,Cancel,Close} return; it should not re-enter Widget::Close at all! In order to avoid that re-entry, this CL has CLDV only close itself if the controller is still not null in ControllerGone(), so the logic in the CLDV's accept/cancel/close callbacks that nulls the controller serves to prevent a recursive close. This allows dramatically simplifying the logic around closure in this dialog, and using the "new" closure methods for dialogs. Bug: 1011446 Change-Id: I60100a31614ba10c5e615b985ff3039a2bfbffe6 Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2028194 Commit-Queue: Elly Fong-Jones <ellyjones@chromium.org> Reviewed-by:Peter Boström <pbos@chromium.org> Reviewed-by:
Vasilii Sukhanov <vasilii@chromium.org> Cr-Commit-Position: refs/heads/master@{#737353}
Showing
Please register or sign in to comment