1 // Copyright (c) 2012 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.
5 #include "chrome/browser/ui/gtk/password_generation_bubble_gtk.h"
7 #include "base/strings/utf_string_conversions.h"
8 #include "chrome/browser/password_manager/chrome_password_manager_client.h"
9 #include "chrome/browser/password_manager/password_manager.h"
10 #include "chrome/browser/profiles/profile.h"
11 #include "chrome/browser/ui/browser.h"
12 #include "chrome/browser/ui/browser_finder.h"
13 #include "chrome/browser/ui/gtk/bubble/bubble_gtk.h"
14 #include "chrome/browser/ui/gtk/gtk_chrome_link_button.h"
15 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
16 #include "chrome/browser/ui/gtk/gtk_util.h"
17 #include "chrome/common/url_constants.h"
18 #include "components/autofill/content/common/autofill_messages.h"
19 #include "components/autofill/core/browser/password_generator.h"
20 #include "content/public/browser/render_view_host.h"
21 #include "content/public/browser/web_contents.h"
22 #include "content/public/browser/web_contents_view.h"
23 #include "grit/generated_resources.h"
24 #include "grit/theme_resources.h"
25 #include "ui/base/gtk/gtk_hig_constants.h"
26 #include "ui/base/l10n/l10n_util.h"
27 #include "ui/base/resource/resource_bundle.h"
29 using content::RenderViewHost
;
33 GdkPixbuf
* GetImage(int resource_id
) {
36 return ui::ResourceBundle::GetSharedInstance().GetNativeImageNamed(
37 resource_id
, ui::ResourceBundle::RTL_ENABLED
).ToGdkPixbuf();
42 PasswordGenerationBubbleGtk::PasswordGenerationBubbleGtk(
43 const gfx::Rect
& anchor_rect
,
44 const autofill::PasswordForm
& form
,
45 content::WebContents
* web_contents
,
46 autofill::PasswordGenerator
* password_generator
)
48 web_contents_(web_contents
),
49 password_generator_(password_generator
) {
50 // TODO(gcasto): Localize text after we have finalized the UI.
52 GtkWidget
* content
= gtk_vbox_new(FALSE
, 5);
54 // We have two lines of content. The first is the title and learn more link.
55 GtkWidget
* title_line
= gtk_hbox_new(FALSE
, 0);
56 GtkWidget
* title
= gtk_label_new(
57 l10n_util::GetStringUTF8(IDS_PASSWORD_GENERATION_BUBBLE_TITLE
).c_str());
58 gtk_box_pack_start(GTK_BOX(title_line
), title
, FALSE
, FALSE
, 0);
59 GtkWidget
* learn_more_link
= gtk_chrome_link_button_new(
60 l10n_util::GetStringUTF8(IDS_LEARN_MORE
).c_str());
61 gtk_button_set_alignment(GTK_BUTTON(learn_more_link
), 0.0, 0.5);
62 gtk_box_pack_start(GTK_BOX(title_line
),
63 gtk_util::IndentWidget(learn_more_link
),
66 // The second contains the password in a text field, a regenerate button, and
68 GtkWidget
* password_line
= gtk_hbox_new(FALSE
, ui::kControlSpacing
);
69 text_field_
= gtk_entry_new();
70 gtk_entry_set_text(GTK_ENTRY(text_field_
),
71 password_generator_
->Generate().c_str());
72 gtk_entry_set_max_length(GTK_ENTRY(text_field_
), 15);
73 gtk_entry_set_icon_from_pixbuf(
74 GTK_ENTRY(text_field_
), GTK_ENTRY_ICON_SECONDARY
, GetImage(IDR_RELOAD
));
75 gtk_entry_set_icon_tooltip_text(
76 GTK_ENTRY(text_field_
), GTK_ENTRY_ICON_SECONDARY
, "Regenerate");
77 GtkWidget
* accept_button
= gtk_button_new_with_label(
78 l10n_util::GetStringUTF8(IDS_PASSWORD_GENERATION_BUTTON_TEXT
).c_str());
79 gtk_box_pack_start(GTK_BOX(password_line
), text_field_
, TRUE
, TRUE
, 0);
80 gtk_box_pack_start(GTK_BOX(password_line
), accept_button
, TRUE
, TRUE
, 0);
82 gtk_container_set_border_width(GTK_CONTAINER(content
),
83 ui::kContentAreaBorder
);
84 gtk_box_pack_start(GTK_BOX(content
), title_line
, TRUE
, TRUE
, 0);
85 gtk_box_pack_start(GTK_BOX(content
), password_line
, TRUE
, TRUE
, 0);
87 // Set initial focus to the text field containing the generated password.
88 gtk_widget_grab_focus(text_field_
);
90 GtkThemeService
* theme_service
= GtkThemeService::GetFrom(
91 Profile::FromBrowserContext(web_contents
->GetBrowserContext()));
93 bubble_
= BubbleGtk::Show(web_contents
->GetView()->GetContentNativeView(),
96 BubbleGtk::ANCHOR_TOP_LEFT
,
97 BubbleGtk::MATCH_SYSTEM_THEME
|
98 BubbleGtk::POPUP_WINDOW
|
99 BubbleGtk::GRAB_INPUT
,
103 g_signal_connect(content
, "destroy",
104 G_CALLBACK(&OnDestroyThunk
), this);
105 g_signal_connect(accept_button
, "clicked",
106 G_CALLBACK(&OnAcceptClickedThunk
), this);
107 g_signal_connect(text_field_
, "icon-press",
108 G_CALLBACK(&OnRegenerateClickedThunk
), this);
109 g_signal_connect(text_field_
, "changed",
110 G_CALLBACK(&OnPasswordEditedThunk
), this);
111 g_signal_connect(learn_more_link
, "clicked",
112 G_CALLBACK(OnLearnMoreLinkClickedThunk
), this);
115 PasswordGenerationBubbleGtk::~PasswordGenerationBubbleGtk() {}
117 void PasswordGenerationBubbleGtk::BubbleClosing(BubbleGtk
* bubble
,
118 bool closed_by_escape
) {
119 autofill::password_generation::LogUserActions(actions_
);
122 void PasswordGenerationBubbleGtk::OnDestroy(GtkWidget
* widget
) {
123 // We are self deleting, we have a destroy signal setup to catch when we are
124 // destroyed (via the BubbleGtk being destroyed), and delete ourself.
128 void PasswordGenerationBubbleGtk::OnAcceptClicked(GtkWidget
* widget
) {
129 actions_
.password_accepted
= true;
130 RenderViewHost
* render_view_host
= web_contents_
->GetRenderViewHost();
131 render_view_host
->Send(new AutofillMsg_GeneratedPasswordAccepted(
132 render_view_host
->GetRoutingID(),
133 base::UTF8ToUTF16(gtk_entry_get_text(GTK_ENTRY(text_field_
)))));
134 ChromePasswordManagerClient::GetManagerFromWebContents(web_contents_
)
135 ->SetFormHasGeneratedPassword(form_
);
139 void PasswordGenerationBubbleGtk::OnRegenerateClicked(
141 GtkEntryIconPosition icon_pos
,
143 gtk_entry_set_text(GTK_ENTRY(text_field_
),
144 password_generator_
->Generate().c_str());
145 actions_
.password_regenerated
= true;
148 void PasswordGenerationBubbleGtk::OnPasswordEdited(GtkWidget
* widget
) {
149 actions_
.password_edited
= true;
152 void PasswordGenerationBubbleGtk::OnLearnMoreLinkClicked(GtkButton
* button
) {
153 actions_
.learn_more_visited
= true;
154 Browser
* browser
= chrome::FindBrowserWithWebContents(web_contents_
);
155 content::OpenURLParams
params(
156 GURL(chrome::kAutoPasswordGenerationLearnMoreURL
), content::Referrer(),
157 NEW_FOREGROUND_TAB
, content::PAGE_TRANSITION_LINK
, false);
158 browser
->OpenURL(params
);