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/gtk/manage_passwords_bubble_gtk.h"
6
7#include "chrome/browser/chrome_notification_types.h"
8#include "chrome/browser/profiles/profile.h"
9#include "chrome/browser/ui/browser.h"
10#include "chrome/browser/ui/browser_finder.h"
11#include "chrome/browser/ui/browser_window.h"
12#include "chrome/browser/ui/gtk/gtk_theme_service.h"
13#include "chrome/browser/ui/gtk/location_bar_view_gtk.h"
14#include "chrome/browser/ui/passwords/manage_passwords_bubble_ui_controller.h"
15#include "grit/generated_resources.h"
16#include "ui/base/gtk/gtk_hig_constants.h"
17#include "ui/base/l10n/l10n_util.h"
18
19namespace {
20
21// Pointer to singleton object (NULL if no bubble is open).
22ManagePasswordsBubbleGtk* g_bubble = NULL;
23
24// Need to manually set anchor width and height to ensure that the bubble shows
25// in the correct spot the first time it is displayed when no icon is present.
26const int kBubbleAnchorWidth = 20;
27const int kBubbleAnchorHeight = 25;
28
29}  // namespace
30
31// static
32void ManagePasswordsBubbleGtk::ShowBubble(content::WebContents* web_contents) {
33  Browser* browser = chrome::FindBrowserWithWebContents(web_contents);
34  DCHECK(browser && browser->window() && browser->fullscreen_controller());
35
36  LocationBar* location_bar = browser->window()->GetLocationBar();
37  GtkWidget* anchor = browser->window()->IsFullscreen() ?
38      GTK_WIDGET(browser->window()->GetNativeWindow()) :
39      static_cast<LocationBarViewGtk*>(location_bar)->
40          manage_passwords_icon_widget();
41
42  g_bubble = new ManagePasswordsBubbleGtk(anchor,
43                                          web_contents,
44                                          browser->fullscreen_controller());
45}
46
47// static
48void ManagePasswordsBubbleGtk::CloseBubble() {
49  if (g_bubble)
50    g_bubble->Close();
51}
52
53// static
54bool ManagePasswordsBubbleGtk::IsShowing() {
55  return g_bubble != NULL;
56}
57
58ManagePasswordsBubbleGtk::ManagePasswordsBubbleGtk(
59    GtkWidget* anchor,
60    content::WebContents* web_contents,
61    FullscreenController* fullscreen_controller)
62    : web_contents_(web_contents) {
63  GtkThemeService* theme_service = GtkThemeService::GetFrom(
64      Profile::FromBrowserContext(web_contents_->GetBrowserContext()));
65
66  GtkWidget* bubble_contents_ = gtk_vbox_new(FALSE, ui::kControlSpacing);
67  gtk_container_set_border_width(GTK_CONTAINER(bubble_contents_),
68                                 ui::kContentAreaBorder);
69  GtkWidget* label = theme_service->BuildLabel(
70      l10n_util::GetStringUTF8(IDS_SAVE_PASSWORD), ui::kGdkBlack);
71  gtk_misc_set_alignment(GTK_MISC(label), 0, 0.5);
72  gtk_box_pack_start(GTK_BOX(bubble_contents_), label, FALSE, FALSE, 0);
73
74  GtkWidget* button_container = gtk_hbox_new(FALSE, 0);
75  GtkWidget* nope_button = gtk_button_new_with_label(l10n_util::GetStringUTF8(
76      IDS_PASSWORD_MANAGER_CANCEL_BUTTON).c_str());
77  g_signal_connect(nope_button, "clicked",
78                   G_CALLBACK(OnNotNowButtonClickedThunk), this);
79  GtkWidget* save_button = gtk_button_new_with_label(
80      l10n_util::GetStringUTF8(IDS_PASSWORD_MANAGER_SAVE_BUTTON).c_str());
81  g_signal_connect(save_button, "clicked",
82                   G_CALLBACK(OnSaveButtonClickedThunk), this);
83
84  gtk_box_pack_end(GTK_BOX(button_container), save_button, FALSE, FALSE, 4);
85  gtk_box_pack_end(GTK_BOX(button_container), nope_button, FALSE, FALSE, 0);
86  gtk_box_pack_start(GTK_BOX(bubble_contents_), button_container, FALSE, FALSE,
87                     0);
88  gtk_widget_grab_focus(save_button);
89
90  gfx::Rect rect = gfx::Rect(kBubbleAnchorWidth, kBubbleAnchorHeight);
91  BubbleGtk::FrameStyle frame_style = gtk_widget_is_toplevel(anchor) ?
92      BubbleGtk::FIXED_TOP_RIGHT : BubbleGtk::ANCHOR_TOP_RIGHT;
93  bubble_ = BubbleGtk::Show(anchor,
94                            &rect,
95                            bubble_contents_,
96                            frame_style,
97                            BubbleGtk::MATCH_SYSTEM_THEME |
98                                BubbleGtk::POPUP_WINDOW |
99                                BubbleGtk::GRAB_INPUT,
100                            theme_service,
101                            NULL);
102
103  g_signal_connect(bubble_contents_, "destroy",
104                   G_CALLBACK(&OnDestroyThunk), this);
105}
106
107ManagePasswordsBubbleGtk::~ManagePasswordsBubbleGtk() {
108  DCHECK_EQ(g_bubble, this);
109  // Set singleton pointer to NULL.
110  g_bubble = NULL;
111}
112
113void ManagePasswordsBubbleGtk::Close() {
114  DCHECK(bubble_);
115  bubble_->Close();
116}
117
118void ManagePasswordsBubbleGtk::OnDestroy(GtkWidget* widget) {
119  // Listen to the destroy signal and delete this instance when it is caught.
120  delete this;
121}
122
123void ManagePasswordsBubbleGtk::OnSaveButtonClicked(GtkWidget* button) {
124  ManagePasswordsBubbleUIController::FromWebContents(web_contents_)->
125      SavePassword();
126  Close();
127}
128
129void ManagePasswordsBubbleGtk::OnNotNowButtonClicked(GtkWidget* button) {
130  Close();
131}
132