1// Copyright 2013 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "chrome/browser/ui/views/toolbar/home_button.h"
6
7#include "base/prefs/pref_service.h"
8#include "chrome/browser/profiles/profile.h"
9#include "chrome/browser/ui/browser.h"
10#include "chrome/browser/ui/views/settings_api_bubble_helper_views.h"
11#include "chrome/common/pref_names.h"
12#include "chrome/grit/generated_resources.h"
13#include "components/user_prefs/user_prefs.h"
14#include "ui/base/l10n/l10n_util.h"
15#include "ui/views/bubble/bubble_delegate.h"
16#include "ui/views/controls/label.h"
17#include "ui/views/controls/link.h"
18#include "ui/views/controls/link_listener.h"
19#include "ui/views/layout/grid_layout.h"
20#include "ui/views/layout/layout_constants.h"
21#include "ui/views/widget/widget.h"
22
23// HomePageUndoBubble --------------------------------------------------------
24
25namespace {
26
27class HomePageUndoBubble : public views::BubbleDelegateView,
28                           public views::LinkListener {
29 public:
30  static void ShowBubble(Browser* browser,
31                         bool undo_value_is_ntp,
32                         const GURL& undo_url,
33                         views::View* anchor_view);
34  static void HideBubble();
35
36 private:
37  HomePageUndoBubble(Browser* browser, bool undo_value_is_ntp,
38                     const GURL& undo_url, views::View* anchor_view);
39  virtual ~HomePageUndoBubble();
40
41  // views::BubbleDelegateView:
42  virtual void Init() OVERRIDE;
43  virtual void WindowClosing() OVERRIDE;
44
45  // views::LinkListener:
46  virtual void LinkClicked(views::Link* source, int event_flags) OVERRIDE;
47
48  static HomePageUndoBubble* home_page_undo_bubble_;
49
50  Browser* browser_;
51  bool undo_value_is_ntp_;
52  GURL undo_url_;
53
54  DISALLOW_COPY_AND_ASSIGN(HomePageUndoBubble);
55};
56
57// static
58HomePageUndoBubble* HomePageUndoBubble::home_page_undo_bubble_ = NULL;
59
60void HomePageUndoBubble::ShowBubble(Browser* browser,
61                                    bool undo_value_is_ntp,
62                                    const GURL& undo_url,
63                                    views::View* anchor_view) {
64  HideBubble();
65  home_page_undo_bubble_ = new HomePageUndoBubble(browser,
66                                                  undo_value_is_ntp,
67                                                  undo_url,
68                                                  anchor_view);
69  views::BubbleDelegateView::CreateBubble(home_page_undo_bubble_)->Show();
70}
71
72void HomePageUndoBubble::HideBubble() {
73  if (home_page_undo_bubble_)
74    home_page_undo_bubble_->GetWidget()->Close();
75}
76
77HomePageUndoBubble::HomePageUndoBubble(
78    Browser* browser,
79    bool undo_value_is_ntp,
80    const GURL& undo_url,
81    views::View* anchor_view)
82    : BubbleDelegateView(anchor_view, views::BubbleBorder::TOP_LEFT),
83      browser_(browser),
84      undo_value_is_ntp_(undo_value_is_ntp),
85      undo_url_(undo_url) {
86}
87
88HomePageUndoBubble::~HomePageUndoBubble() {
89}
90
91void HomePageUndoBubble::Init() {
92  views::GridLayout* layout = new views::GridLayout(this);
93  SetLayoutManager(layout);
94
95  // Create two columns for the message and the undo link.
96  views::ColumnSet* cs = layout->AddColumnSet(0);
97  cs = layout->AddColumnSet(1);
98  cs->AddColumn(views::GridLayout::LEADING, views::GridLayout::BASELINE, 0,
99                views::GridLayout::USE_PREF, 0, 0);
100  cs->AddPaddingColumn(0, views::kRelatedControlHorizontalSpacing);
101  cs->AddColumn(views::GridLayout::CENTER, views::GridLayout::BASELINE, 0,
102                views::GridLayout::USE_PREF, 0, 0);
103
104  views::Label* message_label = new views::Label(
105      l10n_util::GetStringUTF16(IDS_TOOLBAR_INFORM_SET_HOME_PAGE));
106  message_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
107  layout->StartRow(0, 1);
108  layout->AddView(message_label);
109
110  views::Link* undo_link = new views::Link(
111      l10n_util::GetStringUTF16(IDS_ONE_CLICK_BUBBLE_UNDO));
112  undo_link->set_listener(this);
113  layout->AddView(undo_link);
114}
115
116void HomePageUndoBubble::LinkClicked(views::Link* source, int event_flags) {
117  PrefService* prefs = user_prefs::UserPrefs::Get(browser_->profile());
118  prefs->SetBoolean(prefs::kHomePageIsNewTabPage, undo_value_is_ntp_);
119  prefs->SetString(prefs::kHomePage, undo_url_.spec());
120
121  HideBubble();
122}
123
124void HomePageUndoBubble::WindowClosing() {
125  // We have to reset |home_page_undo_bubble_| here, not in our destructor,
126  // because we'll be hidden first, then destroyed asynchronously.  If we wait
127  // to reset this, and the user triggers a call to ShowBubble() while the
128  // window is hidden but not destroyed, GetWidget()->Close() would be
129  // called twice.
130  DCHECK_EQ(this, home_page_undo_bubble_);
131  home_page_undo_bubble_ = NULL;
132}
133
134}  // namespace
135
136
137// HomeButton -----------------------------------------------------------
138
139HomeButton::HomeButton(
140    views::ButtonListener* listener,
141    Browser* browser)
142    : ToolbarButton(listener, NULL),
143      browser_(browser) {
144}
145
146HomeButton::~HomeButton() {
147}
148
149bool HomeButton::GetDropFormats(
150    int* formats,
151    std::set<OSExchangeData::CustomFormat>* custom_formats) {
152  *formats = ui::OSExchangeData::URL;
153  return true;
154}
155
156bool HomeButton::CanDrop(const OSExchangeData& data) {
157  return data.HasURL(ui::OSExchangeData::CONVERT_FILENAMES);
158}
159
160int HomeButton::OnDragUpdated(const ui::DropTargetEvent& event) {
161  return (event.source_operations() & ui::DragDropTypes::DRAG_LINK) ?
162      ui::DragDropTypes::DRAG_LINK : ui::DragDropTypes::DRAG_NONE;
163}
164
165int HomeButton::OnPerformDrop(const ui::DropTargetEvent& event) {
166  GURL new_homepage_url;
167  base::string16 title;
168  if (event.data().GetURLAndTitle(
169          ui::OSExchangeData::CONVERT_FILENAMES, &new_homepage_url, &title) &&
170      new_homepage_url.is_valid()) {
171    PrefService* prefs = browser_->profile()->GetPrefs();
172    bool old_is_ntp = prefs->GetBoolean(prefs::kHomePageIsNewTabPage);
173    GURL old_homepage(prefs->GetString(prefs::kHomePage));
174
175    prefs->SetBoolean(prefs::kHomePageIsNewTabPage, false);
176    prefs->SetString(prefs::kHomePage, new_homepage_url.spec());
177
178    HomePageUndoBubble::ShowBubble(browser_, old_is_ntp, old_homepage, this);
179  }
180  return ui::DragDropTypes::DRAG_NONE;
181}
182
183void HomeButton::NotifyClick(const ui::Event& event) {
184  ToolbarButton::NotifyClick(event);
185  extensions::MaybeShowExtensionControlledHomeNotification(browser_);
186}
187