<commit_before>// Copyright (c) 2010 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/gtk/translate_infobars.h"

#include <string>
#include <vector>

#include "app/l10n_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/gtk/menu_gtk.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/translate/translate_infobars_delegates.h"
#include "chrome/browser/translate/options_menu_model.h"
#include "chrome/common/notification_service.h"
#include "grit/app_resources.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "grit/theme_resources.h"

namespace {

// Reorders the widgets in the NULL terminated array |widgets| that are all
// children of |box|.
void ReorderWidgetsTo(GtkWidget* box, GtkWidget** widgets) {
  for (int count = 0; *widgets != NULL; widgets++) {
    gtk_box_reorder_child(GTK_BOX(box), *widgets, count++);
    gtk_widget_show_all(*widgets);
  }
}

// Creates a combobox set up to display text from a list of language codes
// (translating the codes into the display string).
GtkWidget* BuildLanguageComboboxFrom(
    TranslateInfoBarDelegate* delegate,
    const std::vector<std::string>& languages) {
  GtkListStore* model = gtk_list_store_new(1, G_TYPE_STRING);
  for (std::vector<std::string>::const_iterator iter = languages.begin();
       iter != languages.end(); ++iter) {
    GtkTreeIter tree_iter;
    std::string name = UTF16ToUTF8(delegate->GetDisplayNameForLocale(*iter));
    gtk_list_store_append(model, &tree_iter);
    gtk_list_store_set(model, &tree_iter, 0, name.c_str(), -1);
  }

  GtkWidget* combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
  g_object_unref(model);
  GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), renderer, TRUE);
  gtk_cell_layout_set_attributes(
      GTK_CELL_LAYOUT(combobox), renderer, "text", 0, NULL);

  return combobox;
}

// Builds a button with an arrow in it to emulate the menu-button style from
// the windows version.
GtkWidget* BuildOptionsMenuButton() {
  GtkWidget* button = gtk_button_new();
  GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(button));
  if (former_child)
    gtk_container_remove(GTK_CONTAINER(button), former_child);

  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);

  GtkWidget* label = gtk_label_new(
      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_OPTIONS).c_str());
  gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

  GtkWidget* arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
  gtk_box_pack_start(GTK_BOX(hbox), arrow, FALSE, FALSE, 0);

  gtk_container_add(GTK_CONTAINER(button), hbox);

  return button;
}

}  // namespace

TranslateInfoBar::TranslateInfoBar(TranslateInfoBarDelegate* delegate)
    : InfoBar(delegate),
      swapped_language_placeholders_(false) {
  BuildWidgets();

  // Register for PAGE_TRANSLATED notification.
  notification_registrar_.Add(this, NotificationType::PAGE_TRANSLATED,
      Source<TabContents>(GetDelegate()->tab_contents()));
}

TranslateInfoBar::~TranslateInfoBar() {
}

void TranslateInfoBar::Observe(NotificationType type,
    const NotificationSource& source, const NotificationDetails& details) {
  if (type.value == NotificationType::PAGE_TRANSLATED) {
    TabContents* tab = Source<TabContents>(source).ptr();
    if (tab != GetDelegate()->tab_contents())
      return;

    UpdateState(TranslateInfoBarDelegate::kAfterTranslate);
  } else {
    InfoBar::Observe(type, source, details);
  }
}

bool TranslateInfoBar::IsCommandIdChecked(int command_id) const {
  TranslateInfoBarDelegate* translate_delegate = GetDelegate();
  switch (command_id) {
    case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_LANG :
      return translate_delegate->IsLanguageBlacklisted();

    case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_SITE :
      return translate_delegate->IsSiteBlacklisted();

    case IDC_TRANSLATE_OPTIONS_ALWAYS :
      return translate_delegate->ShouldAlwaysTranslate();

    default:
      NOTREACHED() << "Invalid command_id from menu";
      break;
  }
  return false;
}

bool TranslateInfoBar::IsCommandIdEnabled(int command_id) const {
  return true;
}

bool TranslateInfoBar::GetAcceleratorForCommandId(int command_id,
    menus::Accelerator* accelerator) {
  return false;
}

void TranslateInfoBar::ExecuteCommand(int command_id) {
  switch (command_id) {
    case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_LANG:
      GetDelegate()->ToggleLanguageBlacklist();
      break;

    case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_SITE:
      GetDelegate()->ToggleSiteBlacklist();
      break;

    case IDC_TRANSLATE_OPTIONS_ALWAYS:
      GetDelegate()->ToggleAlwaysTranslate();
      break;

    case IDC_TRANSLATE_OPTIONS_ABOUT: {
      TabContents* tab_contents = GetDelegate()->tab_contents();
      if (tab_contents) {
        string16 url = l10n_util::GetStringUTF16(
            IDS_ABOUT_GOOGLE_TRANSLATE_URL);
        tab_contents->OpenURL(GURL(url), GURL(), NEW_FOREGROUND_TAB,
                              PageTransition::LINK);
      }
      break;
    }

    default:
      NOTREACHED() << "Invalid command id from menu.";
      break;
  }
}

void TranslateInfoBar::BuildWidgets() {
  translate_box_ = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
  gtk_widget_set_no_show_all(translate_box_, TRUE);

  // Add all labels to the translate_box_. Unlike views or cocoa, there's no
  // concept of manual layout in GTK, so we'll manually reorder these widgets
  // inside |translate_box_| and selectively show and hide them.
  label_1_ = gtk_label_new(NULL);
  gtk_box_pack_start(GTK_BOX(translate_box_), label_1_, FALSE, FALSE, 0);

  label_2_ = gtk_label_new(NULL);
  gtk_box_pack_start(GTK_BOX(translate_box_), label_2_, FALSE, FALSE, 0);

  label_3_ = gtk_label_new(NULL);
  gtk_box_pack_start(GTK_BOX(translate_box_), label_3_, FALSE, FALSE, 0);

  translating_label_ = gtk_label_new(
      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_TRANSLATING).c_str());
  gtk_box_pack_start(GTK_BOX(translate_box_), translating_label_,
                     FALSE, FALSE, 0);

  accept_button_ = gtk_button_new_with_label(
      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_ACCEPT).c_str());
  g_signal_connect(accept_button_, "clicked",
                   G_CALLBACK(&OnAcceptPressedThunk), this);
  accept_button_vbox_ = gtk_util::CenterWidgetInHBox(
      translate_box_, accept_button_, false, 0);

  deny_button_ = gtk_button_new_with_label(
      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_DENY).c_str());
  g_signal_connect(deny_button_, "clicked",
                   G_CALLBACK(&OnDenyPressedThunk), this);
  deny_button_vbox_ = gtk_util::CenterWidgetInHBox(
      translate_box_, deny_button_, false, 0);

  std::vector<std::string> orig_languages;
  GetDelegate()->GetAvailableOriginalLanguages(&orig_languages);
  original_language_combobox_ = BuildLanguageComboboxFrom(GetDelegate(),
                                                          orig_languages);
  g_signal_connect(original_language_combobox_, "changed",
                   G_CALLBACK(&OnOriginalModifiedThunk), this);
  original_language_combobox_vbox_ = gtk_util::CenterWidgetInHBox(
      translate_box_, original_language_combobox_, false, 0);

  std::vector<std::string> target_languages;
  GetDelegate()->GetAvailableTargetLanguages(&target_languages);
  target_language_combobox_ = BuildLanguageComboboxFrom(GetDelegate(),
                                                        target_languages);
  g_signal_connect(target_language_combobox_, "changed",
                   G_CALLBACK(&OnTargetModifiedThunk), this);
  target_language_combobox_vbox_ = gtk_util::CenterWidgetInHBox(
      translate_box_, target_language_combobox_, false, 0);

  gtk_box_pack_start(GTK_BOX(hbox_), translate_box_, FALSE, FALSE, 0);

  // The options button sits outside the translate_box so that it can be end
  // packed in hbox_.
  options_menu_button_ = BuildOptionsMenuButton();
  g_signal_connect(options_menu_button_, "clicked",
                   G_CALLBACK(&OnOptionsClickedThunk), this);
  gtk_widget_show_all(options_menu_button_);
  gtk_util::CenterWidgetInHBox(
      hbox_, options_menu_button_, true, 0);

  UpdateState(GetDelegate()->state());

  gtk_widget_show_all(border_bin_.get());
}

void TranslateInfoBar::UpdateState(
    TranslateInfoBarDelegate::TranslateState new_state) {
  // Show the box...
  gtk_widget_show(translate_box_);
  // ...but hide all children of the translate box. They will be selectively
  // unhidden and reordered based on the current translate state.
  gtk_container_foreach(
      GTK_CONTAINER(translate_box_),
      reinterpret_cast<void (*)(GtkWidget*, void*)>(gtk_widget_hide_all), NULL);

  switch (new_state) {
    case TranslateInfoBarDelegate::kBeforeTranslate: {
      SetLabels();

      GtkWidget* before_state[] = {
        label_1_,
        original_language_combobox_vbox_,
        label_2_,
        accept_button_vbox_,
        deny_button_vbox_,
        NULL
      };
      ReorderWidgetsTo(translate_box_, before_state);

      gtk_combo_box_set_active(GTK_COMBO_BOX(original_language_combobox_),
                               GetDelegate()->original_lang_index());
      break;
    }
    case TranslateInfoBarDelegate::kTranslating: {
      gtk_widget_show(translating_label_);
      break;
    }
    case TranslateInfoBarDelegate::kAfterTranslate: {
      SetLabels();
      GtkWidget* first_button_box =
          swapped_language_placeholders_ ?
          target_language_combobox_vbox_ : original_language_combobox_vbox_;
      GtkWidget* second_button_box =
          swapped_language_placeholders_ ?
          original_language_combobox_vbox_ : target_language_combobox_vbox_;

      GtkWidget* after_state[] = {
        label_1_,
        first_button_box,
        label_2_,
        second_button_box,
        label_3_,
        NULL
      };
      ReorderWidgetsTo(translate_box_, after_state);

      gtk_combo_box_set_active(GTK_COMBO_BOX(original_language_combobox_),
                               GetDelegate()->original_lang_index());
      gtk_combo_box_set_active(GTK_COMBO_BOX(target_language_combobox_),
                               GetDelegate()->target_lang_index());
      break;
    }
    default: {
      NOTIMPLEMENTED() << "Received state " << new_state;
    }
  }
}

void TranslateInfoBar::SetLabels() {
  std::vector<size_t> offsets;
  string16 message_text_utf16;
  GetDelegate()->GetMessageText(GetDelegate()->state(), &message_text_utf16,
      &offsets, &swapped_language_placeholders_);

  string16 text = message_text_utf16.substr(0, offsets[0]);
  gtk_label_set_text(GTK_LABEL(label_1_), UTF16ToUTF8(text).c_str());

  text = message_text_utf16.substr(offsets[0], offsets[1] - offsets[0]);
  gtk_label_set_text(GTK_LABEL(label_2_), UTF16ToUTF8(text).c_str());

  if (offsets.size() == 3) {
    text = message_text_utf16.substr(offsets[1], offsets[2] - offsets[1]);
    gtk_label_set_text(GTK_LABEL(label_3_), UTF16ToUTF8(text).c_str());
  }
}

TranslateInfoBarDelegate* TranslateInfoBar::GetDelegate() const {
  return static_cast<TranslateInfoBarDelegate*>(delegate());
}

void TranslateInfoBar::LanguageModified() {
  options_menu_model_.reset();

  // Selecting an item from the "from language" menu in the before translate
  // phase shouldn't trigger translation - http://crbug.com/36666
  if (GetDelegate()->state() == TranslateInfoBarDelegate::kAfterTranslate)
    GetDelegate()->Translate();
}

void TranslateInfoBar::OnOriginalModified(GtkWidget* sender) {
  int index = gtk_combo_box_get_active(GTK_COMBO_BOX(sender));
  if (index == GetDelegate()->original_lang_index())
    return;

  GetDelegate()->ModifyOriginalLanguage(index);

  LanguageModified();
}

void TranslateInfoBar::OnTargetModified(GtkWidget* sender) {
  int index = gtk_combo_box_get_active(GTK_COMBO_BOX(sender));
  if (index == GetDelegate()->target_lang_index())
    return;

  GetDelegate()->ModifyTargetLanguage(index);

  LanguageModified();
}

void TranslateInfoBar::OnAcceptPressed(GtkWidget* sender) {
  GetDelegate()->Translate();
  UpdateState(GetDelegate()->state());
}

void TranslateInfoBar::OnDenyPressed(GtkWidget* sender) {
  GetDelegate()->TranslationDeclined();
  RemoveInfoBar();
}

void TranslateInfoBar::OnOptionsClicked(GtkWidget* sender) {
  if (!options_menu_model_.get()) {
    options_menu_model_.reset(new OptionsMenuModel(this, GetDelegate()));
    options_menu_menu_.reset(new MenuGtk(this, options_menu_model_.get()));
  }
  options_menu_menu_->Popup(sender, 1, gtk_get_current_event_time());
}

// TranslateInfoBarDelegate, InfoBarDelegate overrides: ------------------

InfoBar* TranslateInfoBarDelegate::CreateInfoBar() {
  return new TranslateInfoBar(this);
}
<commit_msg>GTK: Force the labels in the translate infobar to black.<commit_after>// Copyright (c) 2010 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/gtk/translate_infobars.h"

#include <string>
#include <vector>

#include "app/l10n_util.h"
#include "base/utf_string_conversions.h"
#include "chrome/app/chrome_dll_resource.h"
#include "chrome/browser/gtk/gtk_util.h"
#include "chrome/browser/gtk/menu_gtk.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "chrome/browser/translate/translate_infobars_delegates.h"
#include "chrome/browser/translate/options_menu_model.h"
#include "chrome/common/notification_service.h"
#include "gfx/gtk_util.h"
#include "grit/app_resources.h"
#include "grit/generated_resources.h"
#include "grit/locale_settings.h"
#include "grit/theme_resources.h"

namespace {

// Reorders the widgets in the NULL terminated array |widgets| that are all
// children of |box|.
void ReorderWidgetsTo(GtkWidget* box, GtkWidget** widgets) {
  for (int count = 0; *widgets != NULL; widgets++) {
    gtk_box_reorder_child(GTK_BOX(box), *widgets, count++);
    gtk_widget_show_all(*widgets);
  }
}

// Creates a combobox set up to display text from a list of language codes
// (translating the codes into the display string).
GtkWidget* BuildLanguageComboboxFrom(
    TranslateInfoBarDelegate* delegate,
    const std::vector<std::string>& languages) {
  GtkListStore* model = gtk_list_store_new(1, G_TYPE_STRING);
  for (std::vector<std::string>::const_iterator iter = languages.begin();
       iter != languages.end(); ++iter) {
    GtkTreeIter tree_iter;
    std::string name = UTF16ToUTF8(delegate->GetDisplayNameForLocale(*iter));
    gtk_list_store_append(model, &tree_iter);
    gtk_list_store_set(model, &tree_iter, 0, name.c_str(), -1);
  }

  GtkWidget* combobox = gtk_combo_box_new_with_model(GTK_TREE_MODEL(model));
  g_object_unref(model);
  GtkCellRenderer* renderer = gtk_cell_renderer_text_new();
  gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(combobox), renderer, TRUE);
  gtk_cell_layout_set_attributes(
      GTK_CELL_LAYOUT(combobox), renderer, "text", 0, NULL);

  return combobox;
}

// Builds a button with an arrow in it to emulate the menu-button style from
// the windows version.
GtkWidget* BuildOptionsMenuButton() {
  GtkWidget* button = gtk_button_new();
  GtkWidget* former_child = gtk_bin_get_child(GTK_BIN(button));
  if (former_child)
    gtk_container_remove(GTK_CONTAINER(button), former_child);

  GtkWidget* hbox = gtk_hbox_new(FALSE, 0);

  GtkWidget* label = gtk_label_new(
      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_OPTIONS).c_str());
  gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0);

  GtkWidget* arrow = gtk_arrow_new(GTK_ARROW_DOWN, GTK_SHADOW_NONE);
  gtk_box_pack_start(GTK_BOX(hbox), arrow, FALSE, FALSE, 0);

  gtk_container_add(GTK_CONTAINER(button), hbox);

  return button;
}

}  // namespace

TranslateInfoBar::TranslateInfoBar(TranslateInfoBarDelegate* delegate)
    : InfoBar(delegate),
      swapped_language_placeholders_(false) {
  BuildWidgets();

  // Register for PAGE_TRANSLATED notification.
  notification_registrar_.Add(this, NotificationType::PAGE_TRANSLATED,
      Source<TabContents>(GetDelegate()->tab_contents()));
}

TranslateInfoBar::~TranslateInfoBar() {
}

void TranslateInfoBar::Observe(NotificationType type,
    const NotificationSource& source, const NotificationDetails& details) {
  if (type.value == NotificationType::PAGE_TRANSLATED) {
    TabContents* tab = Source<TabContents>(source).ptr();
    if (tab != GetDelegate()->tab_contents())
      return;

    UpdateState(TranslateInfoBarDelegate::kAfterTranslate);
  } else {
    InfoBar::Observe(type, source, details);
  }
}

bool TranslateInfoBar::IsCommandIdChecked(int command_id) const {
  TranslateInfoBarDelegate* translate_delegate = GetDelegate();
  switch (command_id) {
    case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_LANG :
      return translate_delegate->IsLanguageBlacklisted();

    case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_SITE :
      return translate_delegate->IsSiteBlacklisted();

    case IDC_TRANSLATE_OPTIONS_ALWAYS :
      return translate_delegate->ShouldAlwaysTranslate();

    default:
      NOTREACHED() << "Invalid command_id from menu";
      break;
  }
  return false;
}

bool TranslateInfoBar::IsCommandIdEnabled(int command_id) const {
  return true;
}

bool TranslateInfoBar::GetAcceleratorForCommandId(int command_id,
    menus::Accelerator* accelerator) {
  return false;
}

void TranslateInfoBar::ExecuteCommand(int command_id) {
  switch (command_id) {
    case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_LANG:
      GetDelegate()->ToggleLanguageBlacklist();
      break;

    case IDC_TRANSLATE_OPTIONS_NEVER_TRANSLATE_SITE:
      GetDelegate()->ToggleSiteBlacklist();
      break;

    case IDC_TRANSLATE_OPTIONS_ALWAYS:
      GetDelegate()->ToggleAlwaysTranslate();
      break;

    case IDC_TRANSLATE_OPTIONS_ABOUT: {
      TabContents* tab_contents = GetDelegate()->tab_contents();
      if (tab_contents) {
        string16 url = l10n_util::GetStringUTF16(
            IDS_ABOUT_GOOGLE_TRANSLATE_URL);
        tab_contents->OpenURL(GURL(url), GURL(), NEW_FOREGROUND_TAB,
                              PageTransition::LINK);
      }
      break;
    }

    default:
      NOTREACHED() << "Invalid command id from menu.";
      break;
  }
}

void TranslateInfoBar::BuildWidgets() {
  translate_box_ = gtk_hbox_new(FALSE, gtk_util::kControlSpacing);
  gtk_widget_set_no_show_all(translate_box_, TRUE);

  // Add all labels to the translate_box_. Unlike views or cocoa, there's no
  // concept of manual layout in GTK, so we'll manually reorder these widgets
  // inside |translate_box_| and selectively show and hide them.
  label_1_ = gtk_label_new(NULL);
  gtk_box_pack_start(GTK_BOX(translate_box_), label_1_, FALSE, FALSE, 0);
  gtk_widget_modify_fg(label_1_, GTK_STATE_NORMAL, &gfx::kGdkBlack);

  label_2_ = gtk_label_new(NULL);
  gtk_box_pack_start(GTK_BOX(translate_box_), label_2_, FALSE, FALSE, 0);
  gtk_widget_modify_fg(label_2_, GTK_STATE_NORMAL, &gfx::kGdkBlack);

  label_3_ = gtk_label_new(NULL);
  gtk_box_pack_start(GTK_BOX(translate_box_), label_3_, FALSE, FALSE, 0);
  gtk_widget_modify_fg(label_3_, GTK_STATE_NORMAL, &gfx::kGdkBlack);

  translating_label_ = gtk_label_new(
      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_TRANSLATING).c_str());
  gtk_box_pack_start(GTK_BOX(translate_box_), translating_label_,
                     FALSE, FALSE, 0);
  gtk_widget_modify_fg(translating_label_, GTK_STATE_NORMAL, &gfx::kGdkBlack);

  accept_button_ = gtk_button_new_with_label(
      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_ACCEPT).c_str());
  g_signal_connect(accept_button_, "clicked",
                   G_CALLBACK(&OnAcceptPressedThunk), this);
  accept_button_vbox_ = gtk_util::CenterWidgetInHBox(
      translate_box_, accept_button_, false, 0);

  deny_button_ = gtk_button_new_with_label(
      l10n_util::GetStringUTF8(IDS_TRANSLATE_INFOBAR_DENY).c_str());
  g_signal_connect(deny_button_, "clicked",
                   G_CALLBACK(&OnDenyPressedThunk), this);
  deny_button_vbox_ = gtk_util::CenterWidgetInHBox(
      translate_box_, deny_button_, false, 0);

  std::vector<std::string> orig_languages;
  GetDelegate()->GetAvailableOriginalLanguages(&orig_languages);
  original_language_combobox_ = BuildLanguageComboboxFrom(GetDelegate(),
                                                          orig_languages);
  g_signal_connect(original_language_combobox_, "changed",
                   G_CALLBACK(&OnOriginalModifiedThunk), this);
  original_language_combobox_vbox_ = gtk_util::CenterWidgetInHBox(
      translate_box_, original_language_combobox_, false, 0);

  std::vector<std::string> target_languages;
  GetDelegate()->GetAvailableTargetLanguages(&target_languages);
  target_language_combobox_ = BuildLanguageComboboxFrom(GetDelegate(),
                                                        target_languages);
  g_signal_connect(target_language_combobox_, "changed",
                   G_CALLBACK(&OnTargetModifiedThunk), this);
  target_language_combobox_vbox_ = gtk_util::CenterWidgetInHBox(
      translate_box_, target_language_combobox_, false, 0);

  gtk_box_pack_start(GTK_BOX(hbox_), translate_box_, FALSE, FALSE, 0);

  // The options button sits outside the translate_box so that it can be end
  // packed in hbox_.
  options_menu_button_ = BuildOptionsMenuButton();
  g_signal_connect(options_menu_button_, "clicked",
                   G_CALLBACK(&OnOptionsClickedThunk), this);
  gtk_widget_show_all(options_menu_button_);
  gtk_util::CenterWidgetInHBox(
      hbox_, options_menu_button_, true, 0);

  UpdateState(GetDelegate()->state());

  gtk_widget_show_all(border_bin_.get());
}

void TranslateInfoBar::UpdateState(
    TranslateInfoBarDelegate::TranslateState new_state) {
  // Show the box...
  gtk_widget_show(translate_box_);
  // ...but hide all children of the translate box. They will be selectively
  // unhidden and reordered based on the current translate state.
  gtk_container_foreach(
      GTK_CONTAINER(translate_box_),
      reinterpret_cast<void (*)(GtkWidget*, void*)>(gtk_widget_hide_all), NULL);

  switch (new_state) {
    case TranslateInfoBarDelegate::kBeforeTranslate: {
      SetLabels();

      GtkWidget* before_state[] = {
        label_1_,
        original_language_combobox_vbox_,
        label_2_,
        accept_button_vbox_,
        deny_button_vbox_,
        NULL
      };
      ReorderWidgetsTo(translate_box_, before_state);

      gtk_combo_box_set_active(GTK_COMBO_BOX(original_language_combobox_),
                               GetDelegate()->original_lang_index());
      break;
    }
    case TranslateInfoBarDelegate::kTranslating: {
      gtk_widget_show(translating_label_);
      break;
    }
    case TranslateInfoBarDelegate::kAfterTranslate: {
      SetLabels();
      GtkWidget* first_button_box =
          swapped_language_placeholders_ ?
          target_language_combobox_vbox_ : original_language_combobox_vbox_;
      GtkWidget* second_button_box =
          swapped_language_placeholders_ ?
          original_language_combobox_vbox_ : target_language_combobox_vbox_;

      GtkWidget* after_state[] = {
        label_1_,
        first_button_box,
        label_2_,
        second_button_box,
        label_3_,
        NULL
      };
      ReorderWidgetsTo(translate_box_, after_state);

      gtk_combo_box_set_active(GTK_COMBO_BOX(original_language_combobox_),
                               GetDelegate()->original_lang_index());
      gtk_combo_box_set_active(GTK_COMBO_BOX(target_language_combobox_),
                               GetDelegate()->target_lang_index());
      break;
    }
    default: {
      NOTIMPLEMENTED() << "Received state " << new_state;
    }
  }
}

void TranslateInfoBar::SetLabels() {
  std::vector<size_t> offsets;
  string16 message_text_utf16;
  GetDelegate()->GetMessageText(GetDelegate()->state(), &message_text_utf16,
      &offsets, &swapped_language_placeholders_);

  string16 text = message_text_utf16.substr(0, offsets[0]);
  gtk_label_set_text(GTK_LABEL(label_1_), UTF16ToUTF8(text).c_str());

  text = message_text_utf16.substr(offsets[0], offsets[1] - offsets[0]);
  gtk_label_set_text(GTK_LABEL(label_2_), UTF16ToUTF8(text).c_str());

  if (offsets.size() == 3) {
    text = message_text_utf16.substr(offsets[1], offsets[2] - offsets[1]);
    gtk_label_set_text(GTK_LABEL(label_3_), UTF16ToUTF8(text).c_str());
  }
}

TranslateInfoBarDelegate* TranslateInfoBar::GetDelegate() const {
  return static_cast<TranslateInfoBarDelegate*>(delegate());
}

void TranslateInfoBar::LanguageModified() {
  options_menu_model_.reset();

  // Selecting an item from the "from language" menu in the before translate
  // phase shouldn't trigger translation - http://crbug.com/36666
  if (GetDelegate()->state() == TranslateInfoBarDelegate::kAfterTranslate)
    GetDelegate()->Translate();
}

void TranslateInfoBar::OnOriginalModified(GtkWidget* sender) {
  int index = gtk_combo_box_get_active(GTK_COMBO_BOX(sender));
  if (index == GetDelegate()->original_lang_index())
    return;

  GetDelegate()->ModifyOriginalLanguage(index);

  LanguageModified();
}

void TranslateInfoBar::OnTargetModified(GtkWidget* sender) {
  int index = gtk_combo_box_get_active(GTK_COMBO_BOX(sender));
  if (index == GetDelegate()->target_lang_index())
    return;

  GetDelegate()->ModifyTargetLanguage(index);

  LanguageModified();
}

void TranslateInfoBar::OnAcceptPressed(GtkWidget* sender) {
  GetDelegate()->Translate();
  UpdateState(GetDelegate()->state());
}

void TranslateInfoBar::OnDenyPressed(GtkWidget* sender) {
  GetDelegate()->TranslationDeclined();
  RemoveInfoBar();
}

void TranslateInfoBar::OnOptionsClicked(GtkWidget* sender) {
  if (!options_menu_model_.get()) {
    options_menu_model_.reset(new OptionsMenuModel(this, GetDelegate()));
    options_menu_menu_.reset(new MenuGtk(this, options_menu_model_.get()));
  }
  options_menu_menu_->Popup(sender, 1, gtk_get_current_event_time());
}

// TranslateInfoBarDelegate, InfoBarDelegate overrides: ------------------

InfoBar* TranslateInfoBarDelegate::CreateInfoBar() {
  return new TranslateInfoBar(this);
}
<|endoftext|>


<commit_before>// Copyright (c) 2011 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/platform_util.h"

#include <gtk/gtk.h>

#include "base/file_util.h"
#include "base/process_util.h"
#include "base/task.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/file_manager_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/webui/mediaplayer_ui.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#include "content/browser/browser_thread.h"
#include "content/common/process_watcher.h"
#include "googleurl/src/gurl.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"

class Profile;

namespace platform_util {

static const std::string kGmailComposeUrl =
    "https://mail.google.com/mail/?extsrc=mailto&url=";

// Opens file browser on UI thread.
void OpenFileBrowserOnUIThread(const FilePath& dir) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  Browser* browser = BrowserList::GetLastActive();
  if (!browser)
    return;
  GURL url = FileManagerUtil::GetFileBrowserUrlWithParams(
     SelectFileDialog::SELECT_NONE, string16(), dir, NULL, 0,
     FilePath::StringType());
  browser->ShowSingletonTab(url);
}

void ShowItemInFolder(const FilePath& full_path) {
  FilePath dir = full_path.DirName();
  if (!file_util::DirectoryExists(dir))
    return;

  if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    OpenFileBrowserOnUIThread(dir);
  } else {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        NewRunnableFunction(&OpenFileBrowserOnUIThread, dir));
  }
}

void OpenItem(const FilePath& full_path) {
  std::string ext = full_path.Extension();
  // For things supported natively by the browser, we should open it
  // in a tab.
  if (base::strcasecmp(ext.data(), ".jpg") == 0 ||
      base::strcasecmp(ext.data(), ".jpeg") == 0 ||
      base::strcasecmp(ext.data(), ".png") == 0 ||
      base::strcasecmp(ext.data(), ".gif") == 0 ||
      base::strcasecmp(ext.data(), ".txt") == 0 ||
      base::strcasecmp(ext.data(), ".html") == 0 ||
      base::strcasecmp(ext.data(), ".htm") == 0) {
    std::string path;
    path = "file://";
    path.append(full_path.value());
    if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
      bool result = BrowserThread::PostTask(
          BrowserThread::UI, FROM_HERE,
          NewRunnableFunction(&OpenItem, full_path));
      DCHECK(result);
      return;
    }
    Browser* browser = BrowserList::GetLastActive();
    browser->AddSelectedTabWithURL(GURL(path), PageTransition::LINK);
    return;
  }
  if (base::strcasecmp(ext.data(), ".avi") == 0 ||
      base::strcasecmp(ext.data(), ".wav") == 0 ||
      base::strcasecmp(ext.data(), ".mp4") == 0 ||
      base::strcasecmp(ext.data(), ".mp3") == 0 ||
      base::strcasecmp(ext.data(), ".mkv") == 0 ||
      base::strcasecmp(ext.data(), ".ogg") == 0) {
    Browser* browser = BrowserList::GetLastActive();
    if (!browser)
      return;
    MediaPlayer* mediaplayer = MediaPlayer::GetInstance();
    mediaplayer->EnqueueMediaFile(browser->profile(), full_path, NULL);
    return;
  }

  // Unknwon file type. Show an error message to user.
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      NewRunnableFunction(
          &SimpleErrorBox,
          static_cast<gfx::NativeWindow>(NULL),
          l10n_util::GetStringUTF16(IDS_FILEBROWSER_ERROR_TITLE),
          l10n_util::GetStringFUTF16(IDS_FILEBROWSER_ERROR_UNKNOWN_FILE_TYPE,
                                     UTF8ToUTF16(full_path.BaseName().value()))
          ));
}

static void OpenURL(const std::string& url) {
  Browser* browser = BrowserList::GetLastActive();
  browser->AddSelectedTabWithURL(GURL(url), PageTransition::LINK);
}

void OpenExternal(const GURL& url) {
  if (url.SchemeIs("mailto")) {
    std::string string_url = kGmailComposeUrl;
    string_url.append(url.spec());
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE, NewRunnableFunction(OpenURL, string_url));
  }
}

}  // namespace platform_util
<commit_msg>Add native file formats to open in browser (pdf, webm)<commit_after>// Copyright (c) 2011 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/platform_util.h"

#include <gtk/gtk.h>

#include "base/file_util.h"
#include "base/process_util.h"
#include "base/task.h"
#include "base/utf_string_conversions.h"
#include "chrome/browser/extensions/file_manager_util.h"
#include "chrome/browser/ui/browser.h"
#include "chrome/browser/ui/browser_list.h"
#include "chrome/browser/ui/webui/mediaplayer_ui.h"
#include "chrome/browser/tabs/tab_strip_model.h"
#include "content/browser/browser_thread.h"
#include "content/common/process_watcher.h"
#include "googleurl/src/gurl.h"
#include "grit/generated_resources.h"
#include "ui/base/l10n/l10n_util.h"

class Profile;

namespace platform_util {

static const std::string kGmailComposeUrl =
    "https://mail.google.com/mail/?extsrc=mailto&url=";

// Opens file browser on UI thread.
void OpenFileBrowserOnUIThread(const FilePath& dir) {
  DCHECK(BrowserThread::CurrentlyOn(BrowserThread::UI));

  Browser* browser = BrowserList::GetLastActive();
  if (!browser)
    return;
  GURL url = FileManagerUtil::GetFileBrowserUrlWithParams(
     SelectFileDialog::SELECT_NONE, string16(), dir, NULL, 0,
     FilePath::StringType());
  browser->ShowSingletonTab(url);
}

void ShowItemInFolder(const FilePath& full_path) {
  FilePath dir = full_path.DirName();
  if (!file_util::DirectoryExists(dir))
    return;

  if (BrowserThread::CurrentlyOn(BrowserThread::UI)) {
    OpenFileBrowserOnUIThread(dir);
  } else {
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE,
        NewRunnableFunction(&OpenFileBrowserOnUIThread, dir));
  }
}

void OpenItem(const FilePath& full_path) {
  std::string ext = full_path.Extension();
  // For things supported natively by the browser, we should open it
  // in a tab.
  if (base::strcasecmp(ext.data(), ".jpg") == 0 ||
      base::strcasecmp(ext.data(), ".jpeg") == 0 ||
      base::strcasecmp(ext.data(), ".png") == 0 ||
      base::strcasecmp(ext.data(), ".gif") == 0 ||
      base::strcasecmp(ext.data(), ".txt") == 0 ||
      base::strcasecmp(ext.data(), ".pdf") == 0 ||
      base::strcasecmp(ext.data(), ".html") == 0 ||
      base::strcasecmp(ext.data(), ".htm") == 0) {
    std::string path;
    path = "file://";
    path.append(full_path.value());
    if (!BrowserThread::CurrentlyOn(BrowserThread::UI)) {
      bool result = BrowserThread::PostTask(
          BrowserThread::UI, FROM_HERE,
          NewRunnableFunction(&OpenItem, full_path));
      DCHECK(result);
      return;
    }
    Browser* browser = BrowserList::GetLastActive();
    browser->AddSelectedTabWithURL(GURL(path), PageTransition::LINK);
    return;
  }
  if (base::strcasecmp(ext.data(), ".avi") == 0 ||
      base::strcasecmp(ext.data(), ".wav") == 0 ||
      base::strcasecmp(ext.data(), ".mp4") == 0 ||
      base::strcasecmp(ext.data(), ".mp3") == 0 ||
      base::strcasecmp(ext.data(), ".mkv") == 0 ||
      base::strcasecmp(ext.data(), ".ogg") == 0) {
    Browser* browser = BrowserList::GetLastActive();
    if (!browser)
      return;
    MediaPlayer* mediaplayer = MediaPlayer::GetInstance();
    mediaplayer->EnqueueMediaFile(browser->profile(), full_path, NULL);
    return;
  }

  // Unknwon file type. Show an error message to user.
  BrowserThread::PostTask(
      BrowserThread::UI, FROM_HERE,
      NewRunnableFunction(
          &SimpleErrorBox,
          static_cast<gfx::NativeWindow>(NULL),
          l10n_util::GetStringUTF16(IDS_FILEBROWSER_ERROR_TITLE),
          l10n_util::GetStringFUTF16(IDS_FILEBROWSER_ERROR_UNKNOWN_FILE_TYPE,
                                     UTF8ToUTF16(full_path.BaseName().value()))
          ));
}

static void OpenURL(const std::string& url) {
  Browser* browser = BrowserList::GetLastActive();
  browser->AddSelectedTabWithURL(GURL(url), PageTransition::LINK);
}

void OpenExternal(const GURL& url) {
  if (url.SchemeIs("mailto")) {
    std::string string_url = kGmailComposeUrl;
    string_url.append(url.spec());
    BrowserThread::PostTask(
        BrowserThread::UI, FROM_HERE, NewRunnableFunction(OpenURL, string_url));
  }
}

}  // namespace platform_util
<|endoftext|>


<commit_before>// 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/zoom_bubble_gtk.h"

#include "base/utf_string_conversions.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/gtk/gtk_theme_service.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/browser/ui/zoom/zoom_controller.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "grit/generated_resources.h"
#include "ui/base/gtk/gtk_hig_constants.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/rect.h"

namespace {

// Pointer to singleton object (NULL if no bubble is open).
ZoomBubbleGtk* g_bubble = NULL;

// Number of milliseconds the bubble should stay open for if it will auto-close.
const int kBubbleCloseDelay = 1500;

// Need to manually set anchor width and height to ensure that the bubble shows
// in the correct spot the first time it is displayed when no icon is present.
const int kBubbleAnchorWidth = 20;
const int kBubbleAnchorHeight = 25;

}  // namespace

// static
void ZoomBubbleGtk::Show(GtkWidget* anchor,
                         TabContents* tab_contents,
                         bool auto_close) {
  // If the bubble is already showing and its |auto_close_| value is equal to
  // |auto_close|, the bubble can be reused and only the label text needs to
  // be updated.
  if (g_bubble &&
      g_bubble->auto_close_ == auto_close &&
      g_bubble->bubble_->anchor_widget() == anchor) {
    g_bubble->Refresh();
  } else {
    // If the bubble is already showing but its |auto_close_| value is not equal
    // to |auto_close|, the bubble's focus properties must change, so the
    // current bubble must be closed and a new one created.
    if (g_bubble)
      g_bubble->Close();

    g_bubble = new ZoomBubbleGtk(anchor, tab_contents, auto_close);
  }
}

// static
void ZoomBubbleGtk::Close() {
  if (g_bubble)
    g_bubble->CloseBubble();
}

ZoomBubbleGtk::ZoomBubbleGtk(GtkWidget* anchor,
                             TabContents* tab_contents,
                             bool auto_close)
    : auto_close_(auto_close),
      mouse_inside_(false),
      tab_contents_(tab_contents) {
  GtkThemeService* theme_service =
      GtkThemeService::GetFrom(Profile::FromBrowserContext(
          tab_contents->web_contents()->GetBrowserContext()));

  event_box_ = gtk_event_box_new();
  gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_), FALSE);
  GtkWidget* container = gtk_vbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER(event_box_), container);

  int zoom_percent = tab_contents->zoom_controller()->zoom_percent();
  std::string percentage_text = UTF16ToUTF8(l10n_util::GetStringFUTF16Int(
      IDS_TOOLTIP_ZOOM, zoom_percent));
  label_ = theme_service->BuildLabel(percentage_text, ui::kGdkBlack);
  gtk_widget_modify_font(label_, pango_font_description_from_string("13"));
  gtk_misc_set_padding(GTK_MISC(label_),
                       ui::kControlSpacing, ui::kControlSpacing);
  gtk_box_pack_start(GTK_BOX(container), label_, FALSE, FALSE, 0);

  GtkWidget* separator = gtk_hseparator_new();
  gtk_box_pack_start(GTK_BOX(container), separator, FALSE, FALSE, 0);

  GtkWidget* set_default_button = theme_service->BuildChromeButton();
  gtk_button_set_label(GTK_BUTTON(set_default_button),
      l10n_util::GetStringUTF8(IDS_ZOOM_SET_DEFAULT).c_str());

  GtkWidget* alignment = gtk_alignment_new(0, 0, 1, 1);
  gtk_alignment_set_padding(
      GTK_ALIGNMENT(alignment), 0, 0, ui::kControlSpacing, ui::kControlSpacing);
  gtk_container_add(GTK_CONTAINER(alignment), set_default_button);

  gtk_box_pack_start(GTK_BOX(container), alignment, FALSE, FALSE, 0);
  g_signal_connect(set_default_button, "clicked",
                   G_CALLBACK(&OnSetDefaultLinkClickThunk), this);

  gtk_container_set_focus_child(GTK_CONTAINER(container), NULL);

  gfx::Rect rect(kBubbleAnchorWidth, kBubbleAnchorHeight);
  BubbleGtk::ArrowLocationGtk arrow_location =
      BubbleGtk::ARROW_LOCATION_TOP_MIDDLE;
  int bubble_options = BubbleGtk::MATCH_SYSTEM_THEME | BubbleGtk::POPUP_WINDOW;
  bubble_ = BubbleGtk::Show(anchor, &rect, event_box_, arrow_location,
      auto_close ? bubble_options : bubble_options | BubbleGtk::GRAB_INPUT,
      theme_service, NULL);

  if (!bubble_) {
    NOTREACHED();
    return;
  }

  g_signal_connect(event_box_, "destroy",
                   G_CALLBACK(&OnDestroyThunk), this);

  if (auto_close_) {
    // If this is an auto-closing bubble, listen to leave/enter to keep the
    // bubble alive if the mouse stays anywhere inside the bubble.
    gtk_widget_add_events(event_box_, GDK_ENTER_NOTIFY_MASK |
                                      GDK_LEAVE_NOTIFY_MASK);
    g_signal_connect_after(event_box_, "enter-notify-event",
                           G_CALLBACK(&OnMouseEnterThunk), this);
    g_signal_connect(event_box_, "leave-notify-event",
                     G_CALLBACK(&OnMouseLeaveThunk), this);

    // This is required as a leave is fired when the mouse goes from inside the
    // bubble's container to inside the set default button.
    gtk_widget_add_events(set_default_button, GDK_ENTER_NOTIFY_MASK);
    g_signal_connect_after(set_default_button, "enter-notify-event",
                           G_CALLBACK(&OnMouseEnterThunk), this);
  }

  StartTimerIfNecessary();
}

ZoomBubbleGtk::~ZoomBubbleGtk() {
  DCHECK_EQ(g_bubble, this);
  // Set singleton pointer to NULL.
  g_bubble = NULL;
}

void ZoomBubbleGtk::Refresh() {
  int zoom_percent = tab_contents_->zoom_controller()->zoom_percent();
  string16 text =
      l10n_util::GetStringFUTF16Int(IDS_TOOLTIP_ZOOM, zoom_percent);
  gtk_label_set_text(GTK_LABEL(g_bubble->label_), UTF16ToUTF8(text).c_str());
  StartTimerIfNecessary();
}

void ZoomBubbleGtk::StartTimerIfNecessary() {
  if (!auto_close_ || mouse_inside_)
    return;

  if (timer_.IsRunning()) {
    timer_.Reset();
  } else {
    timer_.Start(
        FROM_HERE,
        base::TimeDelta::FromMilliseconds(kBubbleCloseDelay),
        this,
        &ZoomBubbleGtk::CloseBubble);
  }
}

void ZoomBubbleGtk::StopTimerIfNecessary() {
  if (timer_.IsRunning())
    timer_.Stop();
}

void ZoomBubbleGtk::CloseBubble() {
  DCHECK(bubble_);
  bubble_->Close();
}

void ZoomBubbleGtk::OnDestroy(GtkWidget* widget) {
  // Listen to the destroy signal and delete this instance when it is caught.
  delete this;
}

void ZoomBubbleGtk::OnSetDefaultLinkClick(GtkWidget* widget) {
  double default_zoom_level = Profile::FromBrowserContext(
      tab_contents_->web_contents()->GetBrowserContext())->
          GetPrefs()->GetDouble(prefs::kDefaultZoomLevel);
  tab_contents_->web_contents()->GetRenderViewHost()->
      SetZoomLevel(default_zoom_level);
}

gboolean ZoomBubbleGtk::OnMouseEnter(GtkWidget* widget,
                                     GdkEventCrossing* event) {
  mouse_inside_ = true;
  StopTimerIfNecessary();
  return FALSE;
}

gboolean ZoomBubbleGtk::OnMouseLeave(GtkWidget* widget,
                                     GdkEventCrossing* event) {
  mouse_inside_ = false;
  StartTimerIfNecessary();
  return FALSE;
}
<commit_msg>[gtk] fix theming in zoom bubble<commit_after>// 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/zoom_bubble_gtk.h"

#include "base/utf_string_conversions.h"
#include "chrome/browser/prefs/pref_service.h"
#include "chrome/browser/profiles/profile.h"
#include "chrome/browser/ui/gtk/gtk_theme_service.h"
#include "chrome/browser/ui/tab_contents/tab_contents.h"
#include "chrome/browser/ui/zoom/zoom_controller.h"
#include "chrome/common/pref_names.h"
#include "content/public/browser/render_view_host.h"
#include "content/public/browser/web_contents.h"
#include "grit/generated_resources.h"
#include "ui/base/gtk/gtk_hig_constants.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/rect.h"

namespace {

// Pointer to singleton object (NULL if no bubble is open).
ZoomBubbleGtk* g_bubble = NULL;

// Number of milliseconds the bubble should stay open for if it will auto-close.
const int kBubbleCloseDelay = 1500;

// Need to manually set anchor width and height to ensure that the bubble shows
// in the correct spot the first time it is displayed when no icon is present.
const int kBubbleAnchorWidth = 20;
const int kBubbleAnchorHeight = 25;

}  // namespace

// static
void ZoomBubbleGtk::Show(GtkWidget* anchor,
                         TabContents* tab_contents,
                         bool auto_close) {
  // If the bubble is already showing and its |auto_close_| value is equal to
  // |auto_close|, the bubble can be reused and only the label text needs to
  // be updated.
  if (g_bubble &&
      g_bubble->auto_close_ == auto_close &&
      g_bubble->bubble_->anchor_widget() == anchor) {
    g_bubble->Refresh();
  } else {
    // If the bubble is already showing but its |auto_close_| value is not equal
    // to |auto_close|, the bubble's focus properties must change, so the
    // current bubble must be closed and a new one created.
    if (g_bubble)
      g_bubble->Close();

    g_bubble = new ZoomBubbleGtk(anchor, tab_contents, auto_close);
  }
}

// static
void ZoomBubbleGtk::Close() {
  if (g_bubble)
    g_bubble->CloseBubble();
}

ZoomBubbleGtk::ZoomBubbleGtk(GtkWidget* anchor,
                             TabContents* tab_contents,
                             bool auto_close)
    : auto_close_(auto_close),
      mouse_inside_(false),
      tab_contents_(tab_contents) {
  GtkThemeService* theme_service =
      GtkThemeService::GetFrom(Profile::FromBrowserContext(
          tab_contents->web_contents()->GetBrowserContext()));

  event_box_ = gtk_event_box_new();
  gtk_event_box_set_visible_window(GTK_EVENT_BOX(event_box_), FALSE);
  GtkWidget* container = gtk_vbox_new(FALSE, 0);
  gtk_container_add(GTK_CONTAINER(event_box_), container);

  int zoom_percent = tab_contents->zoom_controller()->zoom_percent();
  std::string percentage_text = UTF16ToUTF8(l10n_util::GetStringFUTF16Int(
      IDS_TOOLTIP_ZOOM, zoom_percent));
  label_ = theme_service->BuildLabel(percentage_text, ui::kGdkBlack);
  gtk_widget_modify_font(label_, pango_font_description_from_string("13"));
  gtk_misc_set_padding(GTK_MISC(label_),
                       ui::kControlSpacing, ui::kControlSpacing);
  gtk_box_pack_start(GTK_BOX(container), label_, FALSE, FALSE, 0);

  GtkWidget* separator = gtk_hseparator_new();
  gtk_box_pack_start(GTK_BOX(container), separator, FALSE, FALSE, 0);

  GtkWidget* set_default_button = theme_service->BuildChromeButton();
  GtkWidget* label = theme_service->BuildLabel(
      l10n_util::GetStringUTF8(IDS_ZOOM_SET_DEFAULT).c_str(), ui::kGdkBlack);
  gtk_container_add(GTK_CONTAINER(set_default_button), label);

  GtkWidget* alignment = gtk_alignment_new(0, 0, 1, 1);
  gtk_alignment_set_padding(
      GTK_ALIGNMENT(alignment), 0, 0, ui::kControlSpacing, ui::kControlSpacing);
  gtk_container_add(GTK_CONTAINER(alignment), set_default_button);

  gtk_box_pack_start(GTK_BOX(container), alignment, FALSE, FALSE, 0);
  g_signal_connect(set_default_button, "clicked",
                   G_CALLBACK(&OnSetDefaultLinkClickThunk), this);

  gtk_container_set_focus_child(GTK_CONTAINER(container), NULL);

  gfx::Rect rect(kBubbleAnchorWidth, kBubbleAnchorHeight);
  BubbleGtk::ArrowLocationGtk arrow_location =
      BubbleGtk::ARROW_LOCATION_TOP_MIDDLE;
  int bubble_options = BubbleGtk::MATCH_SYSTEM_THEME | BubbleGtk::POPUP_WINDOW;
  bubble_ = BubbleGtk::Show(anchor, &rect, event_box_, arrow_location,
      auto_close ? bubble_options : bubble_options | BubbleGtk::GRAB_INPUT,
      theme_service, NULL);

  if (!bubble_) {
    NOTREACHED();
    return;
  }

  g_signal_connect(event_box_, "destroy",
                   G_CALLBACK(&OnDestroyThunk), this);

  if (auto_close_) {
    // If this is an auto-closing bubble, listen to leave/enter to keep the
    // bubble alive if the mouse stays anywhere inside the bubble.
    gtk_widget_add_events(event_box_, GDK_ENTER_NOTIFY_MASK |
                                      GDK_LEAVE_NOTIFY_MASK);
    g_signal_connect_after(event_box_, "enter-notify-event",
                           G_CALLBACK(&OnMouseEnterThunk), this);
    g_signal_connect(event_box_, "leave-notify-event",
                     G_CALLBACK(&OnMouseLeaveThunk), this);

    // This is required as a leave is fired when the mouse goes from inside the
    // bubble's container to inside the set default button.
    gtk_widget_add_events(set_default_button, GDK_ENTER_NOTIFY_MASK);
    g_signal_connect_after(set_default_button, "enter-notify-event",
                           G_CALLBACK(&OnMouseEnterThunk), this);
  }

  StartTimerIfNecessary();
}

ZoomBubbleGtk::~ZoomBubbleGtk() {
  DCHECK_EQ(g_bubble, this);
  // Set singleton pointer to NULL.
  g_bubble = NULL;
}

void ZoomBubbleGtk::Refresh() {
  int zoom_percent = tab_contents_->zoom_controller()->zoom_percent();
  string16 text =
      l10n_util::GetStringFUTF16Int(IDS_TOOLTIP_ZOOM, zoom_percent);
  gtk_label_set_text(GTK_LABEL(g_bubble->label_), UTF16ToUTF8(text).c_str());
  StartTimerIfNecessary();
}

void ZoomBubbleGtk::StartTimerIfNecessary() {
  if (!auto_close_ || mouse_inside_)
    return;

  if (timer_.IsRunning()) {
    timer_.Reset();
  } else {
    timer_.Start(
        FROM_HERE,
        base::TimeDelta::FromMilliseconds(kBubbleCloseDelay),
        this,
        &ZoomBubbleGtk::CloseBubble);
  }
}

void ZoomBubbleGtk::StopTimerIfNecessary() {
  if (timer_.IsRunning())
    timer_.Stop();
}

void ZoomBubbleGtk::CloseBubble() {
  DCHECK(bubble_);
  bubble_->Close();
}

void ZoomBubbleGtk::OnDestroy(GtkWidget* widget) {
  // Listen to the destroy signal and delete this instance when it is caught.
  delete this;
}

void ZoomBubbleGtk::OnSetDefaultLinkClick(GtkWidget* widget) {
  double default_zoom_level = Profile::FromBrowserContext(
      tab_contents_->web_contents()->GetBrowserContext())->
          GetPrefs()->GetDouble(prefs::kDefaultZoomLevel);
  tab_contents_->web_contents()->GetRenderViewHost()->
      SetZoomLevel(default_zoom_level);
}

gboolean ZoomBubbleGtk::OnMouseEnter(GtkWidget* widget,
                                     GdkEventCrossing* event) {
  mouse_inside_ = true;
  StopTimerIfNecessary();
  return FALSE;
}

gboolean ZoomBubbleGtk::OnMouseLeave(GtkWidget* widget,
                                     GdkEventCrossing* event) {
  mouse_inside_ = false;
  StartTimerIfNecessary();
  return FALSE;
}
<|endoftext|>


<commit_before>// Copyright (c) 2006-2008 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/views/html_dialog_view.h"

#include "chrome/browser/browser.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "views/widget/root_view.h"
#include "views/widget/widget.h"
#include "views/window/window.h"

namespace browser {

// Declared in browser_dialogs.h so that others don't need to depend on our .h.
void ShowHtmlDialogView(gfx::NativeWindow parent, Browser* browser,
                        HtmlDialogUIDelegate* delegate) {
  HtmlDialogView* html_view = new HtmlDialogView(browser, delegate);
  views::Window::CreateChromeWindow(parent, gfx::Rect(), html_view);
  html_view->InitDialog();
  html_view->window()->Show();
}

}  // namespace browser

////////////////////////////////////////////////////////////////////////////////
// HtmlDialogView, public:

HtmlDialogView::HtmlDialogView(Browser* parent_browser,
                               HtmlDialogUIDelegate* delegate)
    : DOMView(),
      parent_browser_(parent_browser),
      profile_(parent_browser->profile()),
      delegate_(delegate) {
  DCHECK(profile_);
}

HtmlDialogView::~HtmlDialogView() {
}

////////////////////////////////////////////////////////////////////////////////
// HtmlDialogView, views::View implementation:

gfx::Size HtmlDialogView::GetPreferredSize() {
  gfx::Size out;
  delegate_->GetDialogSize(&out);
  return out;
}

////////////////////////////////////////////////////////////////////////////////
// HtmlDialogView, views::WindowDelegate implementation:

bool HtmlDialogView::CanResize() const {
  return true;
}

bool HtmlDialogView::IsModal() const {
  return delegate_->IsDialogModal();
}

std::wstring HtmlDialogView::GetWindowTitle() const {
  return delegate_->GetDialogTitle();
}

void HtmlDialogView::WindowClosing() {
  // If we still have a delegate that means we haven't notified it of the
  // dialog closing. This happens if the user clicks the Close button on the
  // dialog.
  if (delegate_)
    OnDialogClosed("");
}

views::View* HtmlDialogView::GetContentsView() {
  return this;
}

views::View* HtmlDialogView::GetInitiallyFocusedView() {
  return this;
}

////////////////////////////////////////////////////////////////////////////////
// HtmlDialogUIDelegate implementation:

bool HtmlDialogView::IsDialogModal() const {
  return IsModal();
}

std::wstring HtmlDialogView::GetDialogTitle() const {
  return GetWindowTitle();
}

GURL HtmlDialogView::GetDialogContentURL() const {
  return delegate_->GetDialogContentURL();
}

void HtmlDialogView::GetDOMMessageHandlers(
    std::vector<DOMMessageHandler*>* handlers) const {
  delegate_->GetDOMMessageHandlers(handlers);
}

void HtmlDialogView::GetDialogSize(gfx::Size* size) const {
  delegate_->GetDialogSize(size);
}

std::string HtmlDialogView::GetDialogArgs() const {
  return delegate_->GetDialogArgs();
}

void HtmlDialogView::OnDialogClosed(const std::string& json_retval) {
  delegate_->OnDialogClosed(json_retval);
  delegate_ = NULL;  // We will not communicate further with the delegate.
  window()->Close();
}

////////////////////////////////////////////////////////////////////////////////
// TabContentsDelegate implementation:

void HtmlDialogView::OpenURLFromTab(TabContents* source,
                                    const GURL& url,
                                    const GURL& referrer,
                                    WindowOpenDisposition disposition,
                                    PageTransition::Type transition) {
  // Force all links to open in a new window, ignoring the incoming
  // disposition. This is a tabless, modal dialog so we can't just
  // open it in the current frame.
  static_cast<TabContentsDelegate*>(parent_browser_)->OpenURLFromTab(
      source, url, referrer, NEW_WINDOW, transition);
}

void HtmlDialogView::NavigationStateChanged(const TabContents* source,
                                            unsigned changed_flags) {
  // We shouldn't receive any NavigationStateChanged except the first
  // one, which we ignore because we're a dialog box.
}

void HtmlDialogView::ReplaceContents(TabContents* source,
                                     TabContents* new_contents) {
}

void HtmlDialogView::AddNewContents(TabContents* source,
                    TabContents* new_contents,
                    WindowOpenDisposition disposition,
                    const gfx::Rect& initial_pos,
                    bool user_gesture) {
  static_cast<TabContentsDelegate*>(parent_browser_)->AddNewContents(
      source, new_contents, NEW_WINDOW, initial_pos, user_gesture);
}

void HtmlDialogView::ActivateContents(TabContents* contents) {
  // We don't do anything here because there's only one TabContents in
  // this frame and we don't have a TabStripModel.
}

void HtmlDialogView::LoadingStateChanged(TabContents* source) {
  // We don't care about this notification.
}

void HtmlDialogView::CloseContents(TabContents* source) {
  // We receive this message but don't handle it because we really do the
  // cleanup in OnDialogClosed().
}

void HtmlDialogView::MoveContents(TabContents* source, const gfx::Rect& pos) {
  // The contained web page wishes to resize itself. We let it do this because
  // if it's a dialog we know about, we trust it not to be mean to the user.
  GetWidget()->SetBounds(pos);
}

bool HtmlDialogView::IsPopup(TabContents* source) {
  // This needs to return true so that we are allowed to be resized by our
  // contents.
  return true;
}

void HtmlDialogView::ToolbarSizeChanged(TabContents* source,
                                        bool is_animating) {
  Layout();
}

void HtmlDialogView::URLStarredChanged(TabContents* source, bool starred) {
  // We don't have a visible star to click in the window.
  NOTREACHED();
}

void HtmlDialogView::UpdateTargetURL(TabContents* source, const GURL& url) {
  // Ignored.
}

////////////////////////////////////////////////////////////////////////////////
// HtmlDialogView:

void HtmlDialogView::InitDialog() {
  // Now Init the DOMView. This view runs in its own process to render the html.
  DOMView::Init(profile_, NULL);

  tab_contents_->set_delegate(this);

  // Set the delegate. This must be done before loading the page. See
  // the comment above HtmlDialogUI in its header file for why.
  HtmlDialogUI::GetPropertyAccessor().SetProperty(tab_contents_->property_bag(),
                                                  this);

  DOMView::LoadURL(delegate_->GetDialogContentURL());
}
<commit_msg>There is a race condition when the HtmlDialogView is closed which causes a crash while dereferencing an invalid delegate_ (HtmlDialogUIDelegate*) member. I could not reproduce this consistently though. The inference is as below:-<commit_after>// Copyright (c) 2006-2008 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/views/html_dialog_view.h"

#include "chrome/browser/browser.h"
#include "chrome/browser/tab_contents/tab_contents.h"
#include "views/widget/root_view.h"
#include "views/widget/widget.h"
#include "views/window/window.h"

namespace browser {

// Declared in browser_dialogs.h so that others don't need to depend on our .h.
void ShowHtmlDialogView(gfx::NativeWindow parent, Browser* browser,
                        HtmlDialogUIDelegate* delegate) {
  HtmlDialogView* html_view = new HtmlDialogView(browser, delegate);
  views::Window::CreateChromeWindow(parent, gfx::Rect(), html_view);
  html_view->InitDialog();
  html_view->window()->Show();
}

}  // namespace browser

////////////////////////////////////////////////////////////////////////////////
// HtmlDialogView, public:

HtmlDialogView::HtmlDialogView(Browser* parent_browser,
                               HtmlDialogUIDelegate* delegate)
    : DOMView(),
      parent_browser_(parent_browser),
      profile_(parent_browser->profile()),
      delegate_(delegate) {
  DCHECK(profile_);
}

HtmlDialogView::~HtmlDialogView() {
}

////////////////////////////////////////////////////////////////////////////////
// HtmlDialogView, views::View implementation:

gfx::Size HtmlDialogView::GetPreferredSize() {
  gfx::Size out;
  if (delegate_)
    delegate_->GetDialogSize(&out);
  return out;
}

////////////////////////////////////////////////////////////////////////////////
// HtmlDialogView, views::WindowDelegate implementation:

bool HtmlDialogView::CanResize() const {
  return true;
}

bool HtmlDialogView::IsModal() const {
  if (delegate_)
    return delegate_->IsDialogModal();
  else
    return false;
}

std::wstring HtmlDialogView::GetWindowTitle() const {
  if (delegate_)
    return delegate_->GetDialogTitle();
  else
    return std::wstring();
}

void HtmlDialogView::WindowClosing() {
  // If we still have a delegate that means we haven't notified it of the
  // dialog closing. This happens if the user clicks the Close button on the
  // dialog.
  if (delegate_)
    OnDialogClosed("");
}

views::View* HtmlDialogView::GetContentsView() {
  return this;
}

views::View* HtmlDialogView::GetInitiallyFocusedView() {
  return this;
}

////////////////////////////////////////////////////////////////////////////////
// HtmlDialogUIDelegate implementation:

bool HtmlDialogView::IsDialogModal() const {
  return IsModal();
}

std::wstring HtmlDialogView::GetDialogTitle() const {
  return GetWindowTitle();
}

GURL HtmlDialogView::GetDialogContentURL() const {
  if (delegate_)
    return delegate_->GetDialogContentURL();
  else
    return GURL();
}

void HtmlDialogView::GetDOMMessageHandlers(
    std::vector<DOMMessageHandler*>* handlers) const {
  if (delegate_)
    delegate_->GetDOMMessageHandlers(handlers);
}

void HtmlDialogView::GetDialogSize(gfx::Size* size) const {
  if (delegate_)
    delegate_->GetDialogSize(size);
}

std::string HtmlDialogView::GetDialogArgs() const {
  if (delegate_)
    return delegate_->GetDialogArgs();
  else
    return std::string();
}

void HtmlDialogView::OnDialogClosed(const std::string& json_retval) {
  HtmlDialogUIDelegate* dialog_delegate = delegate_;
  delegate_ = NULL;  // We will not communicate further with the delegate.
  dialog_delegate->OnDialogClosed(json_retval);
  window()->Close();
}

////////////////////////////////////////////////////////////////////////////////
// TabContentsDelegate implementation:

void HtmlDialogView::OpenURLFromTab(TabContents* source,
                                    const GURL& url,
                                    const GURL& referrer,
                                    WindowOpenDisposition disposition,
                                    PageTransition::Type transition) {
  // Force all links to open in a new window, ignoring the incoming
  // disposition. This is a tabless, modal dialog so we can't just
  // open it in the current frame.
  static_cast<TabContentsDelegate*>(parent_browser_)->OpenURLFromTab(
      source, url, referrer, NEW_WINDOW, transition);
}

void HtmlDialogView::NavigationStateChanged(const TabContents* source,
                                            unsigned changed_flags) {
  // We shouldn't receive any NavigationStateChanged except the first
  // one, which we ignore because we're a dialog box.
}

void HtmlDialogView::ReplaceContents(TabContents* source,
                                     TabContents* new_contents) {
}

void HtmlDialogView::AddNewContents(TabContents* source,
                    TabContents* new_contents,
                    WindowOpenDisposition disposition,
                    const gfx::Rect& initial_pos,
                    bool user_gesture) {
  static_cast<TabContentsDelegate*>(parent_browser_)->AddNewContents(
      source, new_contents, NEW_WINDOW, initial_pos, user_gesture);
}

void HtmlDialogView::ActivateContents(TabContents* contents) {
  // We don't do anything here because there's only one TabContents in
  // this frame and we don't have a TabStripModel.
}

void HtmlDialogView::LoadingStateChanged(TabContents* source) {
  // We don't care about this notification.
}

void HtmlDialogView::CloseContents(TabContents* source) {
  // We receive this message but don't handle it because we really do the
  // cleanup in OnDialogClosed().
}

void HtmlDialogView::MoveContents(TabContents* source, const gfx::Rect& pos) {
  // The contained web page wishes to resize itself. We let it do this because
  // if it's a dialog we know about, we trust it not to be mean to the user.
  GetWidget()->SetBounds(pos);
}

bool HtmlDialogView::IsPopup(TabContents* source) {
  // This needs to return true so that we are allowed to be resized by our
  // contents.
  return true;
}

void HtmlDialogView::ToolbarSizeChanged(TabContents* source,
                                        bool is_animating) {
  Layout();
}

void HtmlDialogView::URLStarredChanged(TabContents* source, bool starred) {
  // We don't have a visible star to click in the window.
  NOTREACHED();
}

void HtmlDialogView::UpdateTargetURL(TabContents* source, const GURL& url) {
  // Ignored.
}

////////////////////////////////////////////////////////////////////////////////
// HtmlDialogView:

void HtmlDialogView::InitDialog() {
  // Now Init the DOMView. This view runs in its own process to render the html.
  DOMView::Init(profile_, NULL);

  tab_contents_->set_delegate(this);

  // Set the delegate. This must be done before loading the page. See
  // the comment above HtmlDialogUI in its header file for why.
  HtmlDialogUI::GetPropertyAccessor().SetProperty(tab_contents_->property_bag(),
                                                  this);

  DOMView::LoadURL(delegate_->GetDialogContentURL());
}
<|endoftext|>


<commit_before>// Copyright (c) 2009 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/renderer/notification_provider.h"

#include "base/string_util.h"
#include "base/task.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/url_constants.h"
#include "chrome/renderer/render_thread.h"
#include "chrome/renderer/render_view.h"
#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/WebKit/chromium/public/WebNotificationPermissionCallback.h"
#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"

using WebKit::WebDocument;
using WebKit::WebNotification;
using WebKit::WebNotificationPresenter;
using WebKit::WebNotificationPermissionCallback;
using WebKit::WebString;
using WebKit::WebURL;

NotificationProvider::NotificationProvider(RenderView* view)
    : view_(view) {
}

bool NotificationProvider::show(const WebNotification& notification) {
  int notification_id = manager_.RegisterNotification(notification);
  if (notification.isHTML())
    return ShowHTML(notification, notification_id);
  else
    return ShowText(notification, notification_id);
}

void NotificationProvider::cancel(const WebNotification& notification) {
  int id;
  bool id_found = manager_.GetId(notification, id);
  // Won't be found if the notification has already been closed by the user.
  if (id_found)
    Send(new ViewHostMsg_CancelDesktopNotification(view_->routing_id(), id));
}

void NotificationProvider::objectDestroyed(
    const WebNotification& notification) {
  int id;
  bool id_found = manager_.GetId(notification, id);
  // Won't be found if the notification has already been closed by the user.
  if (id_found)
    manager_.UnregisterNotification(id);
}

WebNotificationPresenter::Permission NotificationProvider::checkPermission(
    const WebURL& url, WebDocument* document) {
  int permission;
  Send(new ViewHostMsg_CheckNotificationPermission(
          view_->routing_id(),
          url,
          document ? UTF16ToASCII(document->applicationID()) : "",
          &permission));
  return static_cast<WebNotificationPresenter::Permission>(permission);
}

void NotificationProvider::requestPermission(
    const WebString& origin, WebNotificationPermissionCallback* callback) {
  // We only request permission in response to a user gesture.
  if (!view_->webview()->mainFrame()->isProcessingUserGesture())
    return;

  int id = manager_.RegisterPermissionRequest(callback);

  Send(new ViewHostMsg_RequestNotificationPermission(view_->routing_id(),
                                                     GURL(origin), id));
}

bool NotificationProvider::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(NotificationProvider, message)
    IPC_MESSAGE_HANDLER(ViewMsg_PostDisplayToNotificationObject, OnDisplay);
    IPC_MESSAGE_HANDLER(ViewMsg_PostErrorToNotificationObject, OnError);
    IPC_MESSAGE_HANDLER(ViewMsg_PostCloseToNotificationObject, OnClose);
    IPC_MESSAGE_HANDLER(ViewMsg_PermissionRequestDone,
                        OnPermissionRequestComplete);
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void NotificationProvider::OnNavigate() {
  //  manager_.Clear();
}

bool NotificationProvider::ShowHTML(const WebNotification& notification,
                                    int id) {
  // Disallow HTML notifications from non-HTTP schemes.
  GURL url = notification.url();
  if (!url.SchemeIs(chrome::kHttpScheme) &&
      !url.SchemeIs(chrome::kHttpsScheme) &&
      !url.SchemeIs(chrome::kExtensionScheme))
    return false;

  DCHECK(notification.isHTML());
  return Send(new ViewHostMsg_ShowDesktopNotification(view_->routing_id(),
              GURL(view_->webview()->mainFrame()->url()).GetOrigin(),
              notification.url(), id));
}

bool NotificationProvider::ShowText(const WebNotification& notification,
                                    int id) {
  DCHECK(!notification.isHTML());
  return Send(new ViewHostMsg_ShowDesktopNotificationText(view_->routing_id(),
              GURL(view_->webview()->mainFrame()->url()).GetOrigin(),
              GURL(notification.icon()),
              notification.title(), notification.body(), id));
}

void NotificationProvider::OnDisplay(int id) {
  WebNotification notification;
  bool found = manager_.GetNotification(id, &notification);
  // |found| may be false if the WebNotification went out of scope in
  // the page before it was actually displayed to the user.
  if (found)
    notification.dispatchDisplayEvent();
}

void NotificationProvider::OnError(int id, const WebString& message) {
  WebNotification notification;
  bool found = manager_.GetNotification(id, &notification);
  // |found| may be false if the WebNotification went out of scope in
  // the page before the error occurred.
  if (found)
    notification.dispatchErrorEvent(message);
}

void NotificationProvider::OnClose(int id, bool by_user) {
  WebNotification notification;
  bool found = manager_.GetNotification(id, &notification);
  // |found| may be false if the WebNotification went out of scope in
  // the page before the associated toast was closed by the user.
  if (found) {
    notification.dispatchCloseEvent(by_user);
    manager_.UnregisterNotification(id);
  }
}

void NotificationProvider::OnPermissionRequestComplete(int id) {
  WebNotificationPermissionCallback* callback = manager_.GetCallback(id);
  DCHECK(callback);
  callback->permissionRequestComplete();
  manager_.OnPermissionRequestComplete(id);
}

bool NotificationProvider::Send(IPC::Message* message) {
  return RenderThread::current()->Send(message);
}
<commit_msg>Correct a mistake I made on a previous submission by commenting out an important line!<commit_after>// Copyright (c) 2009 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/renderer/notification_provider.h"

#include "base/string_util.h"
#include "base/task.h"
#include "chrome/common/render_messages.h"
#include "chrome/common/url_constants.h"
#include "chrome/renderer/render_thread.h"
#include "chrome/renderer/render_view.h"
#include "third_party/WebKit/WebKit/chromium/public/WebDocument.h"
#include "third_party/WebKit/WebKit/chromium/public/WebFrame.h"
#include "third_party/WebKit/WebKit/chromium/public/WebNotificationPermissionCallback.h"
#include "third_party/WebKit/WebKit/chromium/public/WebURL.h"

using WebKit::WebDocument;
using WebKit::WebNotification;
using WebKit::WebNotificationPresenter;
using WebKit::WebNotificationPermissionCallback;
using WebKit::WebString;
using WebKit::WebURL;

NotificationProvider::NotificationProvider(RenderView* view)
    : view_(view) {
}

bool NotificationProvider::show(const WebNotification& notification) {
  int notification_id = manager_.RegisterNotification(notification);
  if (notification.isHTML())
    return ShowHTML(notification, notification_id);
  else
    return ShowText(notification, notification_id);
}

void NotificationProvider::cancel(const WebNotification& notification) {
  int id;
  bool id_found = manager_.GetId(notification, id);
  // Won't be found if the notification has already been closed by the user.
  if (id_found)
    Send(new ViewHostMsg_CancelDesktopNotification(view_->routing_id(), id));
}

void NotificationProvider::objectDestroyed(
    const WebNotification& notification) {
  int id;
  bool id_found = manager_.GetId(notification, id);
  // Won't be found if the notification has already been closed by the user.
  if (id_found)
    manager_.UnregisterNotification(id);
}

WebNotificationPresenter::Permission NotificationProvider::checkPermission(
    const WebURL& url, WebDocument* document) {
  int permission;
  Send(new ViewHostMsg_CheckNotificationPermission(
          view_->routing_id(),
          url,
          document ? UTF16ToASCII(document->applicationID()) : "",
          &permission));
  return static_cast<WebNotificationPresenter::Permission>(permission);
}

void NotificationProvider::requestPermission(
    const WebString& origin, WebNotificationPermissionCallback* callback) {
  // We only request permission in response to a user gesture.
  if (!view_->webview()->mainFrame()->isProcessingUserGesture())
    return;

  int id = manager_.RegisterPermissionRequest(callback);

  Send(new ViewHostMsg_RequestNotificationPermission(view_->routing_id(),
                                                     GURL(origin), id));
}

bool NotificationProvider::OnMessageReceived(const IPC::Message& message) {
  bool handled = true;
  IPC_BEGIN_MESSAGE_MAP(NotificationProvider, message)
    IPC_MESSAGE_HANDLER(ViewMsg_PostDisplayToNotificationObject, OnDisplay);
    IPC_MESSAGE_HANDLER(ViewMsg_PostErrorToNotificationObject, OnError);
    IPC_MESSAGE_HANDLER(ViewMsg_PostCloseToNotificationObject, OnClose);
    IPC_MESSAGE_HANDLER(ViewMsg_PermissionRequestDone,
                        OnPermissionRequestComplete);
    IPC_MESSAGE_UNHANDLED(handled = false)
  IPC_END_MESSAGE_MAP()
  return handled;
}

void NotificationProvider::OnNavigate() {
  manager_.Clear();
}

bool NotificationProvider::ShowHTML(const WebNotification& notification,
                                    int id) {
  // Disallow HTML notifications from non-HTTP schemes.
  GURL url = notification.url();
  if (!url.SchemeIs(chrome::kHttpScheme) &&
      !url.SchemeIs(chrome::kHttpsScheme) &&
      !url.SchemeIs(chrome::kExtensionScheme))
    return false;

  DCHECK(notification.isHTML());
  return Send(new ViewHostMsg_ShowDesktopNotification(view_->routing_id(),
              GURL(view_->webview()->mainFrame()->url()).GetOrigin(),
              notification.url(), id));
}

bool NotificationProvider::ShowText(const WebNotification& notification,
                                    int id) {
  DCHECK(!notification.isHTML());
  return Send(new ViewHostMsg_ShowDesktopNotificationText(view_->routing_id(),
              GURL(view_->webview()->mainFrame()->url()).GetOrigin(),
              GURL(notification.icon()),
              notification.title(), notification.body(), id));
}

void NotificationProvider::OnDisplay(int id) {
  WebNotification notification;
  bool found = manager_.GetNotification(id, &notification);
  // |found| may be false if the WebNotification went out of scope in
  // the page before it was actually displayed to the user.
  if (found)
    notification.dispatchDisplayEvent();
}

void NotificationProvider::OnError(int id, const WebString& message) {
  WebNotification notification;
  bool found = manager_.GetNotification(id, &notification);
  // |found| may be false if the WebNotification went out of scope in
  // the page before the error occurred.
  if (found)
    notification.dispatchErrorEvent(message);
}

void NotificationProvider::OnClose(int id, bool by_user) {
  WebNotification notification;
  bool found = manager_.GetNotification(id, &notification);
  // |found| may be false if the WebNotification went out of scope in
  // the page before the associated toast was closed by the user.
  if (found) {
    notification.dispatchCloseEvent(by_user);
    manager_.UnregisterNotification(id);
  }
}

void NotificationProvider::OnPermissionRequestComplete(int id) {
  WebNotificationPermissionCallback* callback = manager_.GetCallback(id);
  DCHECK(callback);
  callback->permissionRequestComplete();
  manager_.OnPermissionRequestComplete(id);
}

bool NotificationProvider::Send(IPC::Message* message) {
  return RenderThread::current()->Send(message);
}
<|endoftext|>


<commit_before>#include <stdio.h>
#include <stdlib.h>

int suma(int desde) {
    if (desde == 0)
	return 0;
    return desde + suma(desde - 1);
}

int main(int argc, char *argv[]){
    int n;

    if (argc < 2)
	return EXIT_FAILURE;

    n = atoi(argv[1]);

    printf("%i\n", suma(n));
    return EXIT_SUCCESS;
}
<commit_msg>Delete suma.cpp<commit_after><|endoftext|>


<commit_before>/* net.cc
   Mathieu Stefani, 12 August 2015

*/

#include <stdexcept>
#include <limits>
#include <cstring>

#include <netinet/in.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <iostream>

#include <pistache/net.h>
#include <pistache/common.h>

using namespace std;

namespace Pistache {

Port::Port(uint16_t port)
    : port(port)
{ }

bool
Port::isReserved() const {
    return port < 1024;
}

bool
Port::isUsed() const {
    throw std::runtime_error("Unimplemented");
    return false;
}

std::string
Port::toString() const {
    return std::to_string(port);
}

Ipv4::Ipv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
    : a(a)
    , b(b)
    , c(c)
    , d(d)
{ }

Ipv4
Ipv4::any() {
    return Ipv4(0, 0, 0, 0);
}

Ipv4
Ipv4::loopback() {
    return Ipv4(127, 0, 0, 1);
}

std::string
Ipv4::toString() const {

    // Use the built-in ipv4 string length from arpa/inet.h
    char buff[INET_ADDRSTRLEN+1];

    in_addr_t addr;
    toNetwork(&addr);

    // Convert the network format address into display format
    inet_ntop(AF_INET, &addr, buff, INET_ADDRSTRLEN);

    return std::string(buff);
}

void Ipv4::toNetwork(in_addr_t *addr) const {
    // Bitshift the bytes into an in_addr_t (a single 32bit unsigned int);
    *addr = htonl( (uint32_t)(a<<24) | (uint32_t)(b<<16) | (uint32_t)(c<<8) | (uint32_t)d );;
}

Ipv6::Ipv6(uint16_t a, uint16_t b, uint16_t c, uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h)
    : a(a)
    , b(b)
    , c(c)
    , d(d)
    , e(e)
    , f(f)
    , g(g)
    , h(h)
{ }

Ipv6
Ipv6::any() {
    return Ipv6(0, 0, 0, 0, 0, 0, 0, 0);
}

Ipv6
Ipv6::loopback() {
    return Ipv6(0, 0, 0, 0, 0, 0, 0, 1);
}

std::string
Ipv6::toString() const {

    // Use the built-in ipv6 string length from arpa/inet.h
    char buff6[INET6_ADDRSTRLEN+1];

    in6_addr addr;
    toNetwork(&addr);

    inet_ntop(AF_INET6, &addr, buff6, INET6_ADDRSTRLEN);

    return std::string(buff6);
}

void Ipv6::toNetwork(in6_addr *addr6) const {
    uint16_t temp_ip6[8] = {a, b, c, d, e, f, g, h};
    uint16_t remap_ip6[8] = {0};
    uint16_t x, y;

     // If native endianness is little-endian swap the bytes, otherwise just copy them into the new array
    if ( htonl(1) != 1 ) {
        for (uint16_t i = 0; i<8; i++) {
            x = temp_ip6[i];
            y = htons(x);
            remap_ip6[i] = y;
        }
    } else {
        memcpy(remap_ip6, temp_ip6, 16);
    }
    // Copy the bytes into the in6_addr struct
    memcpy(addr6->s6_addr16, remap_ip6, 16);
}

bool Ipv6::supported() {
    struct ifaddrs *ifaddr = nullptr;
    struct ifaddrs *ifa = nullptr;
    int family, n;
    bool supportsIpv6 = false;

    if (getifaddrs(&ifaddr) == -1) {
        throw std::runtime_error("Call to getifaddrs() failed");
    }

    for (ifa = ifaddr, n = 0; ifa != nullptr; ifa = ifa->ifa_next, n++) {
        if (ifa->ifa_addr == nullptr) {
            continue;
        }

        family = ifa->ifa_addr->sa_family;
        if (family == AF_INET6) {
            supportsIpv6 = true;
            continue;
        }
    }

    freeifaddrs(ifaddr);
    return supportsIpv6;
}

Address::Address()
    : host_("")
    , port_(0)
{ }

Address::Address(std::string host, Port port)
{
    std::string addr = host;
    addr.append(":");
    addr.append(port.toString());
    init(std::move(addr));
}

Address::Address(std::string addr)
{
    init(std::move(addr));
}

Address::Address(const char* addr)
{
    init(std::string(addr));
}

Address::Address(Ipv4 ip, Port port)
    : host_(ip.toString())
    , port_(port)
    , family_(AF_INET)
{ }

Address::Address(Ipv6 ip, Port port)
    : host_(ip.toString())
    , port_(port)
    , family_(AF_INET6)
{ }

Address
Address::fromUnix(struct sockaddr* addr) {
    if (addr->sa_family == AF_INET) {
        struct sockaddr_in *in_addr = reinterpret_cast<struct sockaddr_in *>(addr);
        char host[INET_ADDRSTRLEN+1];
        inet_ntop(AF_INET, &(in_addr->sin_addr), host, INET_ADDRSTRLEN);
        int port = ntohs(in_addr->sin_port);
        assert(addr);
        return Address(host, port);
    } else if (addr->sa_family == AF_INET6) {
        struct sockaddr_in6 *in_addr = reinterpret_cast<struct sockaddr_in6 *>(addr);
        char host[INET6_ADDRSTRLEN+1];
        inet_ntop(AF_INET6, &(in_addr->sin6_addr), host, INET6_ADDRSTRLEN);
        int port = ntohs(in_addr->sin6_port);
        assert(addr);
        return Address(host, port);
    }
    throw Error("Not an IP socket");
}

std::string
Address::host() const {
    return host_;
}

Port
Address::port() const {
    return port_;
}

int
Address::family() const {
    return family_;
}

void
Address::init(const std::string& addr) {
    unsigned long pos = addr.find(']');
    unsigned long s_pos = addr.find('[');
    if (pos != std::string::npos && s_pos != std::string::npos) {
        //IPv6 address
        host_ = addr.substr(s_pos+1, pos-1);
        family_ = AF_INET6;
        try {
            in6_addr addr6;
            char buff6[INET6_ADDRSTRLEN + 1];
            std::copy(&host_[0], &host_[0] + host_.size(), buff6);
            inet_pton(AF_INET6, buff6, &(addr6.s6_addr16));
        } catch (std::runtime_error) {
            throw std::invalid_argument("Invalid IPv6 address");
        }
        pos++;
    } else {
        //IPv4 address
        pos = addr.find(':');
        if (pos == std::string::npos)
            throw std::invalid_argument("Invalid address");
        host_ = addr.substr(0, pos);
        family_ = AF_INET;
        if (host_ == "*") {
            host_ = "0.0.0.0";
        }
        try {
            in_addr addr;
            char buff[INET_ADDRSTRLEN + 1];
            std::copy(&host_[0], &host_[0] + host_.size(), buff);
            inet_pton(AF_INET, buff, &(addr));
        } catch (std::runtime_error) {
            throw std::invalid_argument("Invalid IPv4 address");
        }
    }
    char *end;
    const std::string portPart = addr.substr(pos + 1);
    if (portPart.empty())
        throw std::invalid_argument("Invalid port");
    long port = strtol(portPart.c_str(), &end, 10);
    if (*end != 0 || port < Port::min() || port > Port::max())
        throw std::invalid_argument("Invalid port");
    port_ = static_cast<uint16_t>(port);
}

Error::Error(const char* message)
    : std::runtime_error(message)
{ }

Error::Error(std::string message)
    : std::runtime_error(std::move(message))
{ }

Error
Error::system(const char* message) {
    const char *err = strerror(errno);

    std::string str(message);
    str += ": ";
    str += err;

    return Error(std::move(str));

}

} // namespace Pistache
<commit_msg>Init buffers<commit_after>/* net.cc
   Mathieu Stefani, 12 August 2015

*/

#include <stdexcept>
#include <limits>
#include <cstring>

#include <netinet/in.h>
#include <arpa/inet.h>
#include <ifaddrs.h>
#include <iostream>

#include <pistache/net.h>
#include <pistache/common.h>

using namespace std;

namespace Pistache {

Port::Port(uint16_t port)
    : port(port)
{ }

bool
Port::isReserved() const {
    return port < 1024;
}

bool
Port::isUsed() const {
    throw std::runtime_error("Unimplemented");
    return false;
}

std::string
Port::toString() const {
    return std::to_string(port);
}

Ipv4::Ipv4(uint8_t a, uint8_t b, uint8_t c, uint8_t d)
    : a(a)
    , b(b)
    , c(c)
    , d(d)
{ }

Ipv4
Ipv4::any() {
    return Ipv4(0, 0, 0, 0);
}

Ipv4
Ipv4::loopback() {
    return Ipv4(127, 0, 0, 1);
}

std::string
Ipv4::toString() const {

    // Use the built-in ipv4 string length from arpa/inet.h
    char buff[INET_ADDRSTRLEN+1];

    in_addr_t addr;
    toNetwork(&addr);

    // Convert the network format address into display format
    inet_ntop(AF_INET, &addr, buff, INET_ADDRSTRLEN);

    return std::string(buff);
}

void Ipv4::toNetwork(in_addr_t *addr) const {
    // Bitshift the bytes into an in_addr_t (a single 32bit unsigned int);
    *addr = htonl( (uint32_t)(a<<24) | (uint32_t)(b<<16) | (uint32_t)(c<<8) | (uint32_t)d );;
}

Ipv6::Ipv6(uint16_t a, uint16_t b, uint16_t c, uint16_t d, uint16_t e, uint16_t f, uint16_t g, uint16_t h)
    : a(a)
    , b(b)
    , c(c)
    , d(d)
    , e(e)
    , f(f)
    , g(g)
    , h(h)
{ }

Ipv6
Ipv6::any() {
    return Ipv6(0, 0, 0, 0, 0, 0, 0, 0);
}

Ipv6
Ipv6::loopback() {
    return Ipv6(0, 0, 0, 0, 0, 0, 0, 1);
}

std::string
Ipv6::toString() const {

    // Use the built-in ipv6 string length from arpa/inet.h
    char buff6[INET6_ADDRSTRLEN+1];

    in6_addr addr;
    toNetwork(&addr);

    inet_ntop(AF_INET6, &addr, buff6, INET6_ADDRSTRLEN);

    return std::string(buff6);
}

void Ipv6::toNetwork(in6_addr *addr6) const {
    uint16_t temp_ip6[8] = {a, b, c, d, e, f, g, h};
    uint16_t remap_ip6[8] = {0};
    uint16_t x, y;

     // If native endianness is little-endian swap the bytes, otherwise just copy them into the new array
    if ( htonl(1) != 1 ) {
        for (uint16_t i = 0; i<8; i++) {
            x = temp_ip6[i];
            y = htons(x);
            remap_ip6[i] = y;
        }
    } else {
        memcpy(remap_ip6, temp_ip6, 16);
    }
    // Copy the bytes into the in6_addr struct
    memcpy(addr6->s6_addr16, remap_ip6, 16);
}

bool Ipv6::supported() {
    struct ifaddrs *ifaddr = nullptr;
    struct ifaddrs *ifa = nullptr;
    int family, n;
    bool supportsIpv6 = false;

    if (getifaddrs(&ifaddr) == -1) {
        throw std::runtime_error("Call to getifaddrs() failed");
    }

    for (ifa = ifaddr, n = 0; ifa != nullptr; ifa = ifa->ifa_next, n++) {
        if (ifa->ifa_addr == nullptr) {
            continue;
        }

        family = ifa->ifa_addr->sa_family;
        if (family == AF_INET6) {
            supportsIpv6 = true;
            continue;
        }
    }

    freeifaddrs(ifaddr);
    return supportsIpv6;
}

Address::Address()
    : host_("")
    , port_(0)
{ }

Address::Address(std::string host, Port port)
{
    std::string addr = host;
    addr.append(":");
    addr.append(port.toString());
    init(std::move(addr));
}

Address::Address(std::string addr)
{
    init(std::move(addr));
}

Address::Address(const char* addr)
{
    init(std::string(addr));
}

Address::Address(Ipv4 ip, Port port)
    : host_(ip.toString())
    , port_(port)
    , family_(AF_INET)
{ }

Address::Address(Ipv6 ip, Port port)
    : host_(ip.toString())
    , port_(port)
    , family_(AF_INET6)
{ }

Address
Address::fromUnix(struct sockaddr* addr) {
    if (addr->sa_family == AF_INET) {
        struct sockaddr_in *in_addr = reinterpret_cast<struct sockaddr_in *>(addr);
        char host[INET_ADDRSTRLEN+1];
        inet_ntop(AF_INET, &(in_addr->sin_addr), host, INET_ADDRSTRLEN);
        int port = ntohs(in_addr->sin_port);
        assert(addr);
        return Address(host, port);
    } else if (addr->sa_family == AF_INET6) {
        struct sockaddr_in6 *in_addr = reinterpret_cast<struct sockaddr_in6 *>(addr);
        char host[INET6_ADDRSTRLEN+1];
        inet_ntop(AF_INET6, &(in_addr->sin6_addr), host, INET6_ADDRSTRLEN);
        int port = ntohs(in_addr->sin6_port);
        assert(addr);
        return Address(host, port);
    }
    throw Error("Not an IP socket");
}

std::string
Address::host() const {
    return host_;
}

Port
Address::port() const {
    return port_;
}

int
Address::family() const {
    return family_;
}

void
Address::init(const std::string& addr) {
    unsigned long pos = addr.find(']');
    unsigned long s_pos = addr.find('[');
    if (pos != std::string::npos && s_pos != std::string::npos) {
        //IPv6 address
        host_ = addr.substr(s_pos+1, pos-1);
        family_ = AF_INET6;
        try {
            in6_addr addr6;
            char buff6[INET6_ADDRSTRLEN + 1] = {0, };
            std::copy(&host_[0], &host_[0] + host_.size(), buff6);
            inet_pton(AF_INET6, buff6, &(addr6.s6_addr16));
        } catch (std::runtime_error) {
            throw std::invalid_argument("Invalid IPv6 address");
        }
        pos++;
    } else {
        //IPv4 address
        pos = addr.find(':');
        if (pos == std::string::npos)
            throw std::invalid_argument("Invalid address");
        host_ = addr.substr(0, pos);
        family_ = AF_INET;
        if (host_ == "*") {
            host_ = "0.0.0.0";
        }
        try {
            in_addr addr;
            char buff[INET_ADDRSTRLEN + 1] = {0, };
            std::copy(&host_[0], &host_[0] + host_.size(), buff);
            inet_pton(AF_INET, buff, &(addr));
        } catch (std::runtime_error) {
            throw std::invalid_argument("Invalid IPv4 address");
        }
    }
    char *end;
    const std::string portPart = addr.substr(pos + 1);
    if (portPart.empty())
        throw std::invalid_argument("Invalid port");
    long port = strtol(portPart.c_str(), &end, 10);
    if (*end != 0 || port < Port::min() || port > Port::max())
        throw std::invalid_argument("Invalid port");
    port_ = static_cast<uint16_t>(port);
}

Error::Error(const char* message)
    : std::runtime_error(message)
{ }

Error::Error(std::string message)
    : std::runtime_error(std::move(message))
{ }

Error
Error::system(const char* message) {
    const char *err = strerror(errno);

    std::string str(message);
    str += ": ";
    str += err;

    return Error(std::move(str));

}

} // namespace Pistache
<|endoftext|>