summaryrefslogtreecommitdiffstats
path: root/chrome/renderer
diff options
context:
space:
mode:
authorjcivelli@chromium.org <jcivelli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-05 04:38:06 +0000
committerjcivelli@chromium.org <jcivelli@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98>2010-09-05 04:38:06 +0000
commit6a8ddba5ea1e8972c2954b138aeb14d77a548a3c (patch)
tree4c1a21857eca96cea8a8743a28209041de389699 /chrome/renderer
parente333e8d07ee32668fc132a21c13cdf674443d1e9 (diff)
downloadchromium_src-6a8ddba5ea1e8972c2954b138aeb14d77a548a3c.zip
chromium_src-6a8ddba5ea1e8972c2954b138aeb14d77a548a3c.tar.gz
chromium_src-6a8ddba5ea1e8972c2954b138aeb14d77a548a3c.tar.bz2
Adding a class to track when a node in a page gets clicked.
This is going to be used by the password/form autofill to trigger the suggestion popup, as part of the effort in moving that code out of WebKit. BUG=None TEST=Run unit-tests. Review URL: http://codereview.chromium.org/3090007 git-svn-id: svn://svn.chromium.org/chrome/trunk/src@58597 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'chrome/renderer')
-rw-r--r--chrome/renderer/autofill_helper.cc13
-rw-r--r--chrome/renderer/autofill_helper.h8
-rw-r--r--chrome/renderer/form_autocomplete_browsertest.cc1
-rw-r--r--chrome/renderer/page_click_listener.h30
-rw-r--r--chrome/renderer/page_click_tracker.cc127
-rw-r--r--chrome/renderer/page_click_tracker.h87
-rw-r--r--chrome/renderer/page_click_tracker_unittest.cc120
-rw-r--r--chrome/renderer/password_autocomplete_manager.cc16
-rw-r--r--chrome/renderer/password_autocomplete_manager.h15
-rw-r--r--chrome/renderer/render_view.cc65
-rw-r--r--chrome/renderer/render_view.h22
-rw-r--r--chrome/renderer/render_widget.cc5
-rw-r--r--chrome/renderer/render_widget.h5
-rw-r--r--chrome/renderer/translate_helper.cc22
14 files changed, 479 insertions, 57 deletions
diff --git a/chrome/renderer/autofill_helper.cc b/chrome/renderer/autofill_helper.cc
index 6e8659b..3737726 100644
--- a/chrome/renderer/autofill_helper.cc
+++ b/chrome/renderer/autofill_helper.cc
@@ -9,10 +9,12 @@
#include "chrome/renderer/render_view.h"
#include "grit/generated_resources.h"
#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
-#include "third_party/WebKit/WebKit/chromium/public/WebInputEvent.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFormControlElement.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h"
#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+#include "webkit/glue/form_data.h"
+#include "webkit/glue/form_field.h"
#include "webkit/glue/password_form.h"
using WebKit::WebFormControlElement;
@@ -216,12 +218,15 @@ void AutoFillHelper::TextDidChangeInTextField(const WebInputElement& element) {
ShowSuggestions(element, false, true);
}
-void AutoFillHelper::InputElementClicked(const WebInputElement& element,
- bool already_focused) {
- if (already_focused)
+bool AutoFillHelper::InputElementClicked(const WebInputElement& element,
+ bool was_focused,
+ bool is_focused) {
+ if (was_focused)
ShowSuggestions(element, true, false);
+ return false;
}
+
void AutoFillHelper::ShowSuggestions(
const WebInputElement& const_element,
bool autofill_on_empty_values,
diff --git a/chrome/renderer/autofill_helper.h b/chrome/renderer/autofill_helper.h
index 64b04c8..d4940d0 100644
--- a/chrome/renderer/autofill_helper.h
+++ b/chrome/renderer/autofill_helper.h
@@ -10,6 +10,7 @@
#include "base/basictypes.h"
#include "chrome/renderer/form_manager.h"
+#include "chrome/renderer/page_click_listener.h"
#include "third_party/WebKit/WebKit/chromium/public/WebNode.h"
class RenderView;
@@ -26,7 +27,7 @@ class WebString;
// - single text field suggestions, that we usually refer to as Autocomplete
// - entire form fill based on one field entry, referred to as form AutoFill.
-class AutoFillHelper {
+class AutoFillHelper : public PageClickListener {
public:
explicit AutoFillHelper(RenderView* render_view);
@@ -99,6 +100,11 @@ class AutoFillHelper {
AUTOFILL_PREVIEW, // Preview the AutoFill form data.
};
+ // PageClickListener implementation:
+ virtual bool InputElementClicked(const WebKit::WebInputElement& element,
+ bool was_focused,
+ bool is_focused);
+
// Shows the autocomplete suggestions for |element|.
// This call is asynchronous and may or may not lead to the showing of a
// suggestion popup (no popup is shown if there are no available suggestions).
diff --git a/chrome/renderer/form_autocomplete_browsertest.cc b/chrome/renderer/form_autocomplete_browsertest.cc
index 164afa2..55429bd 100644
--- a/chrome/renderer/form_autocomplete_browsertest.cc
+++ b/chrome/renderer/form_autocomplete_browsertest.cc
@@ -6,6 +6,7 @@
#include "chrome/test/render_view_test.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFormElement.h"
#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
#include "third_party/WebKit/WebKit/chromium/public/WebURLError.h"
#include "webkit/glue/form_data.h"
diff --git a/chrome/renderer/page_click_listener.h b/chrome/renderer/page_click_listener.h
new file mode 100644
index 0000000..fca52c8
--- /dev/null
+++ b/chrome/renderer/page_click_listener.h
@@ -0,0 +1,30 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_PAGE_CLICK_LISTENER_H_
+#define CHROME_RENDERER_PAGE_CLICK_LISTENER_H_
+
+namespace WebKit {
+class WebInputElement;
+}
+
+// Interface that should be implemented by classes interested in getting
+// notifications for clicks on a page.
+// Register on the PageListenerTracker object.
+class PageClickListener {
+ public:
+ // Notification that |element| was clicked.
+ // |was_focused| is true if |element| had focus BEFORE the click.
+ // |is_focused| is true if |element| has focus AFTER the click was processed.
+ // If this method returns true, the notification will not be propagated to
+ // other listeners.
+ virtual bool InputElementClicked(const WebKit::WebInputElement& element,
+ bool was_focused,
+ bool is_focused) = 0;
+
+ protected:
+ virtual ~PageClickListener() {}
+};
+
+#endif // CHROME_RENDERER_PAGE_CLICK_LISTENER_H_
diff --git a/chrome/renderer/page_click_tracker.cc b/chrome/renderer/page_click_tracker.cc
new file mode 100644
index 0000000..e059bd3
--- /dev/null
+++ b/chrome/renderer/page_click_tracker.cc
@@ -0,0 +1,127 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "chrome/renderer/page_click_tracker.h"
+
+#include "chrome/renderer/page_click_listener.h"
+#include "chrome/renderer/render_view.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebDOMMouseEvent.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebString.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+
+using WebKit::WebDOMEvent;
+using WebKit::WebDOMMouseEvent;
+using WebKit::WebElement;
+using WebKit::WebFormControlElement;
+using WebKit::WebFrame;
+using WebKit::WebInputElement;
+using WebKit::WebInputEvent;
+using WebKit::WebMouseEvent;
+using WebKit::WebNode;
+using WebKit::WebString;
+using WebKit::WebView;
+
+PageClickTracker::PageClickTracker(RenderView* render_view)
+ : render_view_(render_view),
+ was_focused_(false) {
+}
+
+PageClickTracker::~PageClickTracker() {
+ // Note that even though RenderView calls StopTrackingFrame when notified that
+ // a frame was closed, it might not always get that notification from WebKit
+ // for all frames.
+ // By the time we get here, the frame could have been destroyed so we cannot
+ // unregister listeners in frames remaining in tracked_frames_ as they might
+ // be invalid.
+}
+
+void PageClickTracker::StartTrackingFrame(WebFrame* frame) {
+ tracked_frames_.push_back(frame);
+ frame->document().addEventListener("mousedown", this, false);
+}
+
+void PageClickTracker::StopTrackingFrame(WebFrame* frame, bool frame_detached) {
+ FrameList::iterator iter =
+ std::find(tracked_frames_.begin(), tracked_frames_.end(), frame);
+ if (iter == tracked_frames_.end()) {
+ // Some frames might never load contents so we may not have a listener on
+ // them. Calling removeEventListener() on them would trigger an assert, so
+ // we need to keep track of which frames we are listening to.
+ return;
+ }
+ tracked_frames_.erase(iter);
+ // If the frame has been detached, all event listeners have already been
+ // removed.
+ if (!frame_detached)
+ frame->document().removeEventListener("mousedown", this, false);
+}
+
+void PageClickTracker::DidHandleMouseEvent(const WebMouseEvent& event) {
+ if (event.type != WebInputEvent::MouseDown ||
+ last_node_clicked_.isNull()) {
+ return;
+ }
+
+ // We are only interested in text field clicks.
+ if (!last_node_clicked_.isElementNode())
+ return;
+ const WebElement& element = last_node_clicked_.toConst<WebElement>();
+ if (!element.isFormControlElement())
+ return;
+ const WebFormControlElement& control =
+ element.toConst<WebFormControlElement>();
+ if (control.formControlType() != WebString::fromUTF8("text"))
+ return;
+
+ const WebInputElement& input_element = element.toConst<WebInputElement>();
+
+ bool is_focused = (last_node_clicked_ == GetFocusedNode());
+ ObserverListBase<PageClickListener>::Iterator it(listeners_);
+ PageClickListener* listener;
+ while ((listener = it.GetNext()) != NULL) {
+ if (listener->InputElementClicked(input_element, was_focused_, is_focused))
+ break;
+ }
+
+ last_node_clicked_.reset();
+}
+
+void PageClickTracker::AddListener(PageClickListener* listener) {
+ listeners_.AddObserver(listener);
+}
+
+void PageClickTracker::RemoveListener(PageClickListener* listener) {
+ listeners_.RemoveObserver(listener);
+}
+
+void PageClickTracker::handleEvent(const WebDOMEvent& event) {
+ last_node_clicked_.reset();
+
+ DCHECK(event.isMouseEvent());
+ const WebDOMMouseEvent mouse_event = event.toConst<WebDOMMouseEvent>();
+ DCHECK(mouse_event.buttonDown());
+ if (mouse_event.button() != 0)
+ return; // We are only interested in left clicks.
+
+ // Remember which node has focus before the click is processed.
+ // We'll get a notification once the mouse event has been processed
+ // (DidHandleMouseEvent), we'll notify the listener at that point.
+ last_node_clicked_ = mouse_event.target();
+ was_focused_ = (GetFocusedNode() == last_node_clicked_);
+}
+
+WebNode PageClickTracker::GetFocusedNode() {
+ WebView* web_view = render_view_->webview();
+ if (!web_view)
+ return WebNode();
+
+ WebFrame* web_frame = web_view->focusedFrame();
+ if (!web_frame)
+ return WebNode();
+
+ return web_frame->document().focusedNode();
+}
diff --git a/chrome/renderer/page_click_tracker.h b/chrome/renderer/page_click_tracker.h
new file mode 100644
index 0000000..492237c
--- /dev/null
+++ b/chrome/renderer/page_click_tracker.h
@@ -0,0 +1,87 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef CHROME_RENDERER_PAGE_CLICK_TRACKER_H_
+#define CHROME_RENDERER_PAGE_CLICK_TRACKER_H_
+
+#include <vector>
+
+#include "base/basictypes.h"
+#include "base/observer_list.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebDOMEventListener.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebNode.h"
+
+class PageClickListener;
+class RenderView;
+
+namespace WebKit {
+class WebFrame;
+class WebDOMEvent;
+class WebMouseEvent;
+}
+
+// This class is responsible for tracking clicks on elements in web pages and
+// notifiying the associated listener when a node is clicked.
+// Compared to a simple WebDOMEventListener, it offers the added capability of
+// notifying the listeners of whether the clicked node was already focused
+// before it was clicked.
+//
+// This is useful for password/form autofill where we want to trigger a
+// suggestion popup when a text input is clicked.
+// It only notifies of WebInputElement that are text inputs being clicked, but
+// could easily be changed to report click on any type of WebNode.
+//
+// There is one PageClickTracker per RenderView.
+
+class PageClickTracker : public WebKit::WebDOMEventListener {
+ public:
+ explicit PageClickTracker(RenderView* render_view);
+ virtual ~PageClickTracker();
+
+ // Starts reporting node clicks for |frame| on the listener previously
+ // specified with SetListener().
+ void StartTrackingFrame(WebKit::WebFrame* frame);
+
+ // Stops reporting node clicks for |frame|. |frame_detached| should be true
+ // if the frame has already been detached.
+ void StopTrackingFrame(WebKit::WebFrame* frame, bool frame_detached);
+
+ // Called after the mouse event |event| has been processed by WebKit.
+ void DidHandleMouseEvent(const WebKit::WebMouseEvent& event);
+
+ // Adds/removes a listener for getting notification when an element is
+ // clicked. Note that the order of insertion is important as a listener when
+ // notified can decide to stop the propagation of the event (so that listeners
+ // inserted after don't get the notification).
+ void AddListener(PageClickListener* listener);
+ void RemoveListener(PageClickListener* listener);
+
+ private:
+ // WebKit::WebDOMEventListener implementation.
+ virtual void handleEvent(const WebKit::WebDOMEvent& event);
+
+ // Returns the currently focused node in the associated render view.
+ // That node may be null.
+ WebKit::WebNode GetFocusedNode();
+
+ // The last node that was clicked and had focus.
+ WebKit::WebNode last_node_clicked_;
+
+ // The render view we are associated with.
+ RenderView* render_view_;
+
+ // Whether the last clicked node had focused before it was clicked.
+ bool was_focused_;
+
+ // The frames we are listening to for mouse events.
+ typedef std::vector<WebKit::WebFrame*> FrameList;
+ FrameList tracked_frames_;
+
+ // The listener getting the actual notifications.
+ ObserverList<PageClickListener> listeners_;
+
+ DISALLOW_COPY_AND_ASSIGN(PageClickTracker);
+};
+
+#endif // CHROME_RENDERER_PAGE_CLICK_TRACKER_H_
diff --git a/chrome/renderer/page_click_tracker_unittest.cc b/chrome/renderer/page_click_tracker_unittest.cc
new file mode 100644
index 0000000..dcba0bb
--- /dev/null
+++ b/chrome/renderer/page_click_tracker_unittest.cc
@@ -0,0 +1,120 @@
+// Copyright (c) 2010 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "base/basictypes.h"
+
+#include "chrome/common/render_messages.h"
+#include "chrome/renderer/page_click_listener.h"
+#include "chrome/renderer/page_click_tracker.h"
+#include "chrome/test/render_view_test.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebSize.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
+
+class TestPageClickListener : public PageClickListener {
+ public:
+ TestPageClickListener()
+ : called_(false),
+ was_focused_(false),
+ is_focused_(false),
+ notification_response_(false) {
+ }
+
+ virtual bool InputElementClicked(const WebKit::WebInputElement& element,
+ bool was_focused,
+ bool is_focused) {
+ called_ = true;
+ element_clicked_ = element;
+ was_focused_ = was_focused;
+ is_focused_ = is_focused;
+ return notification_response_;
+ }
+
+ void ClearResults() {
+ called_ = false;
+ element_clicked_.reset();
+ was_focused_ = false;
+ is_focused_ = false;
+ }
+
+ bool called_;
+ WebKit::WebInputElement element_clicked_;
+ bool was_focused_;
+ bool is_focused_;
+ bool notification_response_;
+};
+
+// Tests that PageClickTracker does notify correctly when a node is clicked.
+TEST_F(RenderViewTest, PageClickTracker) {
+ TestPageClickListener test_listener1;
+ TestPageClickListener test_listener2;
+ view_->page_click_tracker()->AddListener(&test_listener1);
+ view_->page_click_tracker()->AddListener(&test_listener2);
+
+ LoadHTML("<form>"
+ " <input type='text' id='text'></input><br>"
+ " <input type='button' id='button'></input><br>"
+ "</form>");
+ view_->webwidget()->resize(WebKit::WebSize(500, 500));
+ view_->webwidget()->setFocus(true);
+ WebKit::WebDocument document = view_->webview()->mainFrame()->document();
+ WebKit::WebElement text = document.getElementById("text");
+ ASSERT_FALSE(text.isNull());
+ WebKit::WebElement button = document.getElementById("button");
+ ASSERT_FALSE(button.isNull());
+
+ // Click the text field once.
+ EXPECT_TRUE(SimulateElementClick("text"));
+ EXPECT_TRUE(test_listener1.called_);
+ EXPECT_TRUE(test_listener2.called_);
+ EXPECT_FALSE(test_listener1.was_focused_);
+ EXPECT_FALSE(test_listener2.was_focused_);
+ EXPECT_TRUE(test_listener1.is_focused_);
+ EXPECT_TRUE(test_listener2.is_focused_);
+ EXPECT_TRUE(text == test_listener1.element_clicked_);
+ EXPECT_TRUE(text == test_listener2.element_clicked_);
+ test_listener1.ClearResults();
+ test_listener2.ClearResults();
+
+ // Click the text field again to test that was_focused_ is set correctly.
+ EXPECT_TRUE(SimulateElementClick("text"));
+ EXPECT_TRUE(test_listener1.called_);
+ EXPECT_TRUE(test_listener2.called_);
+ EXPECT_TRUE(test_listener1.was_focused_);
+ EXPECT_TRUE(test_listener2.was_focused_);
+ EXPECT_TRUE(test_listener1.is_focused_);
+ EXPECT_TRUE(test_listener2.is_focused_);
+ EXPECT_TRUE(text == test_listener1.element_clicked_);
+ EXPECT_TRUE(text == test_listener2.element_clicked_);
+ test_listener1.ClearResults();
+ test_listener2.ClearResults();
+
+ // Click the button, no notification should happen (this is not a text-input).
+ EXPECT_TRUE(SimulateElementClick("button"));
+ EXPECT_FALSE(test_listener1.called_);
+ EXPECT_FALSE(test_listener2.called_);
+
+ // Make the first listener stop the event propagation, click the text field
+ // and make sure only the first listener is notified.
+ test_listener1.notification_response_ = true;
+ EXPECT_TRUE(SimulateElementClick("text"));
+ EXPECT_TRUE(test_listener1.called_);
+ EXPECT_FALSE(test_listener2.called_);
+ test_listener1.ClearResults();
+
+ // Make sure removing a listener work.
+ view_->page_click_tracker()->RemoveListener(&test_listener1);
+ EXPECT_TRUE(SimulateElementClick("text"));
+ EXPECT_FALSE(test_listener1.called_);
+ EXPECT_TRUE(test_listener2.called_);
+ test_listener2.ClearResults();
+
+ // Make sure we don't choke when no listeners are registered.
+ view_->page_click_tracker()->RemoveListener(&test_listener2);
+ EXPECT_TRUE(SimulateElementClick("text"));
+ EXPECT_FALSE(test_listener1.called_);
+ EXPECT_FALSE(test_listener2.called_);
+}
diff --git a/chrome/renderer/password_autocomplete_manager.cc b/chrome/renderer/password_autocomplete_manager.cc
index c460db4..3e49a6d 100644
--- a/chrome/renderer/password_autocomplete_manager.cc
+++ b/chrome/renderer/password_autocomplete_manager.cc
@@ -305,11 +305,6 @@ void PasswordAutocompleteManager::TextFieldHandlingKeyDown(
(win_key_code == app::VKEY_BACK || win_key_code == app::VKEY_DELETE);
}
-bool PasswordAutocompleteManager::InputElementClicked(
- const WebKit::WebInputElement& element, bool already_focused) {
- return false;
-}
-
bool PasswordAutocompleteManager::FillPassword(
const WebKit::WebInputElement& user_input) {
LoginToPasswordInfoMap::iterator iter =
@@ -386,6 +381,17 @@ void PasswordAutocompleteManager::SendPasswordForms(WebKit::WebFrame* frame,
}
////////////////////////////////////////////////////////////////////////////////
+// PageClickListener implementation:
+
+bool PasswordAutocompleteManager::InputElementClicked(
+ const WebKit::WebInputElement& element,
+ bool was_focused,
+ bool is_focused) {
+ // TODO(jcivelli): http://crbug.com/51644 Implement behavior.
+ return false;
+}
+
+////////////////////////////////////////////////////////////////////////////////
// PasswordAutocompleteManager, private:
void PasswordAutocompleteManager::GetSuggestions(
diff --git a/chrome/renderer/password_autocomplete_manager.h b/chrome/renderer/password_autocomplete_manager.h
index 40cc893..cf6c4eb 100644
--- a/chrome/renderer/password_autocomplete_manager.h
+++ b/chrome/renderer/password_autocomplete_manager.h
@@ -10,6 +10,7 @@
#include <vector>
#include "base/task.h"
+#include "chrome/renderer/page_click_listener.h"
#include "webkit/glue/password_form_dom_manager.h"
#include "third_party/WebKit/WebKit/chromium/public/WebInputElement.h"
@@ -21,7 +22,7 @@ class WebView;
// This class is responsible for filling password forms.
// There is one PasswordAutocompleteManager per RenderView.
-class PasswordAutocompleteManager {
+class PasswordAutocompleteManager : public PageClickListener {
public:
explicit PasswordAutocompleteManager(RenderView* render_view);
virtual ~PasswordAutocompleteManager();
@@ -61,13 +62,6 @@ class PasswordAutocompleteManager {
void TextFieldHandlingKeyDown(const WebKit::WebInputElement& element,
const WebKit::WebKeyboardEvent& event);
- // Called when an input element in the page has been clicked.
- // |already_focused| is true if |element| was focused before it was clicked.
- // Returns true if the call triggered a suggestion popup.
- // TODO(jcivelli): http://crbug.com/51644 Implement behavior.
- bool InputElementClicked(const WebKit::WebInputElement& element,
- bool already_focused);
-
private:
struct PasswordInfo {
WebKit::WebInputElement password_field;
@@ -77,6 +71,11 @@ class PasswordAutocompleteManager {
};
typedef std::map<WebKit::WebElement, PasswordInfo> LoginToPasswordInfoMap;
+ // PageClickListener implementation:
+ virtual bool InputElementClicked(const WebKit::WebInputElement& element,
+ bool was_focused,
+ bool is_focused);
+
void GetSuggestions(
const webkit_glue::PasswordFormFillData& fill_data,
const string16& input,
diff --git a/chrome/renderer/render_view.cc b/chrome/renderer/render_view.cc
index 9185d48..0c2eb5a 100644
--- a/chrome/renderer/render_view.cc
+++ b/chrome/renderer/render_view.cc
@@ -44,6 +44,7 @@
#include "chrome/common/window_container_type.h"
#include "chrome/renderer/about_handler.h"
#include "chrome/renderer/audio_message_filter.h"
+#include "chrome/renderer/autofill_helper.h"
#include "chrome/renderer/blocked_plugin.h"
#include "chrome/renderer/device_orientation_dispatcher.h"
#include "chrome/renderer/devtools_agent.h"
@@ -60,6 +61,8 @@
#include "chrome/renderer/media/ipc_video_renderer.h"
#include "chrome/renderer/navigation_state.h"
#include "chrome/renderer/notification_provider.h"
+#include "chrome/renderer/page_click_tracker.h"
+#include "chrome/renderer/password_autocomplete_manager.h"
#include "chrome/renderer/plugin_channel_host.h"
#include "chrome/renderer/print_web_view_helper.h"
#include "chrome/renderer/render_process.h"
@@ -458,13 +461,19 @@ RenderView::RenderView(RenderThreadBase* render_thread,
ALLOW_THIS_IN_INITIALIZER_LIST(page_info_method_factory_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(autofill_method_factory_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(translate_helper_(this)),
- ALLOW_THIS_IN_INITIALIZER_LIST(password_autocomplete_manager_(this)),
- ALLOW_THIS_IN_INITIALIZER_LIST(autofill_helper_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(cookie_jar_(this)),
ALLOW_THIS_IN_INITIALIZER_LIST(
notification_provider_(new NotificationProvider(this))),
session_storage_namespace_id_(session_storage_namespace_id),
decrement_shared_popup_at_destruction_(false) {
+ password_autocomplete_manager_.reset(new PasswordAutocompleteManager(this));
+ autofill_helper_.reset(new AutoFillHelper(this));
+ page_click_tracker_.reset(new PageClickTracker(this));
+ // Note that the order of insertion of the listeners is important.
+ // The password_autocomplete_manager_ takes the first shot at processing the
+ // notification and can stop the propagation.
+ page_click_tracker_->AddListener(password_autocomplete_manager_.get());
+ page_click_tracker_->AddListener(autofill_helper_.get());
ClearBlockedContentSettings();
}
@@ -1605,13 +1614,13 @@ void RenderView::OnAutoFillSuggestionsReturned(
const std::vector<string16>& labels,
const std::vector<string16>& icons,
const std::vector<int>& unique_ids) {
- autofill_helper_.SuggestionsReceived(
+ autofill_helper_->SuggestionsReceived(
query_id, values, labels, icons, unique_ids);
}
void RenderView::OnAutoFillFormDataFilled(int query_id,
const webkit_glue::FormData& form) {
- autofill_helper_.FormDataFilled(query_id, form);
+ autofill_helper_->FormDataFilled(query_id, form);
}
void RenderView::OnAllowScriptToClose(bool script_can_close) {
@@ -1873,7 +1882,7 @@ void RenderView::didExecuteCommand(const WebString& command_name) {
void RenderView::textFieldDidEndEditing(
const WebKit::WebInputElement& element) {
#if defined(WEBKIT_BUG_41283_IS_FIXED)
- password_autocomplete_manager_.TextFieldDidEndEditing(element);
+ password_autocomplete_manager_->TextFieldDidEndEditing(element);
#endif
}
@@ -1892,16 +1901,16 @@ void RenderView::textFieldDidChange(const WebKit::WebInputElement& element) {
void RenderView::TextFieldDidChangeImpl(
const WebKit::WebInputElement& element) {
- if (password_autocomplete_manager_.TextDidChangeInTextField(element))
+ if (password_autocomplete_manager_->TextDidChangeInTextField(element))
return;
- autofill_helper_.TextDidChangeInTextField(element);
+ autofill_helper_->TextDidChangeInTextField(element);
}
void RenderView::textFieldDidReceiveKeyDown(
const WebKit::WebInputElement& element,
const WebKit::WebKeyboardEvent& event) {
#if defined(WEBKIT_BUG_41283_IS_FIXED)
- password_autocomplete_manager_.TextFieldHandlingKeyDown(element, event);
+ password_autocomplete_manager_->TextFieldHandlingKeyDown(element, event);
#endif
}
@@ -1933,11 +1942,11 @@ bool RenderView::handleCurrentKeyboardEvent() {
void RenderView::inputElementClicked(const WebKit::WebInputElement& element,
bool already_focused) {
#if defined(WEBKIT_BUG_41283_IS_FIXED)
- if (password_autocomplete_manager_.InputElementClicked(element,
- already_focused)) {
+ if (password_autocomplete_manager_->InputElementClicked(element,
+ already_focused)) {
return;
}
- autofill_helper_.InputElementClicked(element, already_focused);
+ autofill_helper_->InputElementClicked(element, already_focused);
#endif
}
@@ -2198,12 +2207,12 @@ void RenderView::didUpdateInspectorSetting(const WebString& key,
void RenderView::queryAutofillSuggestions(const WebNode& node,
const WebString& name,
const WebString& value) {
- autofill_helper_.QueryAutoFillSuggestions(node, name, value);
+ autofill_helper_->QueryAutoFillSuggestions(node, name, value);
}
void RenderView::removeAutofillSuggestions(const WebString& name,
const WebString& value) {
- autofill_helper_.RemoveAutocompleteSuggestion(name, value);
+ autofill_helper_->RemoveAutocompleteSuggestion(name, value);
}
void RenderView::didAcceptAutoFillSuggestion(const WebKit::WebNode& node,
@@ -2211,25 +2220,25 @@ void RenderView::didAcceptAutoFillSuggestion(const WebKit::WebNode& node,
const WebKit::WebString& label,
int unique_id,
unsigned index) {
- autofill_helper_.DidAcceptAutoFillSuggestion(node, value, label, unique_id,
- index);
+ autofill_helper_->DidAcceptAutoFillSuggestion(node, value, label, unique_id,
+ index);
}
void RenderView::didSelectAutoFillSuggestion(const WebKit::WebNode& node,
const WebKit::WebString& value,
const WebKit::WebString& label,
int unique_id) {
- autofill_helper_.DidSelectAutoFillSuggestion(node, value, label, unique_id);
+ autofill_helper_->DidSelectAutoFillSuggestion(node, value, label, unique_id);
}
void RenderView::didClearAutoFillSelection(const WebKit::WebNode& node) {
- autofill_helper_.DidClearAutoFillSelection(node);
+ autofill_helper_->DidClearAutoFillSelection(node);
}
void RenderView::didAcceptAutocompleteSuggestion(
const WebKit::WebInputElement& user_element) {
#if defined(WEBKIT_BUG_41283_IS_FIXED)
- bool result = password_autocomplete_manager_.FillPassword(user_element);
+ bool result = password_autocomplete_manager_->FillPassword(user_element);
// Since this user name was selected from a suggestion list, we should always
// have password for it.
DCHECK(result);
@@ -2489,7 +2498,8 @@ WebCookieJar* RenderView::cookieJar() {
}
void RenderView::frameDetached(WebFrame* frame) {
- autofill_helper_.FrameDetached(frame);
+ autofill_helper_->FrameDetached(frame);
+ page_click_tracker_->StopTrackingFrame(frame, true);
}
void RenderView::willClose(WebFrame* frame) {
@@ -2511,7 +2521,7 @@ void RenderView::willClose(WebFrame* frame) {
navigation_state->user_script_idle_scheduler()->Cancel();
// TODO(jhawkins): Remove once frameDetached is called by WebKit.
- autofill_helper_.FrameWillClose(frame);
+ autofill_helper_->FrameWillClose(frame);
}
bool RenderView::allowImages(WebFrame* frame, bool enabled_per_settings) {
@@ -3089,10 +3099,11 @@ void RenderView::didFinishDocumentLoad(WebFrame* frame) {
Send(new ViewHostMsg_DocumentLoadedInFrame(routing_id_));
+ page_click_tracker_->StartTrackingFrame(frame);
// The document has now been fully loaded. Scan for forms to be sent up to
// the browser.
- autofill_helper_.FrameContentsAvailable(frame);
- password_autocomplete_manager_.SendPasswordForms(frame, false);
+ autofill_helper_->FrameContentsAvailable(frame);
+ password_autocomplete_manager_->SendPasswordForms(frame, false);
// Check whether we have new encoding name.
UpdateEncoding(frame, frame->view()->pageEncoding().utf8());
@@ -3139,7 +3150,7 @@ void RenderView::didFinishLoad(WebFrame* frame) {
navigation_state->user_script_idle_scheduler()->DidFinishLoad();
// Let the password manager know which password forms are actually visible.
- password_autocomplete_manager_.SendPasswordForms(frame, true);
+ password_autocomplete_manager_->SendPasswordForms(frame, true);
}
void RenderView::didNavigateWithinPage(
@@ -4148,7 +4159,7 @@ void RenderView::OnDragSourceSystemDragEnded() {
void RenderView::OnFillPasswordForm(
const webkit_glue::PasswordFormFillData& form_data) {
#if defined(WEBKIT_BUG_41283_IS_FIXED)
- password_autocomplete_manager_.ReceivedPasswordFormFillData(webview(),
+ password_autocomplete_manager_->ReceivedPasswordFormFillData(webview(),
form_data);
#else
webkit_glue::FillPasswordForm(this->webview(), form_data);
@@ -5455,6 +5466,10 @@ void RenderView::DidHandleKeyEvent() {
edit_commands_.clear();
}
+void RenderView::DidHandleMouseEvent(const WebKit::WebMouseEvent& event) {
+ page_click_tracker_->DidHandleMouseEvent(event);
+}
+
#if defined(OS_MACOSX)
void RenderView::OnWasHidden() {
RenderWidget::OnWasHidden();
@@ -5589,7 +5604,7 @@ void RenderView::OnPageTranslated() {
return;
// The page is translated, so try to extract the form data again.
- autofill_helper_.FrameContentsAvailable(frame);
+ autofill_helper_->FrameContentsAvailable(frame);
}
WebKit::WebGeolocationService* RenderView::geolocationService() {
diff --git a/chrome/renderer/render_view.h b/chrome/renderer/render_view.h
index b318548..cf06c09 100644
--- a/chrome/renderer/render_view.h
+++ b/chrome/renderer/render_view.h
@@ -28,11 +28,9 @@
#include "chrome/common/render_messages.h"
#include "chrome/common/renderer_preferences.h"
#include "chrome/common/view_types.h"
-#include "chrome/renderer/autofill_helper.h"
#include "chrome/renderer/automation/dom_automation_controller.h"
#include "chrome/renderer/dom_ui_bindings.h"
#include "chrome/renderer/external_host_bindings.h"
-#include "chrome/renderer/password_autocomplete_manager.h"
#include "chrome/renderer/pepper_plugin_delegate_impl.h"
#include "chrome/renderer/render_widget.h"
#include "chrome/renderer/renderer_webcookiejar_impl.h"
@@ -56,6 +54,7 @@
#endif
class AudioMessageFilter;
+class AutoFillHelper;
class DictionaryValue;
class DeviceOrientationDispatcher;
class DevToolsAgent;
@@ -66,6 +65,8 @@ class GURL;
class ListValue;
class NavigationState;
class NotificationProvider;
+class PageClickTracker;
+class PasswordAutocompleteManager;
class PepperDeviceTest;
class PluginGroup;
class PrintWebViewHelper;
@@ -111,6 +112,7 @@ class WebInputElement;
class WebKeyboardEvent;
class WebMediaPlayer;
class WebMediaPlayerClient;
+class WebMouseEvent;
class WebNode;
class WebPlugin;
class WebSpeechInputController;
@@ -209,6 +211,10 @@ class RenderView : public RenderWidget,
send_content_state_immediately_ = value;
}
+ PageClickTracker* page_click_tracker() const {
+ return page_click_tracker_.get();
+ }
+
// Called from JavaScript window.external.AddSearchProvider() to add a
// keyword for a provider described in the given OpenSearch document.
void AddSearchProvider(const std::string& url);
@@ -592,6 +598,8 @@ class RenderView : public RenderWidget,
virtual void DidInitiatePaint();
virtual void DidFlushPaint();
virtual void DidHandleKeyEvent();
+ virtual void DidHandleMouseEvent(const WebKit::WebMouseEvent& event);
+
#if OS_MACOSX
virtual void OnSetFocus(bool enable);
virtual void OnWasHidden();
@@ -1211,11 +1219,17 @@ class RenderView : public RenderWidget,
TranslateHelper translate_helper_;
// Responsible for automatically filling login and password textfields.
- PasswordAutocompleteManager password_autocomplete_manager_;
+ scoped_ptr<PasswordAutocompleteManager> password_autocomplete_manager_;
// Responsible for filling forms (AutoFill) and single text entries
// (Autocomplete).
- AutoFillHelper autofill_helper_;
+ scoped_ptr<AutoFillHelper> autofill_helper_;
+
+ // Tracks when text input controls get clicked.
+ // IMPORTANT: this should be declared after autofill_helper_ and
+ // password_autocomplete_manager_ so the tracker is deleted first (so we won't
+ // run the risk of notifying deleted objects).
+ scoped_ptr<PageClickTracker> page_click_tracker_;
RendererWebCookieJarImpl cookie_jar_;
diff --git a/chrome/renderer/render_widget.cc b/chrome/renderer/render_widget.cc
index 9387230..480285a 100644
--- a/chrome/renderer/render_widget.cc
+++ b/chrome/renderer/render_widget.cc
@@ -41,6 +41,7 @@
using WebKit::WebCompositionUnderline;
using WebKit::WebCursorInfo;
using WebKit::WebInputEvent;
+using WebKit::WebMouseEvent;
using WebKit::WebNavigationPolicy;
using WebKit::WebPopupMenu;
using WebKit::WebPopupMenuInfo;
@@ -131,7 +132,7 @@ void RenderWidget::Init(int32 opener_id) {
void RenderWidget::DoInit(int32 opener_id,
- WebKit::WebWidget* web_widget,
+ WebWidget* web_widget,
IPC::SyncMessage* create_widget_message) {
DCHECK(!webwidget_);
@@ -374,6 +375,8 @@ void RenderWidget::OnHandleInputEvent(const IPC::Message& message) {
if (WebInputEvent::isKeyboardEventType(input_event->type))
DidHandleKeyEvent();
+ if (WebInputEvent::isMouseEventType(input_event->type))
+ DidHandleMouseEvent(*(static_cast<const WebMouseEvent*>(input_event)));
}
void RenderWidget::OnMouseCaptureLost() {
diff --git a/chrome/renderer/render_widget.h b/chrome/renderer/render_widget.h
index 2d8ea717..2fa2308 100644
--- a/chrome/renderer/render_widget.h
+++ b/chrome/renderer/render_widget.h
@@ -42,6 +42,7 @@ class PlatformCanvas;
}
namespace WebKit {
+class WebMouseEvent;
class WebWidget;
struct WebPopupMenuInfo;
}
@@ -238,6 +239,10 @@ class RenderWidget : public IPC::Channel::Listener,
// just handled.
virtual void DidHandleKeyEvent() {}
+ // Called by OnHandleInputEvent() to notify subclasses that a mouse event was
+ // just handled.
+ virtual void DidHandleMouseEvent(const WebKit::WebMouseEvent& event) {}
+
// Routing ID that allows us to communicate to the parent browser process
// RenderWidgetHost. When MSG_ROUTING_NONE, no messages may be sent.
int32 routing_id_;
diff --git a/chrome/renderer/translate_helper.cc b/chrome/renderer/translate_helper.cc
index ab8bcdf..a630f51 100644
--- a/chrome/renderer/translate_helper.cc
+++ b/chrome/renderer/translate_helper.cc
@@ -8,14 +8,19 @@
#include "base/utf_string_conversions.h"
#include "chrome/common/chrome_constants.h"
#include "chrome/renderer/render_view.h"
+#include "third_party/WebKit/WebKit/chromium/public/WebElement.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/WebKit/chromium/public/WebScriptSource.h"
#include "third_party/WebKit/WebKit/chromium/public/WebView.h"
#include "v8/include/v8.h"
#include "webkit/glue/dom_operations.h"
+using WebKit::WebDocument;
+using WebKit::WebElement;
using WebKit::WebFrame;
using WebKit::WebScriptSource;
+using WebKit::WebString;
+using WebKit::WebView;
// The delay in millliseconds that we'll wait before checking to see if the
// translate library injected in the page is ready.
@@ -108,15 +113,15 @@ void TranslateHelper::CancelPendingTranslation() {
}
// static
-bool TranslateHelper::IsPageTranslatable(WebKit::WebDocument* document) {
- std::vector<WebKit::WebElement> meta_elements;
+bool TranslateHelper::IsPageTranslatable(WebDocument* document) {
+ std::vector<WebElement> meta_elements;
webkit_glue::GetMetaElementsWithAttribute(document,
ASCIIToUTF16("name"),
ASCIIToUTF16("google"),
&meta_elements);
- std::vector<WebKit::WebElement>::const_iterator iter;
+ std::vector<WebElement>::const_iterator iter;
for (iter = meta_elements.begin(); iter != meta_elements.end(); ++iter) {
- WebKit::WebString attribute = iter->getAttribute("value");
+ WebString attribute = iter->getAttribute("value");
if (attribute.isNull()) // We support both 'value' and 'content'.
attribute = iter->getAttribute("content");
if (attribute.isNull())
@@ -128,13 +133,12 @@ bool TranslateHelper::IsPageTranslatable(WebKit::WebDocument* document) {
}
// static
-std::string TranslateHelper::GetPageLanguageFromMetaTag(
- WebKit::WebDocument* document) {
+std::string TranslateHelper::GetPageLanguageFromMetaTag(WebDocument* document) {
// The META language tag looks like:
// <meta http-equiv="content-language" content="en">
// It can contain more than one language:
// <meta http-equiv="content-language" content="en, fr">
- std::vector<WebKit::WebElement> meta_elements;
+ std::vector<WebElement> meta_elements;
webkit_glue::GetMetaElementsWithAttribute(document,
ASCIIToUTF16("http-equiv"),
ASCIIToUTF16("content-language"),
@@ -144,7 +148,7 @@ std::string TranslateHelper::GetPageLanguageFromMetaTag(
// We don't expect more than one such tag. If there are several, just use the
// first one.
- WebKit::WebString attribute = meta_elements[0].getAttribute("content");
+ WebString attribute = meta_elements[0].getAttribute("content");
if (attribute.isEmpty())
return std::string();
@@ -360,7 +364,7 @@ void TranslateHelper::NotifyBrowserTranslationFailed(
}
WebFrame* TranslateHelper::GetMainFrame() {
- WebKit::WebView* web_view = render_view_->webview();
+ WebView* web_view = render_view_->webview();
if (!web_view) {
// When the WebView is going away, the render view should have called
// CancelPendingTranslation() which should have stopped any pending work, so