// 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/gtk/bookmarks/bookmark_bar_gtk.h"

#include <vector>

#include "base/bind.h"
#include "base/debug/trace_event.h"
#include "base/metrics/histogram.h"
#include "base/pickle.h"
#include "base/prefs/pref_service.h"
#include "base/strings/utf_string_conversions.h"
#include "chrome/browser/bookmarks/bookmark_model.h"
#include "chrome/browser/bookmarks/bookmark_model_factory.h"
#include "chrome/browser/bookmarks/bookmark_node_data.h"
#include "chrome/browser/bookmarks/bookmark_utils.h"
#include "chrome/browser/browser_shutdown.h"
#include "chrome/browser/chrome_notification_types.h"
#include "chrome/browser/extensions/extension_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/themes/theme_properties.h"
#include "chrome/browser/ui/bookmarks/bookmark_bar_constants.h"
#include "chrome/browser/ui/bookmarks/bookmark_drag_drop.h"
#include "chrome/browser/ui/bookmarks/bookmark_utils.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/chrome_pages.h"
#include "chrome/browser/ui/gtk/bookmarks/bookmark_bar_instructions_gtk.h"
#include "chrome/browser/ui/gtk/bookmarks/bookmark_menu_controller_gtk.h"
#include "chrome/browser/ui/gtk/bookmarks/bookmark_utils_gtk.h"
#include "chrome/browser/ui/gtk/browser_window_gtk.h"
#include "chrome/browser/ui/gtk/custom_button.h"
#include "chrome/browser/ui/gtk/event_utils.h"
#include "chrome/browser/ui/gtk/gtk_chrome_button.h"
#include "chrome/browser/ui/gtk/gtk_theme_service.h"
#include "chrome/browser/ui/gtk/gtk_util.h"
#include "chrome/browser/ui/gtk/hover_controller_gtk.h"
#include "chrome/browser/ui/gtk/menu_gtk.h"
#include "chrome/browser/ui/gtk/rounded_window.h"
#include "chrome/browser/ui/gtk/tabstrip_origin_provider.h"
#include "chrome/browser/ui/gtk/view_id_util.h"
#include "chrome/browser/ui/ntp_background_util.h"
#include "chrome/browser/ui/tabs/tab_strip_model.h"
#include "chrome/browser/ui/webui/ntp/core_app_launcher_handler.h"
#include "chrome/common/extensions/extension_constants.h"
#include "chrome/common/pref_names.h"
#include "chrome/common/url_constants.h"
#include "content/public/browser/notification_details.h"
#include "content/public/browser/notification_source.h"
#include "content/public/browser/user_metrics.h"
#include "content/public/browser/web_contents.h"
#include "content/public/browser/web_contents_view.h"
#include "grit/generated_resources.h"
#include "grit/theme_resources.h"
#include "grit/ui_resources.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/dragdrop/gtk_dnd_util.h"
#include "ui/base/gtk/gtk_compat.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas_skia_paint.h"
#include "ui/gfx/gtk_util.h"
#include "ui/gfx/image/cairo_cached_surface.h"
#include "ui/gfx/image/image.h"

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

namespace {

// The showing height of the bar.
const int kBookmarkBarHeight = 29;

// Padding for when the bookmark bar is detached.
const int kTopBottomNTPPadding = 12;
const int kLeftRightNTPPadding = 8;

// Padding around the bar's content area when the bookmark bar is detached.
const int kNTPPadding = 2;

// The number of pixels of rounding on the corners of the bookmark bar content
// area when in detached mode.
const int kNTPRoundedness = 3;

// The height of the bar when it is "hidden". It is usually not completely
// hidden because even when it is closed it forms the bottom few pixels of
// the toolbar.
const int kBookmarkBarMinimumHeight = 3;

// Left-padding for the instructional text.
const int kInstructionsPadding = 6;

// Padding around the "Other Bookmarks" button.
const int kOtherBookmarksPaddingHorizontal = 2;
const int kOtherBookmarksPaddingVertical = 1;

// The targets accepted by the toolbar and folder buttons for DnD.
const int kDestTargetList[] = { ui::CHROME_BOOKMARK_ITEM,
                                ui::CHROME_NAMED_URL,
                                ui::TEXT_URI_LIST,
                                ui::NETSCAPE_URL,
                                ui::TEXT_PLAIN, -1 };

// Acceptable drag actions for the bookmark bar drag destinations.
const GdkDragAction kDragAction =
    GdkDragAction(GDK_ACTION_MOVE | GDK_ACTION_COPY);

void SetToolBarStyle() {
  static bool style_was_set = false;

  if (style_was_set)
    return;
  style_was_set = true;

  gtk_rc_parse_string(
      "style \"chrome-bookmark-toolbar\" {"
      "  xthickness = 0\n"
      "  ythickness = 0\n"
      "  GtkWidget::focus-padding = 0\n"
      "  GtkContainer::border-width = 0\n"
      "  GtkToolbar::internal-padding = 1\n"
      "  GtkToolbar::shadow-type = GTK_SHADOW_NONE\n"
      "}\n"
      "widget \"*chrome-bookmark-toolbar\" style \"chrome-bookmark-toolbar\"");
}

void RecordAppLaunch(Profile* profile, const GURL& url) {
  DCHECK(profile->GetExtensionService());
  const extensions::Extension* extension =
      profile->GetExtensionService()->GetInstalledApp(url);
  if (!extension)
    return;

  CoreAppLauncherHandler::RecordAppLaunchType(
      extension_misc::APP_LAUNCH_BOOKMARK_BAR,
      extension->GetType());
}

}  // namespace

BookmarkBarGtk::BookmarkBarGtk(BrowserWindowGtk* window,
                               Browser* browser,
                               TabstripOriginProvider* tabstrip_origin_provider)
    : page_navigator_(NULL),
      browser_(browser),
      window_(window),
      tabstrip_origin_provider_(tabstrip_origin_provider),
      model_(NULL),
      instructions_(NULL),
      dragged_node_(NULL),
      drag_icon_(NULL),
      toolbar_drop_item_(NULL),
      theme_service_(GtkThemeService::GetFrom(browser->profile())),
      show_instructions_(true),
      menu_bar_helper_(this),
      slide_animation_(this),
      last_allocation_width_(-1),
      throbbing_widget_(NULL),
      weak_factory_(this),
      bookmark_bar_state_(BookmarkBar::DETACHED),
      max_height_(0) {
  Init();
  // Force an update by simulating being in the wrong state.
  // BrowserWindowGtk sets our true state after we're created.
  SetBookmarkBarState(BookmarkBar::SHOW,
                      BookmarkBar::DONT_ANIMATE_STATE_CHANGE);

  registrar_.Add(this, chrome::NOTIFICATION_BROWSER_THEME_CHANGED,
                 content::Source<ThemeService>(theme_service_));

  apps_shortcut_visible_.Init(
      prefs::kShowAppsShortcutInBookmarkBar,
      browser_->profile()->GetPrefs(),
      base::Bind(&BookmarkBarGtk::OnAppsPageShortcutVisibilityChanged,
                 base::Unretained(this)));

  OnAppsPageShortcutVisibilityChanged();

  edit_bookmarks_enabled_.Init(
      prefs::kEditBookmarksEnabled,
      browser_->profile()->GetPrefs(),
      base::Bind(&BookmarkBarGtk::OnEditBookmarksEnabledChanged,
                 base::Unretained(this)));

  OnEditBookmarksEnabledChanged();
}

BookmarkBarGtk::~BookmarkBarGtk() {
  RemoveAllButtons();
  bookmark_toolbar_.Destroy();
  event_box_.Destroy();
}

void BookmarkBarGtk::SetPageNavigator(PageNavigator* navigator) {
  page_navigator_ = navigator;
}

void BookmarkBarGtk::Init() {
  event_box_.Own(gtk_event_box_new());
  g_signal_connect(event_box_.get(), "destroy",
                   G_CALLBACK(&OnEventBoxDestroyThunk), this);
  g_signal_connect(event_box_.get(), "button-press-event",
                   G_CALLBACK(&OnButtonPressedThunk), this);

  ntp_padding_box_ = gtk_alignment_new(0, 0, 1, 1);
  gtk_container_add(GTK_CONTAINER(event_box_.get()), ntp_padding_box_);

  paint_box_ = gtk_event_box_new();
  gtk_container_add(GTK_CONTAINER(ntp_padding_box_), paint_box_);
  GdkColor paint_box_color =
      theme_service_->GetGdkColor(ThemeProperties::COLOR_TOOLBAR);
  gtk_widget_modify_bg(paint_box_, GTK_STATE_NORMAL, &paint_box_color);
  gtk_widget_add_events(paint_box_, GDK_POINTER_MOTION_MASK |
                                    GDK_BUTTON_PRESS_MASK);

  bookmark_hbox_ = gtk_hbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER(paint_box_), bookmark_hbox_);

  apps_shortcut_button_ = theme_service_->BuildChromeButton();
  bookmark_utils::ConfigureAppsShortcutButton(apps_shortcut_button_,
                                              theme_service_);
  g_signal_connect(apps_shortcut_button_, "clicked",
                   G_CALLBACK(OnAppsButtonClickedThunk), this);
  // Accept middle mouse clicking.
  gtk_util::SetButtonClickableByMouseButtons(
      apps_shortcut_button_, true, true, false);
  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), apps_shortcut_button_,
                     FALSE, FALSE, 0);

  instructions_ = gtk_alignment_new(0, 0, 1, 1);
  gtk_alignment_set_padding(GTK_ALIGNMENT(instructions_), 0, 0,
                            kInstructionsPadding, 0);
  Profile* profile = browser_->profile();
  instructions_gtk_.reset(new BookmarkBarInstructionsGtk(this, profile));
  gtk_container_add(GTK_CONTAINER(instructions_), instructions_gtk_->widget());
  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), instructions_,
                     TRUE, TRUE, 0);

  gtk_drag_dest_set(instructions_,
      GtkDestDefaults(GTK_DEST_DEFAULT_DROP | GTK_DEST_DEFAULT_MOTION),
      NULL, 0, kDragAction);
  ui::SetDestTargetList(instructions_, kDestTargetList);
  g_signal_connect(instructions_, "drag-data-received",
                   G_CALLBACK(&OnDragReceivedThunk), this);

  g_signal_connect(event_box_.get(), "expose-event",
                   G_CALLBACK(&OnEventBoxExposeThunk), this);
  UpdateEventBoxPaintability();

  bookmark_toolbar_.Own(gtk_toolbar_new());
  SetToolBarStyle();
  gtk_widget_set_name(bookmark_toolbar_.get(), "chrome-bookmark-toolbar");
  gtk_util::SuppressDefaultPainting(bookmark_toolbar_.get());
  g_signal_connect(bookmark_toolbar_.get(), "size-allocate",
                   G_CALLBACK(&OnToolbarSizeAllocateThunk), this);
  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), bookmark_toolbar_.get(),
                     TRUE, TRUE, 0);

  overflow_button_ = theme_service_->BuildChromeButton();
  g_object_set_data(G_OBJECT(overflow_button_), "left-align-popup",
                    reinterpret_cast<void*>(true));
  SetOverflowButtonAppearance();
  ConnectFolderButtonEvents(overflow_button_, false);
  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), overflow_button_,
                     FALSE, FALSE, 0);

  gtk_drag_dest_set(bookmark_toolbar_.get(), GTK_DEST_DEFAULT_DROP,
                    NULL, 0, kDragAction);
  ui::SetDestTargetList(bookmark_toolbar_.get(), kDestTargetList);
  g_signal_connect(bookmark_toolbar_.get(), "drag-motion",
                   G_CALLBACK(&OnToolbarDragMotionThunk), this);
  g_signal_connect(bookmark_toolbar_.get(), "drag-leave",
                   G_CALLBACK(&OnDragLeaveThunk), this);
  g_signal_connect(bookmark_toolbar_.get(), "drag-data-received",
                   G_CALLBACK(&OnDragReceivedThunk), this);

  other_bookmarks_separator_ = theme_service_->CreateToolbarSeparator();
  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), other_bookmarks_separator_,
                     FALSE, FALSE, 0);

  // We pack the button manually (rather than using gtk_button_set_*) so that
  // we can have finer control over its label.
  other_bookmarks_button_ = theme_service_->BuildChromeButton();
  gtk_widget_show_all(other_bookmarks_button_);
  ConnectFolderButtonEvents(other_bookmarks_button_, false);
  other_padding_ = gtk_alignment_new(0, 0, 1, 1);
  gtk_alignment_set_padding(GTK_ALIGNMENT(other_padding_),
                            kOtherBookmarksPaddingVertical,
                            kOtherBookmarksPaddingVertical,
                            kOtherBookmarksPaddingHorizontal,
                            kOtherBookmarksPaddingHorizontal);
  gtk_container_add(GTK_CONTAINER(other_padding_), other_bookmarks_button_);
  gtk_box_pack_start(GTK_BOX(bookmark_hbox_), other_padding_,
                     FALSE, FALSE, 0);
  gtk_widget_set_no_show_all(other_padding_, TRUE);

  gtk_widget_set_size_request(event_box_.get(), -1, kBookmarkBarMinimumHeight);

  ViewIDUtil::SetID(other_bookmarks_button_, VIEW_ID_OTHER_BOOKMARKS);
  ViewIDUtil::SetID(widget(), VIEW_ID_BOOKMARK_BAR);

  gtk_widget_show_all(widget());
  gtk_widget_hide(widget());

  AddCoreButtons();
  // TODO(erg): Handle extensions
  model_ = BookmarkModelFactory::GetForProfile(profile);
  model_->AddObserver(this);
  if (model_->loaded())
    Loaded(model_, false);
  // else case: we'll receive notification back from the BookmarkModel when done
  // loading, then we'll populate the bar.
}

void BookmarkBarGtk::SetBookmarkBarState(
    BookmarkBar::State state,
    BookmarkBar::AnimateChangeType animate_type) {
  TRACE_EVENT0("ui::gtk", "BookmarkBarGtk::SetBookmarkBarState");
  if (animate_type == BookmarkBar::ANIMATE_STATE_CHANGE &&
      (state == BookmarkBar::DETACHED ||
       bookmark_bar_state_ == BookmarkBar::DETACHED)) {
    // TODO(estade): animate the transition between detached and non or remove
    // detached entirely.
    animate_type = BookmarkBar::DONT_ANIMATE_STATE_CHANGE;
  }
  BookmarkBar::State old_state = bookmark_bar_state_;
  bookmark_bar_state_ = state;
  if (state == BookmarkBar::SHOW || state == BookmarkBar::DETACHED)
    Show(old_state, animate_type);
  else
    Hide(old_state, animate_type);
}

int BookmarkBarGtk::GetHeight() {
  GtkAllocation allocation;
  gtk_widget_get_allocation(event_box_.get(), &allocation);
  return allocation.height - kBookmarkBarMinimumHeight;
}

bool BookmarkBarGtk::IsAnimating() {
  return slide_animation_.is_animating();
}

void BookmarkBarGtk::CalculateMaxHeight() {
  if (theme_service_->UsingNativeTheme()) {
    // Get the requisition of our single child instead of the event box itself
    // because the event box probably already has a size request.
    GtkRequisition req;
    gtk_widget_size_request(ntp_padding_box_, &req);
    max_height_ = req.height;
  } else {
    max_height_ = (bookmark_bar_state_ == BookmarkBar::DETACHED) ?
                  chrome::kNTPBookmarkBarHeight : kBookmarkBarHeight;
  }
}

void BookmarkBarGtk::AnimationProgressed(const ui::Animation* animation) {
  DCHECK_EQ(animation, &slide_animation_);

  gint height =
      static_cast<gint>(animation->GetCurrentValue() *
                        (max_height_ - kBookmarkBarMinimumHeight)) +
      kBookmarkBarMinimumHeight;
  gtk_widget_set_size_request(event_box_.get(), -1, height);
}

void BookmarkBarGtk::AnimationEnded(const ui::Animation* animation) {
  DCHECK_EQ(animation, &slide_animation_);

  if (!slide_animation_.IsShowing()) {
    gtk_widget_hide(bookmark_hbox_);

    // We can be windowless during unit tests.
    if (window_) {
      // Because of our constant resizing and our toolbar/bookmark bar overlap
      // shenanigans, gtk+ gets confused, partially draws parts of the bookmark
      // bar into the toolbar and than doesn't queue a redraw to fix it. So do
      // it manually by telling the toolbar area to redraw itself.
      window_->QueueToolbarRedraw();
    }
  }
}

// MenuBarHelper::Delegate implementation --------------------------------------
void BookmarkBarGtk::PopupForButton(GtkWidget* button) {
  const BookmarkNode* node = GetNodeForToolButton(button);
  DCHECK(node);
  DCHECK(page_navigator_);

  int first_hidden = GetFirstHiddenBookmark(0, NULL);
  if (first_hidden == -1) {
    // No overflow exists: don't show anything for the overflow button.
    if (button == overflow_button_)
      return;
  } else {
    // Overflow exists: don't show anything for an overflowed folder button.
    if (button != overflow_button_ && button != other_bookmarks_button_ &&
        node->parent()->GetIndexOf(node) >= first_hidden) {
      return;
    }
  }

  current_menu_.reset(
      new BookmarkMenuController(browser_, page_navigator_,
          GTK_WINDOW(gtk_widget_get_toplevel(button)),
          node,
          button == overflow_button_ ? first_hidden : 0));
  menu_bar_helper_.MenuStartedShowing(button, current_menu_->widget());
  GdkEvent* event = gtk_get_current_event();
  current_menu_->Popup(button, event->button.button, event->button.time);
  gdk_event_free(event);
}

void BookmarkBarGtk::PopupForButtonNextTo(GtkWidget* button,
                                          GtkMenuDirectionType dir) {
  const BookmarkNode* relative_node = GetNodeForToolButton(button);
  DCHECK(relative_node);

  // Find out the order of the buttons.
  std::vector<GtkWidget*> folder_list;
  const int first_hidden = GetFirstHiddenBookmark(0, &folder_list);
  if (first_hidden != -1)
    folder_list.push_back(overflow_button_);
  folder_list.push_back(other_bookmarks_button_);

  // Find the position of |button|.
  int button_idx = -1;
  for (size_t i = 0; i < folder_list.size(); ++i) {
    if (folder_list[i] == button) {
      button_idx = i;
      break;
    }
  }
  DCHECK_NE(button_idx, -1);

  // Find the GtkWidget* for the actual target button.
  int shift = dir == GTK_MENU_DIR_PARENT ? -1 : 1;
  button_idx = (button_idx + shift + folder_list.size()) % folder_list.size();
  PopupForButton(folder_list[button_idx]);
}

void BookmarkBarGtk::CloseMenu() {
  current_context_menu_->Cancel();
}

void BookmarkBarGtk::Show(BookmarkBar::State old_state,
                          BookmarkBar::AnimateChangeType animate_type) {
  gtk_widget_show_all(widget());
  UpdateDetachedState(old_state);
  CalculateMaxHeight();
  if (animate_type == BookmarkBar::ANIMATE_STATE_CHANGE) {
    slide_animation_.Show();
  } else {
    slide_animation_.Reset(1);
    AnimationProgressed(&slide_animation_);
  }

  if (model_ && model_->loaded())
    UpdateOtherBookmarksVisibility();

  // Hide out behind the findbar. This is rather fragile code, it could
  // probably be improved.
  if (bookmark_bar_state_ == BookmarkBar::DETACHED) {
    if (theme_service_->UsingNativeTheme()) {
      GtkWidget* parent = gtk_widget_get_parent(event_box_.get());
      if (gtk_widget_get_realized(parent))
        gdk_window_lower(gtk_widget_get_window(parent));
      if (gtk_widget_get_realized(event_box_.get()))
        gdk_window_lower(gtk_widget_get_window(event_box_.get()));
    } else {  // Chromium theme mode.
      if (gtk_widget_get_realized(paint_box_)) {
        gdk_window_lower(gtk_widget_get_window(paint_box_));
        // The event box won't stay below its children's GdkWindows unless we
        // toggle the above-child property here. If the event box doesn't stay
        // below its children then events will be routed to it rather than the
        // children.
        gtk_event_box_set_above_child(GTK_EVENT_BOX(event_box_.get()), TRUE);
        gtk_event_box_set_above_child(GTK_EVENT_BOX(event_box_.get()), FALSE);
      }
    }
  }

  // Maybe show the instructions
  gtk_widget_set_visible(bookmark_toolbar_.get(), !show_instructions_);
  gtk_widget_set_visible(instructions_, show_instructions_);

  SetChevronState();
}

void BookmarkBarGtk::Hide(BookmarkBar::State old_state,
                          BookmarkBar::AnimateChangeType animate_type) {
  UpdateDetachedState(old_state);

  // After coming out of fullscreen, the browser window sets the bookmark bar
  // to the "hidden" state, which means we need to show our minimum height.
  if (!window_->IsFullscreen())
    gtk_widget_show(widget());
  CalculateMaxHeight();
  // Sometimes we get called without a matching call to open. If that happens
  // then force hide.
  if (slide_animation_.IsShowing() &&
      animate_type == BookmarkBar::ANIMATE_STATE_CHANGE) {
    slide_animation_.Hide();
  } else {
    gtk_widget_hide(bookmark_hbox_);
    slide_animation_.Reset(0);
    AnimationProgressed(&slide_animation_);
  }
}

void BookmarkBarGtk::SetInstructionState() {
  if (model_)
    show_instructions_ = model_->bookmark_bar_node()->empty();

  gtk_widget_set_visible(bookmark_toolbar_.get(), !show_instructions_);
  gtk_widget_set_visible(instructions_, show_instructions_);
}

void BookmarkBarGtk::SetChevronState() {
  if (!gtk_widget_get_visible(bookmark_hbox_))
    return;

  if (show_instructions_) {
    gtk_widget_hide(overflow_button_);
    return;
  }

  int extra_space = 0;
  if (gtk_widget_get_visible(overflow_button_)) {
    GtkAllocation allocation;
    gtk_widget_get_allocation(overflow_button_, &allocation);
    extra_space = allocation.width;
  }

  int overflow_idx = GetFirstHiddenBookmark(extra_space, NULL);
  if (overflow_idx == -1)
    gtk_widget_hide(overflow_button_);
  else
    gtk_widget_show_all(overflow_button_);
}

void BookmarkBarGtk::UpdateOtherBookmarksVisibility() {
  bool has_other_children = !model_->other_node()->empty();

  gtk_widget_set_visible(other_padding_, has_other_children);
  gtk_widget_set_visible(other_bookmarks_separator_, has_other_children);
}

void BookmarkBarGtk::RemoveAllButtons() {
  gtk_util::RemoveAllChildren(bookmark_toolbar_.get());
  menu_bar_helper_.Clear();
}

void BookmarkBarGtk::AddCoreButtons() {
  menu_bar_helper_.Add(other_bookmarks_button_);
  menu_bar_helper_.Add(overflow_button_);
}

void BookmarkBarGtk::ResetButtons() {
  RemoveAllButtons();
  AddCoreButtons();

  const BookmarkNode* bar = model_->bookmark_bar_node();
  DCHECK(bar && model_->other_node());

  // Create a button for each of the children on the bookmark bar.
  for (int i = 0; i < bar->child_count(); ++i) {
    const BookmarkNode* node = bar->GetChild(i);
    GtkToolItem* item = CreateBookmarkToolItem(node);
    gtk_toolbar_insert(GTK_TOOLBAR(bookmark_toolbar_.get()), item, -1);
    if (node->is_folder())
      menu_bar_helper_.Add(gtk_bin_get_child(GTK_BIN(item)));
  }

  bookmark_utils::ConfigureButtonForNode(model_->other_node(),
      model_, other_bookmarks_button_, theme_service_);

  SetInstructionState();
  SetChevronState();
}

int BookmarkBarGtk::GetBookmarkButtonCount() {
  GList* children = gtk_container_get_children(
      GTK_CONTAINER(bookmark_toolbar_.get()));
  int count = g_list_length(children);
  g_list_free(children);
  return count;
}

bookmark_utils::BookmarkLaunchLocation
    BookmarkBarGtk::GetBookmarkLaunchLocation() const {
  return bookmark_bar_state_ == BookmarkBar::DETACHED ?
      bookmark_utils::LAUNCH_DETACHED_BAR :
      bookmark_utils::LAUNCH_ATTACHED_BAR;
}

void BookmarkBarGtk::SetOverflowButtonAppearance() {
  GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(overflow_button_));
  if (former_child)
    gtk_widget_destroy(former_child);

  GtkWidget* new_child;
  if (theme_service_->UsingNativeTheme()) {
    new_child = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
  } else {
    const gfx::Image& image = ui::ResourceBundle::GetSharedInstance().
        GetNativeImageNamed(IDR_BOOKMARK_BAR_CHEVRONS,
                            ui::ResourceBundle::RTL_ENABLED);
    new_child = gtk_image_new_from_pixbuf(image.ToGdkPixbuf());
  }

  gtk_container_add(GTK_CONTAINER(overflow_button_), new_child);
  SetChevronState();
}

int BookmarkBarGtk::GetFirstHiddenBookmark(int extra_space,
    std::vector<GtkWidget*>* showing_folders) {
  int rv = 0;
  // We're going to keep track of how much width we've used as we move along
  // the bookmark bar. If we ever surpass the width of the bookmark bar, we'll
  // know that's the first hidden bookmark.
  int width_used = 0;
  // GTK appears to require one pixel of padding to the side of the first and
  // last buttons on the bar.
  // TODO(gideonwald): figure out the precise source of these extra two pixels
  // and make this calculation more reliable.
  GtkAllocation allocation;
  gtk_widget_get_allocation(bookmark_toolbar_.get(), &allocation);
  int total_width = allocation.width - 2;
  bool overflow = false;
  GtkRequisition requested_size_;
  GList* toolbar_items =
      gtk_container_get_children(GTK_CONTAINER(bookmark_toolbar_.get()));
  for (GList* iter = toolbar_items; iter; iter = g_list_next(iter)) {
    GtkWidget* tool_item = reinterpret_cast<GtkWidget*>(iter->data);
    gtk_widget_size_request(tool_item, &requested_size_);
    width_used += requested_size_.width;
    // |extra_space| is available if we can remove the chevron, which happens
    // only if there are no more potential overflow bookmarks after this one.
    overflow = width_used > total_width + (g_list_next(iter) ? 0 : extra_space);
    if (overflow)
      break;

    if (showing_folders &&
        model_->bookmark_bar_node()->GetChild(rv)->is_folder()) {
      showing_folders->push_back(gtk_bin_get_child(GTK_BIN(tool_item)));
    }
    rv++;
  }

  g_list_free(toolbar_items);

  if (!overflow)
    return -1;

  return rv;
}

void BookmarkBarGtk::UpdateDetachedState(BookmarkBar::State old_state) {
  bool old_detached = old_state == BookmarkBar::DETACHED;
  bool detached = bookmark_bar_state_ == BookmarkBar::DETACHED;
  if (detached == old_detached)
    return;

  if (detached) {
    gtk_event_box_set_visible_window(GTK_EVENT_BOX(paint_box_), TRUE);
    GdkColor stroke_color = theme_service_->UsingNativeTheme() ?
        theme_service_->GetBorderColor() :
        theme_service_->GetGdkColor(ThemeProperties::COLOR_NTP_HEADER);
    gtk_util::ActAsRoundedWindow(paint_box_, stroke_color, kNTPRoundedness,
                                 gtk_util::ROUNDED_ALL, gtk_util::BORDER_ALL);

    gtk_alignment_set_padding(GTK_ALIGNMENT(ntp_padding_box_),
        kTopBottomNTPPadding, kTopBottomNTPPadding,
        kLeftRightNTPPadding, kLeftRightNTPPadding);
    gtk_container_set_border_width(GTK_CONTAINER(bookmark_hbox_), kNTPPadding);
  } else {
    gtk_util::StopActingAsRoundedWindow(paint_box_);
    gtk_event_box_set_visible_window(GTK_EVENT_BOX(paint_box_), FALSE);
    gtk_alignment_set_padding(GTK_ALIGNMENT(ntp_padding_box_), 0, 0, 0, 0);
    gtk_container_set_border_width(GTK_CONTAINER(bookmark_hbox_), 0);
  }

  UpdateEventBoxPaintability();
  // |window_| can be NULL during testing.
  // Listen for parent size allocations. Only connect once.
  if (window_ && detached) {
    GtkWidget* parent = gtk_widget_get_parent(widget());
    if (parent &&
        g_signal_handler_find(parent, G_SIGNAL_MATCH_FUNC,
            0, 0, NULL, reinterpret_cast<gpointer>(OnParentSizeAllocateThunk),
            NULL) == 0) {
      g_signal_connect(parent, "size-allocate",
                       G_CALLBACK(OnParentSizeAllocateThunk), this);
    }
  }
}

void BookmarkBarGtk::UpdateEventBoxPaintability() {
  gtk_widget_set_app_paintable(
      event_box_.get(),
      (!theme_service_->UsingNativeTheme() ||
       bookmark_bar_state_ == BookmarkBar::DETACHED));
  // When using the GTK+ theme, we need to have the event box be visible so
  // buttons don't get a halo color from the background.  When using Chromium
  // themes, we want to let the background show through the toolbar.

  gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_.get()),
                                   theme_service_->UsingNativeTheme());
}

void BookmarkBarGtk::PaintEventBox() {
  gfx::Size web_contents_size;
  if (GetWebContentsSize(&web_contents_size) &&
      web_contents_size != last_web_contents_size_) {
    last_web_contents_size_ = web_contents_size;
    gtk_widget_queue_draw(event_box_.get());
  }
}

bool BookmarkBarGtk::GetWebContentsSize(gfx::Size* size) {
  Browser* browser = browser_;
  if (!browser) {
    NOTREACHED();
    return false;
  }
  WebContents* web_contents =
      browser->tab_strip_model()->GetActiveWebContents();
  if (!web_contents) {
    // It is possible to have a browser but no WebContents while under testing,
    // so don't NOTREACHED() and error the program.
    return false;
  }
  if (!web_contents->GetView()) {
    NOTREACHED();
    return false;
  }
  *size = web_contents->GetView()->GetContainerSize();
  return true;
}

void BookmarkBarGtk::StartThrobbingAfterAllocation(GtkWidget* item) {
  g_signal_connect_after(
      item, "size-allocate", G_CALLBACK(OnItemAllocateThunk), this);
}

void BookmarkBarGtk::OnItemAllocate(GtkWidget* item,
                                    GtkAllocation* allocation) {
  // We only want to fire on the item's first allocation.
  g_signal_handlers_disconnect_by_func(
      item, reinterpret_cast<gpointer>(&OnItemAllocateThunk), this);

  GtkWidget* button = gtk_bin_get_child(GTK_BIN(item));
  const BookmarkNode* node = GetNodeForToolButton(button);
  if (node)
    StartThrobbing(node);
}

void BookmarkBarGtk::StartThrobbing(const BookmarkNode* node) {
  const BookmarkNode* parent_on_bb = NULL;
  for (const BookmarkNode* parent = node; parent;
       parent = parent->parent()) {
    if (parent->parent() == model_->bookmark_bar_node()) {
      parent_on_bb = parent;
      break;
    }
  }

  GtkWidget* widget_to_throb = NULL;

  if (!parent_on_bb) {
    // Descendant of "Other Bookmarks".
    widget_to_throb = other_bookmarks_button_;
  } else {
    int hidden = GetFirstHiddenBookmark(0, NULL);
    int idx = model_->bookmark_bar_node()->GetIndexOf(parent_on_bb);

    if (hidden >= 0 && hidden <= idx) {
      widget_to_throb = overflow_button_;
    } else {
      widget_to_throb = gtk_bin_get_child(GTK_BIN(gtk_toolbar_get_nth_item(
          GTK_TOOLBAR(bookmark_toolbar_.get()), idx)));
    }
  }

  SetThrobbingWidget(widget_to_throb);
}

void BookmarkBarGtk::SetThrobbingWidget(GtkWidget* widget) {
  if (throbbing_widget_) {
    HoverControllerGtk* hover_controller =
        HoverControllerGtk::GetHoverControllerGtk(throbbing_widget_);
    if (hover_controller)
      hover_controller->StartThrobbing(0);

    g_signal_handlers_disconnect_by_func(
        throbbing_widget_,
        reinterpret_cast<gpointer>(OnThrobbingWidgetDestroyThunk),
        this);
    g_object_unref(throbbing_widget_);
    throbbing_widget_ = NULL;
  }

  if (widget) {
    throbbing_widget_ = widget;
    g_object_ref(throbbing_widget_);
    g_signal_connect(throbbing_widget_, "destroy",
                     G_CALLBACK(OnThrobbingWidgetDestroyThunk), this);

    HoverControllerGtk* hover_controller =
        HoverControllerGtk::GetHoverControllerGtk(throbbing_widget_);
    if (hover_controller)
      hover_controller->StartThrobbing(4);
  }
}

gboolean BookmarkBarGtk::ItemDraggedOverToolbar(GdkDragContext* context,
                                                int index,
                                                guint time) {
  if (!edit_bookmarks_enabled_.GetValue())
    return FALSE;
  GdkAtom target_type =
      gtk_drag_dest_find_target(bookmark_toolbar_.get(), context, NULL);
  if (target_type == GDK_NONE) {
    // We shouldn't act like a drop target when something that we can't deal
    // with is dragged over the toolbar.
    return FALSE;
  }

  if (!toolbar_drop_item_) {
    if (dragged_node_) {
      toolbar_drop_item_ = CreateBookmarkToolItem(dragged_node_);
      g_object_ref_sink(GTK_OBJECT(toolbar_drop_item_));
    } else {
      // Create a fake item the size of other_node().
      //
      // TODO(erg): Maybe somehow figure out the real size for the drop target?
      toolbar_drop_item_ =
          CreateBookmarkToolItem(model_->other_node());
      g_object_ref_sink(GTK_OBJECT(toolbar_drop_item_));
    }
  }

  gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(bookmark_toolbar_.get()),
                                      GTK_TOOL_ITEM(toolbar_drop_item_),
                                      index);
  if (target_type == ui::GetAtomForTarget(ui::CHROME_BOOKMARK_ITEM)) {
    gdk_drag_status(context, GDK_ACTION_MOVE, time);
  } else {
    gdk_drag_status(context, GDK_ACTION_COPY, time);
  }

  return TRUE;
}

int BookmarkBarGtk::GetToolbarIndexForDragOverFolder(GtkWidget* button,
                                                     gint x) {
  GtkAllocation allocation;
  gtk_widget_get_allocation(button, &allocation);

  int margin = std::min(15, static_cast<int>(0.3 * allocation.width));
  if (x > margin && x < (allocation.width - margin))
    return -1;

  GtkWidget* parent = gtk_widget_get_parent(button);
  gint index = gtk_toolbar_get_item_index(GTK_TOOLBAR(bookmark_toolbar_.get()),
                                          GTK_TOOL_ITEM(parent));
  if (x > margin)
    index++;
  return index;
}

void BookmarkBarGtk::ClearToolbarDropHighlighting() {
  if (toolbar_drop_item_) {
    g_object_unref(toolbar_drop_item_);
    toolbar_drop_item_ = NULL;
  }

  gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(bookmark_toolbar_.get()),
                                      NULL, 0);
}

void BookmarkBarGtk::Loaded(BookmarkModel* model, bool ids_reassigned) {
  // If |instructions_| has been nulled, we are in the middle of browser
  // shutdown. Do nothing.
  if (!instructions_)
    return;

  UpdateOtherBookmarksVisibility();
  ResetButtons();
}

void BookmarkBarGtk::BookmarkModelBeingDeleted(BookmarkModel* model) {
  // The bookmark model should never be deleted before us. This code exists
  // to check for regressions in shutdown code and not crash.
  if (!browser_shutdown::ShuttingDownWithoutClosingBrowsers())
    NOTREACHED();

  // Do minimal cleanup, presumably we'll be deleted shortly.
  model_->RemoveObserver(this);
  model_ = NULL;
}

void BookmarkBarGtk::BookmarkNodeMoved(BookmarkModel* model,
                                       const BookmarkNode* old_parent,
                                       int old_index,
                                       const BookmarkNode* new_parent,
                                       int new_index) {
  const BookmarkNode* node = new_parent->GetChild(new_index);
  BookmarkNodeRemoved(model, old_parent, old_index, node);
  BookmarkNodeAdded(model, new_parent, new_index);
}

void BookmarkBarGtk::BookmarkNodeAdded(BookmarkModel* model,
                                       const BookmarkNode* parent,
                                       int index) {
  UpdateOtherBookmarksVisibility();

  const BookmarkNode* node = parent->GetChild(index);
  if (parent != model_->bookmark_bar_node()) {
    StartThrobbing(node);
    return;
  }
  DCHECK(index >= 0 && index <= GetBookmarkButtonCount());

  GtkToolItem* item = CreateBookmarkToolItem(node);
  gtk_toolbar_insert(GTK_TOOLBAR(bookmark_toolbar_.get()),
                     item, index);
  if (node->is_folder())
    menu_bar_helper_.Add(gtk_bin_get_child(GTK_BIN(item)));

  SetInstructionState();
  SetChevronState();

  StartThrobbingAfterAllocation(GTK_WIDGET(item));
}

void BookmarkBarGtk::BookmarkNodeRemoved(BookmarkModel* model,
                                         const BookmarkNode* parent,
                                         int old_index,
                                         const BookmarkNode* node) {
  UpdateOtherBookmarksVisibility();

  if (parent != model_->bookmark_bar_node()) {
    // We only care about nodes on the bookmark bar.
    return;
  }
  DCHECK(old_index >= 0 && old_index < GetBookmarkButtonCount());

  GtkWidget* to_remove = GTK_WIDGET(gtk_toolbar_get_nth_item(
      GTK_TOOLBAR(bookmark_toolbar_.get()), old_index));
  if (node->is_folder())
    menu_bar_helper_.Remove(gtk_bin_get_child(GTK_BIN(to_remove)));
  gtk_container_remove(GTK_CONTAINER(bookmark_toolbar_.get()),
                       to_remove);

  SetInstructionState();
  SetChevronState();
}

void BookmarkBarGtk::BookmarkAllNodesRemoved(BookmarkModel* model) {
  UpdateOtherBookmarksVisibility();
  ResetButtons();
}

void BookmarkBarGtk::BookmarkNodeChanged(BookmarkModel* model,
                                         const BookmarkNode* node) {
  if (node->parent() != model_->bookmark_bar_node()) {
    // We only care about nodes on the bookmark bar.
    return;
  }
  int index = model_->bookmark_bar_node()->GetIndexOf(node);
  DCHECK(index != -1);

  GtkToolItem* item = gtk_toolbar_get_nth_item(
      GTK_TOOLBAR(bookmark_toolbar_.get()), index);
  GtkWidget* button = gtk_bin_get_child(GTK_BIN(item));
  bookmark_utils::ConfigureButtonForNode(node, model, button, theme_service_);
  SetChevronState();
}

void BookmarkBarGtk::BookmarkNodeFaviconChanged(BookmarkModel* model,
                                                const BookmarkNode* node) {
  BookmarkNodeChanged(model, node);
}

void BookmarkBarGtk::BookmarkNodeChildrenReordered(BookmarkModel* model,
                                                   const BookmarkNode* node) {
  if (node != model_->bookmark_bar_node())
    return;  // We only care about reordering of the bookmark bar node.

  ResetButtons();
}

void BookmarkBarGtk::Observe(int type,
                             const content::NotificationSource& source,
                             const content::NotificationDetails& details) {
  if (type == chrome::NOTIFICATION_BROWSER_THEME_CHANGED) {
    if (model_ && model_->loaded()) {
      // Regenerate the bookmark bar with all new objects with their theme
      // properties set correctly for the new theme.
      ResetButtons();
    }

    // Resize the bookmark bar since the target height may have changed.
    CalculateMaxHeight();
    AnimationProgressed(&slide_animation_);

    UpdateEventBoxPaintability();

    GdkColor paint_box_color =
        theme_service_->GetGdkColor(ThemeProperties::COLOR_TOOLBAR);
    gtk_widget_modify_bg(paint_box_, GTK_STATE_NORMAL, &paint_box_color);

    if (bookmark_bar_state_ == BookmarkBar::DETACHED) {
      GdkColor stroke_color = theme_service_->UsingNativeTheme() ?
          theme_service_->GetBorderColor() :
          theme_service_->GetGdkColor(ThemeProperties::COLOR_NTP_HEADER);
      gtk_util::SetRoundedWindowBorderColor(paint_box_, stroke_color);
    }

    SetOverflowButtonAppearance();
  }
}

GtkWidget* BookmarkBarGtk::CreateBookmarkButton(const BookmarkNode* node) {
  GtkWidget* button = theme_service_->BuildChromeButton();
  bookmark_utils::ConfigureButtonForNode(node, model_, button, theme_service_);

  // The tool item is also a source for dragging
  gtk_drag_source_set(button, GDK_BUTTON1_MASK, NULL, 0,
      static_cast<GdkDragAction>(GDK_ACTION_MOVE | GDK_ACTION_COPY));
  int target_mask = bookmark_utils::GetCodeMask(node->is_folder());
  ui::SetSourceTargetListFromCodeMask(button, target_mask);
  g_signal_connect(button, "drag-begin",
                   G_CALLBACK(&OnButtonDragBeginThunk), this);
  g_signal_connect(button, "drag-end",
                   G_CALLBACK(&OnButtonDragEndThunk), this);
  g_signal_connect(button, "drag-data-get",
                   G_CALLBACK(&OnButtonDragGetThunk), this);
  // We deliberately don't connect to "drag-data-delete" because the action of
  // moving a button will regenerate all the contents of the bookmarks bar
  // anyway.

  if (node->is_url()) {
    // Connect to 'button-release-event' instead of 'clicked' because we need
    // access to the modifier keys and we do different things on each
    // button.
    g_signal_connect(button, "button-press-event",
                     G_CALLBACK(OnButtonPressedThunk), this);
    g_signal_connect(button, "clicked",
                     G_CALLBACK(OnClickedThunk), this);
    gtk_util::SetButtonTriggersNavigation(button);
  } else {
    ConnectFolderButtonEvents(button, true);
  }

  return button;
}

GtkToolItem* BookmarkBarGtk::CreateBookmarkToolItem(const BookmarkNode* node) {
  GtkWidget* button = CreateBookmarkButton(node);
  g_object_set_data(G_OBJECT(button), "left-align-popup",
                    reinterpret_cast<void*>(true));

  GtkToolItem* item = gtk_tool_item_new();
  gtk_container_add(GTK_CONTAINER(item), button);
  gtk_widget_show_all(GTK_WIDGET(item));

  return item;
}

void BookmarkBarGtk::ConnectFolderButtonEvents(GtkWidget* widget,
                                               bool is_tool_item) {
  // For toolbar items (i.e. not the overflow button or other bookmarks
  // button), we handle motion and highlighting manually.
  gtk_drag_dest_set(widget,
                    is_tool_item ? GTK_DEST_DEFAULT_DROP :
                                   GTK_DEST_DEFAULT_ALL,
                    NULL,
                    0,
                    kDragAction);
  ui::SetDestTargetList(widget, kDestTargetList);
  g_signal_connect(widget, "drag-data-received",
                   G_CALLBACK(&OnDragReceivedThunk), this);
  if (is_tool_item) {
    g_signal_connect(widget, "drag-motion",
                     G_CALLBACK(&OnFolderDragMotionThunk), this);
    g_signal_connect(widget, "drag-leave",
                     G_CALLBACK(&OnDragLeaveThunk), this);
  }

  g_signal_connect(widget, "button-press-event",
                   G_CALLBACK(OnButtonPressedThunk), this);
  g_signal_connect(widget, "clicked",
                   G_CALLBACK(OnFolderClickedThunk), this);

  // Accept middle mouse clicking (which opens all). This must be called after
  // connecting to "button-press-event" because the handler it attaches stops
  // the propagation of that signal.
  gtk_util::SetButtonClickableByMouseButtons(widget, true, true, false);
}

const BookmarkNode* BookmarkBarGtk::GetNodeForToolButton(GtkWidget* widget) {
  // First check to see if |button| is special cased.
  if (widget == other_bookmarks_button_)
    return model_->other_node();
  else if (widget == event_box_.get() || widget == overflow_button_)
    return model_->bookmark_bar_node();

  // Search the contents of |bookmark_toolbar_| for the corresponding widget
  // and find its index.
  GtkWidget* item_to_find = gtk_widget_get_parent(widget);
  int index_to_use = -1;
  int index = 0;
  GList* children = gtk_container_get_children(
      GTK_CONTAINER(bookmark_toolbar_.get()));
  for (GList* item = children; item; item = item->next, index++) {
    if (item->data == item_to_find) {
      index_to_use = index;
      break;
    }
  }
  g_list_free(children);

  if (index_to_use != -1)
    return model_->bookmark_bar_node()->GetChild(index_to_use);

  return NULL;
}

void BookmarkBarGtk::PopupMenuForNode(GtkWidget* sender,
                                      const BookmarkNode* node,
                                      GdkEventButton* event) {
  if (!model_->loaded()) {
    // Don't do anything if the model isn't loaded.
    return;
  }

  const BookmarkNode* parent = NULL;
  std::vector<const BookmarkNode*> nodes;
  if (sender == other_bookmarks_button_) {
    nodes.push_back(node);
    parent = model_->bookmark_bar_node();
  } else if (sender != bookmark_toolbar_.get()) {
    nodes.push_back(node);
    parent = node->parent();
  } else {
    parent = model_->bookmark_bar_node();
    nodes.push_back(parent);
  }

  GtkWindow* window = GTK_WINDOW(gtk_widget_get_toplevel(sender));
  current_context_menu_controller_.reset(
      new BookmarkContextMenuController(
          window, this, browser_, browser_->profile(), page_navigator_, parent,
          nodes));
  current_context_menu_.reset(
      new MenuGtk(NULL, current_context_menu_controller_->menu_model()));
  current_context_menu_->PopupAsContext(
      gfx::Point(event->x_root, event->y_root),
      event->time);
}

gboolean BookmarkBarGtk::OnButtonPressed(GtkWidget* sender,
                                         GdkEventButton* event) {
  last_pressed_coordinates_ = gfx::Point(event->x, event->y);

  if (event->button == 3 && gtk_widget_get_visible(bookmark_hbox_)) {
    const BookmarkNode* node = GetNodeForToolButton(sender);
    DCHECK(node);
    DCHECK(page_navigator_);
    PopupMenuForNode(sender, node, event);
  }

  return FALSE;
}

void BookmarkBarGtk::OnClicked(GtkWidget* sender) {
  const BookmarkNode* node = GetNodeForToolButton(sender);
  DCHECK(node);
  DCHECK(node->is_url());
  DCHECK(page_navigator_);

  RecordAppLaunch(browser_->profile(), node->url());
  chrome::OpenAll(window_->GetNativeWindow(), page_navigator_, node,
                  event_utils::DispositionForCurrentButtonPressEvent(),
                  browser_->profile());

  bookmark_utils::RecordBookmarkLaunch(GetBookmarkLaunchLocation());
}

void BookmarkBarGtk::OnButtonDragBegin(GtkWidget* button,
                                       GdkDragContext* drag_context) {
  GtkWidget* button_parent = gtk_widget_get_parent(button);

  // The parent tool item might be removed during the drag. Ref it so |button|
  // won't get destroyed.
  g_object_ref(button_parent);

  const BookmarkNode* node = GetNodeForToolButton(button);
  DCHECK(!dragged_node_);
  dragged_node_ = node;
  DCHECK(dragged_node_);

  drag_icon_ = bookmark_utils::GetDragRepresentationForNode(
      node, model_, theme_service_);

  // We have to jump through some hoops to get the drag icon to line up because
  // it is a different size than the button.
  GtkRequisition req;
  gtk_widget_size_request(drag_icon_, &req);
  gfx::Rect button_rect = gtk_util::WidgetBounds(button);
  gfx::Point drag_icon_relative =
      gfx::Rect(req.width, req.height).CenterPoint() +
      (last_pressed_coordinates_ - button_rect.CenterPoint());
  gtk_drag_set_icon_widget(drag_context, drag_icon_,
                           drag_icon_relative.x(),
                           drag_icon_relative.y());

  // Hide our node, but reserve space for it on the toolbar.
  int index = gtk_toolbar_get_item_index(GTK_TOOLBAR(bookmark_toolbar_.get()),
                                         GTK_TOOL_ITEM(button_parent));
  gtk_widget_hide(button);
  toolbar_drop_item_ = CreateBookmarkToolItem(dragged_node_);
  g_object_ref_sink(GTK_OBJECT(toolbar_drop_item_));
  gtk_toolbar_set_drop_highlight_item(GTK_TOOLBAR(bookmark_toolbar_.get()),
                                      GTK_TOOL_ITEM(toolbar_drop_item_), index);
  // Make sure it stays hidden for the duration of the drag.
  gtk_widget_set_no_show_all(button, TRUE);
}

void BookmarkBarGtk::OnButtonDragEnd(GtkWidget* button,
                                     GdkDragContext* drag_context) {
  gtk_widget_show(button);
  gtk_widget_set_no_show_all(button, FALSE);

  ClearToolbarDropHighlighting();

  DCHECK(dragged_node_);
  dragged_node_ = NULL;

  DCHECK(drag_icon_);
  gtk_widget_destroy(drag_icon_);
  drag_icon_ = NULL;

  g_object_unref(gtk_widget_get_parent(button));
}

void BookmarkBarGtk::OnButtonDragGet(GtkWidget* widget,
                                     GdkDragContext* context,
                                     GtkSelectionData* selection_data,
                                     guint target_type,
                                     guint time) {
  const BookmarkNode* node = bookmark_utils::BookmarkNodeForWidget(widget);
  bookmark_utils::WriteBookmarkToSelection(node, selection_data, target_type,
                                           browser_->profile());
}

void BookmarkBarGtk::OnAppsButtonClicked(GtkWidget* sender) {
  content::OpenURLParams params(
      GURL(chrome::kChromeUIAppsURL),
      content::Referrer(),
      event_utils::DispositionForCurrentButtonPressEvent(),
      content::PAGE_TRANSITION_AUTO_BOOKMARK,
      false);
  browser_->OpenURL(params);
  bookmark_utils::RecordAppsPageOpen(GetBookmarkLaunchLocation());
}

void BookmarkBarGtk::OnFolderClicked(GtkWidget* sender) {
  // Stop its throbbing, if any.
  HoverControllerGtk* hover_controller =
      HoverControllerGtk::GetHoverControllerGtk(sender);
  if (hover_controller)
    hover_controller->StartThrobbing(0);

  GdkEvent* event = gtk_get_current_event();
  if (event->button.button == 1 ||
      (event->button.button == 2 && sender == overflow_button_)) {
    bookmark_utils::RecordBookmarkFolderOpen(GetBookmarkLaunchLocation());
    PopupForButton(sender);
  } else if (event->button.button == 2) {
    const BookmarkNode* node = GetNodeForToolButton(sender);
    chrome::OpenAll(window_->GetNativeWindow(), page_navigator_, node,
                    NEW_BACKGROUND_TAB, browser_->profile());
  }
  gdk_event_free(event);
}

gboolean BookmarkBarGtk::OnToolbarDragMotion(GtkWidget* toolbar,
                                             GdkDragContext* context,
                                             gint x,
                                             gint y,
                                             guint time) {
  gint index = gtk_toolbar_get_drop_index(GTK_TOOLBAR(toolbar), x, y);
  return ItemDraggedOverToolbar(context, index, time);
}

void BookmarkBarGtk::OnToolbarSizeAllocate(GtkWidget* widget,
                                           GtkAllocation* allocation) {
  if (allocation->width == last_allocation_width_) {
    // If the width hasn't changed, then the visibility of the chevron
    // doesn't need to change. This check prevents us from getting stuck in a
    // loop where allocates are queued indefinitely while the visibility of
    // overflow chevron toggles without actual resizes of the toolbar.
    return;
  }
  last_allocation_width_ = allocation->width;

  SetChevronState();
}

void BookmarkBarGtk::OnDragReceived(GtkWidget* widget,
                                    GdkDragContext* context,
                                    gint x, gint y,
                                    GtkSelectionData* selection_data,
                                    guint target_type, guint time) {
  if (!edit_bookmarks_enabled_.GetValue()) {
    gtk_drag_finish(context, FALSE, FALSE, time);
    return;
  }

  gboolean dnd_success = FALSE;
  gboolean delete_selection_data = FALSE;

  const BookmarkNode* dest_node = model_->bookmark_bar_node();
  gint index;
  if (widget == bookmark_toolbar_.get()) {
    index = gtk_toolbar_get_drop_index(
      GTK_TOOLBAR(bookmark_toolbar_.get()), x, y);
  } else if (widget == instructions_) {
    dest_node = model_->bookmark_bar_node();
    index = 0;
  } else {
    index = GetToolbarIndexForDragOverFolder(widget, x);
    if (index < 0) {
      dest_node = GetNodeForToolButton(widget);
      index = dest_node->child_count();
    }
  }

  switch (target_type) {
    case ui::CHROME_BOOKMARK_ITEM: {
      gint length = gtk_selection_data_get_length(selection_data);
      Pickle pickle(reinterpret_cast<const char*>(
          gtk_selection_data_get_data(selection_data)), length);
      BookmarkNodeData drag_data;
      if (drag_data.ReadFromPickle(&pickle)) {
        dnd_success = chrome::DropBookmarks(browser_->profile(),
            drag_data, dest_node, index) != ui::DragDropTypes::DRAG_NONE;
      }
      break;
    }

    case ui::CHROME_NAMED_URL: {
      dnd_success = bookmark_utils::CreateNewBookmarkFromNamedUrl(
          selection_data, model_, dest_node, index);
      break;
    }

    case ui::TEXT_URI_LIST: {
      dnd_success = bookmark_utils::CreateNewBookmarksFromURIList(
          selection_data, model_, dest_node, index);
      break;
    }

    case ui::NETSCAPE_URL: {
      dnd_success = bookmark_utils::CreateNewBookmarkFromNetscapeURL(
          selection_data, model_, dest_node, index);
      break;
    }

    case ui::TEXT_PLAIN: {
      guchar* text = gtk_selection_data_get_text(selection_data);
      if (!text)
        break;
      GURL url(reinterpret_cast<char*>(text));
      g_free(text);
      // TODO(estade): It would be nice to head this case off at drag motion,
      // so that it doesn't look like we can drag onto the bookmark bar.
      if (!url.is_valid())
        break;
      string16 title = bookmark_utils::GetNameForURL(url);
      model_->AddURL(dest_node, index, title, url);
      dnd_success = TRUE;
      break;
    }
  }

  gtk_drag_finish(context, dnd_success, delete_selection_data, time);
}

void BookmarkBarGtk::OnDragLeave(GtkWidget* sender,
                                 GdkDragContext* context,
                                 guint time) {
  if (GTK_IS_BUTTON(sender))
    gtk_drag_unhighlight(sender);

  ClearToolbarDropHighlighting();
}

gboolean BookmarkBarGtk::OnFolderDragMotion(GtkWidget* button,
                                            GdkDragContext* context,
                                            gint x,
                                            gint y,
                                            guint time) {
  if (!edit_bookmarks_enabled_.GetValue())
    return FALSE;
  GdkAtom target_type = gtk_drag_dest_find_target(button, context, NULL);
  if (target_type == GDK_NONE)
    return FALSE;

  int index = GetToolbarIndexForDragOverFolder(button, x);
  if (index < 0) {
    ClearToolbarDropHighlighting();

    // Drag is over middle of folder.
    gtk_drag_highlight(button);
    if (target_type == ui::GetAtomForTarget(ui::CHROME_BOOKMARK_ITEM)) {
      gdk_drag_status(context, GDK_ACTION_MOVE, time);
    } else {
      gdk_drag_status(context, GDK_ACTION_COPY, time);
    }

    return TRUE;
  }

  // Remove previous highlighting.
  gtk_drag_unhighlight(button);
  return ItemDraggedOverToolbar(context, index, time);
}

gboolean BookmarkBarGtk::OnEventBoxExpose(GtkWidget* widget,
                                          GdkEventExpose* event) {
  TRACE_EVENT0("ui::gtk", "BookmarkBarGtk::OnEventBoxExpose");
  GtkThemeService* theme_provider = theme_service_;

  // We don't need to render the toolbar image in GTK mode, except when
  // detached.
  if (theme_provider->UsingNativeTheme() &&
      bookmark_bar_state_ != BookmarkBar::DETACHED)
    return FALSE;

  if (bookmark_bar_state_ != BookmarkBar::DETACHED) {
    cairo_t* cr = gdk_cairo_create(gtk_widget_get_window(widget));
    gdk_cairo_rectangle(cr, &event->area);
    cairo_clip(cr);

    // Paint the background theme image.
    gfx::Point tabstrip_origin =
        tabstrip_origin_provider_->GetTabStripOriginForWidget(widget);
    gtk_util::DrawThemedToolbarBackground(widget, cr, event, tabstrip_origin,
                                          theme_provider);

    cairo_destroy(cr);
  } else {
    gfx::Size web_contents_size;
    if (!GetWebContentsSize(&web_contents_size))
      return FALSE;
    gfx::CanvasSkiaPaint canvas(event, true);

    GtkAllocation allocation;
    gtk_widget_get_allocation(widget, &allocation);

    gfx::Rect area = gtk_widget_get_has_window(widget) ?
                     gfx::Rect(0, 0, allocation.width, allocation.height) :
                     gfx::Rect(allocation);
    NtpBackgroundUtil::PaintBackgroundDetachedMode(theme_provider, &canvas,
        area, web_contents_size.height());
  }

  return FALSE;  // Propagate expose to children.
}

void BookmarkBarGtk::OnEventBoxDestroy(GtkWidget* widget) {
  if (model_)
    model_->RemoveObserver(this);
}

void BookmarkBarGtk::OnParentSizeAllocate(GtkWidget* widget,
                                          GtkAllocation* allocation) {
  // In detached mode, our layout depends on the size of the tab contents.
  // We get the size-allocate signal before the tab contents does, hence we
  // need to post a delayed task so we will paint correctly. Note that
  // gtk_widget_queue_draw by itself does not work, despite that it claims to
  // be asynchronous.
  if (bookmark_bar_state_ == BookmarkBar::DETACHED) {
    base::MessageLoop::current()->PostTask(
        FROM_HERE,
        base::Bind(&BookmarkBarGtk::PaintEventBox, weak_factory_.GetWeakPtr()));
  }
}

void BookmarkBarGtk::OnThrobbingWidgetDestroy(GtkWidget* widget) {
  SetThrobbingWidget(NULL);
}

void BookmarkBarGtk::ShowImportDialog() {
  chrome::ShowImportDialog(browser_);
}

void BookmarkBarGtk::OnAppsPageShortcutVisibilityChanged() {
  const bool visible =
      chrome::ShouldShowAppsShortcutInBookmarkBar(browser_->profile());
  gtk_widget_set_visible(apps_shortcut_button_, visible);
  gtk_widget_set_no_show_all(apps_shortcut_button_, !visible);
}

void BookmarkBarGtk::OnEditBookmarksEnabledChanged() {
  GtkDestDefaults dest_defaults =
      *edit_bookmarks_enabled_ ? GTK_DEST_DEFAULT_ALL :
                                 GTK_DEST_DEFAULT_DROP;
  gtk_drag_dest_set(overflow_button_, dest_defaults, NULL, 0, kDragAction);
  gtk_drag_dest_set(other_bookmarks_button_, dest_defaults,
                    NULL, 0, kDragAction);
  ui::SetDestTargetList(overflow_button_, kDestTargetList);
  ui::SetDestTargetList(other_bookmarks_button_, kDestTargetList);
}
