[content shell] implement testRunner.overridePreference
[chromium-blink-merge.git] / content / shell / shell_gtk.cc
blob8365ea13797dfea6d6cfa8f0d602d1cb86df6933
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 "content/shell/shell.h"
7 #include <gdk/gdkkeysyms.h>
8 #include <gtk/gtk.h>
10 #include "base/logging.h"
11 #include "base/string_piece.h"
12 #include "base/utf_string_conversions.h"
13 #include "content/public/browser/browser_context.h"
14 #include "content/public/browser/native_web_keyboard_event.h"
15 #include "content/public/browser/web_contents.h"
16 #include "content/public/browser/web_contents_view.h"
17 #include "content/public/common/renderer_preferences.h"
18 #include "content/shell/shell_browser_context.h"
19 #include "content/shell/shell_content_browser_client.h"
21 namespace content {
23 namespace {
25 // Callback for Debug > Show web inspector... menu item.
26 gboolean ShowWebInspectorActivated(GtkWidget* widget, Shell* shell) {
27 shell->ShowDevTools();
28 return FALSE; // Don't stop this message.
31 GtkWidget* AddMenuEntry(GtkWidget* menu_widget, const char* text,
32 GCallback callback, Shell* shell) {
33 GtkWidget* entry = gtk_menu_item_new_with_label(text);
34 g_signal_connect(entry, "activate", callback, shell);
35 gtk_menu_shell_append(GTK_MENU_SHELL(menu_widget), entry);
36 return entry;
39 GtkWidget* CreateMenu(GtkWidget* menu_bar, const char* text) {
40 GtkWidget* menu_widget = gtk_menu_new();
41 GtkWidget* menu_header = gtk_menu_item_new_with_label(text);
42 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_header), menu_widget);
43 gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), menu_header);
44 return menu_widget;
47 GtkWidget* CreateMenuBar(Shell* shell) {
48 GtkWidget* menu_bar = gtk_menu_bar_new();
49 GtkWidget* debug_menu = CreateMenu(menu_bar, "Debug");
50 AddMenuEntry(debug_menu, "Show web inspector...",
51 G_CALLBACK(ShowWebInspectorActivated), shell);
52 return menu_bar;
55 } // namespace
57 void Shell::PlatformInitialize() {
60 void Shell::PlatformCleanUp() {
61 // Nothing to clean up; GTK will clean up the widgets shortly after.
64 void Shell::PlatformEnableUIControl(UIControl control, bool is_enabled) {
65 if (headless_)
66 return;
68 GtkToolItem* item = NULL;
69 switch (control) {
70 case BACK_BUTTON:
71 item = back_button_;
72 break;
73 case FORWARD_BUTTON:
74 item = forward_button_;
75 break;
76 case STOP_BUTTON:
77 item = stop_button_;
78 break;
79 default:
80 NOTREACHED() << "Unknown UI control";
81 return;
83 gtk_widget_set_sensitive(GTK_WIDGET(item), is_enabled);
86 void Shell::PlatformSetAddressBarURL(const GURL& url) {
87 if (headless_)
88 return;
90 gtk_entry_set_text(GTK_ENTRY(url_edit_view_), url.spec().c_str());
93 void Shell::PlatformSetIsLoading(bool loading) {
94 if (headless_)
95 return;
97 if (loading)
98 gtk_spinner_start(GTK_SPINNER(spinner_));
99 else
100 gtk_spinner_stop(GTK_SPINNER(spinner_));
103 void Shell::PlatformCreateWindow(int width, int height) {
104 if (headless_)
105 return;
107 window_ = GTK_WINDOW(gtk_window_new(GTK_WINDOW_TOPLEVEL));
108 gtk_window_set_title(window_, "Content Shell");
109 g_signal_connect(G_OBJECT(window_), "destroy",
110 G_CALLBACK(OnWindowDestroyedThunk), this);
112 vbox_ = gtk_vbox_new(FALSE, 0);
114 // Create the menu bar.
115 GtkWidget* menu_bar = CreateMenuBar(this);
116 gtk_box_pack_start(GTK_BOX(vbox_), menu_bar, FALSE, FALSE, 0);
118 // Create the object that mediates accelerators.
119 GtkAccelGroup* accel_group = gtk_accel_group_new();
120 gtk_window_add_accel_group(GTK_WINDOW(window_), accel_group);
122 // Set global window handling accelerators:
123 gtk_accel_group_connect(
124 accel_group, GDK_w, GDK_CONTROL_MASK,
125 GTK_ACCEL_VISIBLE,
126 g_cclosure_new(G_CALLBACK(OnCloseWindowKeyPressedThunk),
127 this, NULL));
129 gtk_accel_group_connect(
130 accel_group, GDK_n, GDK_CONTROL_MASK,
131 GTK_ACCEL_VISIBLE,
132 g_cclosure_new(G_CALLBACK(OnNewWindowKeyPressedThunk),
133 this, NULL));
135 GtkWidget* toolbar = gtk_toolbar_new();
136 // Turn off the labels on the toolbar buttons.
137 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS);
139 back_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK);
140 g_signal_connect(back_button_, "clicked",
141 G_CALLBACK(&OnBackButtonClickedThunk), this);
142 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), back_button_, -1 /* append */);
143 gtk_widget_add_accelerator(GTK_WIDGET(back_button_), "clicked", accel_group,
144 GDK_Left, GDK_MOD1_MASK, GTK_ACCEL_VISIBLE);
146 forward_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD);
147 g_signal_connect(forward_button_, "clicked",
148 G_CALLBACK(&OnForwardButtonClickedThunk), this);
149 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), forward_button_, -1 /* append */);
150 gtk_widget_add_accelerator(GTK_WIDGET(forward_button_), "clicked",
151 accel_group,
152 GDK_Right, GDK_MOD1_MASK, GTK_ACCEL_VISIBLE);
154 reload_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_REFRESH);
155 g_signal_connect(reload_button_, "clicked",
156 G_CALLBACK(&OnReloadButtonClickedThunk), this);
157 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), reload_button_, -1 /* append */);
158 gtk_widget_add_accelerator(GTK_WIDGET(reload_button_), "clicked",
159 accel_group,
160 GDK_r, GDK_CONTROL_MASK, GTK_ACCEL_VISIBLE);
162 stop_button_ = gtk_tool_button_new_from_stock(GTK_STOCK_STOP);
163 g_signal_connect(stop_button_, "clicked",
164 G_CALLBACK(&OnStopButtonClickedThunk), this);
165 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), stop_button_, -1 /* append */);
167 url_edit_view_ = gtk_entry_new();
168 g_signal_connect(G_OBJECT(url_edit_view_), "activate",
169 G_CALLBACK(&OnURLEntryActivateThunk), this);
171 gtk_accel_group_connect(
172 accel_group, GDK_l, GDK_CONTROL_MASK,
173 GTK_ACCEL_VISIBLE,
174 g_cclosure_new(G_CALLBACK(OnHighlightURLViewThunk),
175 this, NULL));
177 GtkToolItem* tool_item = gtk_tool_item_new();
178 gtk_container_add(GTK_CONTAINER(tool_item), url_edit_view_);
179 gtk_tool_item_set_expand(tool_item, TRUE);
180 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), tool_item, -1 /* append */);
182 // Center a 20x20 spinner in a 26x24 area.
183 GtkWidget* spinner_alignment = gtk_alignment_new(0.5, 0.5, 0, 0);
184 gtk_alignment_set_padding(GTK_ALIGNMENT(spinner_alignment), 2, 2, 4, 4);
185 spinner_ = gtk_spinner_new();
186 gtk_widget_set_size_request(spinner_, 20, 20);
187 gtk_container_add(GTK_CONTAINER(spinner_alignment), spinner_);
189 spinner_item_ = gtk_tool_item_new();
190 gtk_container_add(GTK_CONTAINER(spinner_item_), spinner_alignment);
191 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), spinner_item_, -1 /* append */);
193 gtk_box_pack_start(GTK_BOX(vbox_), toolbar, FALSE, FALSE, 0);
195 gtk_container_add(GTK_CONTAINER(window_), vbox_);
196 gtk_widget_show_all(GTK_WIDGET(window_));
198 SizeTo(width, height);
201 void Shell::PlatformSetContents() {
202 if (headless_)
203 return;
205 WebContentsView* content_view = web_contents_->GetView();
206 gtk_container_add(GTK_CONTAINER(vbox_), content_view->GetNativeView());
209 void Shell::SizeTo(int width, int height) {
210 content_width_ = width;
211 content_height_ = height;
212 if (web_contents_.get())
213 gtk_widget_set_size_request(web_contents_->GetNativeView(), width, height);
216 void Shell::PlatformResizeSubViews() {
217 SizeTo(content_width_, content_height_);
220 void Shell::Close() {
221 if (headless_)
222 return;
224 gtk_widget_destroy(GTK_WIDGET(window_));
227 void Shell::OnBackButtonClicked(GtkWidget* widget) {
228 GoBackOrForward(-1);
231 void Shell::OnForwardButtonClicked(GtkWidget* widget) {
232 GoBackOrForward(1);
235 void Shell::OnReloadButtonClicked(GtkWidget* widget) {
236 Reload();
239 void Shell::OnStopButtonClicked(GtkWidget* widget) {
240 Stop();
243 void Shell::OnURLEntryActivate(GtkWidget* entry) {
244 const gchar* str = gtk_entry_get_text(GTK_ENTRY(entry));
245 GURL url(str);
246 if (!url.has_scheme())
247 url = GURL(std::string("http://") + std::string(str));
248 LoadURL(GURL(url));
251 // Callback for when the main window is destroyed.
252 gboolean Shell::OnWindowDestroyed(GtkWidget* window) {
253 delete this;
254 return FALSE; // Don't stop this message.
257 gboolean Shell::OnCloseWindowKeyPressed(GtkAccelGroup* accel_group,
258 GObject* acceleratable,
259 guint keyval,
260 GdkModifierType modifier) {
261 gtk_widget_destroy(GTK_WIDGET(window_));
262 return TRUE;
265 gboolean Shell::OnNewWindowKeyPressed(GtkAccelGroup* accel_group,
266 GObject* acceleratable,
267 guint keyval,
268 GdkModifierType modifier) {
269 ShellBrowserContext* browser_context =
270 static_cast<ShellContentBrowserClient*>(
271 GetContentClient()->browser())->browser_context();
272 Shell::CreateNewWindow(browser_context,
273 GURL(),
274 NULL,
275 MSG_ROUTING_NONE,
276 NULL);
277 return TRUE;
280 gboolean Shell::OnHighlightURLView(GtkAccelGroup* accel_group,
281 GObject* acceleratable,
282 guint keyval,
283 GdkModifierType modifier) {
284 gtk_widget_grab_focus(GTK_WIDGET(url_edit_view_));
285 return TRUE;
288 void Shell::PlatformSetTitle(const string16& title) {
289 if (headless_)
290 return;
292 std::string title_utf8 = UTF16ToUTF8(title);
293 gtk_window_set_title(GTK_WINDOW(window_), title_utf8.c_str());
296 } // namespace content