Chromium Code Reviews| Index: components/password_manager/content/browser/content_password_manager_driver.cc |
| diff --git a/components/password_manager/content/browser/content_password_manager_driver.cc b/components/password_manager/content/browser/content_password_manager_driver.cc |
| index 493384977d5f62767cf4b6ddfedf24b6246de217..f56614c9e9828d8e9e0798cf7c4ef5ab2eab9768 100644 |
| --- a/components/password_manager/content/browser/content_password_manager_driver.cc |
| +++ b/components/password_manager/content/browser/content_password_manager_driver.cc |
| @@ -4,6 +4,8 @@ |
| #include "components/password_manager/content/browser/content_password_manager_driver.h" |
| +#include <set> |
| + |
| #include "components/autofill/content/browser/content_autofill_driver.h" |
| #include "components/autofill/core/common/form_data.h" |
| #include "components/autofill/core/common/password_form.h" |
| @@ -16,6 +18,7 @@ |
| #include "content/public/browser/child_process_security_policy.h" |
| #include "content/public/browser/navigation_details.h" |
| #include "content/public/browser/navigation_entry.h" |
| +#include "content/public/browser/navigation_handle.h" |
| #include "content/public/browser/render_frame_host.h" |
| #include "content/public/browser/render_process_host.h" |
| #include "content/public/browser/render_view_host.h" |
| @@ -30,13 +33,88 @@ namespace password_manager { |
| namespace { |
| -void MaybeNotifyPasswordInputShownOnHttp(content::RenderFrameHost* rfh) { |
| - content::WebContents* web_contents = |
| - content::WebContents::FromRenderFrameHost(rfh); |
| - if (!content::IsOriginSecure(web_contents->GetVisibleURL())) { |
| - web_contents->OnPasswordInputShownOnHttp(); |
| +const char kVisiblePasswordObserverWebContentsUserDataKey[] = |
| + "visible_password_observer"; |
| + |
| +// This class tracks password visibility notifications for the |
| +// RenderFrameHosts in a WebContents. There is one |
|
vabr (Chromium)
2016/11/03 14:57:44
Could this WebContentsObserver be simply merged wi
estark
2016/11/03 15:13:35
I did think about putting this logic in ContentPas
vabr (Chromium)
2016/11/03 15:19:59
Good point about keeping the factory focused on ju
|
| +// VisiblePasswordObserver per WebContents. When a RenderFrameHost has a |
| +// visible password field and the top-level URL is HTTP, the |
| +// VisiblePasswordObserver notifies the WebContents, which allows the |
| +// content embedder to adjust security UI. Similarly, when all |
| +// RenderFrameHosts have hidden their password fields (either because |
| +// the renderer sent a message reporting that all password fields are |
| +// gone, or because the renderer crashed), the WebContents is notified |
| +// so that security warnings can be removed by the embedder. |
| +class VisiblePasswordObserver : public content::WebContentsObserver, |
| + public base::SupportsUserData::Data { |
|
dcheng
2016/11/03 05:33:34
I'd recommend using WebContentsUserData, which hel
estark
2016/11/03 15:13:35
Noted, will do once I work out with vabr (above) w
|
| + public: |
| + static VisiblePasswordObserver* GetOrCreateForWebContents( |
| + content::WebContents* web_contents) { |
| + VisiblePasswordObserver* observer = |
|
vabr (Chromium)
2016/11/03 15:29:41
In addition to moving this out to its own .h/.cc f
estark
2016/11/03 18:54:13
Done.
|
| + static_cast<VisiblePasswordObserver*>(web_contents->GetUserData( |
| + kVisiblePasswordObserverWebContentsUserDataKey)); |
| + if (observer) { |
| + return observer; |
| + } |
| + |
| + observer = new VisiblePasswordObserver(web_contents); |
| + web_contents->SetUserData(kVisiblePasswordObserverWebContentsUserDataKey, |
| + observer); |
| + return observer; |
| } |
| -} |
| + |
| + void RenderFrameHasVisiblePasswordField( |
| + content::RenderFrameHost* render_frame_host) { |
| + frame_tree_nodes_with_visible_password_fields_.insert( |
| + render_frame_host->GetFrameTreeNodeId()); |
| + MaybeNotifyPasswordInputShownOnHttp(); |
| + } |
| + |
| + void RenderFrameHasNoVisiblePasswordFields( |
| + content::RenderFrameHost* render_frame_host) { |
| + frame_tree_nodes_with_visible_password_fields_.erase( |
| + render_frame_host->GetFrameTreeNodeId()); |
| + MaybeNotifyAllFieldsInvisible(); |
| + } |
| + |
| + // WebContentsObserver: |
| + void RenderFrameDeleted( |
| + content::RenderFrameHost* render_frame_host) override { |
| + // If a renderer process crashes, it won't send notifications that |
| + // the password fields have been hidden, so watch for crashing |
| + // processes and remove them from |
| + // |frame_tree_nodes_with_visible_password_fields_|. |
| + frame_tree_nodes_with_visible_password_fields_.erase( |
| + render_frame_host->GetFrameTreeNodeId()); |
| + MaybeNotifyAllFieldsInvisible(); |
| + } |
| + |
| + private: |
| + VisiblePasswordObserver(content::WebContents* web_contents) |
| + : content::WebContentsObserver(web_contents), |
| + web_contents_(web_contents) {} |
| + |
| + ~VisiblePasswordObserver() override {} |
| + |
| + void MaybeNotifyPasswordInputShownOnHttp() { |
| + if (!content::IsOriginSecure(web_contents_->GetVisibleURL())) { |
|
vabr (Chromium)
2016/11/03 15:29:41
Just a question: the status of the UI indication d
estark
2016/11/03 18:54:13
That's right. On navigation, we get messages from
|
| + web_contents_->OnPasswordInputShownOnHttp(); |
| + } |
| + } |
| + |
| + void MaybeNotifyAllFieldsInvisible() { |
| + if (frame_tree_nodes_with_visible_password_fields_.empty() && |
| + !content::IsOriginSecure(web_contents_->GetVisibleURL())) { |
| + web_contents_->OnAllPasswordInputsHiddenOnHttp(); |
| + } |
| + } |
| + |
| + content::WebContents* web_contents_; |
| + std::set<int> frame_tree_nodes_with_visible_password_fields_; |
| + |
| + DISALLOW_COPY_AND_ASSIGN(VisiblePasswordObserver); |
| +}; |
| } // namespace |
| @@ -208,14 +286,18 @@ void ContentPasswordManagerDriver::OnFocusedPasswordFormFound( |
| } |
| void ContentPasswordManagerDriver::PasswordFieldVisibleInInsecureContext() { |
| - MaybeNotifyPasswordInputShownOnHttp(render_frame_host_); |
| + VisiblePasswordObserver* observer = |
| + VisiblePasswordObserver::GetOrCreateForWebContents( |
| + content::WebContents::FromRenderFrameHost(render_frame_host_)); |
| + observer->RenderFrameHasVisiblePasswordField(render_frame_host_); |
| } |
| void ContentPasswordManagerDriver:: |
| AllPasswordFieldsInInsecureContextInvisible() { |
| - // TODO(estark): if all frames in the frame tree have their password |
| - // fields hidden, then notify the WebContents that there are no |
| - // visible password fields left. https://crbug.com/658764 |
| + VisiblePasswordObserver* observer = |
| + VisiblePasswordObserver::GetOrCreateForWebContents( |
| + content::WebContents::FromRenderFrameHost(render_frame_host_)); |
| + observer->RenderFrameHasNoVisiblePasswordFields(render_frame_host_); |
| } |
| void ContentPasswordManagerDriver::DidNavigateFrame( |