| OLD | NEW |
| 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2006-2008 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #include "webkit/tools/test_shell/test_shell.h" | 5 #include "webkit/tools/test_shell/test_shell.h" |
| 6 | 6 |
| 7 #include <errno.h> | 7 #include <errno.h> |
| 8 #include <fcntl.h> | 8 #include <fcntl.h> |
| 9 #include <fontconfig/fontconfig.h> | 9 #include <fontconfig/fontconfig.h> |
| 10 #include <gtk/gtk.h> | 10 #include <gtk/gtk.h> |
| (...skipping 135 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 146 TestShell::windowList()->push_back(shell->m_mainWnd); | 146 TestShell::windowList()->push_back(shell->m_mainWnd); |
| 147 return true; | 147 return true; |
| 148 } | 148 } |
| 149 | 149 |
| 150 void TestShell::PlatformCleanUp() { | 150 void TestShell::PlatformCleanUp() { |
| 151 // The GTK widgets will be destroyed, which will free the associated | 151 // The GTK widgets will be destroyed, which will free the associated |
| 152 // objects. So we don't need the scoped_ptr to free the webViewHost. | 152 // objects. So we don't need the scoped_ptr to free the webViewHost. |
| 153 m_webViewHost.release(); | 153 m_webViewHost.release(); |
| 154 } | 154 } |
| 155 | 155 |
| 156 namespace { |
| 157 |
| 156 // GTK callbacks ------------------------------------------------------ | 158 // GTK callbacks ------------------------------------------------------ |
| 157 namespace { | |
| 158 | 159 |
| 159 // Callback for when the main window is destroyed. | 160 // Callback for when the main window is destroyed. |
| 160 gboolean MainWindowDestroyed(GtkWindow* window, TestShell* shell) { | 161 gboolean MainWindowDestroyed(GtkWindow* window, TestShell* shell) { |
| 161 | 162 |
| 162 TestShell::RemoveWindowFromList(GTK_WIDGET(window)); | 163 TestShell::RemoveWindowFromList(GTK_WIDGET(window)); |
| 163 | 164 |
| 164 if (TestShell::windowList()->empty() || shell->is_modal()) { | 165 if (TestShell::windowList()->empty() || shell->is_modal()) { |
| 165 MessageLoop::current()->PostTask(FROM_HERE, | 166 MessageLoop::current()->PostTask(FROM_HERE, |
| 166 new MessageLoop::QuitTask()); | 167 new MessageLoop::QuitTask()); |
| 167 } | 168 } |
| (...skipping 28 matching lines...) Expand all Loading... |
| 196 void ReloadButtonClicked(GtkButton* button, TestShell* shell) { | 197 void ReloadButtonClicked(GtkButton* button, TestShell* shell) { |
| 197 shell->Reload(); | 198 shell->Reload(); |
| 198 } | 199 } |
| 199 | 200 |
| 200 // Callback for when you press enter in the URL box. | 201 // Callback for when you press enter in the URL box. |
| 201 void URLEntryActivate(GtkEntry* entry, TestShell* shell) { | 202 void URLEntryActivate(GtkEntry* entry, TestShell* shell) { |
| 202 const gchar* url = gtk_entry_get_text(entry); | 203 const gchar* url = gtk_entry_get_text(entry); |
| 203 shell->LoadURL(UTF8ToWide(url).c_str()); | 204 shell->LoadURL(UTF8ToWide(url).c_str()); |
| 204 } | 205 } |
| 205 | 206 |
| 207 // Callback for Debug > Dump body text... menu item. |
| 208 gboolean DumpBodyTextActivated(GtkWidget* widget, TestShell* shell) { |
| 209 shell->DumpDocumentText(); |
| 210 return FALSE; // Don't stop this message. |
| 211 } |
| 212 |
| 213 // Callback for Debug > Dump render tree... menu item. |
| 214 gboolean DumpRenderTreeActivated(GtkWidget* widget, TestShell* shell) { |
| 215 shell->DumpRenderTree(); |
| 216 return FALSE; // Don't stop this message. |
| 217 } |
| 218 |
| 219 // Callback for Debug > Show web inspector... menu item. |
| 220 gboolean ShowWebInspectorActivated(GtkWidget* widget, TestShell* shell) { |
| 221 shell->webView()->InspectElement(0, 0); |
| 222 return FALSE; // Don't stop this message. |
| 223 } |
| 224 |
| 225 // GTK utility functions ---------------------------------------------- |
| 226 |
| 227 GtkWidget* AddMenuEntry(GtkWidget* menu_widget, const char* text, |
| 228 GCallback callback, TestShell* shell) { |
| 229 GtkWidget* entry = gtk_menu_item_new_with_label(text); |
| 230 g_signal_connect(G_OBJECT(entry), "activate", callback, shell); |
| 231 gtk_menu_shell_append(GTK_MENU_SHELL(menu_widget), entry); |
| 232 return entry; |
| 233 } |
| 234 |
| 235 GtkWidget* CreateMenu(GtkWidget* menu_bar, const char* text) { |
| 236 GtkWidget* menu_widget = gtk_menu_new(); |
| 237 GtkWidget* menu_header = gtk_menu_item_new_with_label(text); |
| 238 gtk_menu_item_set_submenu(GTK_MENU_ITEM(menu_header), menu_widget); |
| 239 gtk_menu_shell_append(GTK_MENU_SHELL(menu_bar), menu_header); |
| 240 return menu_widget; |
| 241 } |
| 242 |
| 243 GtkWidget* CreateMenuBar(TestShell* shell) { |
| 244 GtkWidget* menu_bar = gtk_menu_bar_new(); |
| 245 GtkWidget* debug_menu = CreateMenu(menu_bar, "Debug"); |
| 246 AddMenuEntry(debug_menu, "Dump body text...", |
| 247 G_CALLBACK(DumpBodyTextActivated), shell); |
| 248 AddMenuEntry(debug_menu, "Dump render tree...", |
| 249 G_CALLBACK(DumpRenderTreeActivated), shell); |
| 250 AddMenuEntry(debug_menu, "Show web inspector...", |
| 251 G_CALLBACK(ShowWebInspectorActivated), shell); |
| 252 return menu_bar; |
| 253 } |
| 254 |
| 206 } | 255 } |
| 207 | 256 |
| 208 bool TestShell::Initialize(const std::wstring& startingURL) { | 257 bool TestShell::Initialize(const std::wstring& startingURL) { |
| 209 m_mainWnd = gtk_window_new(GTK_WINDOW_TOPLEVEL); | 258 m_mainWnd = gtk_window_new(GTK_WINDOW_TOPLEVEL); |
| 210 gtk_window_set_title(GTK_WINDOW(m_mainWnd), "Test Shell"); | 259 gtk_window_set_title(GTK_WINDOW(m_mainWnd), "Test Shell"); |
| 211 gtk_window_set_default_size(GTK_WINDOW(m_mainWnd), 640, 480); | 260 gtk_window_set_default_size(GTK_WINDOW(m_mainWnd), 640, 480); |
| 212 g_signal_connect(G_OBJECT(m_mainWnd), "destroy", | 261 g_signal_connect(G_OBJECT(m_mainWnd), "destroy", |
| 213 G_CALLBACK(MainWindowDestroyed), this); | 262 G_CALLBACK(MainWindowDestroyed), this); |
| 214 g_signal_connect(G_OBJECT(m_mainWnd), "focus-out-event", | 263 g_signal_connect(G_OBJECT(m_mainWnd), "focus-out-event", |
| 215 G_CALLBACK(MainWindowLostFocus), this); | 264 G_CALLBACK(MainWindowLostFocus), this); |
| 216 g_object_set_data(G_OBJECT(m_mainWnd), "test-shell", this); | 265 g_object_set_data(G_OBJECT(m_mainWnd), "test-shell", this); |
| 217 | 266 |
| 218 GtkWidget* vbox = gtk_vbox_new(FALSE, 0); | 267 GtkWidget* vbox = gtk_vbox_new(FALSE, 0); |
| 219 | 268 |
| 269 gtk_box_pack_start(GTK_BOX(vbox), CreateMenuBar(this), FALSE, FALSE, 0); |
| 270 |
| 220 GtkWidget* toolbar = gtk_toolbar_new(); | 271 GtkWidget* toolbar = gtk_toolbar_new(); |
| 221 // Turn off the labels on the toolbar buttons. | 272 // Turn off the labels on the toolbar buttons. |
| 222 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS); | 273 gtk_toolbar_set_style(GTK_TOOLBAR(toolbar), GTK_TOOLBAR_ICONS); |
| 223 | 274 |
| 224 GtkToolItem* back = gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK); | 275 GtkToolItem* back = gtk_tool_button_new_from_stock(GTK_STOCK_GO_BACK); |
| 225 g_signal_connect(G_OBJECT(back), "clicked", | 276 g_signal_connect(G_OBJECT(back), "clicked", |
| 226 G_CALLBACK(BackButtonClicked), this); | 277 G_CALLBACK(BackButtonClicked), this); |
| 227 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), back, -1 /* append */); | 278 gtk_toolbar_insert(GTK_TOOLBAR(toolbar), back, -1 /* append */); |
| 228 | 279 |
| 229 GtkToolItem* forward = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD); | 280 GtkToolItem* forward = gtk_tool_button_new_from_stock(GTK_STOCK_GO_FORWARD); |
| (...skipping 281 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 511 // as well as empty strings. | 562 // as well as empty strings. |
| 512 if (file_util::AbsolutePath(&path)) | 563 if (file_util::AbsolutePath(&path)) |
| 513 gurl = net::FilePathToFileURL(path); | 564 gurl = net::FilePathToFileURL(path); |
| 514 else | 565 else |
| 515 gurl = GURL(WideToUTF8(url)); | 566 gurl = GURL(WideToUTF8(url)); |
| 516 | 567 |
| 517 navigation_controller_->LoadEntry(new TestNavigationEntry( | 568 navigation_controller_->LoadEntry(new TestNavigationEntry( |
| 518 -1, gurl, std::wstring(), frame_string)); | 569 -1, gurl, std::wstring(), frame_string)); |
| 519 } | 570 } |
| 520 | 571 |
| 521 static void WriteTextToFile(const std::wstring& data, | 572 // TODO(agl): PromptForSaveFile should use FilePath |
| 522 const FilePath& filepath) | 573 bool TestShell::PromptForSaveFile(const wchar_t* prompt_title, |
| 523 { | 574 std::wstring* result) { |
| 524 // This function does the same thing as the Windows version except that it | 575 GtkWidget* dialog; |
| 525 // takes a FilePath. We should be using WriteFile in base/file_util.h, but | 576 dialog = gtk_file_chooser_dialog_new(WideToUTF8(prompt_title).c_str(), |
| 526 // the patch to add the FilePath version of that file hasn't landed yet, so | 577 GTK_WINDOW(m_mainWnd), |
| 527 // this is another TODO(agl) for the merging. | 578 GTK_FILE_CHOOSER_ACTION_SAVE, |
| 528 const int fd = open(filepath.value().c_str(), O_TRUNC | O_WRONLY | O_CREAT, 06
00); | 579 GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, |
| 529 if (fd < 0) | 580 GTK_STOCK_SAVE, GTK_RESPONSE_ACCEPT, |
| 530 return; | 581 NULL); // Terminate (button, id) pairs. |
| 531 const std::string data_utf8 = WideToUTF8(data); | 582 gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(dialog), |
| 532 ssize_t n; | 583 TRUE); |
| 533 do { | 584 int dialog_result = gtk_dialog_run(GTK_DIALOG(dialog)); |
| 534 n = write(fd, data_utf8.data(), data.size()); | 585 if (dialog_result != GTK_RESPONSE_ACCEPT) { |
| 535 } while (n == -1 && errno == EINTR); | 586 gtk_widget_destroy(dialog); |
| 536 close(fd); | 587 return false; |
| 537 } | 588 } |
| 538 | 589 char* path = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog)); |
| 539 | 590 gtk_widget_destroy(dialog); |
| 540 // TODO(agl): | 591 *result = UTF8ToWide(path); |
| 541 // This version of PromptForSaveFile uses FilePath, which is what the real | 592 g_free(path); |
| 542 // version should be using. However, I don't want to step on tony's toes (as he | |
| 543 // is also editing this file), so this is a hack until we merge the files again. | |
| 544 // (There is also a PromptForSaveFile member in TestShell which returns a wstrin
g) | |
| 545 static bool PromptForSaveFile(const char* prompt_title, | |
| 546 FilePath* result) | |
| 547 { | |
| 548 char filenamebuffer[512]; | |
| 549 printf("Enter filename for \"%s\"\n", prompt_title); | |
| 550 if (!fgets(filenamebuffer, sizeof(filenamebuffer), stdin)) | |
| 551 return false; // EOF on stdin | |
| 552 *result = FilePath(filenamebuffer); | |
| 553 return true; | 593 return true; |
| 554 } | 594 } |
| 555 | 595 |
| 556 void TestShell::DumpDocumentText() | |
| 557 { | |
| 558 FilePath file_path; | |
| 559 if (!::PromptForSaveFile("Dump document text", &file_path)) | |
| 560 return; | |
| 561 | |
| 562 WriteTextToFile(webkit_glue::DumpDocumentText(webView()->GetMainFrame()), | |
| 563 file_path); | |
| 564 } | |
| 565 | |
| 566 void TestShell::DumpRenderTree() | |
| 567 { | |
| 568 FilePath file_path; | |
| 569 if (!::PromptForSaveFile("Dump render tree", &file_path)) | |
| 570 return; | |
| 571 | |
| 572 WriteTextToFile(webkit_glue::DumpRenderer(webView()->GetMainFrame()), | |
| 573 file_path); | |
| 574 } | |
| 575 | |
| 576 // static | 596 // static |
| 577 std::string TestShell::RewriteLocalUrl(const std::string& url) { | 597 std::string TestShell::RewriteLocalUrl(const std::string& url) { |
| 578 // Convert file:///tmp/LayoutTests urls to the actual location on disk. | 598 // Convert file:///tmp/LayoutTests urls to the actual location on disk. |
| 579 const char kPrefix[] = "file:///tmp/LayoutTests/"; | 599 const char kPrefix[] = "file:///tmp/LayoutTests/"; |
| 580 const int kPrefixLen = arraysize(kPrefix) - 1; | 600 const int kPrefixLen = arraysize(kPrefix) - 1; |
| 581 | 601 |
| 582 std::string new_url(url); | 602 std::string new_url(url); |
| 583 if (url.compare(0, kPrefixLen, kPrefix, kPrefixLen) == 0) { | 603 if (url.compare(0, kPrefixLen, kPrefix, kPrefixLen) == 0) { |
| 584 FilePath replace_path; | 604 FilePath replace_path; |
| 585 PathService::Get(base::DIR_EXE, &replace_path); | 605 PathService::Get(base::DIR_EXE, &replace_path); |
| (...skipping 155 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 741 } | 761 } |
| 742 | 762 |
| 743 bool GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) { | 763 bool GetPlugins(bool refresh, std::vector<WebPluginInfo>* plugins) { |
| 744 // TODO(port): Implement plugins someday. Don't let the error message | 764 // TODO(port): Implement plugins someday. Don't let the error message |
| 745 // of NOTIMPLEMENTED into our layout test diffs. | 765 // of NOTIMPLEMENTED into our layout test diffs. |
| 746 // NOTIMPLEMENTED(); | 766 // NOTIMPLEMENTED(); |
| 747 return false; | 767 return false; |
| 748 } | 768 } |
| 749 | 769 |
| 750 } // namespace webkit_glue | 770 } // namespace webkit_glue |
| OLD | NEW |