Home | History | Annotate | Download | only in autocomplete
      1 // Copyright (c) 2011 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #include "chrome/browser/autocomplete/autocomplete_edit_view_views.h"
      6 
      7 #include "base/logging.h"
      8 #include "base/string_util.h"
      9 #include "base/utf_string_conversions.h"
     10 #include "chrome/app/chrome_command_ids.h"
     11 #include "chrome/browser/autocomplete/autocomplete_edit.h"
     12 #include "chrome/browser/autocomplete/autocomplete_match.h"
     13 #include "chrome/browser/autocomplete/autocomplete_popup_model.h"
     14 #include "chrome/browser/command_updater.h"
     15 #include "chrome/browser/ui/views/autocomplete/autocomplete_popup_contents_view.h"
     16 #include "chrome/browser/ui/views/autocomplete/touch_autocomplete_popup_contents_view.h"
     17 #include "chrome/browser/ui/views/location_bar/location_bar_view.h"
     18 #include "content/browser/tab_contents/tab_contents.h"
     19 #include "content/common/notification_service.h"
     20 #include "googleurl/src/gurl.h"
     21 #include "grit/generated_resources.h"
     22 #include "net/base/escape.h"
     23 #include "ui/base/accessibility/accessible_view_state.h"
     24 #include "ui/base/dragdrop/drag_drop_types.h"
     25 #include "ui/base/l10n/l10n_util.h"
     26 #include "ui/base/resource/resource_bundle.h"
     27 #include "ui/gfx/font.h"
     28 #include "views/border.h"
     29 #include "views/controls/textfield/textfield.h"
     30 #include "views/layout/fill_layout.h"
     31 
     32 namespace {
     33 
     34 // Textfield for autocomplete that intercepts events that are necessary
     35 // for AutocompleteEditViewViews.
     36 class AutocompleteTextfield : public views::Textfield {
     37  public:
     38   explicit AutocompleteTextfield(
     39       AutocompleteEditViewViews* autocomplete_edit_view)
     40       : views::Textfield(views::Textfield::STYLE_DEFAULT),
     41         autocomplete_edit_view_(autocomplete_edit_view) {
     42     DCHECK(autocomplete_edit_view_);
     43     RemoveBorder();
     44   }
     45 
     46   // views::View implementation
     47   virtual void OnFocus() OVERRIDE {
     48     views::Textfield::OnFocus();
     49     autocomplete_edit_view_->HandleFocusIn();
     50   }
     51 
     52   virtual void OnBlur() OVERRIDE {
     53     views::Textfield::OnBlur();
     54     autocomplete_edit_view_->HandleFocusOut();
     55   }
     56 
     57   virtual bool OnKeyPressed(const views::KeyEvent& event) OVERRIDE {
     58     bool handled = views::Textfield::OnKeyPressed(event);
     59     return autocomplete_edit_view_->HandleAfterKeyEvent(event, handled) ||
     60         handled;
     61   }
     62 
     63   virtual bool OnKeyReleased(const views::KeyEvent& event) OVERRIDE {
     64     return autocomplete_edit_view_->HandleKeyReleaseEvent(event);
     65   }
     66 
     67   virtual bool IsFocusable() const OVERRIDE {
     68     // Bypass Textfield::IsFocusable. The omnibox in popup window requires
     69     // focus in order for text selection to work.
     70     return views::View::IsFocusable();
     71   }
     72 
     73  private:
     74   AutocompleteEditViewViews* autocomplete_edit_view_;
     75 
     76   DISALLOW_COPY_AND_ASSIGN(AutocompleteTextfield);
     77 };
     78 
     79 // Stores omnibox state for each tab.
     80 struct ViewState {
     81   explicit ViewState(const ui::Range& selection_range)
     82       : selection_range(selection_range) {
     83   }
     84 
     85   // Range of selected text.
     86   ui::Range selection_range;
     87 };
     88 
     89 struct AutocompleteEditState {
     90   AutocompleteEditState(const AutocompleteEditModel::State& model_state,
     91                         const ViewState& view_state)
     92       : model_state(model_state),
     93         view_state(view_state) {
     94   }
     95 
     96   const AutocompleteEditModel::State model_state;
     97   const ViewState view_state;
     98 };
     99 
    100 // Returns a lazily initialized property bag accessor for saving our state in a
    101 // TabContents.
    102 PropertyAccessor<AutocompleteEditState>* GetStateAccessor() {
    103   static PropertyAccessor<AutocompleteEditState> state;
    104   return &state;
    105 }
    106 
    107 const int kAutocompleteVerticalMargin = 4;
    108 
    109 }  // namespace
    110 
    111 AutocompleteEditViewViews::AutocompleteEditViewViews(
    112     AutocompleteEditController* controller,
    113     ToolbarModel* toolbar_model,
    114     Profile* profile,
    115     CommandUpdater* command_updater,
    116     bool popup_window_mode,
    117     const views::View* location_bar)
    118     : model_(new AutocompleteEditModel(this, controller, profile)),
    119       popup_view_(CreatePopupView(profile, location_bar)),
    120       controller_(controller),
    121       toolbar_model_(toolbar_model),
    122       command_updater_(command_updater),
    123       popup_window_mode_(popup_window_mode),
    124       security_level_(ToolbarModel::NONE),
    125       ime_composing_before_change_(false),
    126       delete_at_end_pressed_(false) {
    127   set_border(views::Border::CreateEmptyBorder(kAutocompleteVerticalMargin, 0,
    128                                               kAutocompleteVerticalMargin, 0));
    129 }
    130 
    131 AutocompleteEditViewViews::~AutocompleteEditViewViews() {
    132   NotificationService::current()->Notify(
    133       NotificationType::AUTOCOMPLETE_EDIT_DESTROYED,
    134       Source<AutocompleteEditViewViews>(this),
    135       NotificationService::NoDetails());
    136   // Explicitly teardown members which have a reference to us.  Just to be safe
    137   // we want them to be destroyed before destroying any other internal state.
    138   popup_view_.reset();
    139   model_.reset();
    140 }
    141 
    142 ////////////////////////////////////////////////////////////////////////////////
    143 // AutocompleteEditViewViews public:
    144 
    145 void AutocompleteEditViewViews::Init() {
    146   // The height of the text view is going to change based on the font used.  We
    147   // don't want to stretch the height, and we want it vertically centered.
    148   // TODO(oshima): make sure the above happens with views.
    149   textfield_ = new AutocompleteTextfield(this);
    150   textfield_->SetController(this);
    151 
    152 #if defined(TOUCH_UI)
    153   textfield_->SetFont(ui::ResourceBundle::GetSharedInstance().GetFont(
    154                       ResourceBundle::LargeFont));
    155 #endif
    156 
    157   if (popup_window_mode_)
    158     textfield_->SetReadOnly(true);
    159 
    160   // Manually invoke SetBaseColor() because TOOLKIT_VIEWS doesn't observe
    161   // themes.
    162   SetBaseColor();
    163 }
    164 
    165 void AutocompleteEditViewViews::SetBaseColor() {
    166   // TODO(oshima): Implment style change.
    167   NOTIMPLEMENTED();
    168 }
    169 
    170 bool AutocompleteEditViewViews::HandleAfterKeyEvent(
    171     const views::KeyEvent& event,
    172     bool handled) {
    173   if (event.key_code() == ui::VKEY_RETURN) {
    174     bool alt_held = event.IsAltDown();
    175     model_->AcceptInput(alt_held ? NEW_FOREGROUND_TAB : CURRENT_TAB, false);
    176     handled = true;
    177   } else if (!handled && event.key_code() == ui::VKEY_ESCAPE) {
    178     // We can handle the Escape key if textfield did not handle it.
    179     // If it's not handled by us, then we need to propagate it up to the parent
    180     // widgets, so that Escape accelerator can still work.
    181     handled = model_->OnEscapeKeyPressed();
    182   } else if (event.key_code() == ui::VKEY_CONTROL) {
    183     // Omnibox2 can switch its contents while pressing a control key. To switch
    184     // the contents of omnibox2, we notify the AutocompleteEditModel class when
    185     // the control-key state is changed.
    186     model_->OnControlKeyChanged(true);
    187   } else if (!handled && event.key_code() == ui::VKEY_DELETE &&
    188              event.IsShiftDown()) {
    189     // If shift+del didn't change the text, we let this delete an entry from
    190     // the popup.  We can't check to see if the IME handled it because even if
    191     // nothing is selected, the IME or the TextView still report handling it.
    192     if (model_->popup_model()->IsOpen())
    193       model_->popup_model()->TryDeletingCurrentItem();
    194   } else if (!handled && event.key_code() == ui::VKEY_UP) {
    195     model_->OnUpOrDownKeyPressed(-1);
    196     handled = true;
    197   } else if (!handled && event.key_code() == ui::VKEY_DOWN) {
    198     model_->OnUpOrDownKeyPressed(1);
    199     handled = true;
    200   } else if (!handled &&
    201              event.key_code() == ui::VKEY_TAB &&
    202              !event.IsShiftDown() &&
    203              !event.IsControlDown()) {
    204     if (model_->is_keyword_hint()) {
    205       handled = model_->AcceptKeyword();
    206     } else {
    207       string16::size_type start = 0;
    208       string16::size_type end = 0;
    209       size_t length = GetTextLength();
    210       GetSelectionBounds(&start, &end);
    211       if (start != end || start < length) {
    212         OnBeforePossibleChange();
    213         SelectRange(length, length);
    214         OnAfterPossibleChange();
    215         handled = true;
    216       }
    217 
    218       // TODO(Oshima): handle instant
    219     }
    220   }
    221   // TODO(oshima): page up & down
    222 
    223   return handled;
    224 }
    225 
    226 bool AutocompleteEditViewViews::HandleKeyReleaseEvent(
    227     const views::KeyEvent& event) {
    228   // Omnibox2 can switch its contents while pressing a control key. To switch
    229   // the contents of omnibox2, we notify the AutocompleteEditModel class when
    230   // the control-key state is changed.
    231   if (event.key_code() == ui::VKEY_CONTROL) {
    232     // TODO(oshima): investigate if we need to support keyboard with two
    233     // controls. See autocomplete_edit_view_gtk.cc.
    234     model_->OnControlKeyChanged(false);
    235     return true;
    236   }
    237   return false;
    238 }
    239 
    240 void AutocompleteEditViewViews::HandleFocusIn() {
    241   // TODO(oshima): Get control key state.
    242   model_->OnSetFocus(false);
    243   // Don't call controller_->OnSetFocus as this view has already
    244   // acquired the focus.
    245 }
    246 
    247 void AutocompleteEditViewViews::HandleFocusOut() {
    248   // TODO(oshima): we don't have native view. This requires
    249   // further refactoring.
    250   model_->OnWillKillFocus(NULL);
    251   // Close the popup.
    252   ClosePopup();
    253   // Tell the model to reset itself.
    254   model_->OnKillFocus();
    255   controller_->OnKillFocus();
    256 }
    257 
    258 ////////////////////////////////////////////////////////////////////////////////
    259 // AutocompleteEditViewViews, views::View implementation:
    260 void AutocompleteEditViewViews::Layout() {
    261   gfx::Insets insets = GetInsets();
    262   textfield_->SetBounds(insets.left(), insets.top(),
    263                         width() - insets.width(),
    264                         height() - insets.height());
    265 }
    266 
    267 void AutocompleteEditViewViews::GetAccessibleState(
    268     ui::AccessibleViewState* state) {
    269   state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION);
    270 }
    271 
    272 ////////////////////////////////////////////////////////////////////////////////
    273 // AutocompleteEditViewViews, AutocopmleteEditView implementation:
    274 
    275 AutocompleteEditModel* AutocompleteEditViewViews::model() {
    276   return model_.get();
    277 }
    278 
    279 const AutocompleteEditModel* AutocompleteEditViewViews::model() const {
    280   return model_.get();
    281 }
    282 
    283 void AutocompleteEditViewViews::SaveStateToTab(TabContents* tab) {
    284   DCHECK(tab);
    285 
    286   // NOTE: GetStateForTabSwitch may affect GetSelection, so order is important.
    287   AutocompleteEditModel::State model_state = model_->GetStateForTabSwitch();
    288   ui::Range selection;
    289   textfield_->GetSelectedRange(&selection);
    290   GetStateAccessor()->SetProperty(
    291       tab->property_bag(),
    292       AutocompleteEditState(model_state, ViewState(selection)));
    293 }
    294 
    295 void AutocompleteEditViewViews::Update(const TabContents* contents) {
    296   // NOTE: We're getting the URL text here from the ToolbarModel.
    297   bool visibly_changed_permanent_text =
    298       model_->UpdatePermanentText(WideToUTF16Hack(toolbar_model_->GetText()));
    299 
    300   ToolbarModel::SecurityLevel security_level =
    301         toolbar_model_->GetSecurityLevel();
    302   bool changed_security_level = (security_level != security_level_);
    303   security_level_ = security_level;
    304 
    305   // TODO(oshima): Copied from gtk implementation which is
    306   // slightly different from WIN impl. Find out the correct implementation
    307   // for views-implementation.
    308   if (contents) {
    309     RevertAll();
    310     const AutocompleteEditState* state =
    311         GetStateAccessor()->GetProperty(contents->property_bag());
    312     if (state) {
    313       model_->RestoreState(state->model_state);
    314 
    315       // Move the marks for the cursor and the other end of the selection to
    316       // the previously-saved offsets (but preserve PRIMARY).
    317       textfield_->SelectRange(state->view_state.selection_range);
    318     }
    319   } else if (visibly_changed_permanent_text) {
    320     RevertAll();
    321   } else if (changed_security_level) {
    322     EmphasizeURLComponents();
    323   }
    324 }
    325 
    326 void AutocompleteEditViewViews::OpenURL(const GURL& url,
    327                                         WindowOpenDisposition disposition,
    328                                         PageTransition::Type transition,
    329                                         const GURL& alternate_nav_url,
    330                                         size_t selected_line,
    331                                         const string16& keyword) {
    332   if (!url.is_valid())
    333     return;
    334 
    335   model_->OpenURL(url, disposition, transition, alternate_nav_url,
    336                   selected_line, keyword);
    337 }
    338 
    339 string16 AutocompleteEditViewViews::GetText() const {
    340   // TODO(oshima): IME support
    341   return textfield_->text();
    342 }
    343 
    344 bool AutocompleteEditViewViews::IsEditingOrEmpty() const {
    345   return model_->user_input_in_progress() || (GetTextLength() == 0);
    346 }
    347 
    348 int AutocompleteEditViewViews::GetIcon() const {
    349   return IsEditingOrEmpty() ?
    350       AutocompleteMatch::TypeToIcon(model_->CurrentTextType()) :
    351       toolbar_model_->GetIcon();
    352 }
    353 
    354 void AutocompleteEditViewViews::SetUserText(const string16& text) {
    355   SetUserText(text, text, true);
    356 }
    357 
    358 void AutocompleteEditViewViews::SetUserText(const string16& text,
    359                                             const string16& display_text,
    360                                             bool update_popup) {
    361   model_->SetUserText(text);
    362   SetWindowTextAndCaretPos(display_text, display_text.length());
    363   if (update_popup)
    364     UpdatePopup();
    365   TextChanged();
    366 }
    367 
    368 void AutocompleteEditViewViews::SetWindowTextAndCaretPos(
    369     const string16& text,
    370     size_t caret_pos) {
    371   const ui::Range range(caret_pos, caret_pos);
    372   SetTextAndSelectedRange(text, range);
    373 }
    374 
    375 void AutocompleteEditViewViews::SetForcedQuery() {
    376   const string16 current_text(GetText());
    377   const size_t start = current_text.find_first_not_of(kWhitespaceUTF16);
    378   if (start == string16::npos || (current_text[start] != '?')) {
    379     SetUserText(ASCIIToUTF16("?"));
    380   } else {
    381     SelectRange(current_text.size(), start + 1);
    382   }
    383 }
    384 
    385 bool AutocompleteEditViewViews::IsSelectAll() {
    386   // TODO(oshima): IME support.
    387   return textfield_->text() == textfield_->GetSelectedText();
    388 }
    389 
    390 bool AutocompleteEditViewViews::DeleteAtEndPressed() {
    391   return delete_at_end_pressed_;
    392 }
    393 
    394 void AutocompleteEditViewViews::GetSelectionBounds(
    395     string16::size_type* start,
    396     string16::size_type* end) {
    397   ui::Range range;
    398   textfield_->GetSelectedRange(&range);
    399   *start = static_cast<size_t>(range.end());
    400   *end = static_cast<size_t>(range.start());
    401 }
    402 
    403 void AutocompleteEditViewViews::SelectAll(bool reversed) {
    404   if (reversed)
    405     SelectRange(GetTextLength(), 0);
    406   else
    407     SelectRange(0, GetTextLength());
    408 }
    409 
    410 void AutocompleteEditViewViews::RevertAll() {
    411   ClosePopup();
    412   model_->Revert();
    413   TextChanged();
    414 }
    415 
    416 void AutocompleteEditViewViews::UpdatePopup() {
    417   model_->SetInputInProgress(true);
    418   if (!model_->has_focus())
    419     return;
    420 
    421   // Don't inline autocomplete when the caret/selection isn't at the end of
    422   // the text, or in the middle of composition.
    423   ui::Range sel;
    424   textfield_->GetSelectedRange(&sel);
    425   bool no_inline_autocomplete =
    426       sel.GetMax() < GetTextLength() || textfield_->IsIMEComposing();
    427 
    428   model_->StartAutocomplete(!sel.is_empty(), no_inline_autocomplete);
    429 }
    430 
    431 void AutocompleteEditViewViews::ClosePopup() {
    432   model_->StopAutocomplete();
    433 }
    434 
    435 void AutocompleteEditViewViews::SetFocus() {
    436   // In views-implementation, the focus is on textfield rather than
    437   // AutocompleteEditView.
    438   textfield_->RequestFocus();
    439 }
    440 
    441 void AutocompleteEditViewViews::OnTemporaryTextMaybeChanged(
    442     const string16& display_text,
    443     bool save_original_selection) {
    444   if (save_original_selection)
    445     textfield_->GetSelectedRange(&saved_temporary_selection_);
    446 
    447   SetWindowTextAndCaretPos(display_text, display_text.length());
    448   TextChanged();
    449 }
    450 
    451 bool AutocompleteEditViewViews::OnInlineAutocompleteTextMaybeChanged(
    452     const string16& display_text,
    453     size_t user_text_length) {
    454   if (display_text == GetText())
    455     return false;
    456   ui::Range range(display_text.size(), user_text_length);
    457   SetTextAndSelectedRange(display_text, range);
    458   TextChanged();
    459   return true;
    460 }
    461 
    462 void AutocompleteEditViewViews::OnRevertTemporaryText() {
    463   textfield_->SelectRange(saved_temporary_selection_);
    464   TextChanged();
    465 }
    466 
    467 void AutocompleteEditViewViews::OnBeforePossibleChange() {
    468   // Record our state.
    469   text_before_change_ = GetText();
    470   textfield_->GetSelectedRange(&sel_before_change_);
    471   ime_composing_before_change_ = textfield_->IsIMEComposing();
    472 }
    473 
    474 bool AutocompleteEditViewViews::OnAfterPossibleChange() {
    475   ui::Range new_sel;
    476   textfield_->GetSelectedRange(&new_sel);
    477 
    478   // See if the text or selection have changed since OnBeforePossibleChange().
    479   const string16 new_text = GetText();
    480   const bool text_changed = (new_text != text_before_change_) ||
    481       (ime_composing_before_change_ != textfield_->IsIMEComposing());
    482   const bool selection_differs =
    483       !((sel_before_change_.is_empty() && new_sel.is_empty()) ||
    484         sel_before_change_.EqualsIgnoringDirection(new_sel));
    485 
    486   // When the user has deleted text, we don't allow inline autocomplete.  Make
    487   // sure to not flag cases like selecting part of the text and then pasting
    488   // (or typing) the prefix of that selection.  (We detect these by making
    489   // sure the caret, which should be after any insertion, hasn't moved
    490   // forward of the old selection start.)
    491   const bool just_deleted_text =
    492       (text_before_change_.length() > new_text.length()) &&
    493       (new_sel.start() <= sel_before_change_.GetMin());
    494 
    495   const bool something_changed = model_->OnAfterPossibleChange(
    496       new_text, new_sel.start(), new_sel.end(), selection_differs,
    497       text_changed, just_deleted_text, !textfield_->IsIMEComposing());
    498 
    499   // If only selection was changed, we don't need to call |model_|'s
    500   // OnChanged() method, which is called in TextChanged().
    501   // But we still need to call EmphasizeURLComponents() to make sure the text
    502   // attributes are updated correctly.
    503   if (something_changed && text_changed)
    504     TextChanged();
    505   else if (selection_differs)
    506     EmphasizeURLComponents();
    507   else if (delete_at_end_pressed_)
    508     model_->OnChanged();
    509 
    510   return something_changed;
    511 }
    512 
    513 gfx::NativeView AutocompleteEditViewViews::GetNativeView() const {
    514   return GetWidget()->GetNativeView();
    515 }
    516 
    517 CommandUpdater* AutocompleteEditViewViews::GetCommandUpdater() {
    518   return command_updater_;
    519 }
    520 
    521 void AutocompleteEditViewViews::SetInstantSuggestion(const string16& input,
    522                                                      bool animate_to_complete) {
    523   NOTIMPLEMENTED();
    524 }
    525 
    526 string16 AutocompleteEditViewViews::GetInstantSuggestion() const {
    527   NOTIMPLEMENTED();
    528   return string16();
    529 }
    530 
    531 int AutocompleteEditViewViews::TextWidth() const {
    532   // TODO(oshima): add horizontal margin.
    533   return textfield_->font().GetStringWidth(textfield_->text());
    534 }
    535 
    536 bool AutocompleteEditViewViews::IsImeComposing() const {
    537   return false;
    538 }
    539 
    540 views::View* AutocompleteEditViewViews::AddToView(views::View* parent) {
    541   parent->AddChildView(this);
    542   AddChildView(textfield_);
    543   return this;
    544 }
    545 
    546 int AutocompleteEditViewViews::OnPerformDrop(
    547     const views::DropTargetEvent& event) {
    548   NOTIMPLEMENTED();
    549   return ui::DragDropTypes::DRAG_NONE;
    550 }
    551 
    552 ////////////////////////////////////////////////////////////////////////////////
    553 // AutocompleteEditViewViews, NotificationObserver implementation:
    554 
    555 void AutocompleteEditViewViews::Observe(NotificationType type,
    556                                       const NotificationSource& source,
    557                                       const NotificationDetails& details) {
    558   DCHECK(type == NotificationType::BROWSER_THEME_CHANGED);
    559   SetBaseColor();
    560 }
    561 
    562 ////////////////////////////////////////////////////////////////////////////////
    563 // AutocompleteEditViewViews, views::TextfieldController implementation:
    564 
    565 void AutocompleteEditViewViews::ContentsChanged(views::Textfield* sender,
    566                                                 const string16& new_contents) {
    567 }
    568 
    569 bool AutocompleteEditViewViews::HandleKeyEvent(
    570     views::Textfield* textfield,
    571     const views::KeyEvent& event) {
    572   delete_at_end_pressed_ = false;
    573 
    574   if (event.key_code() == ui::VKEY_BACK) {
    575     // Checks if it's currently in keyword search mode.
    576     if (model_->is_keyword_hint() || model_->keyword().empty())
    577       return false;
    578     // If there is selection, let textfield handle the backspace.
    579     if (textfield_->HasSelection())
    580       return false;
    581     // If not at the begining of the text, let textfield handle the backspace.
    582     if (textfield_->GetCursorPosition())
    583       return false;
    584     model_->ClearKeyword(GetText());
    585     return true;
    586   }
    587 
    588   if (event.key_code() == ui::VKEY_DELETE && !event.IsAltDown()) {
    589     delete_at_end_pressed_ =
    590         (!textfield_->HasSelection() &&
    591          textfield_->GetCursorPosition() == textfield_->text().length());
    592   }
    593 
    594   return false;
    595 }
    596 
    597 void AutocompleteEditViewViews::OnBeforeUserAction(views::Textfield* sender) {
    598   OnBeforePossibleChange();
    599 }
    600 
    601 void AutocompleteEditViewViews::OnAfterUserAction(views::Textfield* sender) {
    602   OnAfterPossibleChange();
    603 }
    604 
    605 ////////////////////////////////////////////////////////////////////////////////
    606 // AutocompleteEditViewViews, private:
    607 
    608 size_t AutocompleteEditViewViews::GetTextLength() const {
    609   // TODO(oshima): Support instant, IME.
    610   return textfield_->text().length();
    611 }
    612 
    613 void AutocompleteEditViewViews::EmphasizeURLComponents() {
    614   // TODO(oshima): Update URL visual style
    615   NOTIMPLEMENTED();
    616 }
    617 
    618 void AutocompleteEditViewViews::TextChanged() {
    619   EmphasizeURLComponents();
    620   model_->OnChanged();
    621 }
    622 
    623 void AutocompleteEditViewViews::SetTextAndSelectedRange(
    624     const string16& text,
    625     const ui::Range& range) {
    626   if (text != GetText())
    627     textfield_->SetText(text);
    628   textfield_->SelectRange(range);
    629 }
    630 
    631 string16 AutocompleteEditViewViews::GetSelectedText() const {
    632   // TODO(oshima): Support instant, IME.
    633   return textfield_->GetSelectedText();
    634 }
    635 
    636 void AutocompleteEditViewViews::SelectRange(size_t caret, size_t end) {
    637   const ui::Range range(caret, end);
    638   textfield_->SelectRange(range);
    639 }
    640 
    641 AutocompletePopupView* AutocompleteEditViewViews::CreatePopupView(
    642     Profile* profile,
    643     const View* location_bar) {
    644 #if defined(TOUCH_UI)
    645   return new TouchAutocompletePopupContentsView(
    646 #else
    647   return new AutocompletePopupContentsView(
    648 #endif
    649       gfx::Font(), this, model_.get(), profile, location_bar);
    650 }
    651