Index: webkit/glue/autocomplete_input_listener.cc |
=================================================================== |
--- webkit/glue/autocomplete_input_listener.cc (revision 5578) |
+++ webkit/glue/autocomplete_input_listener.cc (working copy) |
@@ -1,231 +0,0 @@ |
-// Copyright (c) 2006-2008 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. |
-// |
-// This file provides an abstract implementation of the inline autocomplete |
-// infrastructure defined in autocomplete_input_listener.h. |
- |
-#include "webkit/glue/autocomplete_input_listener.h" |
-#include <set> |
- |
-MSVC_PUSH_WARNING_LEVEL(0); |
-#include "HTMLInputElement.h" |
-#include "HTMLFormElement.h" |
-#include "Document.h" |
-#include "Frame.h" |
-#include "Editor.h" |
-#include "EventNames.h" |
-#include "Event.h" |
-#include "HTMLNames.h" |
-MSVC_POP_WARNING(); |
- |
-#undef LOG |
- |
-#include "base/logging.h" |
-#include "webkit/glue/editor_client_impl.h" |
-#include "webkit/glue/glue_util.h" |
- |
-namespace webkit_glue { |
- |
-// Hack (1 of 2) for http://bugs.webkit.org/show_bug.cgi?id=16976. This bug |
-// causes the caret position to be set after handling input events, which |
-// trumps our modifications, so for now we tell the EditorClient to preserve |
-// whatever selection set by our code. |
-// TODO(timsteele): Remove this function altogether once bug is fixed. |
-static void PreserveSelection(WebCore::HTMLInputElement* element) { |
- WebCore::EditorClient* ec = |
- element->form()->document()->frame()->editor()->client(); |
- EditorClientImpl* client = static_cast<EditorClientImpl*>(ec); |
- client->PreserveSelection(); |
-} |
- |
-HTMLInputDelegate::HTMLInputDelegate(WebCore::HTMLInputElement* element) |
- : element_(element) { |
- // Reference the element for the lifetime of this delegate. |
- // e is NULL when testing. |
- if (element_) |
- element_->ref(); |
-} |
- |
-HTMLInputDelegate::~HTMLInputDelegate() { |
- if (element_) |
- element_->deref(); |
-} |
- |
-void HTMLInputDelegate::SetValue(const std::wstring& value) { |
- element_->setValue(StdWStringToString(value)); |
-} |
- |
-void HTMLInputDelegate::SetSelectionRange(size_t start, size_t end) { |
- element_->setSelectionRange(start, end); |
- // Hack, see comments for PreserveSelection(). |
- PreserveSelection(element_); |
-} |
- |
-void HTMLInputDelegate::OnFinishedAutocompleting() { |
- // This sets the input element to an autofilled state which will result in it |
- // having a yellow background. |
- element_->setAutofilled(true); |
- // Notify any changeEvent listeners. |
- element_->onChange(); |
-} |
- |
-AutocompleteBodyListener::AutocompleteBodyListener(WebCore::Frame* frame) { |
- WebCore::HTMLElement* body = frame->document()->body(); |
- body->addEventListener(WebCore::eventNames().DOMFocusOutEvent, this, false); |
- body->addEventListener(WebCore::eventNames().inputEvent, this, false); |
- // Attaching to the WebCore body element effectively transfers ownership of |
- // the listener object. When WebCore is tearing down the document, any |
- // attached listeners are destroyed. |
- // See Document::removeAllEventListenersFromAllNodes which is called by |
- // FrameLoader::stopLoading. Also, there is no need for matching calls to |
- // removeEventListener because the simplest and most convienient thing to do |
- // for autocompletion is to stop listening once the element is destroyed. |
-} |
- |
-AutocompleteBodyListener::~AutocompleteBodyListener() { |
- // Delete the listener. Pay special attention since we may have the same |
- // listener registered for several elements. |
- std::set<AutocompleteInputListener*> to_be_deleted_; |
- for (InputElementInfoMap::iterator iter = elements_info_.begin(); |
- iter != elements_info_.end(); ++iter) { |
- to_be_deleted_.insert(iter->second.listener); |
- } |
- |
- std::set<AutocompleteInputListener*>::iterator iter; |
- for (iter = to_be_deleted_.begin(); iter != to_be_deleted_.end(); ++iter) |
- delete *iter; |
- elements_info_.clear(); |
-} |
- |
-// The following method is based on Firefox2 code in |
-// toolkit/components/autocomplete/src/nsAutoCompleteController.cpp |
-// Its license block is |
-// |
- /* ***** BEGIN LICENSE BLOCK ***** |
- * Version: MPL 1.1/GPL 2.0/LGPL 2.1 |
- * |
- * The contents of this file are subject to the Mozilla Public License Version |
- * 1.1 (the "License"); you may not use this file except in compliance with |
- * the License. You may obtain a copy of the License at |
- * http://www.mozilla.org/MPL/ |
- * |
- * Software distributed under the License is distributed on an "AS IS" basis, |
- * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License |
- * for the specific language governing rights and limitations under the |
- * License. |
- * |
- * The Original Code is Mozilla Communicator client code. |
- * |
- * The Initial Developer of the Original Code is |
- * Netscape Communications Corporation. |
- * Portions created by the Initial Developer are Copyright (C) 1998 |
- * the Initial Developer. All Rights Reserved. |
- * |
- * Contributor(s): |
- * Joe Hewitt <hewitt@netscape.com> (Original Author) |
- * Dean Tessman <dean_tessman@hotmail.com> |
- * Johnny Stenback <jst@mozilla.jstenback.com> |
- * Masayuki Nakano <masayuki@d-toybox.com> |
- * |
- * Alternatively, the contents of this file may be used under the terms of |
- * either the GNU General Public License Version 2 or later (the "GPL"), or |
- * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"), |
- * in which case the provisions of the GPL or the LGPL are applicable instead |
- * of those above. If you wish to allow use of your version of this file only |
- * under the terms of either the GPL or the LGPL, and not to allow others to |
- * use your version of this file under the terms of the MPL, indicate your |
- * decision by deleting the provisions above and replace them with the notice |
- * and other provisions required by the GPL or the LGPL. If you do not delete |
- * the provisions above, a recipient may use your version of this file under |
- * the terms of any one of the MPL, the GPL or the LGPL. |
- * |
- * ***** END LICENSE BLOCK ***** */ |
-bool AutocompleteBodyListener::ShouldInlineAutocomplete( |
- WebCore::HTMLInputElement* input, |
- const std::wstring& old_text, |
- const std::wstring& new_text) { |
- size_t prev_length = old_text.length(); |
- // The following are a bunch of early returns in cases we don't want to |
- // go through with inline autocomplete. |
- |
- // Don't bother doing AC if nothing changed. |
- if (new_text.length() > 0 && (new_text == old_text)) |
- return false; |
- |
- // Did user backspace? |
- if ((new_text.length() < old_text.length()) && |
- old_text.substr(0, new_text.length()) == new_text) { |
- return false; |
- } |
- |
- // Is search string empty? |
- if (new_text.empty()) |
- return false; |
- return IsCaretAtEndOfText(input, new_text.length(), prev_length); |
-} |
- |
-void AutocompleteBodyListener::handleEvent(WebCore::Event* event, |
- bool /*is_window_event*/) { |
- const WebCore::AtomicString& webcore_type = event->type(); |
- DCHECK(event->target()->toNode()); |
- if (!event->target()->toNode()->hasTagName(WebCore::HTMLNames::inputTag)) |
- return; // Not a node of interest to us. |
- |
- WebCore::HTMLInputElement* input = |
- static_cast<WebCore::HTMLInputElement*>(event->target()->toNode()); |
- InputElementInfoMap::const_iterator iter = elements_info_.find(input); |
- if (iter == elements_info_.end()) |
- return; // Not an input node we are listening to. |
- |
- InputElementInfo input_info = iter->second; |
- const std::wstring& user_input = StringToStdWString(input->value()); |
- if (webcore_type == WebCore::eventNames().DOMFocusOutEvent) { |
- input_info.listener->OnBlur(input, user_input); |
- } else if (webcore_type == WebCore::eventNames().inputEvent) { |
- // Perform inline autocomplete if it is safe to do so. |
- if (ShouldInlineAutocomplete(input, |
- input_info.previous_text, user_input)) { |
- input_info.listener->OnInlineAutocompleteNeeded(input, user_input); |
- } |
- // Update the info. |
- input_info.previous_text = user_input; |
- elements_info_[input] = input_info; |
- } else { |
- NOTREACHED() << "unexpected EventName for autocomplete listener"; |
- } |
-} |
- |
-void AutocompleteBodyListener::AddInputListener( |
- WebCore::HTMLInputElement* element, |
- AutocompleteInputListener* listener) { |
- DCHECK(elements_info_.find(element) == elements_info_.end()); |
- InputElementInfo elem_info; |
- elem_info.listener = listener; |
- elements_info_[element] = elem_info; |
-} |
- |
-bool AutocompleteBodyListener::IsCaretAtEndOfText( |
- WebCore::HTMLInputElement* element, |
- size_t input_length, |
- size_t previous_length) const { |
- // Hack 2 of 2 for http://bugs.webkit.org/show_bug.cgi?id=16976. |
- // TODO(timsteele): This check should only return early if |
- // !(selectionEnd == selectionStart == user_input.length()). |
- // However, because of webkit bug #16976 the caret is not properly moved |
- // until after the handlers have executed, so for now we do the following |
- // several checks. The first check handles the case webkit sets the End |
- // selection but not the Start selection correctly, and the second is for |
- // when webcore sets neither. This won't be perfect if the user moves the |
- // selection around during inline autocomplete, but for now its the |
- // friendliest behavior we can offer. Once the bug is fixed this method |
- // should no longer need the previous_length parameter. |
- if (((element->selectionEnd() != element->selectionStart() + 1) || |
- (element->selectionEnd() != static_cast<int>(input_length))) && |
- ((element->selectionEnd() != element->selectionStart()) || |
- (element->selectionEnd() != static_cast<int>(previous_length)))) { |
- return false; |
- } |
- return true; |
-} |
-} // webkit_glue |