1/* 2 * Copyright (C) 2012 Igalia S.L. 3 * 4 * This library is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU Lesser General Public 6 * License as published by the Free Software Foundation; either 7 * version 2,1 of the License, or (at your option) any later version. 8 * 9 * This library is distributed in the hope that it will be useful, 10 * but WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * Library General Public License for more details. 13 * 14 * You should have received a copy of the GNU Library General Public License 15 * along with this library; see the file COPYING.LIB. If not, write to 16 * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, 17 * Boston, MA 02110-1301, USA. 18 */ 19 20#include "config.h" 21#include "WebViewTest.h" 22#include <wtf/gobject/GRefPtr.h> 23 24class EditorTest: public WebViewTest { 25public: 26 MAKE_GLIB_TEST_FIXTURE(EditorTest); 27 28 static const unsigned int kClipboardWaitTimeout = 50; 29 static const unsigned int kClipboardWaitMaxTries = 2; 30 31 EditorTest() 32 : m_clipboard(gtk_clipboard_get(GDK_SELECTION_CLIPBOARD)) 33 , m_canExecuteEditingCommand(false) 34 , m_triesCount(0) 35 { 36 gtk_clipboard_clear(m_clipboard); 37 } 38 39 static void canExecuteEditingCommandReadyCallback(GObject*, GAsyncResult* result, EditorTest* test) 40 { 41 GOwnPtr<GError> error; 42 test->m_canExecuteEditingCommand = webkit_web_view_can_execute_editing_command_finish(test->m_webView, result, &error.outPtr()); 43 g_assert(!error.get()); 44 g_main_loop_quit(test->m_mainLoop); 45 } 46 47 bool canExecuteEditingCommand(const char* command) 48 { 49 m_canExecuteEditingCommand = false; 50 webkit_web_view_can_execute_editing_command(m_webView, command, 0, reinterpret_cast<GAsyncReadyCallback>(canExecuteEditingCommandReadyCallback), this); 51 g_main_loop_run(m_mainLoop); 52 return m_canExecuteEditingCommand; 53 } 54 55 static gboolean waitForClipboardText(EditorTest* test) 56 { 57 test->m_triesCount++; 58 if (gtk_clipboard_wait_is_text_available(test->m_clipboard) || test->m_triesCount > kClipboardWaitMaxTries) { 59 g_main_loop_quit(test->m_mainLoop); 60 return FALSE; 61 } 62 63 return TRUE; 64 } 65 66 void copyClipboard() 67 { 68 webkit_web_view_execute_editing_command(m_webView, WEBKIT_EDITING_COMMAND_COPY); 69 // There's no way to know when the selection has been copied to 70 // the clipboard, so use a timeout source to query the clipboard. 71 m_triesCount = 0; 72 g_timeout_add(kClipboardWaitTimeout, reinterpret_cast<GSourceFunc>(waitForClipboardText), this); 73 g_main_loop_run(m_mainLoop); 74 } 75 76 GtkClipboard* m_clipboard; 77 bool m_canExecuteEditingCommand; 78 size_t m_triesCount; 79}; 80 81static void testWebViewEditorCutCopyPasteNonEditable(EditorTest* test, gconstpointer) 82{ 83 static const char* selectedSpanHTML = "<html><body contentEditable=\"false\">" 84 "<span id=\"mainspan\">All work and no play <span id=\"subspan\">make Jack a dull</span> boy.</span>" 85 "<script>document.getSelection().collapse();\n" 86 "document.getSelection().selectAllChildren(document.getElementById('subspan'));\n" 87 "</script></body></html>"; 88 89 // Nothing loaded yet. 90 g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT)); 91 g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY)); 92 g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE)); 93 94 test->loadHtml(selectedSpanHTML, 0); 95 test->waitUntilLoadFinished(); 96 97 g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY)); 98 // It's not possible to cut and paste when content is not editable 99 // even if there's a selection. 100 g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT)); 101 g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE)); 102 103 test->copyClipboard(); 104 GOwnPtr<char> clipboardText(gtk_clipboard_wait_for_text(test->m_clipboard)); 105 g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull"); 106} 107 108static void testWebViewEditorCutCopyPasteEditable(EditorTest* test, gconstpointer) 109{ 110 static const char* selectedSpanHTML = "<html><body contentEditable=\"true\">" 111 "<span id=\"mainspan\">All work and no play <span>make Jack a dull</span> boy.</span>" 112 "<script>document.getSelection().collapse();\n" 113 "document.getSelection().selectAllChildren(document.getElementById('mainspan'));\n" 114 "</script></body></html>"; 115 116 // Nothing loaded yet. 117 g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT)); 118 g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY)); 119 g_assert(!test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE)); 120 121 test->loadHtml(selectedSpanHTML, 0); 122 test->waitUntilLoadFinished(); 123 124 // There's a selection. 125 g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_CUT)); 126 g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_COPY)); 127 g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_PASTE)); 128 129 test->copyClipboard(); 130 GOwnPtr<char> clipboardText(gtk_clipboard_wait_for_text(test->m_clipboard)); 131 g_assert_cmpstr(clipboardText.get(), ==, "All work and no play make Jack a dull boy."); 132} 133 134static void testWebViewEditorSelectAllNonEditable(EditorTest* test, gconstpointer) 135{ 136 static const char* selectedSpanHTML = "<html><body contentEditable=\"false\">" 137 "<span id=\"mainspan\">All work and no play <span id=\"subspan\">make Jack a dull</span> boy.</span>" 138 "<script>document.getSelection().collapse();\n" 139 "document.getSelection().selectAllChildren(document.getElementById('subspan'));\n" 140 "</script></body></html>"; 141 142 g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL)); 143 144 test->loadHtml(selectedSpanHTML, 0); 145 test->waitUntilLoadFinished(); 146 147 g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL)); 148 149 test->copyClipboard(); 150 GOwnPtr<char> clipboardText(gtk_clipboard_wait_for_text(test->m_clipboard)); 151 152 // Initially only the subspan is selected. 153 g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull"); 154 155 webkit_web_view_execute_editing_command(test->m_webView, WEBKIT_EDITING_COMMAND_SELECT_ALL); 156 test->copyClipboard(); 157 clipboardText.set(gtk_clipboard_wait_for_text(test->m_clipboard)); 158 159 // The mainspan should be selected after calling SELECT_ALL. 160 g_assert_cmpstr(clipboardText.get(), ==, "All work and no play make Jack a dull boy."); 161} 162 163static void testWebViewEditorSelectAllEditable(EditorTest* test, gconstpointer) 164{ 165 static const char* selectedSpanHTML = "<html><body contentEditable=\"true\">" 166 "<span id=\"mainspan\">All work and no play <span id=\"subspan\">make Jack a dull</span> boy.</span>" 167 "<script>document.getSelection().collapse();\n" 168 "document.getSelection().selectAllChildren(document.getElementById('subspan'));\n" 169 "</script></body></html>"; 170 171 g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL)); 172 173 test->loadHtml(selectedSpanHTML, 0); 174 test->waitUntilLoadFinished(); 175 176 g_assert(test->canExecuteEditingCommand(WEBKIT_EDITING_COMMAND_SELECT_ALL)); 177 178 test->copyClipboard(); 179 GOwnPtr<char> clipboardText(gtk_clipboard_wait_for_text(test->m_clipboard)); 180 181 // Initially only the subspan is selected. 182 g_assert_cmpstr(clipboardText.get(), ==, "make Jack a dull"); 183 184 webkit_web_view_execute_editing_command(test->m_webView, WEBKIT_EDITING_COMMAND_SELECT_ALL); 185 test->copyClipboard(); 186 clipboardText.set(gtk_clipboard_wait_for_text(test->m_clipboard)); 187 188 // The mainspan should be selected after calling SELECT_ALL. 189 g_assert_cmpstr(clipboardText.get(), ==, "All work and no play make Jack a dull boy."); 190} 191 192void beforeAll() 193{ 194 EditorTest::add("WebKitWebView", "cut-copy-paste/non-editable", testWebViewEditorCutCopyPasteNonEditable); 195 EditorTest::add("WebKitWebView", "cut-copy-paste/editable", testWebViewEditorCutCopyPasteEditable); 196 EditorTest::add("WebKitWebView", "select-all/non-editable", testWebViewEditorSelectAllNonEditable); 197 EditorTest::add("WebKitWebView", "select-all/editable", testWebViewEditorSelectAllEditable); 198} 199 200void afterAll() 201{ 202} 203