// Copyright (c) 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/cocoa/omnibox/omnibox_view_mac.h"

#include <Carbon/Carbon.h>  // kVK_Return

#include "base/mac/foundation_util.h"
#include "base/metrics/histogram.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/autocomplete/autocomplete_input.h"
#include "chrome/browser/autocomplete/autocomplete_match.h"
#include "chrome/browser/browser_process.h"
#include "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_cell.h"
#import "chrome/browser/ui/cocoa/location_bar/autocomplete_text_field_editor.h"
#include "chrome/browser/ui/cocoa/omnibox/omnibox_popup_view_mac.h"
#include "chrome/browser/ui/omnibox/omnibox_edit_controller.h"
#include "chrome/browser/ui/omnibox/omnibox_popup_model.h"
#include "chrome/browser/ui/toolbar/toolbar_model.h"
#include "content/public/browser/web_contents.h"
#include "extensions/common/constants.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#import "third_party/mozilla/NSPasteboard+Utils.h"
#include "ui/base/clipboard/clipboard.h"
#import "ui/base/cocoa/cocoa_event_utils.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/rect.h"

using content::WebContents;

// Focus-handling between |field_| and model() is a bit subtle.
// Other platforms detect change of focus, which is inconvenient
// without subclassing NSTextField (even with a subclass, the use of a
// field editor may complicate things).
//
// model() doesn't actually do anything when it gains focus, it just
// initializes.  Visible activity happens only after the user edits.
// NSTextField delegate receives messages around starting and ending
// edits, so that suffices to catch focus changes.  Since all calls
// into model() start from OmniboxViewMac, in the worst case
// we can add code to sync up the sense of focus as needed.
//
// I've added DCHECK(IsFirstResponder()) in the places which I believe
// should only be reachable when |field_| is being edited.  If these
// fire, it probably means someone unexpected is calling into
// model().
//
// Other platforms don't appear to have the sense of "key window" that
// Mac does (I believe their fields lose focus when the window loses
// focus).  Rather than modifying focus outside the control's edit
// scope, when the window resigns key the autocomplete popup is
// closed.  model() still believes it has focus, and the popup will
// be regenerated on the user's next edit.  That seems to match how
// things work on other platforms.

namespace {

// TODO(shess): This is ugly, find a better way.  Using it right now
// so that I can crib from gtk and still be able to see that I'm using
// the same values easily.
NSColor* ColorWithRGBBytes(int rr, int gg, int bb) {
  DCHECK_LE(rr, 255);
  DCHECK_LE(bb, 255);
  DCHECK_LE(gg, 255);
  return [NSColor colorWithCalibratedRed:static_cast<float>(rr)/255.0
                                   green:static_cast<float>(gg)/255.0
                                    blue:static_cast<float>(bb)/255.0
                                   alpha:1.0];
}

NSColor* HostTextColor() {
  return [NSColor blackColor];
}
NSColor* BaseTextColor() {
  return [NSColor darkGrayColor];
}
NSColor* SecureSchemeColor() {
  return ColorWithRGBBytes(0x07, 0x95, 0x00);
}
NSColor* SecurityErrorSchemeColor() {
  return ColorWithRGBBytes(0xa2, 0x00, 0x00);
}

const char kOmniboxViewMacStateKey[] = "OmniboxViewMacState";

// Store's the model and view state across tab switches.
struct OmniboxViewMacState : public base::SupportsUserData::Data {
  OmniboxViewMacState(const OmniboxEditModel::State model_state,
                      const bool has_focus,
                      const NSRange& selection)
      : model_state(model_state),
        has_focus(has_focus),
        selection(selection) {
  }
  virtual ~OmniboxViewMacState() {}

  const OmniboxEditModel::State model_state;
  const bool has_focus;
  const NSRange selection;
};

// Accessors for storing and getting the state from the tab.
void StoreStateToTab(WebContents* tab,
                     OmniboxViewMacState* state) {
  tab->SetUserData(kOmniboxViewMacStateKey, state);
}
const OmniboxViewMacState* GetStateFromTab(const WebContents* tab) {
  return static_cast<OmniboxViewMacState*>(
      tab->GetUserData(&kOmniboxViewMacStateKey));
}

// Helper to make converting url_parse ranges to NSRange easier to
// read.
NSRange ComponentToNSRange(const url_parse::Component& component) {
  return NSMakeRange(static_cast<NSInteger>(component.begin),
                     static_cast<NSInteger>(component.len));
}

}  // namespace

// static
NSImage* OmniboxViewMac::ImageForResource(int resource_id) {
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  return rb.GetNativeImageNamed(resource_id).ToNSImage();
}

// static
NSColor* OmniboxViewMac::SuggestTextColor() {
  return [NSColor colorWithCalibratedWhite:0.0 alpha:0.5];
}

OmniboxViewMac::OmniboxViewMac(OmniboxEditController* controller,
                               Profile* profile,
                               CommandUpdater* command_updater,
                               AutocompleteTextField* field)
    : OmniboxView(profile, controller, command_updater),
      popup_view_(new OmniboxPopupViewMac(this, model(), field)),
      field_(field),
      saved_temporary_selection_(NSMakeRange(0, 0)),
      selection_before_change_(NSMakeRange(0, 0)),
      marked_range_before_change_(NSMakeRange(0, 0)),
      delete_was_pressed_(false),
      delete_at_end_pressed_(false) {
  [field_ setObserver:this];

  // Needed so that editing doesn't lose the styling.
  [field_ setAllowsEditingTextAttributes:YES];

  // Get the appropriate line height for the font that we use.
  base::scoped_nsobject<NSLayoutManager> layoutManager(
      [[NSLayoutManager alloc] init]);
  [layoutManager setUsesScreenFonts:YES];
}

OmniboxViewMac::~OmniboxViewMac() {
  // Destroy popup view before this object in case it tries to call us
  // back in the destructor.
  popup_view_.reset();

  // Disconnect from |field_|, it outlives this object.
  [field_ setObserver:NULL];
}

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

  const bool hasFocus = [field_ currentEditor] ? true : false;

  NSRange range;
  if (hasFocus) {
    range = GetSelectedRange();
  } else {
    // If we are not focussed, there is no selection.  Manufacture
    // something reasonable in case it starts to matter in the future.
    range = NSMakeRange(0, GetTextLength());
  }

  OmniboxViewMacState* state =
      new OmniboxViewMacState(model()->GetStateForTabSwitch(), hasFocus, range);
  StoreStateToTab(tab, state);
}

void OmniboxViewMac::OnTabChanged(const WebContents* web_contents) {
  const OmniboxViewMacState* state = GetStateFromTab(web_contents);
  model()->RestoreState(state ? &state->model_state : NULL);
  // Restore focus and selection if they were present when the tab
  // was switched away.
  if (state && state->has_focus) {
    // TODO(shess): Unfortunately, there is no safe way to update
    // this because TabStripController -selectTabWithContents:* is
    // also messing with focus.  Both parties need to agree to
    // store existing state before anyone tries to setup the new
    // state.  Anyhow, it would look something like this.
#if 0
    [[field_ window] makeFirstResponder:field_];
    [[field_ currentEditor] setSelectedRange:state->selection];
#endif
  }
}

void OmniboxViewMac::Update() {
  if (model()->UpdatePermanentText()) {
    // Something visibly changed.  Re-enable URL replacement.
    controller()->GetToolbarModel()->set_url_replacement_enabled(true);
    model()->UpdatePermanentText();

    // Restore everything to the baseline look.
    RevertAll();

    // TODO(shess): Figure out how this case is used, to make sure
    // we're getting the selection and popup right.
  } else {
    // TODO(shess): This corresponds to _win and _gtk, except those
    // guard it with a test for whether the security level changed.
    // But AFAICT, that can only change if the text changed, and that
    // code compares the toolbar model security level with the local
    // security level.  Dig in and figure out why this isn't a no-op
    // that should go away.
    EmphasizeURLComponents();
  }
}

base::string16 OmniboxViewMac::GetText() const {
  return base::SysNSStringToUTF16([field_ stringValue]);
}

NSRange OmniboxViewMac::GetSelectedRange() const {
  return [[field_ currentEditor] selectedRange];
}

NSRange OmniboxViewMac::GetMarkedRange() const {
  DCHECK([field_ currentEditor]);
  return [(NSTextView*)[field_ currentEditor] markedRange];
}

void OmniboxViewMac::SetSelectedRange(const NSRange range) {
  // This can be called when we don't have focus.  For instance, when
  // the user clicks the "Go" button.
  if (model()->has_focus()) {
    // TODO(shess): If model() thinks we have focus, this should not
    // be necessary.  Try to convert to DCHECK(IsFirstResponder()).
    if (![field_ currentEditor]) {
      [[field_ window] makeFirstResponder:field_];
    }

    // TODO(shess): What if it didn't get first responder, and there is
    // no field editor?  This will do nothing.  Well, at least it won't
    // crash.  Think of something more productive to do, or prove that
    // it cannot occur and DCHECK appropriately.
    [[field_ currentEditor] setSelectedRange:range];
  }
}

void OmniboxViewMac::SetWindowTextAndCaretPos(const base::string16& text,
                                              size_t caret_pos,
                                              bool update_popup,
                                              bool notify_text_changed) {
  DCHECK_LE(caret_pos, text.size());
  SetTextAndSelectedRange(text, NSMakeRange(caret_pos, 0));

  if (update_popup)
    UpdatePopup();

  if (notify_text_changed)
    TextChanged();
}

void OmniboxViewMac::SetForcedQuery() {
  // We need to do this first, else |SetSelectedRange()| won't work.
  FocusLocation(true);

  const base::string16 current_text(GetText());
  const size_t start = current_text.find_first_not_of(base::kWhitespaceUTF16);
  if (start == base::string16::npos || (current_text[start] != '?')) {
    SetUserText(ASCIIToUTF16("?"));
  } else {
    NSRange range = NSMakeRange(start + 1, current_text.size() - start - 1);
    [[field_ currentEditor] setSelectedRange:range];
  }
}

bool OmniboxViewMac::IsSelectAll() const {
  if (![field_ currentEditor])
    return true;
  const NSRange all_range = NSMakeRange(0, GetTextLength());
  return NSEqualRanges(all_range, GetSelectedRange());
}

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

void OmniboxViewMac::GetSelectionBounds(base::string16::size_type* start,
                                        base::string16::size_type* end) const {
  if (![field_ currentEditor]) {
    *start = *end = 0;
    return;
  }

  const NSRange selected_range = GetSelectedRange();
  *start = static_cast<size_t>(selected_range.location);
  *end = static_cast<size_t>(NSMaxRange(selected_range));
}

void OmniboxViewMac::SelectAll(bool reversed) {
  // TODO(shess): Figure out what |reversed| implies.  The gtk version
  // has it imply inverting the selection front to back, but I don't
  // even know if that makes sense for Mac.

  // TODO(shess): Verify that we should be stealing focus at this
  // point.
  SetSelectedRange(NSMakeRange(0, GetTextLength()));
}

void OmniboxViewMac::RevertAll() {
  OmniboxView::RevertAll();
  [field_ clearUndoChain];
}

void OmniboxViewMac::UpdatePopup() {
  model()->SetInputInProgress(true);
  if (!model()->has_focus())
    return;

  // Comment copied from OmniboxViewWin::UpdatePopup():
  // 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
  bool prevent_inline_autocomplete = IsImeComposing();
  NSTextView* editor = (NSTextView*)[field_ currentEditor];
  if (editor) {
    if (NSMaxRange([editor selectedRange]) < [[editor textStorage] length])
      prevent_inline_autocomplete = true;
  }

  model()->StartAutocomplete([editor selectedRange].length != 0,
                            prevent_inline_autocomplete);
}

void OmniboxViewMac::CloseOmniboxPopup() {
  // Call both base class methods.
  ClosePopup();
  OmniboxView::CloseOmniboxPopup();
}

void OmniboxViewMac::SetFocus() {
  FocusLocation(false);
  model()->SetCaretVisibility(true);
}

void OmniboxViewMac::ApplyCaretVisibility() {
  [[field_ cell] setHideFocusState:!model()->is_caret_visible()
                            ofView:field_];
}

void OmniboxViewMac::SetText(const base::string16& display_text) {
  SetTextInternal(display_text);
}

void OmniboxViewMac::SetTextInternal(const base::string16& display_text) {
  NSString* ss = base::SysUTF16ToNSString(display_text);
  NSMutableAttributedString* as =
      [[[NSMutableAttributedString alloc] initWithString:ss] autorelease];

  ApplyTextAttributes(display_text, as);
  [field_ setAttributedStringValue:as];

  // TODO(shess): This may be an appropriate place to call:
  //   model()->OnChanged();
  // In the current implementation, this tells LocationBarViewMac to
  // mess around with model() and update |field_|.  Unfortunately,
  // when I look at our peer implementations, it's not entirely clear
  // to me if this is safe.  SetTextInternal() is sort of an utility method,
  // and different callers sometimes have different needs.  Research
  // this issue so that it can be added safely.

  // TODO(shess): Also, consider whether this code couldn't just
  // manage things directly.  Windows uses a series of overlaid view
  // objects to accomplish the hinting stuff that OnChanged() does, so
  // it makes sense to have it in the controller that lays those
  // things out.  Mac instead pushes the support into a custom
  // text-field implementation.
}

void OmniboxViewMac::SetTextAndSelectedRange(const base::string16& display_text,
                                             const NSRange range) {
  SetText(display_text);
  SetSelectedRange(range);
}

void OmniboxViewMac::EmphasizeURLComponents() {
  NSTextView* editor = (NSTextView*)[field_ currentEditor];
  // If the autocomplete text field is in editing mode, then we can just change
  // its attributes through its editor. Otherwise, we simply reset its content.
  if (editor) {
    NSTextStorage* storage = [editor textStorage];
    [storage beginEditing];

    // Clear the existing attributes from the text storage, then
    // overlay the appropriate Omnibox attributes.
    [storage setAttributes:[NSDictionary dictionary]
                     range:NSMakeRange(0, [storage length])];
    ApplyTextAttributes(GetText(), storage);

    [storage endEditing];
  } else {
    SetText(GetText());
  }
}

void OmniboxViewMac::ApplyTextAttributes(const base::string16& display_text,
                                         NSMutableAttributedString* as) {
  NSUInteger as_length = [as length];
  NSRange as_entire_string = NSMakeRange(0, as_length);

  [as addAttribute:NSFontAttributeName value:GetFieldFont()
             range:as_entire_string];

  // A kinda hacky way to add breaking at periods. This is what Safari does.
  // This works for IDNs too, despite the "en_US".
  [as addAttribute:@"NSLanguage" value:@"en_US_POSIX"
             range:as_entire_string];

  // Make a paragraph style locking in the standard line height as the maximum,
  // otherwise the baseline may shift "downwards".
  base::scoped_nsobject<NSMutableParagraphStyle> paragraph_style(
      [[NSMutableParagraphStyle alloc] init]);
  CGFloat line_height = [[field_ cell] lineHeight];
  [paragraph_style setMaximumLineHeight:line_height];
  [paragraph_style setMinimumLineHeight:line_height];
  [paragraph_style setLineBreakMode:NSLineBreakByTruncatingTail];
  [as addAttribute:NSParagraphStyleAttributeName value:paragraph_style
             range:as_entire_string];

  url_parse::Component scheme, host;
  AutocompleteInput::ParseForEmphasizeComponents(
      display_text, &scheme, &host);
  bool grey_out_url = display_text.substr(scheme.begin, scheme.len) ==
      UTF8ToUTF16(extensions::kExtensionScheme);
  if (model()->CurrentTextIsURL() &&
      (host.is_nonempty() || grey_out_url)) {
    [as addAttribute:NSForegroundColorAttributeName value:BaseTextColor()
               range:as_entire_string];

    if (!grey_out_url) {
      [as addAttribute:NSForegroundColorAttributeName value:HostTextColor()
               range:ComponentToNSRange(host)];
    }
  }

  // TODO(shess): GTK has this as a member var, figure out why.
  // [Could it be to not change if no change?  If so, I'm guessing
  // AppKit may already handle that.]
  const ToolbarModel::SecurityLevel security_level =
      controller()->GetToolbarModel()->GetSecurityLevel(false);

  // Emphasize the scheme for security UI display purposes (if necessary).
  if (!model()->user_input_in_progress() && model()->CurrentTextIsURL() &&
      scheme.is_nonempty() && (security_level != ToolbarModel::NONE)) {
    NSColor* color;
    if (security_level == ToolbarModel::EV_SECURE ||
        security_level == ToolbarModel::SECURE) {
      color = SecureSchemeColor();
    } else if (security_level == ToolbarModel::SECURITY_ERROR) {
      color = SecurityErrorSchemeColor();
      // Add a strikethrough through the scheme.
      [as addAttribute:NSStrikethroughStyleAttributeName
                 value:[NSNumber numberWithInt:NSUnderlineStyleSingle]
                 range:ComponentToNSRange(scheme)];
    } else if (security_level == ToolbarModel::SECURITY_WARNING) {
      color = BaseTextColor();
    } else {
      NOTREACHED();
      color = BaseTextColor();
    }
    [as addAttribute:NSForegroundColorAttributeName value:color
               range:ComponentToNSRange(scheme)];
  }
}

void OmniboxViewMac::OnTemporaryTextMaybeChanged(
    const base::string16& display_text,
    bool save_original_selection,
    bool notify_text_changed) {
  if (save_original_selection)
    saved_temporary_selection_ = GetSelectedRange();

  SetWindowTextAndCaretPos(display_text, display_text.size(), false, false);
  if (notify_text_changed)
    model()->OnChanged();
  [field_ clearUndoChain];
}

bool OmniboxViewMac::OnInlineAutocompleteTextMaybeChanged(
    const base::string16& display_text,
    size_t user_text_length) {
  // TODO(shess): Make sure that this actually works.  The round trip
  // to native form and back may mean that it's the same but not the
  // same.
  if (display_text == GetText())
    return false;

  DCHECK_LE(user_text_length, display_text.size());
  const NSRange range =
      NSMakeRange(user_text_length, display_text.size() - user_text_length);
  SetTextAndSelectedRange(display_text, range);
  model()->OnChanged();
  [field_ clearUndoChain];

  return true;
}

void OmniboxViewMac::OnInlineAutocompleteTextCleared() {
}

void OmniboxViewMac::OnRevertTemporaryText() {
  SetSelectedRange(saved_temporary_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.
}

bool OmniboxViewMac::IsFirstResponder() const {
  return [field_ currentEditor] != nil ? true : false;
}

void OmniboxViewMac::OnBeforePossibleChange() {
  // We should only arrive here when the field is focussed.
  DCHECK(IsFirstResponder());

  selection_before_change_ = GetSelectedRange();
  text_before_change_ = GetText();
  marked_range_before_change_ = GetMarkedRange();
}

bool OmniboxViewMac::OnAfterPossibleChange() {
  // We should only arrive here when the field is focussed.
  DCHECK(IsFirstResponder());

  const NSRange new_selection(GetSelectedRange());
  const base::string16 new_text(GetText());
  const size_t length = new_text.length();

  const bool selection_differs =
      (new_selection.length || selection_before_change_.length) &&
      !NSEqualRanges(new_selection, selection_before_change_);
  const bool at_end_of_edit = (length == new_selection.location);
  const bool text_differs = (new_text != text_before_change_) ||
      !NSEqualRanges(marked_range_before_change_, GetMarkedRange());

  // When the user has deleted text, we don't allow inline
  // autocomplete.  This is assumed if the text has gotten shorter AND
  // the selection has shifted towards the front of the text.  During
  // normal typing the text will almost always be shorter (as the new
  // input replaces the autocomplete suggestion), but in that case the
  // selection point will have moved towards the end of the text.
  // TODO(shess): In our implementation, we can catch -deleteBackward:
  // and other methods to provide positive knowledge that a delete
  // occured, rather than intuiting it from context.  Consider whether
  // that would be a stronger approach.
  const bool just_deleted_text =
      (length < text_before_change_.length() &&
       new_selection.location <= selection_before_change_.location);

  delete_at_end_pressed_ = false;

  const bool something_changed = model()->OnAfterPossibleChange(
      text_before_change_, new_text, new_selection.location,
      NSMaxRange(new_selection), selection_differs, text_differs,
      just_deleted_text, !IsImeComposing());

  if (delete_was_pressed_ && at_end_of_edit)
    delete_at_end_pressed_ = true;

  // Restyle in case the user changed something.
  // TODO(shess): I believe there are multiple-redraw cases, here.
  // Linux watches for something_changed && text_differs, but that
  // fails for us in case you copy the URL and paste the identical URL
  // back (we'll lose the styling).
  TextChanged();

  delete_was_pressed_ = false;

  return something_changed;
}

gfx::NativeView OmniboxViewMac::GetNativeView() const {
  return field_;
}

gfx::NativeView OmniboxViewMac::GetRelativeWindowForPopup() const {
  // Not used on mac.
  NOTREACHED();
  return NULL;
}

void OmniboxViewMac::SetGrayTextAutocompletion(
    const base::string16& suggest_text) {
  if (suggest_text == suggest_text_)
    return;
  suggest_text_ = suggest_text;
  [field_ setGrayTextAutocompletion:base::SysUTF16ToNSString(suggest_text)
                          textColor:SuggestTextColor()];
}

base::string16 OmniboxViewMac::GetGrayTextAutocompletion() const {
  return suggest_text_;
}

int OmniboxViewMac::GetTextWidth() const {
  // Not used on mac.
  NOTREACHED();
  return 0;
}

int OmniboxViewMac::GetWidth() const {
  return ceil([field_ bounds].size.width);
}

bool OmniboxViewMac::IsImeComposing() const {
  return [(NSTextView*)[field_ currentEditor] hasMarkedText];
}

void OmniboxViewMac::OnDidBeginEditing() {
  // We should only arrive here when the field is focussed.
  DCHECK([field_ currentEditor]);
}

void OmniboxViewMac::OnBeforeChange() {
  // Capture the current state.
  OnBeforePossibleChange();
}

void OmniboxViewMac::OnDidChange() {
  // Figure out what changed and notify the model.
  OnAfterPossibleChange();
}

void OmniboxViewMac::OnDidEndEditing() {
  ClosePopup();
}

bool OmniboxViewMac::OnDoCommandBySelector(SEL cmd) {
  if (cmd == @selector(deleteForward:))
    delete_was_pressed_ = true;

  if (cmd == @selector(moveDown:)) {
    model()->OnUpOrDownKeyPressed(1);
    return true;
  }

  if (cmd == @selector(moveUp:)) {
    model()->OnUpOrDownKeyPressed(-1);
    return true;
  }

  if (model()->popup_model()->IsOpen()) {
    if (cmd == @selector(insertBacktab:)) {
      if (model()->popup_model()->selected_line_state() ==
            OmniboxPopupModel::KEYWORD) {
        model()->ClearKeyword(GetText());
        return true;
      } else {
        model()->OnUpOrDownKeyPressed(-1);
        return true;
      }
    }

    if ((cmd == @selector(insertTab:) ||
        cmd == @selector(insertTabIgnoringFieldEditor:)) &&
        !model()->is_keyword_hint()) {
      model()->OnUpOrDownKeyPressed(1);
      return true;
    }
  }

  if (cmd == @selector(moveRight:)) {
    // Only commit suggested text if the cursor is all the way to the right and
    // there is no selection.
    if (suggest_text_.length() > 0 && IsCaretAtEnd()) {
      model()->CommitSuggestedText();
      return true;
    }
  }

  if (cmd == @selector(scrollPageDown:)) {
    model()->OnUpOrDownKeyPressed(model()->result().size());
    return true;
  }

  if (cmd == @selector(scrollPageUp:)) {
    model()->OnUpOrDownKeyPressed(-model()->result().size());
    return true;
  }

  if (cmd == @selector(cancelOperation:)) {
    return model()->OnEscapeKeyPressed();
  }

  if ((cmd == @selector(insertTab:) ||
      cmd == @selector(insertTabIgnoringFieldEditor:)) &&
      model()->is_keyword_hint()) {
    return model()->AcceptKeyword(ENTERED_KEYWORD_MODE_VIA_TAB);
  }

  // |-noop:| is sent when the user presses Cmd+Return. Override the no-op
  // behavior with the proper WindowOpenDisposition.
  NSEvent* event = [NSApp currentEvent];
  if (cmd == @selector(insertNewline:) ||
     (cmd == @selector(noop:) &&
      ([event type] == NSKeyDown || [event type] == NSKeyUp) &&
      [event keyCode] == kVK_Return)) {
    WindowOpenDisposition disposition =
        ui::WindowOpenDispositionFromNSEvent(event);
    model()->AcceptInput(disposition, false);
    // Opening a URL in a background tab should also revert the omnibox contents
    // to their original state.  We cannot do a blanket revert in OpenURL()
    // because middle-clicks also open in a new background tab, but those should
    // not revert the omnibox text.
    RevertAll();
    return true;
  }

  // Option-Return
  if (cmd == @selector(insertNewlineIgnoringFieldEditor:)) {
    model()->AcceptInput(NEW_FOREGROUND_TAB, false);
    return true;
  }

  // When the user does Control-Enter, the existing content has "www."
  // prepended and ".com" appended.  model() should already have
  // received notification when the Control key was depressed, but it
  // is safe to tell it twice.
  if (cmd == @selector(insertLineBreak:)) {
    OnControlKeyChanged(true);
    WindowOpenDisposition disposition =
        ui::WindowOpenDispositionFromNSEvent([NSApp currentEvent]);
    model()->AcceptInput(disposition, false);
    return true;
  }

  if (cmd == @selector(deleteBackward:)) {
    if (OnBackspacePressed()) {
      return true;
    }
  }

  if (cmd == @selector(deleteForward:)) {
    const NSUInteger modifiers = [[NSApp currentEvent] modifierFlags];
    if ((modifiers & NSShiftKeyMask) != 0) {
      if (model()->popup_model()->IsOpen()) {
        model()->popup_model()->TryDeletingCurrentItem();
        return true;
      }
    }
  }

  return false;
}

void OmniboxViewMac::OnSetFocus(bool control_down) {
  model()->OnSetFocus(control_down);
  controller()->OnSetFocus();
}

void OmniboxViewMac::OnKillFocus() {
  // Tell the model to reset itself.
  model()->OnWillKillFocus(NULL);
  model()->OnKillFocus();
}

void OmniboxViewMac::OnMouseDown(NSInteger button_number) {
  // Restore caret visibility whenever the user clicks in the the omnibox. This
  // is not always covered by OnSetFocus() because when clicking while the
  // omnibox has invisible focus does not trigger a new OnSetFocus() call.
  if (button_number == 0 || button_number == 1)
    model()->SetCaretVisibility(true);
}

bool OmniboxViewMac::ShouldSelectAllOnMouseDown() {
  return !controller()->GetToolbarModel()->WouldPerformSearchTermReplacement(
      false);
}

bool OmniboxViewMac::CanCopy() {
  const NSRange selection = GetSelectedRange();
  return selection.length > 0;
}

void OmniboxViewMac::CopyToPasteboard(NSPasteboard* pb) {
  DCHECK(CanCopy());

  const NSRange selection = GetSelectedRange();
  base::string16 text = base::SysNSStringToUTF16(
      [[field_ stringValue] substringWithRange:selection]);

  // Copy the URL unless this is the search URL and it's being replaced by the
  // Extended Instant API.
  GURL url;
  bool write_url = false;
  if (!controller()->GetToolbarModel()->WouldPerformSearchTermReplacement(
      false)) {
    model()->AdjustTextForCopy(selection.location, IsSelectAll(), &text, &url,
                               &write_url);
  }

  if (IsSelectAll())
    UMA_HISTOGRAM_COUNTS(OmniboxEditModel::kCutOrCopyAllTextHistogram, 1);

  NSString* nstext = base::SysUTF16ToNSString(text);
  [pb declareTypes:[NSArray arrayWithObject:NSStringPboardType] owner:nil];
  [pb setString:nstext forType:NSStringPboardType];

  if (write_url) {
    [pb declareURLPasteboardWithAdditionalTypes:[NSArray array] owner:nil];
    [pb setDataForURL:base::SysUTF8ToNSString(url.spec()) title:nstext];
  }
}

void OmniboxViewMac::ShowURL() {
  DCHECK(ShouldEnableShowURL());
  OmniboxView::ShowURL();
}

void OmniboxViewMac::OnPaste() {
  // This code currently expects |field_| to be focussed.
  DCHECK([field_ currentEditor]);

  base::string16 text = GetClipboardText();
  if (text.empty()) {
    return;
  }
  NSString* s = base::SysUTF16ToNSString(text);

  // -shouldChangeTextInRange:* and -didChangeText are documented in
  // NSTextView as things you need to do if you write additional
  // user-initiated editing functions.  They cause the appropriate
  // delegate methods to be called.
  // TODO(shess): It would be nice to separate the Cocoa-specific code
  // from the Chrome-specific code.
  NSTextView* editor = static_cast<NSTextView*>([field_ currentEditor]);
  const NSRange selectedRange = GetSelectedRange();
  if ([editor shouldChangeTextInRange:selectedRange replacementString:s]) {
    // Record this paste, so we can do different behavior.
    model()->OnPaste();

    // 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();

    [editor replaceCharactersInRange:selectedRange withString:s];
    [editor didChangeText];
  }
}

// TODO(dominich): Move to OmniboxView base class? Currently this is defined on
// the AutocompleteTextFieldObserver but the logic is shared between all
// platforms. Some refactor might be necessary to simplify this. Or at least
// this method could call the OmniboxView version.
bool OmniboxViewMac::ShouldEnableShowURL() {
  return controller()->GetToolbarModel()->WouldReplaceURL();
}

bool OmniboxViewMac::CanPasteAndGo() {
  return model()->CanPasteAndGo(GetClipboardText());
}

int OmniboxViewMac::GetPasteActionStringId() {
  base::string16 text(GetClipboardText());
  DCHECK(model()->CanPasteAndGo(text));
  return model()->IsPasteAndSearch(text) ?
      IDS_PASTE_AND_SEARCH : IDS_PASTE_AND_GO;
}

void OmniboxViewMac::OnPasteAndGo() {
  base::string16 text(GetClipboardText());
  if (model()->CanPasteAndGo(text))
    model()->PasteAndGo(text);
}

void OmniboxViewMac::OnFrameChanged() {
  // TODO(shess): UpdatePopupAppearance() is called frequently, so it
  // should be really cheap, but in this case we could probably make
  // things even cheaper by refactoring between the popup-placement
  // code and the matrix-population code.
  popup_view_->UpdatePopupAppearance();

  // Give controller a chance to rearrange decorations.
  model()->OnChanged();
}

void OmniboxViewMac::ClosePopup() {
  OmniboxView::CloseOmniboxPopup();
}

bool OmniboxViewMac::OnBackspacePressed() {
  // Don't intercept if not in keyword search mode.
  if (model()->is_keyword_hint() || model()->keyword().empty()) {
    return false;
  }

  // Don't intercept if there is a selection, or the cursor isn't at
  // the leftmost position.
  const NSRange selection = GetSelectedRange();
  if (selection.length > 0 || selection.location > 0) {
    return false;
  }

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

NSRange OmniboxViewMac::SelectionRangeForProposedRange(NSRange proposed_range) {
  return proposed_range;
}

void OmniboxViewMac::OnControlKeyChanged(bool pressed) {
  model()->OnControlKeyChanged(pressed);
}

void OmniboxViewMac::FocusLocation(bool select_all) {
  if ([field_ isEditable]) {
    // If the text field has a field editor, it's the first responder, meaning
    // that it's already focused. makeFirstResponder: will select all, so only
    // call it if this behavior is desired.
    if (select_all || ![field_ currentEditor])
      [[field_ window] makeFirstResponder:field_];
    DCHECK_EQ([field_ currentEditor], [[field_ window] firstResponder]);
  }
}

// static
NSFont* OmniboxViewMac::GetFieldFont() {
  // This value should be kept in sync with InstantPage::InitializeFonts.
  ResourceBundle& rb = ResourceBundle::GetSharedInstance();
  return rb.GetFont(ResourceBundle::BaseFont).DeriveFont(1).GetNativeFont();
}

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

NSUInteger OmniboxViewMac::GetTextLength() const {
  return [field_ currentEditor] ?  [[[field_ currentEditor] string] length] :
                                   [[field_ stringValue] length];
}

bool OmniboxViewMac::IsCaretAtEnd() const {
  const NSRange selection = GetSelectedRange();
  return NSMaxRange(selection) == GetTextLength();
}
