summaryrefslogtreecommitdiffstats
path: root/chrome/renderer/page_click_tracker.cc
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/page_click_tracker.cc
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/page_click_tracker.cc')
-rw-r--r--chrome/renderer/page_click_tracker.cc127
1 files changed, 127 insertions, 0 deletions
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();
+}