autofill_popup_controller_impl.cc revision eb525c5499e34cc9c4b825d6d9e75bb07cc06ace
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// found in the LICENSE file. 42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/autofill/autofill_popup_controller_impl.h" 62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <algorithm> 82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include <utility> 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/logging.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "base/strings/utf_string_conversions.h" 122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "chrome/browser/ui/autofill/autofill_popup_view.h" 132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "components/autofill/core/browser/autofill_popup_delegate.h" 142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "content/public/browser/native_web_keyboard_event.h" 152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "grit/webkit_resources.h" 162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "third_party/WebKit/public/web/WebAutofillClient.h" 172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/events/event.h" 182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "ui/base/text/text_elider.h" 1990dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/display.h" 2090dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/rect_conversions.h" 2190dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/screen.h" 2290dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)#include "ui/gfx/vector2d.h" 2390dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 2490dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using base::WeakPtr; 2590dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles)using WebKit::WebAutofillClient; 2690dce4d38c5ff5333bea97d859d4e484e27edf0cTorne (Richard Coles) 272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace autofill { 282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)namespace { 292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Used to indicate that no line is currently selected by the user. 312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kNoSelection = -1; 322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Size difference between name and subtext in pixels. 342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const int kLabelFontSizeDelta = -2; 352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The vertical height of each row in pixels. 372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kRowHeight = 24; 382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The vertical height of a separator in pixels. 402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kSeparatorHeight = 1; 412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// The maximum amount of characters to display from either the name or subtext. 432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kMaxTextLength = 15; 442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_ANDROID) 462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kNamePadding = AutofillPopupView::kNamePadding; 472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kIconPadding = AutofillPopupView::kIconPadding; 482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kEndPadding = AutofillPopupView::kEndPadding; 492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const size_t kAutofillIconWidth = AutofillPopupView::kAutofillIconWidth; 502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)struct DataResource { 532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const char* name; 542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int id; 552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const DataResource kDataResources[] = { 582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { "americanExpressCC", IDR_AUTOFILL_CC_AMEX }, 592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { "dinersCC", IDR_AUTOFILL_CC_DINERS }, 602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { "discoverCC", IDR_AUTOFILL_CC_DISCOVER }, 612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { "genericCC", IDR_AUTOFILL_CC_GENERIC }, 622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { "jcbCC", IDR_AUTOFILL_CC_JCB }, 632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { "masterCardCC", IDR_AUTOFILL_CC_MASTERCARD }, 642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) { "visaCC", IDR_AUTOFILL_CC_VISA }, 652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)}; 662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} // namespace 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)WeakPtr<AutofillPopupControllerImpl> AutofillPopupControllerImpl::GetOrCreate( 712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WeakPtr<AutofillPopupControllerImpl> previous, 722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WeakPtr<AutofillPopupDelegate> delegate, 732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::NativeView container_view, 742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::RectF& element_bounds, 752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::i18n::TextDirection text_direction) { 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(!previous.get() || previous->delegate_.get() == delegate.get()); 772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (previous.get() && previous->container_view() == container_view && 792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) previous->element_bounds() == element_bounds) { 802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) previous->ClearState(); 812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return previous; 822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (previous.get()) 852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) previous->Hide(); 862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AutofillPopupControllerImpl* controller = 882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new AutofillPopupControllerImpl( 892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate, container_view, element_bounds, text_direction); 902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return controller->GetWeakPtr(); 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AutofillPopupControllerImpl::AutofillPopupControllerImpl( 942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::WeakPtr<AutofillPopupDelegate> delegate, 952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) gfx::NativeView container_view, 962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const gfx::RectF& element_bounds, 972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) base::i18n::TextDirection text_direction) 982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) : view_(NULL), 992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_(delegate), 1002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) container_view_(container_view), 1012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) element_bounds_(element_bounds), 1022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) text_direction_(text_direction), 1032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) weak_ptr_factory_(this) { 1042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ClearState(); 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_ANDROID) 1062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) subtext_font_ = name_font_.DeriveFont(kLabelFontSizeDelta); 1072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) warning_font_ = name_font_.DeriveFont(0, gfx::Font::ITALIC); 1082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)AutofillPopupControllerImpl::~AutofillPopupControllerImpl() {} 1122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutofillPopupControllerImpl::Show( 1142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<string16>& names, 1152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<string16>& subtexts, 1162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<string16>& icons, 1172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<int>& identifiers) { 1182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetValues(names, subtexts, icons, identifiers); 1192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_ANDROID) 1212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Android displays the long text with ellipsis using the view attributes. 122868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) 1232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdatePopupBounds(); 1242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int popup_width = popup_bounds().width(); 1252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Elide the name and subtext strings so that the popup fits in the available 1272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // space. 1282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < names_.size(); ++i) { 1292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int name_width = GetNameFontForRow(i).GetStringWidth(names_[i]); 1302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int subtext_width = subtext_font().GetStringWidth(subtexts_[i]); 1312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int total_text_length = name_width + subtext_width; 1322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The line can have no strings if it represents a UI element, such as 1342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // a separator line. 1352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (total_text_length == 0) 1362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) continue; 1372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int available_width = popup_width - RowWidthWithoutText(i); 1392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Each field recieves space in proportion to its length. 1412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int name_size = available_width * name_width / total_text_length; 1422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) names_[i] = ui::ElideText(names_[i], 1432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetNameFontForRow(i), 1442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) name_size, 1452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ELIDE_AT_END); 1462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int subtext_size = available_width * subtext_width / total_text_length; 1482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) subtexts_[i] = ui::ElideText(subtexts_[i], 1492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) subtext_font(), 1502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) subtext_size, 1512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ui::ELIDE_AT_END); 1522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 1542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 155868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) if (!view_) { 1562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view_ = AutofillPopupView::Create(this); 1572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // It is possible to fail to create the popup, in this case 1592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // treat the popup as hiding right away. 1602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!view_) { 1612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Hide(); 1622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 1632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 1642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ShowView(); 1662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 1672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateBoundsAndRedrawPopup(); 168868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) } 1692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->OnPopupShown(this); 1712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutofillPopupControllerImpl::Hide() { 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (delegate_.get()) 1752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->OnPopupHidden(this); 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (view_) 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view_->Hide(); 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delete this; 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutofillPopupControllerImpl::ViewDestroyed() { 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The view has already been destroyed so clear the reference to it. 1852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view_ = NULL; 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Hide(); 1882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 190c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)bool AutofillPopupControllerImpl::HandleKeyPressEvent( 191c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) const content::NativeWebKeyboardEvent& event) { 1922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) switch (event.windowsKeyCode) { 1932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ui::VKEY_UP: 1942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SelectPreviousLine(); 1952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ui::VKEY_DOWN: 1972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SelectNextLine(); 1982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 1992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ui::VKEY_PRIOR: // Page up. 2002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetSelectedLine(0); 2012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ui::VKEY_NEXT: // Page down. 203c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) SetSelectedLine(names().size() - 1); 2042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ui::VKEY_ESCAPE: 2062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Hide(); 2072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 2082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ui::VKEY_DELETE: 2092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return (event.modifiers & content::NativeWebKeyboardEvent::ShiftKey) && 2102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) RemoveSelectedLine(); 211868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) case ui::VKEY_TAB: 2122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // A tab press should cause the highlighted line to be selected, but still 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // return false so the tab key press propagates and changes the cursor 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // location. 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AcceptSelectedLine(); 2162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) case ui::VKEY_RETURN: 2182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return AcceptSelectedLine(); 2192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) default: 2202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 2212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutofillPopupControllerImpl::UpdateBoundsAndRedrawPopup() { 2252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_ANDROID) 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(csharp): Since UpdatePopupBounds can change the position of the popup, 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // the popup could end up jumping from above the element to below it. 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // It is unclear if it is better to keep the popup where it was, or if it 2292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // should try and move to its desired position. 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdatePopupBounds(); 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view_->UpdateBoundsAndRedrawPopup(); 2342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutofillPopupControllerImpl::MouseHovered(int x, int y) { 2372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetSelectedLine(LineFromY(y)); 2382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutofillPopupControllerImpl::MouseClicked(int x, int y) { 2412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) MouseHovered(x, y); 2422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AcceptSelectedLine(); 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutofillPopupControllerImpl::MouseExitedPopup() { 2462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetSelectedLine(kNoSelection); 2472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutofillPopupControllerImpl::AcceptSuggestion(size_t index) { 2502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->DidAcceptSuggestion(full_names_[index], identifiers_[index]); 2512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int AutofillPopupControllerImpl::GetIconResourceID( 2542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const string16& resource_name) { 255c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) for (size_t i = 0; i < arraysize(kDataResources); ++i) { 256c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) if (resource_name == ASCIIToUTF16(kDataResources[i].name)) 2572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kDataResources[i].id; 2582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 2592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return -1; 2612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 262c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AutofillPopupControllerImpl::CanDelete(size_t index) const { 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(isherman): Native AddressBook suggestions on Mac and Android should 2652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // not be considered to be deleteable. 266c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) int id = identifiers_[index]; 267c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) return id > 0 || 2682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) id == WebAutofillClient::MenuItemIDAutocompleteEntry || 2692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) id == WebAutofillClient::MenuItemIDPasswordEntry; 2702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AutofillPopupControllerImpl::IsWarning(size_t index) const { 2732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return identifiers_[index] == WebAutofillClient::MenuItemIDWarningMessage; 2742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 276c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)gfx::Rect AutofillPopupControllerImpl::GetRowBounds(size_t index) { 2772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int top = 0; 2782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < index; ++i) { 2792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) top += GetRowHeightFromId(identifiers()[i]); 280c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) } 281c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return gfx::Rect( 2832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 0, 2842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) top, 2852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) popup_bounds_.width(), 2862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) GetRowHeightFromId(identifiers()[index])); 2872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 289c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)void AutofillPopupControllerImpl::SetPopupBounds(const gfx::Rect& bounds) { 2902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) popup_bounds_ = bounds; 2912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateBoundsAndRedrawPopup(); 292c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 293c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles) 2942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const gfx::Rect& AutofillPopupControllerImpl::popup_bounds() const { 2952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return popup_bounds_; 2962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)gfx::NativeView AutofillPopupControllerImpl::container_view() const { 2992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return container_view_; 3002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const gfx::RectF& AutofillPopupControllerImpl::element_bounds() const { 3032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return element_bounds_; 3042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AutofillPopupControllerImpl::IsRTL() const { 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return text_direction_ == base::i18n::RIGHT_TO_LEFT; 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::vector<string16>& AutofillPopupControllerImpl::names() const { 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return names_; 3122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::vector<string16>& AutofillPopupControllerImpl::subtexts() const { 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return subtexts_; 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::vector<string16>& AutofillPopupControllerImpl::icons() const { 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return icons_; 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const std::vector<int>& AutofillPopupControllerImpl::identifiers() const { 3232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return identifiers_; 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#if !defined(OS_ANDROID) 3272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const gfx::Font& AutofillPopupControllerImpl::GetNameFontForRow(size_t index) 3282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const { 3292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (identifiers_[index] == WebAutofillClient::MenuItemIDWarningMessage) 3302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return warning_font_; 3312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return name_font_; 3332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)const gfx::Font& AutofillPopupControllerImpl::subtext_font() const { 3362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return subtext_font_; 3372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#endif 3392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int AutofillPopupControllerImpl::selected_line() const { 3412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return selected_line_; 342c2e0dbddbe15c98d52c4786dac06cb8952a8ae6dTorne (Richard Coles)} 3432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutofillPopupControllerImpl::SetSelectedLine(int selected_line) { 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (selected_line_ == selected_line) 3462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return; 3472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (selected_line_ != kNoSelection && 3492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) static_cast<size_t>(selected_line_) < identifiers_.size()) 3502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InvalidateRow(selected_line_); 3512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (selected_line != kNoSelection) 3532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) InvalidateRow(selected_line); 3542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) selected_line_ = selected_line; 3562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (selected_line_ != kNoSelection) 3582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->DidSelectSuggestion(identifiers_[selected_line_]); 3592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) else 3602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->ClearPreviewedForm(); 3612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutofillPopupControllerImpl::SelectNextLine() { 3642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int new_selected_line = selected_line_ + 1; 3652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Skip over any lines that can't be selected. 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (static_cast<size_t>(new_selected_line) < names_.size() && 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !CanAccept(identifiers()[new_selected_line])) { 3692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) ++new_selected_line; 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_selected_line >= static_cast<int>(names_.size())) 3732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_selected_line = 0; 3742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetSelectedLine(new_selected_line); 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutofillPopupControllerImpl::SelectPreviousLine() { 3792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int new_selected_line = selected_line_ - 1; 3802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Skip over any lines that can't be selected. 3822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) while (new_selected_line > kNoSelection && 3832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) !CanAccept(identifiers()[new_selected_line])) { 3842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) --new_selected_line; 3852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 3862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (new_selected_line <= kNoSelection) 3882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) new_selected_line = names_.size() - 1; 3892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetSelectedLine(new_selected_line); 3912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AutofillPopupControllerImpl::AcceptSelectedLine() { 3942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (selected_line_ == kNoSelection) 3952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 3962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_GE(selected_line_, 0); 3982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_LT(selected_line_, static_cast<int>(names_.size())); 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!CanAccept(identifiers_[selected_line_])) 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) AcceptSuggestion(selected_line_); 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 4052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AutofillPopupControllerImpl::RemoveSelectedLine() { 4082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (selected_line_ == kNoSelection) 4092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_GE(selected_line_, 0); 4122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_LT(selected_line_, static_cast<int>(names_.size())); 4132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (!CanDelete(selected_line_)) 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->RemoveSuggestion(full_names_[selected_line_], 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) identifiers_[selected_line_]); 4192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // Remove the deleted element. 4212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) names_.erase(names_.begin() + selected_line_); 4222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) full_names_.erase(full_names_.begin() + selected_line_); 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) subtexts_.erase(subtexts_.begin() + selected_line_); 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icons_.erase(icons_.begin() + selected_line_); 4252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) identifiers_.erase(identifiers_.begin() + selected_line_); 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SetSelectedLine(kNoSelection); 4282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (HasSuggestions()) { 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) delegate_->ClearPreviewedForm(); 4312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) UpdateBoundsAndRedrawPopup(); 4322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) Hide(); 4342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 4372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int AutofillPopupControllerImpl::LineFromY(int y) { 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) int current_height = 0; 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4422a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < identifiers().size(); ++i) { 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) current_height += GetRowHeightFromId(identifiers()[i]); 4442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (y <= current_height) 4462a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return i; 4472a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4482a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // The y value goes beyond the popup so stop the selection at the last line. 4502a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return identifiers().size() - 1; 4512a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)int AutofillPopupControllerImpl::GetRowHeightFromId(int identifier) const { 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (identifier == WebAutofillClient::MenuItemIDSeparator) 4552a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kSeparatorHeight; 4562a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4572a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return kRowHeight; 4582a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4592a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4602a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AutofillPopupControllerImpl::CanAccept(int id) { 4612a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return id != WebAutofillClient::MenuItemIDSeparator && 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) id != WebAutofillClient::MenuItemIDWarningMessage; 4632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4652a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool AutofillPopupControllerImpl::HasSuggestions() { 4662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return identifiers_.size() != 0 && 4672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) (identifiers_[0] > 0 || 4682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) identifiers_[0] == 4692a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) WebAutofillClient::MenuItemIDAutocompleteEntry || 4702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) identifiers_[0] == WebAutofillClient::MenuItemIDPasswordEntry || 4712a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) identifiers_[0] == WebAutofillClient::MenuItemIDDataListEntry); 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutofillPopupControllerImpl::SetValues( 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<string16>& names, 4762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<string16>& subtexts, 4772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<string16>& icons, 4782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const std::vector<int>& identifiers) { 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) names_ = names; 4802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) full_names_ = names; 4812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) subtexts_ = subtexts; 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) icons_ = icons; 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) identifiers_ = identifiers; 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4852a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutofillPopupControllerImpl::ShowView() { 4872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) view_->Show(); 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void AutofillPopupControllerImpl::InvalidateRow(size_t row) { 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(0 <= row); 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(row < identifiers_.size()); 493 view_->InvalidateRow(row); 494} 495 496#if !defined(OS_ANDROID) 497int AutofillPopupControllerImpl::GetDesiredPopupWidth() const { 498 if (!name_font_.platform_font() || !subtext_font_.platform_font()) { 499 // We can't calculate the size of the popup if the fonts 500 // aren't present. 501 return 0; 502 } 503 504 int popup_width = RoundedElementBounds().width(); 505 DCHECK_EQ(names().size(), subtexts().size()); 506 for (size_t i = 0; i < names().size(); ++i) { 507 int row_size = name_font_.GetStringWidth(names()[i]) + 508 subtext_font_.GetStringWidth(subtexts()[i]) + 509 RowWidthWithoutText(i); 510 511 popup_width = std::max(popup_width, row_size); 512 } 513 514 return popup_width; 515} 516 517int AutofillPopupControllerImpl::GetDesiredPopupHeight() const { 518 int popup_height = 0; 519 520 for (size_t i = 0; i < identifiers().size(); ++i) { 521 popup_height += GetRowHeightFromId(identifiers()[i]); 522 } 523 524 return popup_height; 525} 526 527int AutofillPopupControllerImpl::RowWidthWithoutText(int row) const { 528 int row_size = kEndPadding; 529 530 if (!subtexts_[row].empty()) 531 row_size += kNamePadding; 532 533 // Add the Autofill icon size, if required. 534 if (!icons_[row].empty()) 535 row_size += kAutofillIconWidth + kIconPadding; 536 537 // Add the padding at the end 538 row_size += kEndPadding; 539 540 return row_size; 541} 542 543void AutofillPopupControllerImpl::UpdatePopupBounds() { 544 int popup_required_width = GetDesiredPopupWidth(); 545 int popup_height = GetDesiredPopupHeight(); 546 // This is the top left point of the popup if the popup is above the element 547 // and grows to the left (since that is the highest and furthest left the 548 // popup go could). 549 gfx::Point top_left_corner_of_popup = RoundedElementBounds().origin() + 550 gfx::Vector2d(RoundedElementBounds().width() - popup_required_width, 551 -popup_height); 552 553 // This is the bottom right point of the popup if the popup is below the 554 // element and grows to the right (since the is the lowest and furthest right 555 // the popup could go). 556 gfx::Point bottom_right_corner_of_popup = RoundedElementBounds().origin() + 557 gfx::Vector2d(popup_required_width, 558 RoundedElementBounds().height() + popup_height); 559 560 gfx::Display top_left_display = GetDisplayNearestPoint( 561 top_left_corner_of_popup); 562 gfx::Display bottom_right_display = GetDisplayNearestPoint( 563 bottom_right_corner_of_popup); 564 565 std::pair<int, int> popup_x_and_width = CalculatePopupXAndWidth( 566 top_left_display, bottom_right_display, popup_required_width); 567 std::pair<int, int> popup_y_and_height = CalculatePopupYAndHeight( 568 top_left_display, bottom_right_display, popup_height); 569 570 popup_bounds_ = gfx::Rect(popup_x_and_width.first, 571 popup_y_and_height.first, 572 popup_x_and_width.second, 573 popup_y_and_height.second); 574} 575#endif // !defined(OS_ANDROID) 576 577WeakPtr<AutofillPopupControllerImpl> AutofillPopupControllerImpl::GetWeakPtr() { 578 return weak_ptr_factory_.GetWeakPtr(); 579} 580 581void AutofillPopupControllerImpl::ClearState() { 582 // Don't clear view_, because otherwise the popup will have to get regenerated 583 // and this will cause flickering. 584 585 popup_bounds_ = gfx::Rect(); 586 587 names_.clear(); 588 subtexts_.clear(); 589 icons_.clear(); 590 identifiers_.clear(); 591 full_names_.clear(); 592 593 selected_line_ = kNoSelection; 594} 595 596const gfx::Rect AutofillPopupControllerImpl::RoundedElementBounds() const { 597 return gfx::ToEnclosingRect(element_bounds_); 598} 599 600gfx::Display AutofillPopupControllerImpl::GetDisplayNearestPoint( 601 const gfx::Point& point) const { 602 return gfx::Screen::GetScreenFor(container_view())->GetDisplayNearestPoint( 603 point); 604} 605 606std::pair<int, int> AutofillPopupControllerImpl::CalculatePopupXAndWidth( 607 const gfx::Display& left_display, 608 const gfx::Display& right_display, 609 int popup_required_width) const { 610 int leftmost_display_x = left_display.bounds().x(); 611 int rightmost_display_x = 612 right_display.GetSizeInPixel().width() + right_display.bounds().x(); 613 614 // Calculate the start coordinates for the popup if it is growing right or 615 // the end position if it is growing to the left, capped to screen space. 616 int right_growth_start = std::max(leftmost_display_x, 617 std::min(rightmost_display_x, 618 RoundedElementBounds().x())); 619 int left_growth_end = std::max(leftmost_display_x, 620 std::min(rightmost_display_x, 621 RoundedElementBounds().right())); 622 623 int right_available = rightmost_display_x - right_growth_start; 624 int left_available = left_growth_end - leftmost_display_x; 625 626 int popup_width = std::min(popup_required_width, 627 std::max(right_available, left_available)); 628 629 // If there is enough space for the popup on the right, show it there, 630 // otherwise choose the larger size. 631 if (right_available >= popup_width || right_available >= left_available) 632 return std::make_pair(right_growth_start, popup_width); 633 else 634 return std::make_pair(left_growth_end - popup_width, popup_width); 635} 636 637std::pair<int,int> AutofillPopupControllerImpl::CalculatePopupYAndHeight( 638 const gfx::Display& top_display, 639 const gfx::Display& bottom_display, 640 int popup_required_height) const { 641 int topmost_display_y = top_display.bounds().y(); 642 int bottommost_display_y = 643 bottom_display.GetSizeInPixel().height() + bottom_display.bounds().y(); 644 645 // Calculate the start coordinates for the popup if it is growing down or 646 // the end position if it is growing up, capped to screen space. 647 int top_growth_end = std::max(topmost_display_y, 648 std::min(bottommost_display_y, 649 RoundedElementBounds().y())); 650 int bottom_growth_start = std::max(topmost_display_y, 651 std::min(bottommost_display_y, RoundedElementBounds().bottom())); 652 653 int top_available = bottom_growth_start - topmost_display_y; 654 int bottom_available = bottommost_display_y - top_growth_end; 655 656 // TODO(csharp): Restrict the popup height to what is available. 657 if (bottom_available >= popup_required_height || 658 bottom_available >= top_available) { 659 // The popup can appear below the field. 660 return std::make_pair(bottom_growth_start, popup_required_height); 661 } else { 662 // The popup must appear above the field. 663 return std::make_pair(top_growth_end - popup_required_height, 664 popup_required_height); 665 } 666} 667 668} // namespace autofill 669