summaryrefslogtreecommitdiffstats
path: root/chrome/renderer
diff options
context:
space:
mode:
authorgcasto@chromium.org <gcasto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-01 20:29:59 +0000
committergcasto@chromium.org <gcasto@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2012-06-01 20:29:59 +0000
commitb9c2571754f15540116873367429a8f7bb560510 (patch)
treed73e6d706c00e1e86cc2c8ddea45fa39453c066b /chrome/renderer
parentea5c5f05ca982448272cbfc9d0384a542c84d3b8 (diff)
downloadchromium_src-b9c2571754f15540116873367429a8f7bb560510.zip
chromium_src-b9c2571754f15540116873367429a8f7bb560510.tar.gz
chromium_src-b9c2571754f15540116873367429a8f7bb560510.tar.bz2
Use shadow DOM API to show icon for password generation.
The key icon in this CL is rough draft and will be improved before launch. BUG=114092 TEST=Ran PasswordGenerationManagerTest Review URL: https://chromiumcodereview.appspot.com/10449099 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@140091 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r--chrome/renderer/autofill/password_generation_manager.cc84
-rw-r--r--chrome/renderer/autofill/password_generation_manager.h31
-rw-r--r--chrome/renderer/autofill/password_generation_manager_browsertest.cc31
3 files changed, 98 insertions, 48 deletions
diff --git a/chrome/renderer/autofill/password_generation_manager.cc b/chrome/renderer/autofill/password_generation_manager.cc
index b4bc16f..6abe555 100644
--- a/chrome/renderer/autofill/password_generation_manager.cc
+++ b/chrome/renderer/autofill/password_generation_manager.cc
@@ -6,11 +6,14 @@
#include "base/logging.h"
#include "chrome/common/autofill_messages.h"
+#include "content/public/renderer/render_view.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebDocument.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFormElement.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebSecurityOrigin.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebView.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebCString.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebRect.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/platform/WebVector.h"
#include "ui/gfx/rect.h"
@@ -20,7 +23,9 @@ namespace autofill {
PasswordGenerationManager::PasswordGenerationManager(
content::RenderView* render_view)
: content::RenderViewObserver(render_view),
- enabled_(false) {}
+ enabled_(false) {
+ render_view->GetWebView()->addTextFieldDecoratorClient(this);
+}
PasswordGenerationManager::~PasswordGenerationManager() {}
void PasswordGenerationManager::DidFinishDocumentLoad(WebKit::WebFrame* frame) {
@@ -29,14 +34,14 @@ void PasswordGenerationManager::DidFinishDocumentLoad(WebKit::WebFrame* frame) {
if (!enabled_)
return;
- if (!ShouldAnalyzeFrame(*frame))
+ if (!ShouldAnalyzeDocument(frame->document()))
return;
WebKit::WebVector<WebKit::WebFormElement> forms;
frame->document().forms(forms);
for (size_t i = 0; i < forms.size(); ++i) {
const WebKit::WebFormElement& web_form = forms[i];
- if (!web_form.autoComplete())
+ if (web_form.isNull() || !web_form.autoComplete())
continue;
// Grab all of the passwords for each form.
@@ -50,21 +55,26 @@ void PasswordGenerationManager::DidFinishDocumentLoad(WebKit::WebFrame* frame) {
if (input_element && input_element->isPasswordField())
passwords.push_back(*input_element);
}
+
// For now, just assume that if there are two password fields in the
- // form that this is meant for account creation.
+ // form that this is meant for account creation. Also, we assume that there
+ // is only one account creation field per URL.
// TODO(gcasto): Determine better heauristics for this.
if (passwords.size() == 2) {
- account_creation_elements_ = make_pair(passwords[0], passwords);
- break;
+ passwords_ = passwords;
+ // Make the decoration visible for this element.
+ passwords[0].decorationElementFor(this).setAttribute("style",
+ "display:block");
+ return;
}
}
}
-bool PasswordGenerationManager::ShouldAnalyzeFrame(
- const WebKit::WebFrame& frame) const {
+bool PasswordGenerationManager::ShouldAnalyzeDocument(
+ const WebKit::WebDocument& document) const {
// Make sure that this security origin is allowed to use password manager.
// Generating a password that can't be saved is a bad idea.
- WebKit::WebSecurityOrigin origin = frame.document().securityOrigin();
+ WebKit::WebSecurityOrigin origin = document.securityOrigin();
if (!origin.canAccessPasswordManager()) {
DVLOG(1) << "No PasswordManager access";
return false;
@@ -73,25 +83,44 @@ bool PasswordGenerationManager::ShouldAnalyzeFrame(
return true;
}
-void PasswordGenerationManager::FocusedNodeChanged(
- const WebKit::WebNode& node) {
- WebKit::WebInputElement input_element =
- node.toConst<WebKit::WebInputElement>();
- if (!input_element.isNull() &&
- account_creation_elements_.first == input_element) {
- gfx::Rect rect(input_element.boundsInViewportSpace());
- webkit::forms::PasswordForm* password_form(
- webkit::forms::PasswordFormDomManager::CreatePasswordForm(
- input_element.form()));
-
- if (password_form) {
- Send(new AutofillHostMsg_ShowPasswordGenerationPopup(routing_id(),
- rect,
- *password_form));
- }
+bool PasswordGenerationManager::shouldAddDecorationTo(
+ const WebKit::WebInputElement& element) {
+ return element.isPasswordField();
+}
+
+bool PasswordGenerationManager::visibleByDefault() {
+ return false;
+}
+
+WebKit::WebCString PasswordGenerationManager::imageNameForNormalState() {
+ return WebKit::WebCString("generatePassword");
+}
+
+WebKit::WebCString PasswordGenerationManager::imageNameForDisabledState() {
+ return imageNameForNormalState();
+}
+
+WebKit::WebCString PasswordGenerationManager::imageNameForReadOnlyState() {
+ return imageNameForNormalState();
+}
+
+void PasswordGenerationManager::handleClick(WebKit::WebInputElement& element) {
+ gfx::Rect rect(element.decorationElementFor(this).boundsInViewportSpace());
+ webkit::forms::PasswordForm* password_form(
+ webkit::forms::PasswordFormDomManager::CreatePasswordForm(
+ element.form()));
+ if (password_form) {
+ Send(new AutofillHostMsg_ShowPasswordGenerationPopup(routing_id(),
+ rect,
+ *password_form));
}
}
+void PasswordGenerationManager::willDetach(
+ const WebKit::WebInputElement& element) {
+ // No implementation
+}
+
bool PasswordGenerationManager::OnMessageReceived(const IPC::Message& message) {
bool handled = true;
IPC_BEGIN_MESSAGE_MAP(PasswordGenerationManager, message)
@@ -105,9 +134,8 @@ bool PasswordGenerationManager::OnMessageReceived(const IPC::Message& message) {
}
void PasswordGenerationManager::OnPasswordAccepted(const string16& password) {
- for (std::vector<WebKit::WebInputElement>::iterator it =
- account_creation_elements_.second.begin();
- it != account_creation_elements_.second.end(); ++it) {
+ for (std::vector<WebKit::WebInputElement>::iterator it = passwords_.begin();
+ it != passwords_.end(); ++it) {
it->setValue(password);
it->setAutofilled(true);
}
diff --git a/chrome/renderer/autofill/password_generation_manager.h b/chrome/renderer/autofill/password_generation_manager.h
index 8aa656f..e22531e 100644
--- a/chrome/renderer/autofill/password_generation_manager.h
+++ b/chrome/renderer/autofill/password_generation_manager.h
@@ -12,23 +12,28 @@
#include "content/public/renderer/render_view_observer.h"
#include "third_party/WebKit/Source/WebKit/chromium/public/WebInputElement.h"
+#include "third_party/WebKit/Source/WebKit/chromium/public/WebTextFieldDecoratorClient.h"
+
+namespace WebKit {
+class WebCString;
+class WebDocument;
+}
namespace autofill {
// This class is responsible for controlling communication for password
// generation between the browser (which shows the popup and generates
-// passwords) and WebKit (determines which fields are for account signup and
-// fills in the generated passwords). Currently the WebKit part is not
-// implemented.
-class PasswordGenerationManager : public content::RenderViewObserver {
+// passwords) and WebKit (shows the generation icon in the password field).
+class PasswordGenerationManager : public content::RenderViewObserver,
+ public WebKit::WebTextFieldDecoratorClient {
public:
explicit PasswordGenerationManager(content::RenderView* render_view);
virtual ~PasswordGenerationManager();
protected:
- // Returns true if this frame is one that we should consider analyzing.
+ // Returns true if this document is one that we should consider analyzing.
// Virtual so that it can be overriden during testing.
- virtual bool ShouldAnalyzeFrame(const WebKit::WebFrame& frame) const;
+ virtual bool ShouldAnalyzeDocument(const WebKit::WebDocument& document) const;
// RenderViewObserver:
virtual bool OnMessageReceived(const IPC::Message& message) OVERRIDE;
@@ -36,7 +41,16 @@ class PasswordGenerationManager : public content::RenderViewObserver {
private:
// RenderViewObserver:
virtual void DidFinishDocumentLoad(WebKit::WebFrame* frame) OVERRIDE;
- virtual void FocusedNodeChanged(const WebKit::WebNode& node) OVERRIDE;
+
+ // WebTextFieldDecoratorClient:
+ virtual bool shouldAddDecorationTo(
+ const WebKit::WebInputElement& element) OVERRIDE;
+ virtual bool visibleByDefault() OVERRIDE;
+ virtual WebKit::WebCString imageNameForNormalState() OVERRIDE;
+ virtual WebKit::WebCString imageNameForDisabledState() OVERRIDE;
+ virtual WebKit::WebCString imageNameForReadOnlyState() OVERRIDE;
+ virtual void handleClick(WebKit::WebInputElement& element) OVERRIDE;
+ virtual void willDetach(const WebKit::WebInputElement&) OVERRIDE;
// Message handlers.
void OnPasswordAccepted(const string16& password);
@@ -46,8 +60,7 @@ class PasswordGenerationManager : public content::RenderViewObserver {
// with this renderer.
bool enabled_;
- std::pair<WebKit::WebInputElement,
- std::vector<WebKit::WebInputElement> > account_creation_elements_;
+ std::vector<WebKit::WebInputElement> passwords_;
DISALLOW_COPY_AND_ASSIGN(PasswordGenerationManager);
};
diff --git a/chrome/renderer/autofill/password_generation_manager_browsertest.cc b/chrome/renderer/autofill/password_generation_manager_browsertest.cc
index ce9367f..d51e8c2 100644
--- a/chrome/renderer/autofill/password_generation_manager_browsertest.cc
+++ b/chrome/renderer/autofill/password_generation_manager_browsertest.cc
@@ -37,7 +37,7 @@ class TestPasswordGenerationManager : public PasswordGenerationManager {
}
protected:
- virtual bool ShouldAnalyzeFrame(const WebKit::WebFrame& frame) const
+ virtual bool ShouldAnalyzeDocument(const WebKit::WebDocument& document) const
OVERRIDE {
return true;
}
@@ -65,6 +65,18 @@ class PasswordGenerationManagerTest : public ChromeRenderViewTest {
generation_manager_.reset(new TestPasswordGenerationManager(view_));
}
+ void SimulateClickOnDecoration(WebKit::WebInputElement* input_element) {
+ WebKit::WebElement decoration =
+ input_element->decorationElementFor(generation_manager_.get());
+ decoration.simulateClick();
+ }
+
+ bool DecorationIsVisible(WebKit::WebInputElement* input_element) {
+ WebKit::WebElement decoration =
+ input_element->decorationElementFor(generation_manager_.get());
+ return decoration.hasNonEmptyBoundingBox();
+ }
+
protected:
scoped_ptr<TestPasswordGenerationManager> generation_manager_;
@@ -95,39 +107,36 @@ TEST_F(PasswordGenerationManagerTest, DetectionTest) {
document.getElementById(WebString::fromUTF8("password"));
ASSERT_FALSE(element.isNull());
WebInputElement password_element = element.to<WebInputElement>();
- EXPECT_EQ(0u, generation_manager_->messages().size());
+ EXPECT_FALSE(DecorationIsVisible(&password_element));
LoadHTML(kAccountCreationFormHTML);
- // We don't do anything yet because the feature is disabled.
+ // We don't show the decoration yet because the feature isn't enabled.
document = GetMainFrame()->document();
element = document.getElementById(WebString::fromUTF8("first_password"));
ASSERT_FALSE(element.isNull());
WebInputElement first_password_element = element.to<WebInputElement>();
- EXPECT_EQ(0u, generation_manager_->messages().size());
element = document.getElementById(WebString::fromUTF8("second_password"));
ASSERT_FALSE(element.isNull());
WebInputElement second_password_element = element.to<WebInputElement>();
- EXPECT_EQ(0u, generation_manager_->messages().size());
- SetFocused(first_password_element.to<WebNode>());
- EXPECT_EQ(0u, generation_manager_->messages().size());
+ EXPECT_FALSE(DecorationIsVisible(&first_password_element));
// Pretend like password generation was enabled.
AutofillMsg_PasswordGenerationEnabled msg(0, true);
generation_manager_->OnMessageReceived(msg);
- // Now we will send a message once the first password feld is focused.
+ // Now check that the decoration is visible on the first password field and
+ // that we send a message after the decoration is clicked.
LoadHTML(kAccountCreationFormHTML);
document = GetMainFrame()->document();
element = document.getElementById(WebString::fromUTF8("first_password"));
ASSERT_FALSE(element.isNull());
first_password_element = element.to<WebInputElement>();
- EXPECT_EQ(0u, generation_manager_->messages().size());
element = document.getElementById(WebString::fromUTF8("second_password"));
ASSERT_FALSE(element.isNull());
second_password_element = element.to<WebInputElement>();
- EXPECT_EQ(0u, generation_manager_->messages().size());
- SetFocused(first_password_element.to<WebNode>());
+ EXPECT_TRUE(DecorationIsVisible(&first_password_element));
+ SimulateClickOnDecoration(&first_password_element);
EXPECT_EQ(1u, generation_manager_->messages().size());
EXPECT_EQ(AutofillHostMsg_ShowPasswordGenerationPopup::ID,
generation_manager_->messages()[0]->type());