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/script_bubble_gtk.h"
10 #include "base/i18n/rtl.h"
11 #include "base/strings/string_number_conversions.h"
12 #include "chrome/browser/extensions/extension_service.h"
13 #include "chrome/browser/extensions/extension_system.h"
14 #include "chrome/browser/extensions/image_loader.h"
15 #include "chrome/browser/extensions/script_bubble_controller.h"
16 #include "chrome/browser/extensions/tab_helper.h"
17 #include "chrome/browser/profiles/profile.h"
18 #include "chrome/browser/ui/gtk/gtk_theme_service.h"
19 #include "chrome/common/extensions/manifest_handlers/icons_handler.h"
20 #include "chrome/common/url_constants.h"
21 #include "content/public/browser/web_contents.h"
22 #include "extensions/common/extension.h"
23 #include "extensions/common/extension_set.h"
24 #include "grit/generated_resources.h"
25 #include "grit/theme_resources.h"
26 #include "grit/ui_resources.h"
27 #include "ui/base/gtk/gtk_hig_constants.h"
28 #include "ui/base/l10n/l10n_util.h"
30 using content::WebContents
;
31 using content::OpenURLParams
;
32 using content::Referrer
;
33 using extensions::Extension
;
34 using extensions::ExtensionSystem
;
35 using extensions::TabHelper
;
36 using extensions::ImageLoader
;
40 // The currently open app-modal bubble singleton, or NULL if none is open.
41 ScriptBubbleGtk
* g_bubble
= NULL
;
47 void ScriptBubbleGtk::Show(GtkWidget
* anchor
, WebContents
* web_contents
) {
49 g_bubble
= new ScriptBubbleGtk(anchor
, web_contents
);
53 void ScriptBubbleGtk::OnItemLinkClickedThunk(GtkWidget
* sender
,
55 g_bubble
->OnItemLinkClicked(sender
);
58 ScriptBubbleGtk::ScriptBubbleGtk(GtkWidget
* anchor
, WebContents
* web_contents
)
60 web_contents_(web_contents
),
61 profile_(Profile::FromBrowserContext(web_contents_
->GetBrowserContext())),
62 weak_ptr_factory_(this) {
66 ScriptBubbleGtk::~ScriptBubbleGtk() {
69 void ScriptBubbleGtk::Close() {
74 void ScriptBubbleGtk::BubbleClosing(BubbleGtk
* bubble
,
75 bool closed_by_escape
) {
80 void ScriptBubbleGtk::BuildBubble() {
81 GtkThemeService
* theme_provider
= GtkThemeService::GetFrom(profile_
);
83 GtkWidget
* bubble_content
= gtk_vbox_new(FALSE
, ui::kControlSpacing
);
84 gtk_container_set_border_width(GTK_CONTAINER(bubble_content
),
85 ui::kContentAreaBorder
);
87 extensions::TabHelper
* tab_helper
=
88 extensions::TabHelper::FromWebContents(web_contents_
);
89 const std::set
<std::string
>& extensions_running_scripts
=
90 tab_helper
->script_bubble_controller()->extensions_running_scripts();
91 const extensions::ExtensionSet
* loaded_extensions
=
92 ExtensionSystem::Get(profile_
)->extension_service()->extensions();
94 std::string heading_string
=
95 l10n_util::GetStringUTF8(IDS_SCRIPT_BUBBLE_HEADLINE
);
96 GtkWidget
* heading
= gtk_label_new(heading_string
.c_str());
97 gtk_misc_set_alignment(GTK_MISC(heading
), 0, 0);
98 gtk_box_pack_start(GTK_BOX(bubble_content
), heading
, FALSE
, FALSE
, 0);
100 for (std::set
<std::string
>::const_iterator iter
=
101 extensions_running_scripts
.begin();
102 iter
!= extensions_running_scripts
.end(); ++iter
) {
103 const Extension
* extension
= loaded_extensions
->GetByID(*iter
);
107 GtkWidget
* item
= gtk_hbox_new(FALSE
, ui::kControlSpacing
);
108 gtk_box_pack_start(GTK_BOX(bubble_content
), item
, FALSE
, FALSE
, 0);
110 GtkWidget
* image
= gtk_image_new();
111 gtk_widget_set_usize(image
, 16, 16);
112 gtk_box_pack_start(GTK_BOX(item
), image
, FALSE
, FALSE
, 0);
114 // Load the image asynchronously.
115 icon_controls_
[extension
->id()] = GTK_IMAGE(image
);
116 ImageLoader::Get(profile_
)->LoadImageAsync(
118 extensions::IconsInfo::GetIconResource(
120 extension_misc::EXTENSION_ICON_BITTY
,
121 ExtensionIconSet::MATCH_EXACTLY
),
122 gfx::Size(extension_misc::EXTENSION_ICON_BITTY
,
123 extension_misc::EXTENSION_ICON_BITTY
),
124 base::Bind(&ScriptBubbleGtk::OnIconLoaded
,
125 weak_ptr_factory_
.GetWeakPtr(),
128 GtkWidget
* link
= theme_provider
->BuildChromeLinkButton(
129 extension
->name().c_str());
130 gtk_box_pack_start(GTK_BOX(item
), link
, FALSE
, FALSE
, 0);
131 link_controls_
[GTK_WIDGET(link
)] = extension
->id();
132 g_signal_connect(link
, "button-press-event",
133 G_CALLBACK(&OnItemLinkClickedThunk
), this);
136 bubble_
= BubbleGtk::Show(anchor_
,
139 BubbleGtk::ANCHOR_TOP_RIGHT
,
140 BubbleGtk::MATCH_SYSTEM_THEME
|
141 BubbleGtk::POPUP_WINDOW
|
142 BubbleGtk::GRAB_INPUT
,
147 void ScriptBubbleGtk::OnIconLoaded(const std::string
& extension_id
,
148 const gfx::Image
& icon
) {
149 gtk_image_set_from_pixbuf(
150 icon_controls_
[extension_id
],
151 (!icon
.IsEmpty() ? icon
:
152 GtkThemeService::GetFrom(profile_
)->GetImageNamed(
153 IDR_EXTENSIONS_FAVICON
)).ToGdkPixbuf());
156 void ScriptBubbleGtk::OnItemLinkClicked(GtkWidget
* button
) {
157 std::string
link(chrome::kChromeUIExtensionsURL
);
158 link
+= "?id=" + link_controls_
[button
];
159 web_contents_
->OpenURL(OpenURLParams(GURL(link
),
162 content::PAGE_TRANSITION_LINK
,