Changeset 193826 in webkit
- Timestamp:
- Dec 9, 2015, 5:32:54 AM (11 years ago)
- Location:
- trunk
- Files:
-
- 11 edited
-
Source/WebKit2/ChangeLog (modified) (1 diff)
-
Source/WebKit2/UIProcess/API/gtk/WebKitScriptDialog.cpp (modified) (1 diff)
-
Source/WebKit2/UIProcess/API/gtk/WebKitScriptDialog.h (modified) (2 diffs)
-
Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp (modified) (1 diff)
-
Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp (modified) (8 diffs)
-
Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h (modified) (1 diff)
-
Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h (modified) (1 diff)
-
Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt (modified) (1 diff)
-
Tools/ChangeLog (modified) (1 diff)
-
Tools/MiniBrowser/gtk/BrowserWindow.c (modified) (3 diffs)
-
Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp (modified) (9 diffs)
Legend:
- Unmodified
- Added
- Removed
-
trunk/Source/WebKit2/ChangeLog
r193822 r193826 1 2015-12-09 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 [GTK] Add API to handle beforeunload events 4 https://bugs.webkit.org/show_bug.cgi?id=139090 5 6 Reviewed by Gustavo Noronha Silva. 7 8 beforeunload is fired when a page is about to be closed, to ask 9 the user for confirmation. This happens when reloading a page, 10 when navigating to another page or when the page is closed by a 11 user action (a tab or window closed). In the first two cases, the 12 event is automatically fired by WebCore, but in the case of a user 13 action we need additional API to ensure the event is fired before 14 the page is closed. A new script dialog type has been added to 15 handle beforeunload events and webkit_web_view_try_close() to 16 allow applications to try to close the page. 17 18 * UIProcess/API/gtk/WebKitScriptDialog.cpp: 19 (webkit_script_dialog_confirm_set_confirmed): BeforeUnloadConfirm 20 dialogs can also be confirmed. 21 * UIProcess/API/gtk/WebKitScriptDialog.h: Add 22 WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM script dialog type. 23 * UIProcess/API/gtk/WebKitUIClient.cpp: Implement 24 canRunBeforeUnloadConfirmPanel() and runBeforeUnloadConfirmPanel(). 25 * UIProcess/API/gtk/WebKitWebView.cpp: 26 (webkitWebViewCreateJavaScriptDialog): Add secondaryText optional 27 parameter for BeforeUnloadConfirm dialogs. Do not set the default 28 response if the dialog was created without buttons. 29 (webkitWebViewScriptDialog): Handle 30 WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM script dialog type to 31 create a message dialog for beforeunlos events. 32 (webkit_web_view_class_init): Update documentation of 33 WebKitWebView::close and WebKitWebView::script-dialog. 34 (webkitWebViewRunJavaScriptBeforeUnloadConfirm): Emit WebKitWebView::script-dialog. 35 (webkit_web_view_try_close): Try to close the page. 36 * UIProcess/API/gtk/WebKitWebView.h: 37 * UIProcess/API/gtk/WebKitWebViewPrivate.h: 38 * UIProcess/API/gtk/docs/webkit2gtk-sections.txt: Add new symbol. 39 1 40 2015-12-09 Gyuyoung Kim <gyuyoung.kim@webkit.org> 2 41 -
trunk/Source/WebKit2/UIProcess/API/gtk/WebKitScriptDialog.cpp
r187485 r193826 73 73 * @confirmed: whether user confirmed the dialog 74 74 * 75 * This method is used for %WEBKIT_SCRIPT_DIALOG_CONFIRM dialogs when75 * This method is used for %WEBKIT_SCRIPT_DIALOG_CONFIRM and %WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM dialogs when 76 76 * #WebKitWebView::script-dialog signal is emitted to set whether the user 77 77 * confirmed the dialog or not. The default implementation of #WebKitWebView::script-dialog 78 * signal sets %TRUE when the OK button isclicked and %FALSE otherwise.78 * signal sets %TRUE when the OK or Stay buttons are clicked and %FALSE otherwise. 79 79 * It's an error to use this method with a #WebKitScriptDialog that is not of type 80 * %WEBKIT_SCRIPT_DIALOG_CONFIRM .80 * %WEBKIT_SCRIPT_DIALOG_CONFIRM or %WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM 81 81 */ 82 82 void webkit_script_dialog_confirm_set_confirmed(WebKitScriptDialog* dialog, gboolean confirmed) 83 83 { 84 84 g_return_if_fail(dialog); 85 g_return_if_fail(dialog->type == WEBKIT_SCRIPT_DIALOG_CONFIRM );85 g_return_if_fail(dialog->type == WEBKIT_SCRIPT_DIALOG_CONFIRM || dialog->type == WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM); 86 86 87 87 dialog->confirmed = confirmed; -
trunk/Source/WebKit2/UIProcess/API/gtk/WebKitScriptDialog.h
r109880 r193826 42 42 * @WEBKIT_SCRIPT_DIALOG_PROMPT: Prompt script dialog, used to ask 43 43 * information to the user. 44 * @WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM: Before unload confirm dialog, 45 * used to ask confirmation to leave the current page to the user. Since 2.12 44 46 * 45 47 * Enum values used for determining the type of #WebKitScriptDialog … … 48 50 WEBKIT_SCRIPT_DIALOG_ALERT, 49 51 WEBKIT_SCRIPT_DIALOG_CONFIRM, 50 WEBKIT_SCRIPT_DIALOG_PROMPT 52 WEBKIT_SCRIPT_DIALOG_PROMPT, 53 WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM 51 54 } WebKitScriptDialogType; 52 55 -
trunk/Source/WebKit2/UIProcess/API/gtk/WebKitUIClient.cpp
r190823 r193826 85 85 } 86 86 87 virtual bool canRunBeforeUnloadConfirmPanel() const override { return true; } 88 89 virtual bool runBeforeUnloadConfirmPanel(WebPageProxy*, const String& message, WebFrameProxy*) override 90 { 91 return webkitWebViewRunJavaScriptBeforeUnloadConfirm(m_webView, message.utf8()); 92 } 93 87 94 virtual void mouseDidMoveOverElement(WebPageProxy*, const WebHitTestResultData& data, WebEvent::Modifiers modifiers, API::Object*) override 88 95 { -
trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.cpp
r193721 r193826 326 326 } 327 327 328 static GtkWidget* webkitWebViewCreateJavaScriptDialog(WebKitWebView* webView, GtkMessageType type, GtkButtonsType buttons, int defaultResponse, const char* message)328 static GtkWidget* webkitWebViewCreateJavaScriptDialog(WebKitWebView* webView, GtkMessageType type, GtkButtonsType buttons, int defaultResponse, const char* primaryText, const char* secondaryText = nullptr) 329 329 { 330 330 GtkWidget* parent = gtk_widget_get_toplevel(GTK_WIDGET(webView)); 331 GtkWidget* dialog = gtk_message_dialog_new(widgetIsOnscreenToplevelWindow(parent) ? GTK_WINDOW(parent) : 0, 332 GTK_DIALOG_DESTROY_WITH_PARENT, type, buttons, "%s", message); 331 GtkWidget* dialog = gtk_message_dialog_new(widgetIsOnscreenToplevelWindow(parent) ? GTK_WINDOW(parent) : nullptr, 332 GTK_DIALOG_DESTROY_WITH_PARENT, type, buttons, "%s", primaryText); 333 if (secondaryText) 334 gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog), "%s", secondaryText); 333 335 GUniquePtr<char> title(g_strdup_printf("JavaScript - %s", webkit_web_view_get_uri(webView))); 334 336 gtk_window_set_title(GTK_WINDOW(dialog), title.get()); 335 gtk_dialog_set_default_response(GTK_DIALOG(dialog), defaultResponse); 337 if (buttons != GTK_BUTTONS_NONE) 338 gtk_dialog_set_default_response(GTK_DIALOG(dialog), defaultResponse); 336 339 337 340 return dialog; … … 351 354 scriptDialog->confirmed = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK; 352 355 break; 353 case WEBKIT_SCRIPT_DIALOG_PROMPT: 356 case WEBKIT_SCRIPT_DIALOG_PROMPT: { 354 357 dialog = webkitWebViewCreateJavaScriptDialog(webView, GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK_CANCEL, GTK_RESPONSE_OK, scriptDialog->message.data()); 355 358 GtkWidget* entry = gtk_entry_new(); … … 360 363 if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK) 361 364 scriptDialog->text = gtk_entry_get_text(GTK_ENTRY(entry)); 365 break; 366 } 367 case WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM: 368 dialog = webkitWebViewCreateJavaScriptDialog(webView, GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, GTK_RESPONSE_OK, 369 _("Are you sure you want to leave this page?"), scriptDialog->message.data()); 370 gtk_dialog_add_buttons(GTK_DIALOG(dialog), _("Stay on Page"), GTK_RESPONSE_CLOSE, _("Leave Page"), GTK_RESPONSE_OK, nullptr); 371 gtk_dialog_set_default_response(GTK_DIALOG(dialog), GTK_RESPONSE_OK); 372 scriptDialog->confirmed = gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_OK; 362 373 break; 363 374 } … … 1202 1213 /** 1203 1214 * WebKitWebView::close: 1204 * @web View: the #WebKitWebView on which the signal is emitted1215 * @web_view: the #WebKitWebView on which the signal is emitted 1205 1216 * 1206 1217 * Emitted when closing a #WebKitWebView is requested. This occurs when a 1207 * call is made from JavaScript's <function>window.close</function> function. 1218 * call is made from JavaScript's <function>window.close</function> function or 1219 * after trying to close the @web_view with webkit_web_view_try_close(). 1208 1220 * It is the owner's responsibility to handle this signal to hide or 1209 1221 * destroy the #WebKitWebView, if necessary. … … 1224 1236 * 1225 1237 * Emitted when JavaScript code calls <function>window.alert</function>, 1226 * <function>window.confirm</function> or <function>window.prompt</function>. 1238 * <function>window.confirm</function> or <function>window.prompt</function>, 1239 * or when <function>onbeforeunload</function> event is fired. 1227 1240 * The @dialog parameter should be used to build the dialog. 1228 1241 * If the signal is not handled a different dialog will be built and shown depending … … 1238 1251 * %WEBKIT_SCRIPT_DIALOG_PROMPT: message dialog with OK and Cancel buttons and 1239 1252 * a text entry with the default text. 1253 * </para></listitem> 1254 * <listitem><para> 1255 * %WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM: message dialog with Stay and Leave buttons. 1240 1256 * </para></listitem> 1241 1257 * </itemizedlist> … … 1930 1946 } 1931 1947 1948 bool webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView* webView, const CString& message) 1949 { 1950 WebKitScriptDialog dialog(WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM, message); 1951 gboolean returnValue; 1952 g_signal_emit(webView, signals[SCRIPT_DIALOG], 0, &dialog, &returnValue); 1953 return dialog.confirmed; 1954 } 1955 1932 1956 void webkitWebViewMakePolicyDecision(WebKitWebView* webView, WebKitPolicyDecisionType type, WebKitPolicyDecision* decision) 1933 1957 { … … 2249 2273 2250 2274 return webView->priv->userContentManager.get(); 2275 } 2276 2277 /** 2278 * webkit_web_view_try_close: 2279 * @web_view: a #WebKitWebView 2280 * 2281 * Tries to close the @web_view. This will fire the onbeforeunload event 2282 * to ask the user for confirmation to close the page. If there isn't an 2283 * onbeforeunload event handler or the user confirms to close the page, 2284 * the #WebKitWebView::close signal is emitted, otherwise nothing happens. 2285 * 2286 * Since: 2.12 2287 */ 2288 void webkit_web_view_try_close(WebKitWebView *webView) 2289 { 2290 g_return_if_fail(WEBKIT_IS_WEB_VIEW(webView)); 2291 if (getPage(webView)->tryClose()) 2292 webkitWebViewClosePage(webView); 2251 2293 } 2252 2294 -
trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebView.h
r187220 r193826 278 278 279 279 WEBKIT_API void 280 webkit_web_view_try_close (WebKitWebView *web_view); 281 282 WEBKIT_API void 280 283 webkit_web_view_load_uri (WebKitWebView *web_view, 281 284 const gchar *uri); -
trunk/Source/WebKit2/UIProcess/API/gtk/WebKitWebViewPrivate.h
r190823 r193826 45 45 bool webkitWebViewRunJavaScriptConfirm(WebKitWebView*, const CString& message); 46 46 CString webkitWebViewRunJavaScriptPrompt(WebKitWebView*, const CString& message, const CString& defaultText); 47 bool webkitWebViewRunJavaScriptBeforeUnloadConfirm(WebKitWebView*, const CString& message); 47 48 void webkitWebViewMakePermissionRequest(WebKitWebView*, WebKitPermissionRequest*); 48 49 void webkitWebViewMakePolicyDecision(WebKitWebView*, WebKitPolicyDecisionType, WebKitPolicyDecision*); -
trunk/Source/WebKit2/UIProcess/API/gtk/docs/webkit2gtk-4.0-sections.txt
r193721 r193826 158 158 webkit_web_view_get_context 159 159 webkit_web_view_get_user_content_manager 160 webkit_web_view_try_close 160 161 webkit_web_view_load_uri 161 162 webkit_web_view_load_html -
trunk/Tools/ChangeLog
r193815 r193826 1 2015-12-09 Carlos Garcia Campos <cgarcia@igalia.com> 2 3 [GTK] Add API to handle beforeunload events 4 https://bugs.webkit.org/show_bug.cgi?id=139090 5 6 Reviewed by Gustavo Noronha Silva. 7 8 * MiniBrowser/gtk/BrowserWindow.c: 9 (browserWindowConstructed): 10 (browserWindowDeleteEvent): 11 (browser_window_class_init): 12 Handle delete-event to prevent the window from being closed when 13 the page has beforeunload handlers. Use 14 webkit_web_view_try_close() when the window is requested to be 15 closed. 16 * TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp: 17 (testWebViewJavaScriptDialogs): 18 Add a test case for the WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM 19 script dialog type. 20 1 21 2015-12-09 Mario Sanchez Prada <mario@endlessm.com> 2 22 -
trunk/Tools/MiniBrowser/gtk/BrowserWindow.c
r188121 r193826 1097 1097 g_signal_connect(window->webView, "notify::title", G_CALLBACK(webViewTitleChanged), window); 1098 1098 g_signal_connect(window->webView, "create", G_CALLBACK(webViewCreate), window); 1099 g_signal_connect(window->webView, "close", G_CALLBACK(webViewClose), window); 1099 1100 g_signal_connect(window->webView, "load-failed", G_CALLBACK(webViewLoadFailed), window); 1100 1101 g_signal_connect(window->webView, "load-failed-with-tls-errors", G_CALLBACK(webViewLoadFailedWithTLSerrors), window); … … 1151 1152 } 1152 1153 1154 static gboolean browserWindowDeleteEvent(GtkWidget *widget, GdkEventAny* event) 1155 { 1156 BrowserWindow *window = BROWSER_WINDOW(widget); 1157 webkit_web_view_try_close(window->webView); 1158 return TRUE; 1159 } 1160 1153 1161 static void browser_window_class_init(BrowserWindowClass *klass) 1154 1162 { … … 1159 1167 gobjectClass->set_property = browserWindowSetProperty; 1160 1168 gobjectClass->finalize = browserWindowFinalize; 1169 1170 GtkWidgetClass *widgetClass = GTK_WIDGET_CLASS(klass); 1171 widgetClass->delete_event = browserWindowDeleteEvent; 1161 1172 1162 1173 g_object_class_install_property(gobjectClass, -
trunk/Tools/TestWebKitAPI/Tests/WebKit2Gtk/TestUIClient.cpp
r185502 r193826 28 28 static const char* kPromptDialogMessage = "WebKitGTK+ prompt dialog message"; 29 29 static const char* kPromptDialogReturnedText = "WebKitGTK+ prompt dialog returned text"; 30 static const char* kBeforeUnloadConfirmDialogMessage = "WebKitGTK+ beforeunload dialog message"; 30 31 31 32 class UIClientTest: public WebViewTest { … … 147 148 g_assert_cmpstr(webkit_script_dialog_get_message(dialog), ==, kPromptDialogReturnedText); 148 149 break; 150 case WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM: 151 g_assert_not_reached(); 152 break; 149 153 } 150 154 … … 164 168 g_assert_cmpstr(webkit_script_dialog_prompt_get_default_text(dialog), ==, "default"); 165 169 webkit_script_dialog_prompt_set_text(dialog, kPromptDialogReturnedText); 170 } 171 172 void scriptBeforeUnloadConfirm(WebKitScriptDialog* dialog) 173 { 174 g_assert_cmpstr(webkit_script_dialog_get_message(dialog), ==, kBeforeUnloadConfirmDialogMessage); 175 m_scriptDialogConfirmed = true; 176 webkit_script_dialog_confirm_set_confirmed(dialog, m_scriptDialogConfirmed); 166 177 } 167 178 … … 178 189 test->scriptPrompt(dialog); 179 190 break; 191 case WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM: 192 test->scriptBeforeUnloadConfirm(dialog); 193 break; 180 194 } 181 195 … … 231 245 { 232 246 g_signal_handlers_disconnect_matched(m_webView, G_SIGNAL_MATCH_DATA, 0, 0, 0, 0, this); 247 } 248 249 static void tryWebViewCloseCallback(UIClientTest* test) 250 { 251 g_main_loop_quit(test->m_mainLoop); 252 } 253 254 void tryCloseAndWaitUntilClosed() 255 { 256 gulong handler = g_signal_connect_swapped(m_webView, "close", G_CALLBACK(tryWebViewCloseCallback), this); 257 // Use an idle because webkit_web_view_try_close can emit the close signal in the 258 // current run loop iteration. 259 g_idle_add([](gpointer data) -> gboolean { 260 webkit_web_view_try_close(WEBKIT_WEB_VIEW(data)); 261 return G_SOURCE_REMOVE; 262 }, m_webView); 263 g_main_loop_run(m_mainLoop); 264 g_signal_handler_disconnect(m_webView, handler); 233 265 } 234 266 … … 474 506 static const char* jsConfirmFormat = "do { confirmed = confirm('%s'); } while (!confirmed); alert('confirmed');"; 475 507 static const char* jsPromptFormat = "alert(prompt('%s', 'default'));"; 508 static const char* htmlOnBeforeUnloadFormat = 509 "<html><body onbeforeunload=\"return beforeUnloadHandler();\"><script>function beforeUnloadHandler() { return \"%s\"; }</script></body></html>"; 476 510 477 511 test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_ALERT; … … 480 514 test->loadHtml(alertHTML.get(), 0); 481 515 test->waitUntilMainLoopFinishes(); 516 webkit_web_view_stop_loading(test->m_webView); 517 test->waitUntilLoadFinished(); 482 518 483 519 test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_CONFIRM; … … 486 522 test->loadHtml(confirmHTML.get(), 0); 487 523 test->waitUntilMainLoopFinishes(); 524 webkit_web_view_stop_loading(test->m_webView); 525 test->waitUntilLoadFinished(); 488 526 489 527 test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_PROMPT; … … 492 530 test->loadHtml(promptHTML.get(), 0); 493 531 test->waitUntilMainLoopFinishes(); 532 webkit_web_view_stop_loading(test->m_webView); 533 test->waitUntilLoadFinished(); 534 535 test->m_scriptDialogType = WEBKIT_SCRIPT_DIALOG_BEFORE_UNLOAD_CONFIRM; 536 GUniquePtr<char> beforeUnloadDialogHTML(g_strdup_printf(htmlOnBeforeUnloadFormat, kBeforeUnloadConfirmDialogMessage)); 537 test->loadHtml(beforeUnloadDialogHTML.get(), nullptr); 538 test->waitUntilLoadFinished(); 539 540 // Reload should trigger onbeforeunload. 541 #if 0 542 // FIXME: reloading HTML data doesn't emit finished load event. 543 // See https://bugs.webkit.org/show_bug.cgi?id=139089. 544 test->m_scriptDialogConfirmed = false; 545 webkit_web_view_reload(test->m_webView); 546 test->waitUntilLoadFinished(); 547 g_assert(test->m_scriptDialogConfirmed); 548 #endif 549 550 // Navigation should trigger onbeforeunload. 551 test->m_scriptDialogConfirmed = false; 552 test->loadHtml("<html></html>", nullptr); 553 test->waitUntilLoadFinished(); 554 g_assert(test->m_scriptDialogConfirmed); 555 556 // Try close should trigger onbeforeunload. 557 test->m_scriptDialogConfirmed = false; 558 test->loadHtml(beforeUnloadDialogHTML.get(), nullptr); 559 test->waitUntilLoadFinished(); 560 test->tryCloseAndWaitUntilClosed(); 561 g_assert(test->m_scriptDialogConfirmed); 562 563 // Try close on a page with no unload handlers should not trigger onbeforeunload, 564 // but should actually close the page. 565 test->m_scriptDialogConfirmed = false; 566 test->loadHtml("<html><body></body></html>", nullptr); 567 test->waitUntilLoadFinished(); 568 // We got a onbeforeunload of the previous page. 569 g_assert(test->m_scriptDialogConfirmed); 570 test->m_scriptDialogConfirmed = false; 571 test->tryCloseAndWaitUntilClosed(); 572 g_assert(!test->m_scriptDialogConfirmed); 494 573 } 495 574
Note:
See TracChangeset
for help on using the changeset viewer.