// Copyright 2012 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/browser/ui/views/omnibox/omnibox_view_win.h"

#include <algorithm>
#include <locale>
#include <string>

#include <richedit.h>
#include <textserv.h>

#include "base/auto_reset.h"
#include "base/basictypes.h"
#include "base/bind.h"
#include "base/i18n/rtl.h"
#include "base/lazy_instance.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/iat_patch_function.h"
#include "base/win/metro.h"
#include "base/win/scoped_hdc.h"
#include "base/win/scoped_select_object.h"
#include "base/win/windows_version.h"
#include "chrome/app/chrome_command_ids.h"
#include "chrome/browser/autocomplete/autocomplete_input.h"
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/autocomplete/keyword_provider.h"
#include "chrome/browser/bookmarks/bookmark_node_data.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/command_updater.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/search/search.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/omnibox/omnibox_edit_controller.h"
#include "chrome/browser/ui/omnibox/omnibox_edit_model.h"
#include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
#include "chrome/browser/ui/views/location_bar/location_bar_view.h"
#include "chrome/browser/ui/views/omnibox/omnibox_view_views.h"
#include "chrome/common/net/url_fixer_upper.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "extensions/common/constants.h"
#include "grit/generated_resources.h"
#include "net/base/escape.h"
#include "skia/ext/skia_utils_win.h"
#include "ui/base/accessibility/accessible_view_state.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/drag_source_win.h"
#include "ui/base/dragdrop/drop_target_win.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
#include "ui/base/ime/win/tsf_bridge.h"
#include "ui/base/ime/win/tsf_event_router.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/l10n/l10n_util_win.h"
#include "ui/base/touch/touch_enabled.h"
#include "ui/base/win/mouse_wheel_util.h"
#include "ui/base/win/touch_input.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/win/hwnd_util.h"
#include "ui/views/button_drag_utils.h"
#include "ui/views/controls/menu/menu_item_view.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/textfield/native_textfield_win.h"
#include "ui/views/widget/widget.h"
#include "url/url_util.h"
#include "win8/util/win8_util.h"

#pragma comment(lib, "oleacc.lib")  // Needed for accessibility support.

using content::UserMetricsAction;
using content::WebContents;

namespace {

const char kAutocompleteEditStateKey[] = "AutocompleteEditState";

// msftedit.dll is RichEdit ver 4.1.
// This version is available from WinXP SP1 and has TSF support.
const wchar_t* kRichEditDLLName = L"msftedit.dll";

// A helper method for determining a valid DROPEFFECT given the allowed
// DROPEFFECTS.  We prefer copy over link.
DWORD CopyOrLinkDropEffect(DWORD effect) {
  if (effect & DROPEFFECT_COPY)
    return DROPEFFECT_COPY;
  if (effect & DROPEFFECT_LINK)
    return DROPEFFECT_LINK;
  return DROPEFFECT_NONE;
}

// A helper method for determining a valid drag operation given the allowed
// operation.  We prefer copy over link.
int CopyOrLinkDragOperation(int drag_operation) {
  if (drag_operation & ui::DragDropTypes::DRAG_COPY)
    return ui::DragDropTypes::DRAG_COPY;
  if (drag_operation & ui::DragDropTypes::DRAG_LINK)
    return ui::DragDropTypes::DRAG_LINK;
  return ui::DragDropTypes::DRAG_NONE;
}

// The AutocompleteEditState struct contains enough information about the
// OmniboxEditModel and OmniboxViewWin to save/restore a user's
// typing, caret position, etc. across tab changes.  We explicitly don't
// preserve things like whether the popup was open as this might be weird.
struct AutocompleteEditState : public base::SupportsUserData::Data {
  AutocompleteEditState(const OmniboxEditModel::State& model_state,
                        const OmniboxViewWin::State& view_state)
      : model_state(model_state),
        view_state(view_state) {
  }
  virtual ~AutocompleteEditState() {}

  const OmniboxEditModel::State model_state;
  const OmniboxViewWin::State view_state;
};

// Returns true if the current point is far enough from the origin that it
// would be considered a drag.
bool IsDrag(const POINT& origin, const POINT& current) {
  return views::View::ExceededDragThreshold(
      gfx::Point(current) - gfx::Point(origin));
}

}  // namespace

// EditDropTarget is the IDropTarget implementation installed on
// OmniboxViewWin. EditDropTarget prefers URL over plain text. A drop
// of a URL replaces all the text of the edit and navigates immediately to the
// URL. A drop of plain text from the same edit either copies or moves the
// selected text, and a drop of plain text from a source other than the edit
// does a paste and go.
class OmniboxViewWin::EditDropTarget : public ui::DropTargetWin {
 public:
  explicit EditDropTarget(OmniboxViewWin* edit);

 protected:
  virtual DWORD OnDragEnter(IDataObject* data_object,
                            DWORD key_state,
                            POINT cursor_position,
                            DWORD effect);
  virtual DWORD OnDragOver(IDataObject* data_object,
                           DWORD key_state,
                           POINT cursor_position,
                           DWORD effect);
  virtual void OnDragLeave(IDataObject* data_object);
  virtual DWORD OnDrop(IDataObject* data_object,
                       DWORD key_state,
                       POINT cursor_position,
                       DWORD effect);

 private:
  // If dragging a string, the drop highlight position of the edit is reset
  // based on the mouse position.
  void UpdateDropHighlightPosition(const POINT& cursor_screen_position);

  // Resets the visual drop indicates we install on the edit.
  void ResetDropHighlights();

  // The edit we're the drop target for.
  OmniboxViewWin* edit_;

  // If true, the drag session contains a URL.
  bool drag_has_url_;

  // If true, the drag session contains a string. If drag_has_url_ is true,
  // this is false regardless of whether the clipboard has a string.
  bool drag_has_string_;

  DISALLOW_COPY_AND_ASSIGN(EditDropTarget);
};

OmniboxViewWin::EditDropTarget::EditDropTarget(OmniboxViewWin* edit)
    : ui::DropTargetWin(edit->m_hWnd),
      edit_(edit),
      drag_has_url_(false),
      drag_has_string_(false) {
}

DWORD OmniboxViewWin::EditDropTarget::OnDragEnter(IDataObject* data_object,
                                                  DWORD key_state,
                                                  POINT cursor_position,
                                                  DWORD effect) {
  ui::OSExchangeData os_data(new ui::OSExchangeDataProviderWin(data_object));
  drag_has_url_ = os_data.HasURL();
  drag_has_string_ = !drag_has_url_ && os_data.HasString();
  if (drag_has_url_) {
    if (edit_->in_drag()) {
      // The edit we're associated with originated the drag. No point in
      // allowing the user to drop back on us.
      drag_has_url_ = false;
    }
    // NOTE: it would be nice to visually show all the text is going to
    // be replaced by selecting all, but this caused painting problems. In
    // particular the flashing caret would appear outside the edit! For now
    // we stick with no visual indicator other than that shown own the mouse
    // cursor.
  }
  return OnDragOver(data_object, key_state, cursor_position, effect);
}

DWORD OmniboxViewWin::EditDropTarget::OnDragOver(IDataObject* data_object,
                                                 DWORD key_state,
                                                 POINT cursor_position,
                                                 DWORD effect) {
  if (drag_has_url_)
    return CopyOrLinkDropEffect(effect);

  if (drag_has_string_) {
    UpdateDropHighlightPosition(cursor_position);
    if (edit_->drop_highlight_position() == -1 && edit_->in_drag())
      return DROPEFFECT_NONE;
    if (edit_->in_drag()) {
      // The edit we're associated with originated the drag.  Do the normal drag
      // behavior.
      DCHECK((effect & DROPEFFECT_COPY) && (effect & DROPEFFECT_MOVE));
      return (key_state & MK_CONTROL) ? DROPEFFECT_COPY : DROPEFFECT_MOVE;
    }
    // Our edit didn't originate the drag, only allow link or copy.
    return CopyOrLinkDropEffect(effect);
  }

  return DROPEFFECT_NONE;
}

void OmniboxViewWin::EditDropTarget::OnDragLeave(IDataObject* data_object) {
  ResetDropHighlights();
}

DWORD OmniboxViewWin::EditDropTarget::OnDrop(IDataObject* data_object,
                                             DWORD key_state,
                                             POINT cursor_position,
                                             DWORD effect) {
  effect = OnDragOver(data_object, key_state, cursor_position, effect);

  ui::OSExchangeData os_data(new ui::OSExchangeDataProviderWin(data_object));
  gfx::Point point(cursor_position.x, cursor_position.y);
  ui::DropTargetEvent event(
      os_data, point, point,
      ui::DragDropTypes::DropEffectToDragOperation(effect));

  int drag_operation = edit_->OnPerformDropImpl(event, edit_->in_drag());

  if (!drag_has_url_)
    ResetDropHighlights();

  return ui::DragDropTypes::DragOperationToDropEffect(drag_operation);
}

void OmniboxViewWin::EditDropTarget::UpdateDropHighlightPosition(
    const POINT& cursor_screen_position) {
  if (drag_has_string_) {
    POINT client_position = cursor_screen_position;
    ::ScreenToClient(edit_->m_hWnd, &client_position);
    int drop_position = edit_->CharFromPos(client_position);
    if (edit_->in_drag()) {
      // Our edit originated the drag, don't allow a drop if over the selected
      // region.
      LONG sel_start, sel_end;
      edit_->GetSel(sel_start, sel_end);
      if ((sel_start != sel_end) && (drop_position >= sel_start) &&
          (drop_position <= sel_end))
        drop_position = -1;
    } else {
      // A drop from a source other than the edit replaces all the text, so
      // we don't show the drop location. See comment in OnDragEnter as to why
      // we don't try and select all here.
      drop_position = -1;
    }
    edit_->SetDropHighlightPosition(drop_position);
  }
}

void OmniboxViewWin::EditDropTarget::ResetDropHighlights() {
  if (drag_has_string_)
    edit_->SetDropHighlightPosition(-1);
}

///////////////////////////////////////////////////////////////////////////////
// Helper classes

OmniboxViewWin::ScopedFreeze::ScopedFreeze(OmniboxViewWin* edit,
                                           ITextDocument* text_object_model)
    : edit_(edit),
      text_object_model_(text_object_model) {
  // Freeze the screen.
  if (text_object_model_) {
    long count;
    text_object_model_->Freeze(&count);
  }
}

OmniboxViewWin::ScopedFreeze::~ScopedFreeze() {
  // Unfreeze the screen.
  // NOTE: If this destructor is reached while the edit is being destroyed (for
  // example, because we double-clicked the edit of a popup and caused it to
  // transform to an unconstrained window), it will no longer have an HWND, and
  // text_object_model_ may point to a destroyed object, so do nothing here.
  if (edit_->IsWindow() && text_object_model_) {
    long count;
    text_object_model_->Unfreeze(&count);
    if (count == 0) {
      // We need to UpdateWindow() here in addition to InvalidateRect() because,
      // as far as I can tell, the edit likes to synchronously erase its
      // background when unfreezing, thus requiring us to synchronously redraw
      // if we don't want flicker.
      edit_->InvalidateRect(NULL, false);
      edit_->UpdateWindow();
    }
  }
}

OmniboxViewWin::ScopedSuspendUndo::ScopedSuspendUndo(
    ITextDocument* text_object_model)
    : text_object_model_(text_object_model) {
  // Suspend Undo processing.
  if (text_object_model_)
    text_object_model_->Undo(tomSuspend, NULL);
}

OmniboxViewWin::ScopedSuspendUndo::~ScopedSuspendUndo() {
  // Resume Undo processing.
  if (text_object_model_)
    text_object_model_->Undo(tomResume, NULL);
}

// A subclass of NativeViewHost that provides accessibility info for the
// underlying Omnibox view.
class OmniboxViewWrapper : public views::NativeViewHost {
 public:
  explicit OmniboxViewWrapper(OmniboxViewWin* omnibox_view_win)
      : omnibox_view_win_(omnibox_view_win) {}

  gfx::NativeViewAccessible GetNativeViewAccessible() {
    // This forces it to use NativeViewAccessibilityWin rather than
    // any accessibility provided natively by the HWND.
    return View::GetNativeViewAccessible();
  }

  // views::View
  virtual void GetAccessibleState(ui::AccessibleViewState* state) {
    views::NativeViewHost::GetAccessibleState(state);
    state->name = l10n_util::GetStringUTF16(IDS_ACCNAME_LOCATION);
    state->role = ui::AccessibilityTypes::ROLE_TEXT;
    state->value = omnibox_view_win_->GetText();
    state->state = ui::AccessibilityTypes::STATE_EDITABLE;
    size_t sel_start;
    size_t sel_end;
    omnibox_view_win_->GetSelectionBounds(&sel_start, &sel_end);
    state->selection_start = sel_start;
    state->selection_end = sel_end;
  }

 private:
  OmniboxViewWin* omnibox_view_win_;

  DISALLOW_COPY_AND_ASSIGN(OmniboxViewWrapper);
};

///////////////////////////////////////////////////////////////////////////////
// OmniboxViewWin

namespace {

// These are used to hook the CRichEditCtrl's calls to BeginPaint() and
// EndPaint() and provide a memory DC instead.  See OnPaint().
HWND edit_hwnd = NULL;
PAINTSTRUCT paint_struct;

// Intercepted method for BeginPaint(). Must use __stdcall convention.
HDC WINAPI BeginPaintIntercept(HWND hWnd, LPPAINTSTRUCT lpPaint) {
  if (!edit_hwnd || (hWnd != edit_hwnd))
    return ::BeginPaint(hWnd, lpPaint);

  *lpPaint = paint_struct;
  return paint_struct.hdc;
}

// Intercepted method for EndPaint(). Must use __stdcall convention.
BOOL WINAPI EndPaintIntercept(HWND hWnd, const PAINTSTRUCT* lpPaint) {
  return (edit_hwnd && (hWnd == edit_hwnd)) || ::EndPaint(hWnd, lpPaint);
}

class PaintPatcher {
 public:
  PaintPatcher();
  ~PaintPatcher();

  void RefPatch();
  void DerefPatch();

 private:
  size_t refcount_;
  base::win::IATPatchFunction begin_paint_;
  base::win::IATPatchFunction end_paint_;

  DISALLOW_COPY_AND_ASSIGN(PaintPatcher);
};

PaintPatcher::PaintPatcher() : refcount_(0) {
}

PaintPatcher::~PaintPatcher() {
  DCHECK_EQ(0U, refcount_);
}

void PaintPatcher::RefPatch() {
  if (refcount_ == 0) {
    DCHECK(!begin_paint_.is_patched());
    DCHECK(!end_paint_.is_patched());
    begin_paint_.Patch(kRichEditDLLName, "user32.dll", "BeginPaint",
                       &BeginPaintIntercept);
    end_paint_.Patch(kRichEditDLLName, "user32.dll", "EndPaint",
                     &EndPaintIntercept);
  }
  ++refcount_;
}

void PaintPatcher::DerefPatch() {
  DCHECK(begin_paint_.is_patched());
  DCHECK(end_paint_.is_patched());
  --refcount_;
  if (refcount_ == 0) {
    begin_paint_.Unpatch();
    end_paint_.Unpatch();
  }
}

base::LazyInstance<PaintPatcher> g_paint_patcher = LAZY_INSTANCE_INITIALIZER;

// twips are a unit of type measurement, and RichEdit controls use them
// to set offsets.
const int kTwipsPerInch = 1440;

}  // namespace

HMODULE OmniboxViewWin::loaded_library_module_ = NULL;

OmniboxViewWin::OmniboxViewWin(OmniboxEditController* controller,
                               LocationBarView* location_bar,
                               CommandUpdater* command_updater,
                               bool popup_window_mode,
                               const gfx::FontList& font_list,
                               int font_y_offset)
    : OmniboxView(location_bar->profile(), controller, command_updater),
      popup_view_(OmniboxPopupContentsView::Create(
          font_list, this, model(), location_bar)),
      location_bar_(location_bar),
      popup_window_mode_(popup_window_mode),
      force_hidden_(false),
      tracking_click_(),
      tracking_double_click_(false),
      double_click_time_(0),
      can_discard_mousemove_(false),
      ignore_ime_messages_(false),
      delete_at_end_pressed_(false),
      font_list_(font_list),
      font_y_adjustment_(font_y_offset),
      possible_drag_(false),
      in_drag_(false),
      initiated_drag_(false),
      drop_highlight_position_(-1),
      ime_candidate_window_open_(false),
      background_color_(skia::SkColorToCOLORREF(location_bar->GetColor(
          ToolbarModel::NONE, LocationBarView::BACKGROUND))),
      security_level_(ToolbarModel::NONE),
      text_object_model_(NULL),
      tsf_event_router_(base::win::IsTSFAwareRequired() ?
          new ui::TSFEventRouter(this) : NULL) {
  if (!loaded_library_module_)
    loaded_library_module_ = LoadLibrary(kRichEditDLLName);
  // RichEdit should be available; rare exceptions should use the Views omnibox.
  DCHECK(loaded_library_module_);

  saved_selection_for_focus_change_.cpMin = -1;

  g_paint_patcher.Pointer()->RefPatch();

  Create(location_bar->GetWidget()->GetNativeView(), 0, 0, 0,
         l10n_util::GetExtendedStyles());
  SetReadOnly(popup_window_mode_);
  gfx::NativeFont native_font(font_list_.GetPrimaryFont().GetNativeFont());
  SetFont(native_font);

  // IMF_DUALFONT (on by default) is supposed to use one font for ASCII text
  // and a different one for Asian text.  In some cases, ASCII characters may
  // be mis-marked as Asian, e.g. because input from the keyboard may be
  // auto-stamped with the keyboard language.  As a result adjacent characters
  // can render in different fonts, which looks bizarre.  To fix this we
  // disable dual-font mode, which forces the control to use a single font for
  // everything.
  // Note that we should not disable the very similar IMF_AUTOFONT flag, which
  // allows the control to hunt for fonts that can display all the current
  // characters; doing this results in "missing glyph" boxes when the user
  // enters characters not available in the currently-chosen font.
  const LRESULT lang_options = SendMessage(m_hWnd, EM_GETLANGOPTIONS, 0, 0);
  SendMessage(m_hWnd, EM_SETLANGOPTIONS, 0, lang_options & ~IMF_DUALFONT);

  // NOTE: Do not use SetWordBreakProcEx() here, that is no longer supported as
  // of Rich Edit 2.0 onward.
  SendMessage(m_hWnd, EM_SETWORDBREAKPROC, 0,
              reinterpret_cast<LPARAM>(&WordBreakProc));

  // Get the metrics for the font.
  base::win::ScopedGetDC screen_dc(NULL);
  base::win::ScopedSelectObject font_in_dc(screen_dc, native_font);
  TEXTMETRIC tm = {0};
  GetTextMetrics(screen_dc, &tm);
  int cap_height = font_list_.GetBaseline() - tm.tmInternalLeading;
  // The ratio of a font's x-height to its cap height.  Sadly, Windows
  // doesn't provide a true value for a font's x-height in its text
  // metrics, so we approximate.
  const float kXHeightRatio = 0.7f;
  font_x_height_ = static_cast<int>(
      (static_cast<float>(cap_height) * kXHeightRatio) + 0.5);

  // Get the number of twips per pixel, which we need below to offset our text
  // by the desired number of pixels.
  const long kTwipsPerPixel =
      kTwipsPerInch / GetDeviceCaps(screen_dc, LOGPIXELSY);

  // Set the default character style -- adjust to our desired baseline.
  CHARFORMAT cf = {0};
  cf.dwMask = CFM_OFFSET;
  cf.yOffset = -font_y_adjustment_ * kTwipsPerPixel;
  SetDefaultCharFormat(cf);

  SetBackgroundColor(background_color_);

  if (!popup_window_mode_) {
    // Non-read-only edit controls have a drop target.  Revoke it so that we can
    // install our own.  Revoking automatically deletes the existing one.
    HRESULT hr = RevokeDragDrop(m_hWnd);
    DCHECK_EQ(S_OK, hr);

    // Register our drop target.  The scoped_refptr here will delete the drop
    // target if it fails to register itself correctly on |m_hWnd|.  Otherwise,
    // the edit control will invoke RevokeDragDrop when it's being destroyed, so
    // we don't have to do so.
    scoped_refptr<EditDropTarget> drop_target(new EditDropTarget(this));
  }
}

OmniboxViewWin::~OmniboxViewWin() {
  // Explicitly release the text object model now that we're done with it, and
  // before we free the library. If the library gets unloaded before this
  // released, it becomes garbage. Note that since text_object_model_ is lazy
  // initialized, it may still be null.
  if (text_object_model_)
    text_object_model_->Release();

  // We balance our reference count and unpatch when the last instance has
  // been destroyed.  This prevents us from relying on the AtExit or static
  // destructor sequence to do our unpatching, which is generally fragile.
  g_paint_patcher.Pointer()->DerefPatch();
}

views::View* OmniboxViewWin::parent_view() const {
  return location_bar_;
}

void OmniboxViewWin::SaveStateToTab(WebContents* tab) {
  DCHECK(tab);

  const OmniboxEditModel::State model_state(model()->GetStateForTabSwitch());

  CHARRANGE selection;
  GetSelection(selection);
  tab->SetUserData(
      kAutocompleteEditStateKey,
      new AutocompleteEditState(
          model_state,
          State(selection, saved_selection_for_focus_change_)));
}

void OmniboxViewWin::OnTabChanged(const content::WebContents* web_contents) {
  ScopedFreeze freeze(this, GetTextObjectModel());
  security_level_ = controller()->GetToolbarModel()->GetSecurityLevel(false);

  const AutocompleteEditState* state = static_cast<AutocompleteEditState*>(
      web_contents->GetUserData(&kAutocompleteEditStateKey));
  model()->RestoreState(state ? &state->model_state : NULL);
  if (state) {
    SetSelectionRange(state->view_state.selection);
    saved_selection_for_focus_change_ =
        state->view_state.saved_selection_for_focus_change;
  }
}

void OmniboxViewWin::Update() {
  const ToolbarModel::SecurityLevel old_security_level = security_level_;
  security_level_ = controller()->GetToolbarModel()->GetSecurityLevel(false);
  if (model()->UpdatePermanentText()) {
    ScopedFreeze freeze(this, GetTextObjectModel());

    // Something visibly changed.  Re-enable search term replacement.
    controller()->GetToolbarModel()->set_search_term_replacement_enabled(true);
    model()->UpdatePermanentText();

    // Tweak: if the user had all the text selected, select all the new text.
    // This makes one particular case better: the user clicks in the box to
    // change it right before the permanent URL is changed.  Since the new URL
    // is still fully selected, the user's typing will replace the edit contents
    // as they'd intended.
    CHARRANGE sel;
    GetSelection(sel);
    const bool was_select_all = IsSelectAllForRange(sel);

    RevertAll();

    // Only select all when we have focus.  If we don't have focus, selecting
    // all is unnecessary since the selection will change on regaining focus,
    // and can in fact cause artifacts, e.g. if the user is on the NTP and
    // clicks a link to navigate, causing |was_select_all| to be vacuously true
    // for the empty omnibox, and we then select all here, leading to the
    // trailing portion of a long URL being scrolled into view.  We could try
    // and address cases like this, but it seems better to just not muck with
    // things when the omnibox isn't focused to begin with.
    if (was_select_all && model()->has_focus())
      SelectAll(sel.cpMin > sel.cpMax);
  } else if (old_security_level != security_level_) {
    EmphasizeURLComponents();
  }
}

void OmniboxViewWin::OpenMatch(const AutocompleteMatch& match,
                               WindowOpenDisposition disposition,
                               const GURL& alternate_nav_url,
                               size_t selected_line) {
  // When we navigate, we first revert to the unedited state, then if necessary
  // synchronously change the permanent text to the new URL.  If we don't freeze
  // here, the user could potentially see a flicker of the current URL before
  // the new one reappears, which would look glitchy.
  ScopedFreeze freeze(this, GetTextObjectModel());
  OmniboxView::OpenMatch(match, disposition, alternate_nav_url, selected_line);
}

string16 OmniboxViewWin::GetText() const {
  const int len = GetTextLength() + 1;
  string16 str;
  if (len > 1)
    GetWindowText(WriteInto(&str, len), len);
  return str;
}

void OmniboxViewWin::SetUserText(const string16& text,
                                 const string16& display_text,
                                 bool update_popup) {
  ScopedFreeze freeze(this, GetTextObjectModel());
  saved_selection_for_focus_change_.cpMin = -1;
  OmniboxView::SetUserText(text, display_text, update_popup);
}

void OmniboxViewWin::SetWindowTextAndCaretPos(const string16& text,
                                              size_t caret_pos,
                                              bool update_popup,
                                              bool notify_text_changed) {
  SetWindowText(text.c_str());
  PlaceCaretAt(caret_pos);

  if (update_popup)
    UpdatePopup();

  if (notify_text_changed)
    TextChanged();
}

void OmniboxViewWin::SetForcedQuery() {
  const string16 current_text(GetText());
  const size_t start = current_text.find_first_not_of(kWhitespaceWide);
  if (start == string16::npos || (current_text[start] != '?'))
    OmniboxView::SetUserText(L"?");
  else
    SetSelection(current_text.length(), start + 1);
}

bool OmniboxViewWin::IsSelectAll() const {
  CHARRANGE selection;
  GetSel(selection);
  return IsSelectAllForRange(selection);
}

bool OmniboxViewWin::DeleteAtEndPressed() {
  return delete_at_end_pressed_;
}

void OmniboxViewWin::GetSelectionBounds(string16::size_type* start,
                                        string16::size_type* end) const {
  CHARRANGE selection;
  GetSel(selection);
  *start = static_cast<size_t>(selection.cpMin);
  *end = static_cast<size_t>(selection.cpMax);
}

void OmniboxViewWin::SelectAll(bool reversed) {
  if (reversed)
    SetSelection(GetTextLength(), 0);
  else
    SetSelection(0, GetTextLength());
}

void OmniboxViewWin::RevertAll() {
  ScopedFreeze freeze(this, GetTextObjectModel());
  saved_selection_for_focus_change_.cpMin = -1;
  OmniboxView::RevertAll();
}

void OmniboxViewWin::UpdatePopup() {
  ScopedFreeze freeze(this, GetTextObjectModel());
  model()->SetInputInProgress(true);

  // Don't allow the popup to open while the candidate window is open, so
  // they don't overlap.
  if (ime_candidate_window_open_)
    return;

  if (!model()->has_focus()) {
    // When we're in the midst of losing focus, don't rerun autocomplete.  This
    // can happen when losing focus causes the IME to cancel/finalize a
    // composition.  We still want to note that user input is in progress, we
    // just don't want to do anything else.
    //
    // Note that in this case the ScopedFreeze above was unnecessary; however,
    // we're inside the callstack of OnKillFocus(), which has already frozen the
    // edit, so this will never result in an unnecessary UpdateWindow() call.
    return;
  }

  // Don't inline autocomplete when:
  //   * The user is deleting text
  //   * The caret/selection isn't at the end of the text
  //   * The user has just pasted in something that replaced all the text
  //   * The user is trying to compose something in an IME
  CHARRANGE sel;
  GetSel(sel);
  model()->StartAutocomplete(sel.cpMax != sel.cpMin,
                            (sel.cpMax < GetTextLength()) || IsImeComposing());
}

void OmniboxViewWin::SetFocus() {
  ::SetFocus(m_hWnd);
  // Restore caret visibility if focus is explicitly requested. This is
  // necessary because if we already have invisible focus, the ::SetFocus()
  // call above will short-circuit, preventing us from reaching
  // OmniboxEditModel::OnSetFocus(), which handles restoring visibility when the
  // omnibox regains focus after losing focus.
  model()->SetCaretVisibility(true);
}

void OmniboxViewWin::ApplyCaretVisibility() {
  // We hide the caret just before destroying it, since destroying a caret that
  // is in the "solid" phase of its blinking will leave a solid vertical bar.
  // We even hide and destroy the caret if we're going to create it again below.
  // If the caret was already visible on entry to this function, the
  // CreateCaret() call (which first destroys the old caret) might leave a solid
  // vertical bar for the same reason as above.  Unconditionally hiding prevents
  // this.  The caret could be visible on entry to this function if the
  // underlying edit control had re-created it automatically (see comments in
  // OnPaint()).
  HideCaret();
  // We use DestroyCaret()/CreateCaret() instead of simply HideCaret()/
  // ShowCaret() because HideCaret() is not sticky across paint events, e.g. a
  // window resize will effectively restore caret visibility, regardless of
  // whether HideCaret() was called before. While we do catch and handle these
  // paint events (see OnPaint()), it doesn't seem to be enough to simply call
  // HideCaret() while handling them because of the unpredictability of this
  // Windows API. According to the documentation, it should be a cumulative call
  // e.g. 5 hide calls should be balanced by 5 show calls. We have not found
  // this to be true, which may be explained by the fact that this API is called
  // internally in Windows, as well.
  ::DestroyCaret();
  if (model()->is_caret_visible()) {
    ::CreateCaret(m_hWnd, (HBITMAP) NULL, 1, font_list_.GetHeight());
    // According to the Windows API documentation, a newly created caret needs
    // ShowCaret to be visible.
    ShowCaret();
  }
}

void OmniboxViewWin::SetDropHighlightPosition(int position) {
  if (drop_highlight_position_ != position) {
    RepaintDropHighlight(drop_highlight_position_);
    drop_highlight_position_ = position;
    RepaintDropHighlight(drop_highlight_position_);
  }
}

void OmniboxViewWin::MoveSelectedText(int new_position) {
  const string16 selected_text(GetSelectedText());
  CHARRANGE sel;
  GetSel(sel);
  DCHECK((sel.cpMax != sel.cpMin) && (new_position >= 0) &&
         (new_position <= GetTextLength()));

  ScopedFreeze freeze(this, GetTextObjectModel());
  OnBeforePossibleChange();

  // Nuke the selected text.
  ReplaceSel(L"", TRUE);

  // And insert it into the new location.
  if (new_position >= sel.cpMin)
    new_position -= (sel.cpMax - sel.cpMin);
  PlaceCaretAt(new_position);
  ReplaceSel(selected_text.c_str(), TRUE);

  OnAfterPossibleChange();
}

void OmniboxViewWin::InsertText(int position, const string16& text) {
  DCHECK((position >= 0) && (position <= GetTextLength()));
  ScopedFreeze freeze(this, GetTextObjectModel());
  OnBeforePossibleChange();
  SetSelection(position, position);
  ReplaceSel(text.c_str());
  OnAfterPossibleChange();
}

void OmniboxViewWin::OnTemporaryTextMaybeChanged(const string16& display_text,
                                                 bool save_original_selection,
                                                 bool notify_text_changed) {
  if (save_original_selection)
    GetSelection(original_selection_);

  // Set new text and cursor position.  Sometimes this does extra work (e.g.
  // when the new text and the old text are identical), but it's only called
  // when the user manually changes the selected line in the popup, so that's
  // not really a problem.  Also, even when the text hasn't changed we'd want to
  // update the caret, because if the user had the cursor in the middle of the
  // text and then arrowed to another entry with the same text, we'd still want
  // to move the caret.
  ScopedFreeze freeze(this, GetTextObjectModel());
  SetWindowTextAndCaretPos(display_text, display_text.length(), false,
                           notify_text_changed);
}

bool OmniboxViewWin::OnInlineAutocompleteTextMaybeChanged(
    const string16& display_text,
    size_t user_text_length) {
  // Update the text and selection.  Because this can be called repeatedly while
  // typing, we've careful not to freeze the edit unless we really need to.
  // Also, unlike in the temporary text case above, here we don't want to update
  // the caret/selection unless we have to, since this might make the user's
  // caret position change without warning during typing.
  if (display_text == GetText())
    return false;

  ScopedFreeze freeze(this, GetTextObjectModel());
  SetWindowText(display_text.c_str());
  // Set a reversed selection to keep the caret in the same position, which
  // avoids scrolling the user's text.
  SetSelection(static_cast<LONG>(display_text.length()),
               static_cast<LONG>(user_text_length));
  TextChanged();
  return true;
}

void OmniboxViewWin::OnRevertTemporaryText() {
  SetSelectionRange(original_selection_);
  // We got here because the user hit the Escape key. We explicitly don't call
  // TextChanged(), since OmniboxPopupModel::ResetToDefaultMatch() has already
  // been called by now, and it would've called TextChanged() if it was
  // warranted.
}

void OmniboxViewWin::OnBeforePossibleChange() {
  // Record our state.
  text_before_change_ = GetText();
  GetSelection(sel_before_change_);
}

bool OmniboxViewWin::OnAfterPossibleChange() {
  return OnAfterPossibleChangeInternal(false);
}

bool OmniboxViewWin::OnAfterPossibleChangeInternal(bool force_text_changed) {
  // Prevent the user from selecting the "phantom newline" at the end of the
  // edit.  If they try, we just silently move the end of the selection back to
  // the end of the real text.
  CHARRANGE new_sel;
  GetSelection(new_sel);
  const int length = GetTextLength();
  if ((new_sel.cpMin > length) || (new_sel.cpMax > length)) {
    if (new_sel.cpMin > length)
      new_sel.cpMin = length;
    if (new_sel.cpMax > length)
      new_sel.cpMax = length;
    SetSelectionRange(new_sel);
  }
  const bool selection_differs =
      ((new_sel.cpMin != new_sel.cpMax) ||
       (sel_before_change_.cpMin != sel_before_change_.cpMax)) &&
      ((new_sel.cpMin != sel_before_change_.cpMin) ||
       (new_sel.cpMax != sel_before_change_.cpMax));

  // See if the text or selection have changed since OnBeforePossibleChange().
  const string16 new_text(GetText());
  const bool text_differs = (new_text != text_before_change_) ||
      force_text_changed;

  // When the user has deleted text, we don't allow inline autocomplete.  Make
  // sure to not flag cases like selecting part of the text and then pasting
  // (or typing) the prefix of that selection.  (We detect these by making
  // sure the caret, which should be after any insertion, hasn't moved
  // forward of the old selection start.)
  const bool just_deleted_text =
      (text_before_change_.length() > new_text.length()) &&
      (new_sel.cpMin <= std::min(sel_before_change_.cpMin,
                                 sel_before_change_.cpMax));

  const bool something_changed = model()->OnAfterPossibleChange(
      text_before_change_, new_text, new_sel.cpMin, new_sel.cpMax,
      selection_differs, text_differs, just_deleted_text, !IsImeComposing());

  if (something_changed && text_differs)
    TextChanged();

  if (text_differs) {
    // Note that a TEXT_CHANGED event implies that the cursor/selection
    // probably changed too, so we don't need to send both.
    native_view_host_->NotifyAccessibilityEvent(
        ui::AccessibilityTypes::EVENT_TEXT_CHANGED, true);
  } else if (selection_differs) {
    // Notify assistive technology that the cursor or selection changed.
    native_view_host_->NotifyAccessibilityEvent(
        ui::AccessibilityTypes::EVENT_SELECTION_CHANGED, true);
  } else if (delete_at_end_pressed_) {
    model()->OnChanged();
  }

  return something_changed;
}

void OmniboxViewWin::OnCandidateWindowCountChanged(size_t window_count) {
  ime_candidate_window_open_ = (window_count != 0);
  if (ime_candidate_window_open_) {
    CloseOmniboxPopup();
  } else if (model()->user_input_in_progress()) {
    // UpdatePopup assumes user input is in progress, so only call it if
    // that's the case. Otherwise, autocomplete may run on an empty user
    // text.
    UpdatePopup();
  }
}

void OmniboxViewWin::OnTextUpdated(const gfx::Range& /*composition_range*/) {
  if (ignore_ime_messages_)
    return;
  OnAfterPossibleChangeInternal(true);
  // Call OnBeforePossibleChange function here to get correct diff in next IME
  // update. The Text Services Framework does not provide any notification
  // before entering edit session, therefore we don't have good place to call
  // OnBeforePossibleChange.
  OnBeforePossibleChange();
}

gfx::NativeView OmniboxViewWin::GetNativeView() const {
  return m_hWnd;
}

// static
gfx::NativeView OmniboxViewWin::GetRelativeWindowForNativeView(
    gfx::NativeView edit_native_view) {
  // When an IME is attached to the rich-edit control, retrieve its window
  // handle, and the popup window of OmniboxPopupView will be shown under the
  // IME windows.
  // Otherwise, the popup window will be shown under top-most windows.
  // TODO(hbono): http://b/1111369 if we exclude this popup window from the
  // display area of IME windows, this workaround becomes unnecessary.
  HWND ime_window = ImmGetDefaultIMEWnd(edit_native_view);
  return ime_window ? ime_window : HWND_NOTOPMOST;
}

gfx::NativeView OmniboxViewWin::GetRelativeWindowForPopup() const {
  return GetRelativeWindowForNativeView(GetNativeView());
}

void OmniboxViewWin::SetGrayTextAutocompletion(const string16& suggestion) {
  location_bar_->SetGrayTextAutocompletion(suggestion);
}

int OmniboxViewWin::TextWidth() const {
  return WidthNeededToDisplay(GetText());
}

string16 OmniboxViewWin::GetGrayTextAutocompletion() const {
  return location_bar_->GetGrayTextAutocompletion();
}

bool OmniboxViewWin::IsImeComposing() const {
  if (tsf_event_router_)
    return tsf_event_router_->IsImeComposing();
  bool ime_composing = false;
  HIMC context = ImmGetContext(m_hWnd);
  if (context) {
    ime_composing = !!ImmGetCompositionString(context, GCS_COMPSTR, NULL, 0);
    ImmReleaseContext(m_hWnd, context);
  }
  return ime_composing;
}

int OmniboxViewWin::GetMaxEditWidth(int entry_width) const {
  RECT formatting_rect;
  GetRect(&formatting_rect);
  RECT edit_bounds;
  GetClientRect(&edit_bounds);
  return entry_width - formatting_rect.left -
      (edit_bounds.right - formatting_rect.right);
}

views::View* OmniboxViewWin::AddToView(views::View* parent) {
  native_view_host_ = new OmniboxViewWrapper(this);
  parent->AddChildView(native_view_host_);
  native_view_host_->set_focus_view(parent);
  native_view_host_->Attach(GetNativeView());
  return native_view_host_;
}

int OmniboxViewWin::OnPerformDrop(const ui::DropTargetEvent& event) {
  return OnPerformDropImpl(event, false);
}

int OmniboxViewWin::OnPerformDropImpl(const ui::DropTargetEvent& event,
                                      bool in_drag) {
  const ui::OSExchangeData& data = event.data();

  if (data.HasURL()) {
    GURL url;
    string16 title;
    if (data.GetURLAndTitle(&url, &title)) {
      string16 text(StripJavascriptSchemas(UTF8ToUTF16(url.spec())));
      OmniboxView::SetUserText(text);
      model()->AcceptInput(CURRENT_TAB, true);
      return CopyOrLinkDragOperation(event.source_operations());
    }
  } else if (data.HasString()) {
    int string_drop_position = drop_highlight_position();
    string16 text;
    if ((string_drop_position != -1 || !in_drag) && data.GetString(&text)) {
      DCHECK(string_drop_position == -1 ||
             ((string_drop_position >= 0) &&
              (string_drop_position <= GetTextLength())));
      if (in_drag) {
        if (event.source_operations()== ui::DragDropTypes::DRAG_MOVE)
          MoveSelectedText(string_drop_position);
        else
          InsertText(string_drop_position, text);
      } else {
        string16 collapsed_text(CollapseWhitespace(text, true));
        if (model()->CanPasteAndGo(collapsed_text))
          model()->PasteAndGo(collapsed_text);
      }
      return CopyOrLinkDragOperation(event.source_operations());
    }
  }

  return ui::DragDropTypes::DRAG_NONE;
}

bool OmniboxViewWin::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
  // Skip processing of [Alt]+<num-pad digit> Unicode alt key codes.
  if (event.IsUnicodeKeyCode())
    return true;

  // Skip accelerators for key combinations omnibox wants to crack. This list
  // should be synced with OnKeyDownOnlyWritable() (but for tab which is dealt
  // with above in LocationBarView::SkipDefaultKeyEventProcessing).
  //
  // We cannot return true for all keys because we still need to handle some
  // accelerators (e.g., F5 for reload the page should work even when the
  // Omnibox gets focused).
  switch (event.key_code()) {
    case ui::VKEY_ESCAPE: {
      ScopedFreeze freeze(this, GetTextObjectModel());
      return model()->OnEscapeKeyPressed();
    }

    case ui::VKEY_RETURN:
      return true;

    case ui::VKEY_UP:
    case ui::VKEY_DOWN:
      return !event.IsAltDown();

    case ui::VKEY_DELETE:
    case ui::VKEY_INSERT:
      return !event.IsAltDown() && event.IsShiftDown() &&
          !event.IsControlDown();

    case ui::VKEY_X:
    case ui::VKEY_V:
      return !event.IsAltDown() && event.IsControlDown();

    case ui::VKEY_BACK:
      return true;

    default:
      return false;
  }
}

void OmniboxViewWin::HandleExternalMsg(UINT msg,
                                       UINT flags,
                                       const CPoint& screen_point) {
  if (msg == WM_CAPTURECHANGED) {
    SendMessage(msg, 0, NULL);
    return;
  }

  CPoint client_point(screen_point);
  ::MapWindowPoints(NULL, m_hWnd, &client_point, 1);
  SendMessage(msg, flags, MAKELPARAM(client_point.x, client_point.y));
}

bool OmniboxViewWin::IsCommandIdChecked(int command_id) const {
  return false;
}

bool OmniboxViewWin::IsCommandIdEnabled(int command_id) const {
  switch (command_id) {
    case IDS_UNDO:
      return !!CanUndo();
    case IDC_CUT:
      return !!CanCut();
    case IDC_COPY:
      return !!CanCopy();
    case IDC_PASTE:
      return !!CanPaste();
    case IDS_PASTE_AND_GO:
      return model()->CanPasteAndGo(GetClipboardText());
    case IDS_SELECT_ALL:
      return !!CanSelectAll();
    case IDS_SHOW_URL:
      return controller()->GetToolbarModel()->
          WouldPerformSearchTermReplacement(false);
    case IDC_EDIT_SEARCH_ENGINES:
      return command_updater()->IsCommandEnabled(command_id);
    default:
      NOTREACHED();
      return false;
  }
}

bool OmniboxViewWin::GetAcceleratorForCommandId(
    int command_id,
    ui::Accelerator* accelerator) {
  return location_bar_->GetWidget()->GetAccelerator(command_id, accelerator);
}

bool OmniboxViewWin::IsItemForCommandIdDynamic(int command_id) const {
  // No need to change the default IDS_PASTE_AND_GO label unless this is a
  // search.
  return command_id == IDS_PASTE_AND_GO;
}

string16 OmniboxViewWin::GetLabelForCommandId(int command_id) const {
  DCHECK_EQ(IDS_PASTE_AND_GO, command_id);
  return l10n_util::GetStringUTF16(
      model()->IsPasteAndSearch(GetClipboardText()) ?
      IDS_PASTE_AND_SEARCH : IDS_PASTE_AND_GO);
}

void OmniboxViewWin::ExecuteCommand(int command_id, int event_flags) {
  ScopedFreeze freeze(this, GetTextObjectModel());
  // These commands don't invoke the popup via OnBefore/AfterPossibleChange().
  if (command_id == IDC_COPY) {
    Copy();
    return;
  }
  if (command_id == IDS_PASTE_AND_GO) {
    model()->PasteAndGo(GetClipboardText());
    return;
  }
  if (command_id == IDS_SHOW_URL) {
    ShowURL();
    return;
  }
  if (command_id == IDC_EDIT_SEARCH_ENGINES) {
    command_updater()->ExecuteCommand(command_id);
    return;
  }

  OnBeforePossibleChange();
  switch (command_id) {
    case IDS_UNDO:
      Undo();
      break;

    case IDC_CUT:
      Cut();
      break;

    case IDC_PASTE:
      Paste();
      break;

    case IDS_SELECT_ALL:
      SelectAll(false);
      break;

    default:
      NOTREACHED();
      break;
  }
  OnAfterPossibleChange();
}

// static
int CALLBACK OmniboxViewWin::WordBreakProc(LPTSTR edit_text,
                                           int current_pos,
                                           int length,
                                           int action) {
  // TODO(pkasting): http://b/1111308 We should let other people, like ICU and
  // GURL, do the work for us here instead of writing all this ourselves.

  // With no clear guidance from the MSDN docs on how to handle "not found" in
  // the "find the nearest xxx..." cases below, I cap the return values at
  // [0, length].  Since one of these (0) is also a valid position, the return
  // values are thus ambiguous :(
  switch (action) {
    // Find nearest character before current position that begins a word.
    case WB_LEFT:
    case WB_MOVEWORDLEFT: {
      if (current_pos < 2) {
        // Either current_pos == 0, so we have a "not found" case and return 0,
        // or current_pos == 1, and the only character before this position is
        // at 0.
        return 0;
      }

      // Look for a delimiter before the previous character; the previous word
      // starts immediately after.  (If we looked for a delimiter before the
      // current character, we could stop on the immediate prior character,
      // which would mean we'd return current_pos -- which isn't "before the
      // current position".)
      const int prev_delim =
          WordBreakProc(edit_text, current_pos - 1, length, WB_LEFTBREAK);

      if ((prev_delim == 0) &&
          !WordBreakProc(edit_text, 0, length, WB_ISDELIMITER)) {
        // Got back 0, but position 0 isn't a delimiter.  This was a "not
        // found" 0, so return one of our own.
        return 0;
      }

      return prev_delim + 1;
    }

    // Find nearest character after current position that begins a word.
    case WB_RIGHT:
    case WB_MOVEWORDRIGHT: {
      if (WordBreakProc(edit_text, current_pos, length, WB_ISDELIMITER)) {
        // The current character is a delimiter, so the next character starts
        // a new word.  Done.
        return current_pos + 1;
      }

      // Look for a delimiter after the current character; the next word starts
      // immediately after.
      const int next_delim =
          WordBreakProc(edit_text, current_pos, length, WB_RIGHTBREAK);
      if (next_delim == length) {
        // Didn't find a delimiter.  Return length to signal "not found".
        return length;
      }

      return next_delim + 1;
    }

    // Determine if the current character delimits words.
    case WB_ISDELIMITER:
      return !!(WordBreakProc(edit_text, current_pos, length, WB_CLASSIFY) &
                WBF_BREAKLINE);

    // Return the classification of the current character.
    case WB_CLASSIFY:
      if (IsWhitespace(edit_text[current_pos])) {
        // Whitespace normally breaks words, but the MSDN docs say that we must
        // not break on the CRs in a "CR, LF" or a "CR, CR, LF" sequence.  Just
        // check for an arbitrarily long sequence of CRs followed by LF and
        // report "not a delimiter" for the current CR in that case.
        while ((current_pos < (length - 1)) &&
               (edit_text[current_pos] == 0x13)) {
          if (edit_text[++current_pos] == 0x10)
            return WBF_ISWHITE;
        }
        return WBF_BREAKLINE | WBF_ISWHITE;
      }

      // Punctuation normally breaks words, but the first two characters in
      // "://" (end of scheme) should not be breaks, so that "http://" will be
      // treated as one word.
      if (ispunct(edit_text[current_pos], std::locale()) &&
          !SchemeEnd(edit_text, current_pos, length) &&
          !SchemeEnd(edit_text, current_pos - 1, length))
        return WBF_BREAKLINE;

      // Normal character, no flags.
      return 0;

    // Finds nearest delimiter before current position.
    case WB_LEFTBREAK:
      for (int i = current_pos - 1; i >= 0; --i) {
        if (WordBreakProc(edit_text, i, length, WB_ISDELIMITER))
          return i;
      }
      return 0;

    // Finds nearest delimiter after current position.
    case WB_RIGHTBREAK:
      for (int i = current_pos + 1; i < length; ++i) {
        if (WordBreakProc(edit_text, i, length, WB_ISDELIMITER))
          return i;
      }
      return length;
  }

  NOTREACHED();
  return 0;
}

// static
bool OmniboxViewWin::SchemeEnd(LPTSTR edit_text,
                               int current_pos,
                               int length) {
  return (current_pos >= 0) &&
         ((length - current_pos) > 2) &&
         (edit_text[current_pos] == ':') &&
         (edit_text[current_pos + 1] == '/') &&
         (edit_text[current_pos + 2] == '/');
}

void OmniboxViewWin::OnChar(TCHAR ch, UINT repeat_count, UINT flags) {
  // Don't let alt-enter beep.  Not sure this is necessary, as the standard
  // alt-enter will hit DiscardWMSysChar() and get thrown away, and
  // ctrl-alt-enter doesn't seem to reach here for some reason?  At least not on
  // my system... still, this is harmless and maybe necessary in other locales.
  if (ch == VK_RETURN && (flags & KF_ALTDOWN))
    return;

  // Escape is processed in OnKeyDown.  Don't let any WM_CHAR messages propagate
  // as we don't want the RichEdit to do anything funky.
  if (ch == VK_ESCAPE && !(flags & KF_ALTDOWN))
    return;

  if (ch == VK_TAB) {
    // Don't add tabs to the input.
    return;
  }

  HandleKeystroke(GetCurrentMessage()->message, ch, repeat_count, flags);
}

void OmniboxViewWin::OnContextMenu(HWND window, const CPoint& point) {
  BuildContextMenu();

  context_menu_runner_.reset(
      new views::MenuRunner(context_menu_contents_.get()));

  gfx::Point location(point);
  if (point.x == -1 || point.y == -1) {
    POINT p;
    GetCaretPos(&p);
    MapWindowPoints(HWND_DESKTOP, &p, 1);
    location.SetPoint(p.x, p.y);
  }

  ignore_result(context_menu_runner_->RunMenuAt(native_view_host_->GetWidget(),
      NULL, gfx::Rect(location, gfx::Size()), views::MenuItemView::TOPLEFT,
      ui::MENU_SOURCE_MOUSE, views::MenuRunner::HAS_MNEMONICS));
}

void OmniboxViewWin::OnCopy() {
  string16 text(GetSelectedText());
  if (text.empty())
    return;

  CHARRANGE sel;
  GURL url;
  bool write_url = false;
  GetSel(sel);
  // GetSel() doesn't preserve selection direction, so sel.cpMin will always be
  // the smaller value.
  model()->AdjustTextForCopy(sel.cpMin, IsSelectAll(), &text, &url, &write_url);
  if (write_url) {
    BookmarkNodeData data;
    data.ReadFromTuple(url, text);
    data.WriteToClipboard(ui::CLIPBOARD_TYPE_COPY_PASTE);
  } else {
    ui::ScopedClipboardWriter scw(ui::Clipboard::GetForCurrentThread(),
                                  ui::CLIPBOARD_TYPE_COPY_PASTE);
    scw.WriteText(text);
  }
}

LRESULT OmniboxViewWin::OnCreate(const CREATESTRUCTW* /*create_struct*/) {
  if (base::win::IsTSFAwareRequired()) {
    // Enable TSF support of RichEdit.
    SetEditStyle(SES_USECTF, SES_USECTF);
  }
  if ((base::win::GetVersion() >= base::win::VERSION_WIN8) &&
      ui::AreTouchEventsEnabled()) {
    BOOL touch_mode = RegisterTouchWindow(m_hWnd, TWF_WANTPALM);
    DCHECK(touch_mode);
  }
  SetMsgHandled(FALSE);

  // When TSF is enabled, OnTextUpdated() may be called without any previous
  // call that would have indicated the start of an editing session.  In order
  // to guarantee we've always called OnBeforePossibleChange() before
  // OnAfterPossibleChange(), we therefore call that here.  Note that multiple
  // (i.e. unmatched) calls to this function in a row are safe.
  if (base::win::IsTSFAwareRequired())
    OnBeforePossibleChange();
  return 0;
}

void OmniboxViewWin::OnCut() {
  OnCopy();

  // This replace selection will have no effect (even on the undo stack) if the
  // current selection is empty.
  ReplaceSel(L"", true);
}

LRESULT OmniboxViewWin::OnGetObject(UINT message,
                                    WPARAM wparam,
                                    LPARAM lparam) {
  // This is a request for the native accessibility object.
  if (lparam == OBJID_CLIENT) {
    return LresultFromObject(IID_IAccessible, wparam,
                             native_view_host_->GetNativeViewAccessible());
  }
  return 0;
}

LRESULT OmniboxViewWin::OnImeComposition(UINT message,
                                         WPARAM wparam,
                                         LPARAM lparam) {
  if (ignore_ime_messages_) {
    // This message was sent while we're in the middle of meddling with the
    // underlying edit control.  If we handle it below, OnAfterPossibleChange()
    // can get bogus text for the edit, and rerun autocomplete, destructively
    // modifying the result set that we're in the midst of using.  For example,
    // if SetWindowTextAndCaretPos() was called due to the user clicking an
    // entry in the popup, we're in the middle of executing SetSelectedLine(),
    // and changing the results can cause checkfailures.
    return DefWindowProc(message, wparam, lparam);
  }

  ScopedFreeze freeze(this, GetTextObjectModel());
  OnBeforePossibleChange();
  LRESULT result = DefWindowProc(message, wparam, lparam);
  // Force an IME composition confirmation operation to trigger the text_changed
  // code in OnAfterPossibleChange(), even if identical contents are confirmed,
  // to make sure the model can update its internal states correctly.
  OnAfterPossibleChangeInternal((lparam & GCS_RESULTSTR) != 0);
  return result;
}

LRESULT OmniboxViewWin::OnImeEndComposition(UINT message, WPARAM wparam,
                                            LPARAM lparam) {
  // The edit control auto-clears the selection on WM_IME_ENDCOMPOSITION, which
  // means any inline autocompletion we were showing will no longer be
  // selected, and therefore no longer replaced by further user typing.  To
  // avoid this we manually restore the original selection after the edit
  // handles the message.
  CHARRANGE range;
  GetSel(range);
  LRESULT result = DefWindowProc(message, wparam, lparam);
  SetSel(range);
  return result;
}

LRESULT OmniboxViewWin::OnImeNotify(UINT message,
                                    WPARAM wparam,
                                    LPARAM lparam) {
  // Close the popup when the IME composition window is open, so they don't
  // overlap.
  switch (wparam) {
    case IMN_OPENCANDIDATE:
      ime_candidate_window_open_ = true;
      CloseOmniboxPopup();
      break;
    case IMN_CLOSECANDIDATE:
      ime_candidate_window_open_ = false;

      // UpdatePopup assumes user input is in progress, so only call it if
      // that's the case. Otherwise, autocomplete may run on an empty user
      // text. For example, Baidu Japanese IME sends IMN_CLOSECANDIDATE when
      // composition mode is entered, but the user may not have input anything
      // yet.
      if (model()->user_input_in_progress())
        UpdatePopup();

      break;
    default:
      break;
  }
  return DefWindowProc(message, wparam, lparam);
}

LRESULT OmniboxViewWin::OnTouchEvent(UINT message,
                                     WPARAM wparam,
                                     LPARAM lparam) {
  // There is a bug in Windows 8 where in the generated mouse messages
  // after touch go to the window which previously had focus. This means that
  // if a user taps the omnibox to give it focus, we don't get the simulated
  // WM_LBUTTONDOWN, and thus don't properly select all the text. To ensure
  // that we get this message, we capture the mouse when the user is doing a
  // single-point tap on an unfocused model.
  if ((wparam == 1) && !model()->has_focus()) {
    TOUCHINPUT point = {0};
    if (ui::GetTouchInputInfoWrapper(reinterpret_cast<HTOUCHINPUT>(lparam), 1,
                                     &point, sizeof(TOUCHINPUT))) {
      if (point.dwFlags & TOUCHEVENTF_DOWN)
        SetCapture();
      else if (point.dwFlags & TOUCHEVENTF_UP)
        ReleaseCapture();
    }
  }
  SetMsgHandled(false);
  return 0;
}

void OmniboxViewWin::OnKeyDown(TCHAR key,
                               UINT repeat_count,
                               UINT flags) {
  delete_at_end_pressed_ = false;

  if (OnKeyDownAllModes(key, repeat_count, flags))
    return;

  // Make sure that we handle system key events like Alt-F4.
  if (popup_window_mode_) {
    DefWindowProc(GetCurrentMessage()->message, key, MAKELPARAM(repeat_count,
                                                                flags));
    return;
  }

  if (OnKeyDownOnlyWritable(key, repeat_count, flags))
    return;

  // CRichEditCtrl changes its text on WM_KEYDOWN instead of WM_CHAR for many
  // different keys (backspace, ctrl-v, ...), so we call this in both cases.
  HandleKeystroke(GetCurrentMessage()->message, key, repeat_count, flags);
}

void OmniboxViewWin::OnKeyUp(TCHAR key,
                             UINT repeat_count,
                             UINT flags) {
  if (key == VK_CONTROL)
    model()->OnControlKeyChanged(false);

  // On systems with RTL input languages, ctrl+shift toggles the reading order
  // (depending on which shift key is pressed). But by default the CRichEditCtrl
  // only changes the current reading order, and as soon as the user deletes all
  // the text, or we call SetWindowText(), it reverts to the "default" order.
  // To work around this, if the user hits ctrl+shift, we pass it to
  // DefWindowProc() while the edit is empty, which toggles the default reading
  // order; then we restore the user's input.
  if (!(flags & KF_ALTDOWN) &&
      (((key == VK_CONTROL) && (GetKeyState(VK_SHIFT) < 0)) ||
       ((key == VK_SHIFT) && (GetKeyState(VK_CONTROL) < 0)))) {
    ScopedFreeze freeze(this, GetTextObjectModel());

    string16 saved_text(GetText());
    CHARRANGE saved_sel;
    GetSelection(saved_sel);

    SetWindowText(L"");

    DefWindowProc(WM_KEYUP, key, MAKELPARAM(repeat_count, flags));

    SetWindowText(saved_text.c_str());
    SetSelectionRange(saved_sel);
    return;
  }

  SetMsgHandled(false);
}

void OmniboxViewWin::OnKillFocus(HWND focus_wnd) {
  if (m_hWnd == focus_wnd) {
    // Focus isn't actually leaving.
    SetMsgHandled(false);
    return;
  }

  // This must be invoked before ClosePopup.
  model()->OnWillKillFocus(focus_wnd);

  // Close the popup.
  CloseOmniboxPopup();

  // Save the user's existing selection to restore it later.
  GetSelection(saved_selection_for_focus_change_);

  // Tell the model to reset itself.
  model()->OnKillFocus();

  // Let the CRichEditCtrl do its default handling.  This will complete any
  // in-progress IME composition.  We must do this after setting has_focus_ to
  // false so that UpdatePopup() will know not to rerun autocomplete.
  ScopedFreeze freeze(this, GetTextObjectModel());
  DefWindowProc(WM_KILLFOCUS, reinterpret_cast<WPARAM>(focus_wnd), 0);

  // Cancel any user selection and scroll the text back to the beginning of the
  // URL.  We have to do this after calling DefWindowProc() because otherwise
  // an in-progress IME composition will be completed at the new caret position,
  // resulting in the string jumping unexpectedly to the front of the edit.
  //
  // Crazy hack: If we just do PlaceCaretAt(0), and the beginning of the text is
  // currently scrolled out of view, we can wind up with a blinking cursor in
  // the toolbar at the current X coordinate of the beginning of the text.  By
  // first doing a reverse-select-all to scroll the beginning of the text into
  // view, we work around this CRichEditCtrl bug.
  SelectAll(true);
  PlaceCaretAt(0);

  if (tsf_event_router_)
    tsf_event_router_->SetManager(NULL);
}

void OmniboxViewWin::OnLButtonDblClk(UINT keys, const CPoint& point) {
  // Save the double click info for later triple-click detection.
  tracking_double_click_ = true;
  double_click_point_ = point;
  double_click_time_ = GetCurrentMessage()->time;
  possible_drag_ = false;

  // Modifying the selection counts as accepting any inline autocompletion, so
  // track "changes" made by clicking the mouse button.
  ScopedFreeze freeze(this, GetTextObjectModel());
  OnBeforePossibleChange();

  DefWindowProc(WM_LBUTTONDBLCLK, keys,
                MAKELPARAM(ClipXCoordToVisibleText(point.x, false), point.y));

  // Rich Edit 4.1 doesn't select the last word when the user double clicks
  // past the text. Do it manually.
  CHARRANGE selection;
  GetSelection(selection);
  // The default window proc for Rich Edit 4.1 seems to select the CHARRANGE
  // {text_length, text_length + 1} after a double click past the text.
  int length = GetTextLength();
  if (selection.cpMin == length && selection.cpMax == length + 1) {
    string16 text = GetText();
    int word_break = WordBreakProc(&text[0], length, length, WB_LEFT);
    selection.cpMin = word_break;
    selection.cpMax = length;
    SetSelectionRange(selection);
  }

  OnAfterPossibleChange();

  gaining_focus_.reset();  // See NOTE in OnMouseActivate().
}

void OmniboxViewWin::OnLButtonDown(UINT keys, const CPoint& point) {
  TrackMousePosition(kLeft, point);
  if (gaining_focus_.get()) {
    // When Chrome was already the activated app, we haven't reached
    // OnSetFocus() yet.  When we get there, don't restore the saved selection,
    // since it will just screw up the user's interaction with the edit.
    saved_selection_for_focus_change_.cpMin = -1;

    // Crazy hack: In this particular case, the CRichEditCtrl seems to have an
    // internal flag that discards the next WM_LBUTTONDOWN without processing
    // it, so that clicks on the edit when its owning app is not activated are
    // eaten rather than processed (despite whatever the return value of
    // DefWindowProc(WM_MOUSEACTIVATE, ...) may say).  This behavior is
    // confusing and we want the click to be treated normally.  So, to reset the
    // CRichEditCtrl's internal flag, we pass it an extra WM_LBUTTONDOWN here
    // (as well as a matching WM_LBUTTONUP, just in case we'd be confusing some
    // kind of state tracking otherwise).
    DefWindowProc(WM_LBUTTONDOWN, keys, MAKELPARAM(point.x, point.y));
    DefWindowProc(WM_LBUTTONUP, keys, MAKELPARAM(point.x, point.y));
  }

  // Check for triple click, then reset tracker.  Should be safe to subtract
  // double_click_time_ from the current message's time even if the timer has
  // wrapped in between.
  const bool is_triple_click = tracking_double_click_ &&
      views::NativeTextfieldWin::IsDoubleClick(double_click_point_, point,
          GetCurrentMessage()->time - double_click_time_);
  tracking_double_click_ = false;

  if (!gaining_focus_.get() && !is_triple_click)
    OnPossibleDrag(point);

  // Modifying the selection counts as accepting any inline autocompletion, so
  // track "changes" made by clicking the mouse button.
  ScopedFreeze freeze(this, GetTextObjectModel());
  OnBeforePossibleChange();
  DefWindowProc(WM_LBUTTONDOWN, keys,
                MAKELPARAM(ClipXCoordToVisibleText(point.x, is_triple_click),
                           point.y));
  OnAfterPossibleChange();

  gaining_focus_.reset();
}

void OmniboxViewWin::OnLButtonUp(UINT keys, const CPoint& point) {
  // default processing should happen first so we can see the result of the
  // selection
  ScopedFreeze freeze(this, GetTextObjectModel());
  DefWindowProc(WM_LBUTTONUP, keys,
                MAKELPARAM(ClipXCoordToVisibleText(point.x, false), point.y));

  SelectAllIfNecessary(kLeft, point);

  tracking_click_[kLeft] = false;

  possible_drag_ = false;
}

void OmniboxViewWin::OnMButtonDblClk(UINT /*keys*/, const CPoint& /*point*/) {
  gaining_focus_.reset();  // See NOTE in OnMouseActivate().

  // By default, the edit responds to middle-clicks by capturing the mouse and
  // ignoring all subsequent events until it receives another click (of any of
  // the left, middle, or right buttons).  This bizarre behavior is not only
  // useless but can cause the UI to appear unresponsive if a user accidentally
  // middle-clicks the edit (instead of a tab above it), so we purposefully eat
  // this message (instead of calling SetMsgHandled(false)) to avoid triggering
  // this.
}

void OmniboxViewWin::OnMButtonDown(UINT /*keys*/, const CPoint& /*point*/) {
  tracking_double_click_ = false;

  // See note in OnMButtonDblClk above.
}

void OmniboxViewWin::OnMButtonUp(UINT /*keys*/, const CPoint& /*point*/) {
  possible_drag_ = false;

  // See note in OnMButtonDblClk above.
}

LRESULT OmniboxViewWin::OnMouseActivate(HWND window,
                                        UINT hit_test,
                                        UINT mouse_message) {
  // First, give other handlers a chance to handle the message to see if we are
  // actually going to activate and gain focus.
  LRESULT result = DefWindowProc(WM_MOUSEACTIVATE,
                                 reinterpret_cast<WPARAM>(window),
                                 MAKELPARAM(hit_test, mouse_message));
  // Check if we're getting focus from a click.  We have to do this here rather
  // than in OnXButtonDown() since in many scenarios OnSetFocus() will be
  // reached before OnXButtonDown(), preventing us from detecting this properly
  // there.  Also in those cases, we need to already know in OnSetFocus() that
  // we should not restore the saved selection.
  if ((!model()->has_focus() ||
       (model()->focus_state() == OMNIBOX_FOCUS_INVISIBLE)) &&
      ((mouse_message == WM_LBUTTONDOWN || mouse_message == WM_RBUTTONDOWN)) &&
      (result == MA_ACTIVATE)) {
    if (gaining_focus_) {
      // On Windows 8 in metro mode, we get two WM_MOUSEACTIVATE messages when
      // we click on the omnibox with the mouse.
      DCHECK(win8::IsSingleWindowMetroMode());
      return result;
    }
    gaining_focus_.reset(new ScopedFreeze(this, GetTextObjectModel()));

    // Restore caret visibility whenever the user clicks in the omnibox in a
    // way that would give it focus.  We must handle this case separately here
    // because if the omnibox currently has invisible focus, the mouse event
    // won't trigger either SetFocus() or OmniboxEditModel::OnSetFocus().
    model()->SetCaretVisibility(true);

    // NOTE: Despite |mouse_message| being WM_XBUTTONDOWN here, we're not
    // guaranteed to call OnXButtonDown() later!  Specifically, if this is the
    // second click of a double click, we'll reach here but later call
    // OnXButtonDblClk().  Make sure |gaining_focus_| gets reset both places,
    // or we'll have visual glitchiness and then DCHECK failures.

    // Don't restore saved selection, it will just screw up our interaction
    // with this edit.
    saved_selection_for_focus_change_.cpMin = -1;
  }
  return result;
}

void OmniboxViewWin::OnMouseMove(UINT keys, const CPoint& point) {
  if (possible_drag_) {
    StartDragIfNecessary(point);
    // Don't fall through to default mouse handling, otherwise a second
    // drag session may start.
    return;
  }

  if (tracking_click_[kLeft] && !IsDrag(click_point_[kLeft], point))
    return;

  tracking_click_[kLeft] = false;

  // Return quickly if this can't change the selection/cursor, so we don't
  // create a ScopedFreeze (and thus do an UpdateWindow()) on every
  // WM_MOUSEMOVE.
  if (!(keys & MK_LBUTTON)) {
    DefWindowProc(WM_MOUSEMOVE, keys, MAKELPARAM(point.x, point.y));
    return;
  }

  // Clamp the selection to the visible text so the user can't drag to select
  // the "phantom newline".  In theory we could achieve this by clipping the X
  // coordinate, but in practice the edit seems to behave nondeterministically
  // with similar sequences of clipped input coordinates fed to it.  Maybe it's
  // reading the mouse cursor position directly?
  //
  // This solution has a minor visual flaw, however: if there's a visible cursor
  // at the edge of the text (only true when there's no selection), dragging the
  // mouse around outside that edge repaints the cursor on every WM_MOUSEMOVE
  // instead of allowing it to blink normally.  To fix this, we special-case
  // this exact case and discard the WM_MOUSEMOVE messages instead of passing
  // them along.
  //
  // But even this solution has a flaw!  (Argh.)  In the case where the user has
  // a selection that starts at the edge of the edit, and proceeds to the middle
  // of the edit, and the user is dragging back past the start edge to remove
  // the selection, there's a redraw problem where the change between having the
  // last few bits of text still selected and having nothing selected can be
  // slow to repaint (which feels noticeably strange).  This occurs if you only
  // let the edit receive a single WM_MOUSEMOVE past the edge of the text.  I
  // think on each WM_MOUSEMOVE the edit is repainting its previous state, then
  // updating its internal variables to the new state but not repainting.  To
  // fix this, we allow one more WM_MOUSEMOVE through after the selection has
  // supposedly been shrunk to nothing; this makes the edit redraw the selection
  // quickly so it feels smooth.
  CHARRANGE selection;
  GetSel(selection);
  const bool possibly_can_discard_mousemove =
      (selection.cpMin == selection.cpMax) &&
      (((selection.cpMin == 0) &&
        (ClipXCoordToVisibleText(point.x, false) > point.x)) ||
       ((selection.cpMin == GetTextLength()) &&
        (ClipXCoordToVisibleText(point.x, false) < point.x)));
  if (!can_discard_mousemove_ || !possibly_can_discard_mousemove) {
    can_discard_mousemove_ = possibly_can_discard_mousemove;
    ScopedFreeze freeze(this, GetTextObjectModel());
    OnBeforePossibleChange();
    // Force the Y coordinate to the center of the clip rect.  The edit
    // behaves strangely when the cursor is dragged vertically: if the cursor
    // is in the middle of the text, drags inside the clip rect do nothing,
    // and drags outside the clip rect act as if the cursor jumped to the
    // left edge of the text.  When the cursor is at the right edge, drags of
    // just a few pixels vertically end up selecting the "phantom newline"...
    // sometimes.
    RECT r;
    GetRect(&r);
    DefWindowProc(WM_MOUSEMOVE, keys,
                  MAKELPARAM(point.x, (r.bottom - r.top) / 2));
    OnAfterPossibleChange();
  }
}

void OmniboxViewWin::OnPaint(HDC bogus_hdc) {
  // We need to paint over the top of the edit.  If we simply let the edit do
  // its default painting, then do ours into the window DC, the screen is
  // updated in between and we can get flicker.  To avoid this, we force the
  // edit to paint into a memory DC, which we also paint onto, then blit the
  // whole thing to the screen.

  // Don't paint if not necessary.
  CRect paint_clip_rect;
  if (!GetUpdateRect(&paint_clip_rect, true))
    return;

  // Begin painting, and create a memory DC for the edit to paint into.
  CPaintDC paint_dc(m_hWnd);
  CDC memory_dc(CreateCompatibleDC(paint_dc));
  CRect rect;
  GetClientRect(&rect);
  // NOTE: This next call uses |paint_dc| instead of |memory_dc| because
  // |memory_dc| contains a 1x1 monochrome bitmap by default, which will cause
  // |memory_bitmap| to be monochrome, which isn't what we want.
  CBitmap memory_bitmap(CreateCompatibleBitmap(paint_dc, rect.Width(),
                                               rect.Height()));
  HBITMAP old_bitmap = memory_dc.SelectBitmap(memory_bitmap);

  // Tell our intercept functions to supply our memory DC to the edit when it
  // tries to call BeginPaint().
  //
  // The sane way to do this would be to use WM_PRINTCLIENT to ask the edit to
  // paint into our desired DC.  Unfortunately, the Rich Edit 3.0 that ships
  // with Windows 2000/XP/Vista doesn't handle WM_PRINTCLIENT correctly; it
  // treats it just like WM_PAINT and calls BeginPaint(), ignoring our provided
  // DC.  The Rich Edit 6.0 that ships with Office 2007 handles this better, but
  // has other issues, and we can't redistribute that DLL anyway.  So instead,
  // we use this scary hack.
  //
  // NOTE: It's possible to get nested paint calls (!) (try setting the
  // permanent URL to something longer than the edit width, then selecting the
  // contents of the edit, typing a character, and hitting <esc>), so we can't
  // DCHECK(!edit_hwnd_) here.  Instead, just save off the old HWND, which most
  // of the time will be NULL.
  HWND old_edit_hwnd = edit_hwnd;
  edit_hwnd = m_hWnd;
  paint_struct = paint_dc.m_ps;
  paint_struct.hdc = memory_dc;
  DefWindowProc(WM_PAINT, reinterpret_cast<WPARAM>(bogus_hdc), 0);

  // Make the selection look better.
  EraseTopOfSelection(&memory_dc, rect, paint_clip_rect);

  // Draw a slash through the scheme if this is insecure.
  if (insecure_scheme_component_.is_nonempty())
    DrawSlashForInsecureScheme(memory_dc, rect, paint_clip_rect);

  // Draw the drop highlight.
  if (drop_highlight_position_ != -1)
    DrawDropHighlight(memory_dc, rect, paint_clip_rect);

  // Blit the memory DC to the actual paint DC and clean up.
  BitBlt(paint_dc, rect.left, rect.top, rect.Width(), rect.Height(), memory_dc,
         rect.left, rect.top, SRCCOPY);
  memory_dc.SelectBitmap(old_bitmap);
  edit_hwnd = old_edit_hwnd;

  // If textfield has focus, reaffirm its caret visibility (without focus, a new
  // caret could be created and confuse the user as to where the focus is). This
  // needs to be called regardless of the current visibility of the caret. This
  // is because the underlying edit control will automatically re-create the
  // caret when it receives certain events that trigger repaints, e.g. window
  // resize events. This also checks for the existence of selected text, in
  // which case there shouldn't be a recreated caret since this would create
  // both a highlight and a blinking caret.
  if (model()->has_focus()) {
    CHARRANGE sel;
    GetSel(sel);
    if (sel.cpMin == sel.cpMax)
      ApplyCaretVisibility();
  }
}

void OmniboxViewWin::OnPaste() {
  // Replace the selection if we have something to paste.
  const string16 text(GetClipboardText());
  if (!text.empty()) {
    // Record this paste, so we can do different behavior.
    model()->on_paste();
    // Force a Paste operation to trigger the text_changed code in
    // OnAfterPossibleChange(), even if identical contents are pasted into the
    // text box.
    text_before_change_.clear();
    ReplaceSel(text.c_str(), true);
  }
}

void OmniboxViewWin::OnRButtonDblClk(UINT /*keys*/, const CPoint& /*point*/) {
  gaining_focus_.reset();  // See NOTE in OnMouseActivate().
  SetMsgHandled(false);
}

void OmniboxViewWin::OnRButtonDown(UINT /*keys*/, const CPoint& point) {
  TrackMousePosition(kRight, point);
  tracking_double_click_ = false;
  possible_drag_ = false;
  gaining_focus_.reset();
  SetMsgHandled(false);
}

void OmniboxViewWin::OnRButtonUp(UINT /*keys*/, const CPoint& point) {
  SelectAllIfNecessary(kRight, point);
  tracking_click_[kRight] = false;
  SetMsgHandled(false);
}

void OmniboxViewWin::OnSetFocus(HWND focus_wnd) {
  views::FocusManager* focus_manager = location_bar_->GetFocusManager();
  if (focus_manager) {
    // Notify the FocusManager that the focused view is now the location bar
    // (our parent view).
    focus_manager->SetFocusedView(location_bar_);
  } else {
    NOTREACHED();
  }

  model()->OnSetFocus(GetKeyState(VK_CONTROL) < 0);

  // Restore saved selection if available.
  if (saved_selection_for_focus_change_.cpMin != -1) {
    SetSelectionRange(saved_selection_for_focus_change_);
    saved_selection_for_focus_change_.cpMin = -1;
  }

  if (!tsf_event_router_) {
    SetMsgHandled(false);
  } else {
    DefWindowProc();
    // Document manager created by RichEdit can be obtained only after
    // WM_SETFOCUS event is handled.
    tsf_event_router_->SetManager(
        ui::TSFBridge::GetInstance()->GetThreadManager());
    SetMsgHandled(true);
  }
}

LRESULT OmniboxViewWin::OnSetText(const wchar_t* text) {
  // Ignore all IME messages while we process this WM_SETTEXT message.
  // When SetWindowText() is called while an IME is composing text, the IME
  // calls SendMessage() to send a WM_IME_COMPOSITION message. When we receive
  // this WM_IME_COMPOSITION message, we update the omnibox and may call
  // SetWindowText() again. To stop this recursive message-handler call, we
  // stop updating the omnibox while we process a WM_SETTEXT message.
  // We wouldn't need to do this update anyway, because either we're in the
  // middle of updating the omnibox already or the caller of SetWindowText()
  // is going to update the omnibox next.
  base::AutoReset<bool> auto_reset_ignore_ime_messages(
      &ignore_ime_messages_, true);
  return DefWindowProc(WM_SETTEXT, 0, reinterpret_cast<LPARAM>(text));
}

void OmniboxViewWin::OnSysChar(TCHAR ch,
                               UINT repeat_count,
                               UINT flags) {
  DCHECK(flags & KF_ALTDOWN);
  // Explicitly show the system menu at a good location on [Alt]+[Space].
  // Nearly all other [Alt]+<xxx> combos result in beeping rather than doing
  // something useful, so discard those. Note that [Ctrl]+[Alt]+<xxx> generates
  // WM_CHAR instead of WM_SYSCHAR, so it is not handled here.
  if (ch == VK_SPACE) {
    gfx::ShowSystemMenu(
      native_view_host_->GetWidget()->GetTopLevelWidget()->GetNativeWindow());
  }
}

void OmniboxViewWin::OnWindowPosChanging(WINDOWPOS* window_pos) {
  if (force_hidden_)
    window_pos->flags &= ~SWP_SHOWWINDOW;
  SetMsgHandled(true);
}

BOOL OmniboxViewWin::OnMouseWheel(UINT flags, short delta, CPoint point) {
  // Forward the mouse-wheel message to the window under the mouse.
  if (!ui::RerouteMouseWheel(m_hWnd, MAKEWPARAM(flags, delta),
                             MAKELPARAM(point.x, point.y)))
    SetMsgHandled(false);
  return 0;
}

void OmniboxViewWin::HandleKeystroke(UINT message,
                                     TCHAR key,
                                     UINT repeat_count,
                                     UINT flags) {
  ScopedFreeze freeze(this, GetTextObjectModel());
  OnBeforePossibleChange();

  if (key == ui::VKEY_HOME || key == ui::VKEY_END) {
    // DefWindowProc() might reset the keyboard layout when it receives a
    // keydown event for VKEY_HOME or VKEY_END. When the window was created
    // with WS_EX_LAYOUTRTL and the current keyboard layout is not a RTL one,
    // if the input text is pure LTR text, the layout changes to the first RTL
    // keyboard layout in keyboard layout queue; if the input text is
    // bidirectional text, the layout changes to the keyboard layout of the
    // first RTL character in input text. When the window was created without
    // WS_EX_LAYOUTRTL and the current keyboard layout is not a LTR one, if the
    // input text is pure RTL text, the layout changes to English; if the input
    // text is bidirectional text, the layout changes to the keyboard layout of
    // the first LTR character in input text. Such keyboard layout change
    // behavior is surprising and inconsistent with keyboard behavior
    // elsewhere, so reset the layout in this case.
    HKL layout = GetKeyboardLayout(0);
    DefWindowProc(message, key, MAKELPARAM(repeat_count, flags));
    ActivateKeyboardLayout(layout, KLF_REORDER);
  } else {
    DefWindowProc(message, key, MAKELPARAM(repeat_count, flags));
  }

  // CRichEditCtrl automatically turns on IMF_AUTOKEYBOARD when the user
  // inputs an RTL character, making it difficult for the user to control
  // what language is set as they type. Force this off to make the edit's
  // behavior more stable.
  const int lang_options = SendMessage(EM_GETLANGOPTIONS, 0, 0);
  if (lang_options & IMF_AUTOKEYBOARD)
    SendMessage(EM_SETLANGOPTIONS, 0, lang_options & ~IMF_AUTOKEYBOARD);

  OnAfterPossibleChange();
}

bool OmniboxViewWin::OnKeyDownOnlyWritable(TCHAR key,
                                           UINT repeat_count,
                                           UINT flags) {
  // NOTE: Annoyingly, ctrl-alt-<key> generates WM_KEYDOWN rather than
  // WM_SYSKEYDOWN, so we need to check (flags & KF_ALTDOWN) in various places
  // in this function even with a WM_SYSKEYDOWN handler.

  // If adding a new key that could possibly be an accelerator then you'll need
  // to update LocationBarView::SkipDefaultKeyEventProcessing() as well.
  int count = repeat_count;
  switch (key) {
    case VK_RIGHT:
      // TODO(sky): figure out RTL.
      if (base::i18n::IsRTL())
        return false;
      {
        CHARRANGE selection;
        GetSel(selection);
        return (selection.cpMin == selection.cpMax) &&
            (selection.cpMin == GetTextLength()) &&
            model()->CommitSuggestedText();
      }

    case VK_RETURN:
      model()->AcceptInput((flags & KF_ALTDOWN) ?
          NEW_FOREGROUND_TAB : CURRENT_TAB, false);
      return true;

    case VK_PRIOR:
    case VK_NEXT:
      count = model()->result().size();
      // FALL THROUGH
    case VK_UP:
    case VK_DOWN:
      // Ignore alt + numpad, but treat alt + (non-numpad) like (non-numpad).
      if ((flags & KF_ALTDOWN) && !(flags & KF_EXTENDED))
        return false;

      model()->OnUpOrDownKeyPressed(((key == VK_PRIOR) || (key == VK_UP)) ?
          -count : count);
      return true;

    // Hijacking Editing Commands
    //
    // We hijack the keyboard short-cuts for Cut, Copy, and Paste here so that
    // they go through our clipboard routines.  This allows us to be smarter
    // about how we interact with the clipboard and avoid bugs in the
    // CRichEditCtrl.  If we didn't hijack here, the edit control would handle
    // these internally with sending the WM_CUT, WM_COPY, or WM_PASTE messages.
    //
    // Cut:   Shift-Delete and Ctrl-x are treated as cut.  Ctrl-Shift-Delete and
    //        Ctrl-Shift-x are not treated as cut even though the underlying
    //        CRichTextEdit would treat them as such.  Also note that we bring
    //        up 'clear browsing data' on control-shift-delete.
    // Copy:  Ctrl-Insert and Ctrl-c is treated as copy.  Shift-Ctrl-c is not.
    //        (This is handled in OnKeyDownAllModes().)
    // Paste: Shift-Insert and Ctrl-v are treated as paste.  Ctrl-Shift-Insert
    //        and Ctrl-Shift-v are not.
    //
    // This behavior matches most, but not all Windows programs, and largely
    // conforms to what users expect.

    case VK_DELETE:
      if (flags & KF_ALTDOWN)
        return false;
      if (GetKeyState(VK_SHIFT) >= 0) {
        if (GetKeyState(VK_CONTROL) >= 0) {
          CHARRANGE selection;
          GetSel(selection);
          delete_at_end_pressed_ = ((selection.cpMin == selection.cpMax) &&
                                    (selection.cpMin == GetTextLength()));
        }
        return false;
      }
      if (GetKeyState(VK_CONTROL) >= 0) {
        // Cut text if possible.
        CHARRANGE selection;
        GetSel(selection);
        if (selection.cpMin != selection.cpMax) {
          ScopedFreeze freeze(this, GetTextObjectModel());
          OnBeforePossibleChange();
          Cut();
          OnAfterPossibleChange();
        } else {
          if (model()->popup_model()->IsOpen()) {
            // This is a bit overloaded, but we hijack Shift-Delete in this
            // case to delete the current item from the pop-up.  We prefer
            // cutting to this when possible since that's the behavior more
            // people expect from Shift-Delete, and it's more commonly useful.
            model()->popup_model()->TryDeletingCurrentItem();
          }
        }
      }
      return true;

    case 'X':
      if ((flags & KF_ALTDOWN) || (GetKeyState(VK_CONTROL) >= 0))
        return false;
      if (GetKeyState(VK_SHIFT) >= 0) {
        ScopedFreeze freeze(this, GetTextObjectModel());
        OnBeforePossibleChange();
        Cut();
        OnAfterPossibleChange();
      }
      return true;

    case VK_INSERT:
      // Ignore insert by itself, so we don't turn overtype mode on/off.
      if (!(flags & KF_ALTDOWN) && (GetKeyState(VK_SHIFT) >= 0) &&
          (GetKeyState(VK_CONTROL) >= 0))
        return true;
      // FALL THROUGH
    case 'V':
      if ((flags & KF_ALTDOWN) ||
          (GetKeyState((key == 'V') ? VK_CONTROL : VK_SHIFT) >= 0))
        return false;
      if (GetKeyState((key == 'V') ? VK_SHIFT : VK_CONTROL) >= 0) {
        ScopedFreeze freeze(this, GetTextObjectModel());
        OnBeforePossibleChange();
        Paste();
        OnAfterPossibleChange();
      }
      return true;

    case VK_BACK: {
      if ((flags & KF_ALTDOWN) || model()->is_keyword_hint() ||
          model()->keyword().empty())
        return false;

      {
        CHARRANGE selection;
        GetSel(selection);
        if ((selection.cpMin != selection.cpMax) || (selection.cpMin != 0))
          return false;
      }

      // We're showing a keyword and the user pressed backspace at the beginning
      // of the text. Delete the selected keyword.
      ScopedFreeze freeze(this, GetTextObjectModel());
      model()->ClearKeyword(GetText());
      return true;
    }

    case VK_TAB: {
      const bool shift_pressed = GetKeyState(VK_SHIFT) < 0;
      if (model()->is_keyword_hint() && !shift_pressed) {
        // Accept the keyword.
        ScopedFreeze freeze(this, GetTextObjectModel());
        model()->AcceptKeyword(ENTERED_KEYWORD_MODE_VIA_TAB);
      } else if (shift_pressed &&
                 model()->popup_model()->selected_line_state() ==
                    OmniboxPopupModel::KEYWORD) {
        model()->ClearKeyword(GetText());
      } else {
        model()->OnUpOrDownKeyPressed(shift_pressed ? -count : count);
      }
      return true;
    }

    case 0xbb:  // Ctrl-'='.  Triggers subscripting (even in plain text mode).
                // We don't use VK_OEM_PLUS in case the macro isn't defined.
                // (e.g., we don't have this symbol in embeded environment).
      return true;

    default:
      return false;
  }
}

bool OmniboxViewWin::OnKeyDownAllModes(TCHAR key,
                                       UINT repeat_count,
                                       UINT flags) {
  // See KF_ALTDOWN comment atop OnKeyDownOnlyWritable().

  switch (key) {
    case VK_CONTROL:
      model()->OnControlKeyChanged(true);
      return false;

    case VK_INSERT:
    case 'C':
      // See more detailed comments in OnKeyDownOnlyWritable().
      if ((flags & KF_ALTDOWN) || (GetKeyState(VK_CONTROL) >= 0))
        return false;
      if (GetKeyState(VK_SHIFT) >= 0)
        Copy();
      return true;

    default:
      return false;
  }
}

void OmniboxViewWin::GetSelection(CHARRANGE& sel) const {
  GetSel(sel);

  // See if we need to reverse the direction of the selection.
  ITextDocument* const text_object_model = GetTextObjectModel();
  if (!text_object_model)
    return;
  base::win::ScopedComPtr<ITextSelection> selection;
  const HRESULT hr = text_object_model->GetSelection(selection.Receive());
  DCHECK_EQ(S_OK, hr);
  long flags;
  selection->GetFlags(&flags);
  if (flags & tomSelStartActive)
    std::swap(sel.cpMin, sel.cpMax);
}

string16 OmniboxViewWin::GetSelectedText() const {
  CHARRANGE sel;
  GetSel(sel);
  string16 str;
  if (sel.cpMin != sel.cpMax)
    GetSelText(WriteInto(&str, sel.cpMax - sel.cpMin + 1));
  return str;
}

void OmniboxViewWin::SetSelection(LONG start, LONG end) {
  SetSel(start, end);

  if (start <= end)
    return;

  // We need to reverse the direction of the selection.
  ITextDocument* const text_object_model = GetTextObjectModel();
  if (!text_object_model)
    return;
  base::win::ScopedComPtr<ITextSelection> selection;
  const HRESULT hr = text_object_model->GetSelection(selection.Receive());
  DCHECK_EQ(S_OK, hr);
  selection->SetFlags(tomSelStartActive);
}

void OmniboxViewWin::PlaceCaretAt(string16::size_type pos) {
  SetSelection(static_cast<LONG>(pos), static_cast<LONG>(pos));
}

bool OmniboxViewWin::IsSelectAllForRange(const CHARRANGE& sel) const {
  const int text_length = GetTextLength();
  return ((sel.cpMin == 0) && (sel.cpMax >= text_length)) ||
      ((sel.cpMax == 0) && (sel.cpMin >= text_length));
}

LONG OmniboxViewWin::ClipXCoordToVisibleText(LONG x,
                                             bool is_triple_click) const {
  // Clip the X coordinate to the left edge of the text. Careful:
  // PosFromChar(0) may return a negative X coordinate if the beginning of the
  // text has scrolled off the edit, so don't go past the clip rect's edge.
  PARAFORMAT2 pf2;
  GetParaFormat(pf2);
  // Calculation of the clipped coordinate is more complicated if the paragraph
  // layout is RTL layout, or if there is RTL characters inside the LTR layout
  // paragraph.
  const bool ltr_text_in_ltr_layout = !(pf2.wEffects & PFE_RTLPARA) &&
      !base::i18n::StringContainsStrongRTLChars(GetText());
  const int length = GetTextLength();
  RECT r;
  GetRect(&r);
  // The values returned by PosFromChar() seem to refer always
  // to the left edge of the character's bounding box.
  const LONG first_position_x = PosFromChar(0).x;
  LONG min_x = first_position_x;
  if (!ltr_text_in_ltr_layout) {
    for (int i = 1; i < length; ++i)
      min_x = std::min(min_x, PosFromChar(i).x);
  }
  const LONG left_bound = std::max(r.left, min_x);
  // PosFromChar(length) is a phantom character past the end of the text. It is
  // not necessarily a right bound; in RTL controls it may be a left bound. So
  // treat it as a right bound only if it is to the right of the first
  // character.
  LONG right_bound = r.right;
  LONG end_position_x = PosFromChar(length).x;
  if (end_position_x >= first_position_x) {
    right_bound = std::min(right_bound, end_position_x);  // LTR case.
  }
  // For trailing characters that are 2 pixels wide or less (like "l" in some
  // fonts), we have a problem:
  //   * Clicks on any pixel within the character will place the cursor before
  //     the character.
  //   * Clicks on the pixel just after the character will not allow triple-
  //     click to work properly (true for any last character width).
  // So, we move to the last pixel of the character when this is a
  // triple-click, and moving to one past the last pixel in all other
  // scenarios.  This way, all clicks that can move the cursor will place it at
  // the end of the text, but triple-click will still work.
  if (x < left_bound) {
    return (is_triple_click && ltr_text_in_ltr_layout) ? left_bound - 1 :
                                                         left_bound;
  }
  if ((length == 0) || (x < right_bound))
    return x;
  return is_triple_click ? (right_bound - 1) : right_bound;
}

int OmniboxViewWin::GetOmniboxTextLength() const {
  return static_cast<int>(GetTextLength());
}

void OmniboxViewWin::EmphasizeURLComponents() {
  ITextDocument* const text_object_model = GetTextObjectModel();
  ScopedFreeze freeze(this, text_object_model);
  ScopedSuspendUndo suspend_undo(text_object_model);

  // Save the selection.
  CHARRANGE saved_sel;
  GetSelection(saved_sel);

  // See whether the contents are a URL with a non-empty host portion, which we
  // should emphasize.  To check for a URL, rather than using the type returned
  // by Parse(), ask the model, which will check the desired page transition for
  // this input.  This can tell us whether an UNKNOWN input string is going to
  // be treated as a search or a navigation, and is the same method the Paste
  // And Go system uses.
  url_parse::Component scheme, host;
  string16 text(GetText());
  AutocompleteInput::ParseForEmphasizeComponents(text, &scheme, &host);

  // Set the baseline emphasis.
  CHARFORMAT cf = {0};
  cf.dwMask = CFM_COLOR;
  // If we're going to emphasize parts of the text, then the baseline state
  // should be "de-emphasized".  If not, then everything should be rendered in
  // the standard text color unless we should grey out the entire URL.
  bool grey_out_url = text.substr(scheme.begin, scheme.len) ==
      UTF8ToUTF16(extensions::kExtensionScheme);
  bool grey_base = model()->CurrentTextIsURL() &&
      (host.is_nonempty() || grey_out_url);
  cf.crTextColor = skia::SkColorToCOLORREF(location_bar_->GetColor(
      security_level_,
      grey_base ? LocationBarView::DEEMPHASIZED_TEXT : LocationBarView::TEXT));
  // NOTE: Don't use SetDefaultCharFormat() instead of the below; that sets
  // the format that will get applied to text added in the future, not to text
  // already in the edit.
  SelectAll(false);
  SetSelectionCharFormat(cf);
  if (host.is_nonempty() && !grey_out_url) {
    // We've found a host name and we should provide emphasis to host names,
    // so emphasize it.
    cf.crTextColor = skia::SkColorToCOLORREF(location_bar_->GetColor(
        security_level_, LocationBarView::TEXT));
    SetSelection(host.begin, host.end());
    SetSelectionCharFormat(cf);
  }

  // Emphasize the scheme for security UI display purposes (if necessary).
  insecure_scheme_component_.reset();
  if (!model()->user_input_in_progress() && model()->CurrentTextIsURL() &&
      scheme.is_nonempty() && (security_level_ != ToolbarModel::NONE)) {
    if (security_level_ == ToolbarModel::SECURITY_ERROR) {
      insecure_scheme_component_.begin = scheme.begin;
      insecure_scheme_component_.len = scheme.len;
    }
    cf.crTextColor = skia::SkColorToCOLORREF(location_bar_->GetColor(
        security_level_, LocationBarView::SECURITY_TEXT));
    SetSelection(scheme.begin, scheme.end());
    SetSelectionCharFormat(cf);
  }

  // Restore the selection.
  SetSelectionRange(saved_sel);
}

void OmniboxViewWin::EraseTopOfSelection(CDC* dc,
                                         const CRect& client_rect,
                                         const CRect& paint_clip_rect) {
  // Find the area we care about painting.   We could calculate the rect
  // containing just the selected portion, but there's no harm in simply erasing
  // the whole top of the client area, and at least once I saw us manage to
  // select the "phantom newline" briefly, which looks very weird if not clipped
  // off at the same height.
  CRect erase_rect(client_rect.left, client_rect.top, client_rect.right,
                   client_rect.top + font_y_adjustment_);
  erase_rect.IntersectRect(erase_rect, paint_clip_rect);

  // Erase to the background color.
  if (!erase_rect.IsRectNull())
    dc->FillSolidRect(&erase_rect, background_color_);
}

void OmniboxViewWin::DrawSlashForInsecureScheme(HDC hdc,
                                                const CRect& client_rect,
                                                const CRect& paint_clip_rect) {
  DCHECK(insecure_scheme_component_.is_nonempty());

  // Calculate the rect, in window coordinates, containing the portion of the
  // scheme where we'll be drawing the slash.  Vertically, we draw across one
  // x-height of text, plus an additional 3 stroke diameters (the stroke width
  // plus a half-stroke width of space between the stroke and the text, both
  // above and below the text).
  const int font_top = client_rect.top + font_y_adjustment_;
  const SkScalar kStrokeWidthPixels = SkIntToScalar(2);
  const int kAdditionalSpaceOutsideFont =
      static_cast<int>(ceil(kStrokeWidthPixels * 1.5f));
  const int font_ascent = font_list_.GetBaseline();
  const CRect scheme_rect(
      PosFromChar(insecure_scheme_component_.begin).x,
      font_top + font_ascent - font_x_height_ - kAdditionalSpaceOutsideFont,
      PosFromChar(insecure_scheme_component_.end()).x,
      font_top + font_ascent + kAdditionalSpaceOutsideFont);

  // Clip to the portion we care about and translate to canvas coordinates
  // (see the canvas creation below) for use later.
  CRect canvas_clip_rect, canvas_paint_clip_rect;
  canvas_clip_rect.IntersectRect(scheme_rect, client_rect);
  canvas_paint_clip_rect.IntersectRect(canvas_clip_rect, paint_clip_rect);
  if (canvas_paint_clip_rect.IsRectNull())
    return;  // We don't need to paint any of this region, so just bail early.
  canvas_clip_rect.OffsetRect(-scheme_rect.left, -scheme_rect.top);
  canvas_paint_clip_rect.OffsetRect(-scheme_rect.left, -scheme_rect.top);

  // Create a paint context for drawing the antialiased stroke.
  SkPaint paint;
  paint.setAntiAlias(true);
  paint.setStrokeWidth(kStrokeWidthPixels);
  paint.setStrokeCap(SkPaint::kRound_Cap);

  // Create a canvas as large as |scheme_rect| to do our drawing, and initialize
  // it to fully transparent so any antialiasing will look nice when painted
  // atop the edit.
  gfx::Canvas canvas(gfx::Size(scheme_rect.Width(), scheme_rect.Height()),
                     1.0f, false);
  SkCanvas* sk_canvas = canvas.sk_canvas();
  sk_canvas->getDevice()->accessBitmap(true).eraseARGB(0, 0, 0, 0);

  // Calculate the start and end of the stroke, which are just the lower left
  // and upper right corners of the canvas, inset by the radius of the endcap
  // so we don't clip the endcap off.
  const SkScalar kEndCapRadiusPixels = kStrokeWidthPixels / SkIntToScalar(2);
  const SkPoint start_point = {
      kEndCapRadiusPixels,
      SkIntToScalar(scheme_rect.Height()) - kEndCapRadiusPixels };
  const SkPoint end_point = {
      SkIntToScalar(scheme_rect.Width()) - kEndCapRadiusPixels,
      kEndCapRadiusPixels };

  // Calculate the selection rectangle in canvas coordinates, which we'll use
  // to clip the stroke so we can draw the unselected and selected portions.
  CHARRANGE sel;
  GetSel(sel);
  const SkRect selection_rect = {
      SkIntToScalar(PosFromChar(sel.cpMin).x - scheme_rect.left),
      SkIntToScalar(0),
      SkIntToScalar(PosFromChar(sel.cpMax).x - scheme_rect.left),
      SkIntToScalar(scheme_rect.Height()) };

  // Draw the unselected portion of the stroke.
  sk_canvas->save();
  if (selection_rect.isEmpty() ||
      sk_canvas->clipRect(selection_rect, SkRegion::kDifference_Op)) {
    paint.setColor(location_bar_->GetColor(security_level_,
                                           LocationBarView::SECURITY_TEXT));
    sk_canvas->drawLine(start_point.fX, start_point.fY,
                        end_point.fX, end_point.fY, paint);
  }
  sk_canvas->restore();

  // Draw the selected portion of the stroke.
  if (!selection_rect.isEmpty() && sk_canvas->clipRect(selection_rect)) {
    paint.setColor(location_bar_->GetColor(security_level_,
                                           LocationBarView::SELECTED_TEXT));
    sk_canvas->drawLine(start_point.fX, start_point.fY,
                        end_point.fX, end_point.fY, paint);
  }

  // Now copy what we drew to the target HDC.
  skia::DrawToNativeContext(sk_canvas, hdc,
      scheme_rect.left + canvas_paint_clip_rect.left - canvas_clip_rect.left,
      std::max(scheme_rect.top, client_rect.top) + canvas_paint_clip_rect.top -
          canvas_clip_rect.top, &canvas_paint_clip_rect);
}

void OmniboxViewWin::DrawDropHighlight(HDC hdc,
                                       const CRect& client_rect,
                                       const CRect& paint_clip_rect) {
  DCHECK_NE(-1, drop_highlight_position_);

  const int highlight_y = client_rect.top + font_y_adjustment_;
  const int highlight_x = PosFromChar(drop_highlight_position_).x - 1;
  const CRect highlight_rect(highlight_x,
                             highlight_y,
                             highlight_x + 1,
                             highlight_y + font_list_.GetHeight());

  // Clip the highlight to the region being painted.
  CRect clip_rect;
  clip_rect.IntersectRect(highlight_rect, paint_clip_rect);
  if (clip_rect.IsRectNull())
    return;

  HGDIOBJ last_pen = SelectObject(hdc, CreatePen(PS_SOLID, 1, RGB(0, 0, 0)));
  MoveToEx(hdc, clip_rect.left, clip_rect.top, NULL);
  LineTo(hdc, clip_rect.left, clip_rect.bottom);
  DeleteObject(SelectObject(hdc, last_pen));
}

void OmniboxViewWin::TextChanged() {
  ScopedFreeze freeze(this, GetTextObjectModel());
  OmniboxView::TextChanged();
}

ITextDocument* OmniboxViewWin::GetTextObjectModel() const {
  if (!text_object_model_) {
    // This is lazily initialized, instead of being initialized in the
    // constructor, in order to avoid hurting startup performance.
    base::win::ScopedComPtr<IRichEditOle, NULL> ole_interface;
    ole_interface.Attach(GetOleInterface());
    if (ole_interface) {
      ole_interface.QueryInterface(
          __uuidof(ITextDocument),
          reinterpret_cast<void**>(&text_object_model_));
    }
  }
  return text_object_model_;
}

void OmniboxViewWin::StartDragIfNecessary(const CPoint& point) {
  if (initiated_drag_ || !IsDrag(click_point_[kLeft], point))
    return;

  ui::OSExchangeData data;

  DWORD supported_modes = DROPEFFECT_COPY;

  CHARRANGE sel;
  GetSelection(sel);

  // We're about to start a drag session, but the edit is expecting a mouse up
  // that it uses to reset internal state.  If we don't send a mouse up now,
  // when the mouse moves back into the edit the edit will reset the selection.
  // So, we send the event now which resets the selection.  We then restore the
  // selection and start the drag.  We always send lbuttonup as otherwise we
  // might trigger a context menu (right up).  This seems scary, but doesn't
  // seem to cause problems.
  {
    ScopedFreeze freeze(this, GetTextObjectModel());
    DefWindowProc(WM_LBUTTONUP, 0,
                  MAKELPARAM(click_point_[kLeft].x, click_point_[kLeft].y));
    SetSelectionRange(sel);
  }

  const string16 start_text(GetText());
  string16 text_to_write(GetSelectedText());
  GURL url;
  bool write_url;
  const bool is_all_selected = IsSelectAllForRange(sel);

  // |sel| was set by GetSelection(), which preserves selection direction, so
  // sel.cpMin may not be the smaller value.
  model()->AdjustTextForCopy(std::min(sel.cpMin, sel.cpMax), is_all_selected,
                             &text_to_write, &url, &write_url);

  if (write_url) {
    string16 title;
    gfx::Image favicon;
    if (is_all_selected)
      model()->GetDataForURLExport(&url, &title, &favicon);
    button_drag_utils::SetURLAndDragImage(url, title, favicon.AsImageSkia(),
        &data, native_view_host_->GetWidget());
    supported_modes |= DROPEFFECT_LINK;
    content::RecordAction(UserMetricsAction("Omnibox_DragURL"));
  } else {
    supported_modes |= DROPEFFECT_MOVE;
    content::RecordAction(UserMetricsAction("Omnibox_DragString"));
  }

  data.SetString(text_to_write);

  scoped_refptr<ui::DragSourceWin> drag_source(new ui::DragSourceWin);
  DWORD dropped_mode;
  base::AutoReset<bool> auto_reset_in_drag(&in_drag_, true);
  if (DoDragDrop(ui::OSExchangeDataProviderWin::GetIDataObject(data),
                 drag_source, supported_modes, &dropped_mode) ==
          DRAGDROP_S_DROP) {
    if ((dropped_mode == DROPEFFECT_MOVE) && (start_text == GetText())) {
      ScopedFreeze freeze(this, GetTextObjectModel());
      OnBeforePossibleChange();
      SetSelectionRange(sel);
      ReplaceSel(L"", true);
      OnAfterPossibleChange();
    }
    // else case, not a move or it was a move and the drop was on us.
    // If the drop was on us, EditDropTarget took care of the move so that
    // we don't have to delete the text.
    possible_drag_ = false;
  } else {
    // Drag was canceled or failed. The mouse may still be down and
    // over us, in which case we need possible_drag_ to remain true so
    // that we don't forward mouse move events to the edit which will
    // start another drag.
    //
    // NOTE: we didn't use mouse capture during the mouse down as DoDragDrop
    // does its own capture.
    CPoint cursor_location;
    GetCursorPos(&cursor_location);

    CRect client_rect;
    GetClientRect(&client_rect);

    CPoint client_origin_on_screen(client_rect.left, client_rect.top);
    ClientToScreen(&client_origin_on_screen);
    client_rect.MoveToXY(client_origin_on_screen.x,
                         client_origin_on_screen.y);
    possible_drag_ = (client_rect.PtInRect(cursor_location) &&
                      ((GetKeyState(VK_LBUTTON) != 0) ||
                       (GetKeyState(VK_MBUTTON) != 0) ||
                       (GetKeyState(VK_RBUTTON) != 0)));
  }

  initiated_drag_ = true;
  tracking_click_[kLeft] = false;
}

void OmniboxViewWin::OnPossibleDrag(const CPoint& point) {
  if (possible_drag_)
    return;

  click_point_[kLeft] = point;
  initiated_drag_ = false;

  CHARRANGE selection;
  GetSel(selection);
  if (selection.cpMin != selection.cpMax) {
    const POINT min_sel_location(PosFromChar(selection.cpMin));
    const POINT max_sel_location(PosFromChar(selection.cpMax));
    // NOTE: we don't consider the y location here as we always pass a
    // y-coordinate in the middle to the default handler which always triggers
    // a drag regardless of the y-coordinate.
    possible_drag_ = (point.x >= min_sel_location.x) &&
                     (point.x < max_sel_location.x);
  }
}

void OmniboxViewWin::RepaintDropHighlight(int position) {
  if ((position != -1) && (position <= GetTextLength())) {
    const POINT min_loc(PosFromChar(position));
    const RECT highlight_bounds = {min_loc.x - 1, font_y_adjustment_,
        min_loc.x + 2, font_list_.GetHeight() + font_y_adjustment_};
    InvalidateRect(&highlight_bounds, false);
  }
}

void OmniboxViewWin::BuildContextMenu() {
  if (context_menu_contents_.get())
    return;

  context_menu_contents_.reset(new ui::SimpleMenuModel(this));
  // Set up context menu.
  if (!popup_window_mode_) {
    context_menu_contents_->AddItemWithStringId(IDS_UNDO, IDS_UNDO);
    context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
    context_menu_contents_->AddItemWithStringId(IDC_CUT, IDS_CUT);
  }
  context_menu_contents_->AddItemWithStringId(IDC_COPY, IDS_COPY);
  if (!popup_window_mode_) {
    context_menu_contents_->AddItemWithStringId(IDC_PASTE, IDS_PASTE);
    // GetContextualLabel() will override this next label with the
    // IDS_PASTE_AND_SEARCH label as needed.
    context_menu_contents_->AddItemWithStringId(IDS_PASTE_AND_GO,
                                                IDS_PASTE_AND_GO);
  }
  context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
  context_menu_contents_->AddItemWithStringId(IDS_SELECT_ALL, IDS_SELECT_ALL);
  if (chrome::IsQueryExtractionEnabled() || !popup_window_mode_) {
    context_menu_contents_->AddSeparator(ui::NORMAL_SEPARATOR);
    if (chrome::IsQueryExtractionEnabled())
      context_menu_contents_->AddItemWithStringId(IDS_SHOW_URL, IDS_SHOW_URL);
    if (!popup_window_mode_) {
      context_menu_contents_->AddItemWithStringId(IDC_EDIT_SEARCH_ENGINES,
                                                  IDS_EDIT_SEARCH_ENGINES);
    }
  }
}

void OmniboxViewWin::SelectAllIfNecessary(MouseButton button,
                                          const CPoint& point) {
  // When the user has clicked and released to give us focus, select all unless
  // we're doing search term replacement (in which case refining the existing
  // query is common enough that we do click-to-place-cursor).
  if (tracking_click_[button] && !IsDrag(click_point_[button], point) &&
      !controller()->GetToolbarModel()->WouldPerformSearchTermReplacement(
          false)) {
    // Select all in the reverse direction so as not to scroll the caret
    // into view and shift the contents jarringly.
    SelectAll(true);
    possible_drag_ = false;
  }
}

void OmniboxViewWin::TrackMousePosition(MouseButton button,
                                        const CPoint& point) {
  if (gaining_focus_.get()) {
    // This click is giving us focus, so we need to track how much the mouse
    // moves to see if it's a drag or just a click. Clicks should select all
    // the text.
    tracking_click_[button] = true;
    click_point_[button] = point;
  }
}

int OmniboxViewWin::GetHorizontalMargin() const {
  RECT rect;
  GetRect(&rect);
  RECT client_rect;
  GetClientRect(&client_rect);
  return (rect.left - client_rect.left) + (client_rect.right - rect.right);
}

int OmniboxViewWin::WidthNeededToDisplay(const string16& text) const {
  // Use font_list_.GetPrimaryFont().GetStringWidth() instead of
  // PosFromChar(GetTextLength()) because PosFromChar() is apparently buggy.
  // In both LTR UI and RTL UI with left-to-right layout, PosFromChar(i) might
  // return 0 when i is greater than 1.
  return font_list_.GetPrimaryFont().GetStringWidth(text) +
      GetHorizontalMargin();
}
