diff options
| author | Roland Grunberg | 2017-10-12 20:31:17 +0000 |
|---|---|---|
| committer | Leo Ufimtsev | 2017-11-06 15:27:33 +0000 |
| commit | efc5563b7cb50fbcec6327f029f63a31292bde26 (patch) | |
| tree | 12bdcf93cb0243bdcaee690d444e32e0b67730d7 | |
| parent | 5226b884e7ad613b411b5872742aec832d341e01 (diff) | |
| download | eclipse.platform.swt-efc5563b7cb50fbcec6327f029f63a31292bde26.tar.gz eclipse.platform.swt-efc5563b7cb50fbcec6327f029f63a31292bde26.tar.xz eclipse.platform.swt-efc5563b7cb50fbcec6327f029f63a31292bde26.zip | |
Bug 525946: [Webkit2] Port download functionality to WebKit2.
- On WEBKIT2, the file dialog logic is now done in same thread as the
signal handler since it does not freeze the UI, as may have been the
case on WEBKIT1
- Use the 'download-requested' signal on WEBKIT2 as an entrypoint for
other signals necessary to successfully download a file
- Handle 'decide-destination' signal on WEBKIT2, and place file dialog
logic there so that file path may be changed while still having the
suggested file name
- Handle 'finished', and 'failed' to be aware of download termination as
well as disposing of the progress dialog
- On WEBKIT2, state of a WebKitDownload is only informed through signals
so create a webkitDownloadStatus Map so that the download window may be
aware of download state
- Re-use status codes from WEBKIT1 in the WEBKIT2 code to keep logic as
similar as possible
Tested on WEBKIT1 and WEBKIT2 with 2 browser instances each downloading
the same large file (different destination) while alternating between
instances and downloading smaller files.
Change-Id: Ib4d1e5552eedcb73a61ae671f14408ff00f9b9a4
Signed-off-by: Roland Grunberg <rgrunber@redhat.com>
6 files changed, 499 insertions, 53 deletions
diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.c b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.c index 403f0f2e89..dc647bd51f 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.c +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk.c @@ -1436,6 +1436,66 @@ JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1download_1get_1network_1re } #endif +#ifndef NO__1webkit_1download_1get_1received_1data_1length +JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(_1webkit_1download_1get_1received_1data_1length) + (JNIEnv *env, jclass that, jintLong arg0) +{ + jlong rc = 0; + WebKitGTK_NATIVE_ENTER(env, that, _1webkit_1download_1get_1received_1data_1length_FUNC); +/* + rc = (jlong)webkit_download_get_received_data_length(arg0); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_download_get_received_data_length) + if (fp) { + rc = (jlong)((jlong (CALLING_CONVENTION*)(jintLong))fp)(arg0); + } + } + WebKitGTK_NATIVE_EXIT(env, that, _1webkit_1download_1get_1received_1data_1length_FUNC); + return rc; +} +#endif + +#ifndef NO__1webkit_1download_1get_1request +JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1download_1get_1request) + (JNIEnv *env, jclass that, jintLong arg0) +{ + jintLong rc = 0; + WebKitGTK_NATIVE_ENTER(env, that, _1webkit_1download_1get_1request_FUNC); +/* + rc = (jintLong)webkit_download_get_request(arg0); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_download_get_request) + if (fp) { + rc = (jintLong)((jintLong (CALLING_CONVENTION*)(jintLong))fp)(arg0); + } + } + WebKitGTK_NATIVE_EXIT(env, that, _1webkit_1download_1get_1request_FUNC); + return rc; +} +#endif + +#ifndef NO__1webkit_1download_1get_1response +JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1download_1get_1response) + (JNIEnv *env, jclass that, jintLong arg0) +{ + jintLong rc = 0; + WebKitGTK_NATIVE_ENTER(env, that, _1webkit_1download_1get_1response_FUNC); +/* + rc = (jintLong)webkit_download_get_response(arg0); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_download_get_response) + if (fp) { + rc = (jintLong)((jintLong (CALLING_CONVENTION*)(jintLong))fp)(arg0); + } + } + WebKitGTK_NATIVE_EXIT(env, that, _1webkit_1download_1get_1response_FUNC); + return rc; +} +#endif + #ifndef NO__1webkit_1download_1get_1status JNIEXPORT jint JNICALL WebKitGTK_NATIVE(_1webkit_1download_1get_1status) (JNIEnv *env, jclass that, jintLong arg0) @@ -1496,6 +1556,26 @@ JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(_1webkit_1download_1get_1total_1size) } #endif +#ifndef NO__1webkit_1download_1get_1type +JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1download_1get_1type) + (JNIEnv *env, jclass that) +{ + jintLong rc = 0; + WebKitGTK_NATIVE_ENTER(env, that, _1webkit_1download_1get_1type_FUNC); +/* + rc = (jintLong)webkit_download_get_type(); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_download_get_type) + if (fp) { + rc = (jintLong)((jintLong (CALLING_CONVENTION*)())fp)(); + } + } + WebKitGTK_NATIVE_EXIT(env, that, _1webkit_1download_1get_1type_FUNC); + return rc; +} +#endif + #ifndef NO__1webkit_1download_1get_1uri JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1download_1get_1uri) (JNIEnv *env, jclass that, jintLong arg0) @@ -1516,6 +1596,26 @@ JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1download_1get_1uri) } #endif +#ifndef NO__1webkit_1download_1get_1web_1view +JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1download_1get_1web_1view) + (JNIEnv *env, jclass that, jintLong arg0) +{ + jintLong rc = 0; + WebKitGTK_NATIVE_ENTER(env, that, _1webkit_1download_1get_1web_1view_FUNC); +/* + rc = (jintLong)webkit_download_get_web_view(arg0); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_download_get_web_view) + if (fp) { + rc = (jintLong)((jintLong (CALLING_CONVENTION*)(jintLong))fp)(arg0); + } + } + WebKitGTK_NATIVE_EXIT(env, that, _1webkit_1download_1get_1web_1view_FUNC); + return rc; +} +#endif + #ifndef NO__1webkit_1download_1new JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1download_1new) (JNIEnv *env, jclass that, jintLong arg0) @@ -1536,6 +1636,46 @@ JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1download_1new) } #endif +#ifndef NO__1webkit_1download_1set_1allow_1overwrite +JNIEXPORT void JNICALL WebKitGTK_NATIVE(_1webkit_1download_1set_1allow_1overwrite) + (JNIEnv *env, jclass that, jintLong arg0, jboolean arg1) +{ + WebKitGTK_NATIVE_ENTER(env, that, _1webkit_1download_1set_1allow_1overwrite_FUNC); +/* + webkit_download_set_allow_overwrite(arg0, arg1); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_download_set_allow_overwrite) + if (fp) { + ((void (CALLING_CONVENTION*)(jintLong, jboolean))fp)(arg0, arg1); + } + } + WebKitGTK_NATIVE_EXIT(env, that, _1webkit_1download_1set_1allow_1overwrite_FUNC); +} +#endif + +#ifndef NO__1webkit_1download_1set_1destination +JNIEXPORT void JNICALL WebKitGTK_NATIVE(_1webkit_1download_1set_1destination) + (JNIEnv *env, jclass that, jintLong arg0, jbyteArray arg1) +{ + jbyte *lparg1=NULL; + WebKitGTK_NATIVE_ENTER(env, that, _1webkit_1download_1set_1destination_FUNC); + if (arg1) if ((lparg1 = (*env)->GetByteArrayElements(env, arg1, NULL)) == NULL) goto fail; +/* + webkit_download_set_destination(arg0, lparg1); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_download_set_destination) + if (fp) { + ((void (CALLING_CONVENTION*)(jintLong, jbyte *))fp)(arg0, lparg1); + } + } +fail: + if (arg1 && lparg1) (*env)->ReleaseByteArrayElements(env, arg1, lparg1, 0); + WebKitGTK_NATIVE_EXIT(env, that, _1webkit_1download_1set_1destination_FUNC); +} +#endif + #ifndef NO__1webkit_1download_1set_1destination_1uri JNIEXPORT void JNICALL WebKitGTK_NATIVE(_1webkit_1download_1set_1destination_1uri) (JNIEnv *env, jclass that, jintLong arg0, jbyteArray arg1) @@ -2116,6 +2256,26 @@ fail: } #endif +#ifndef NO__1webkit_1uri_1response_1get_1content_1length +JNIEXPORT jlong JNICALL WebKitGTK_NATIVE(_1webkit_1uri_1response_1get_1content_1length) + (JNIEnv *env, jclass that, jintLong arg0) +{ + jlong rc = 0; + WebKitGTK_NATIVE_ENTER(env, that, _1webkit_1uri_1response_1get_1content_1length_FUNC); +/* + rc = (jlong)webkit_uri_response_get_content_length(arg0); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_uri_response_get_content_length) + if (fp) { + rc = (jlong)((jlong (CALLING_CONVENTION*)(jintLong))fp)(arg0); + } + } + WebKitGTK_NATIVE_EXIT(env, that, _1webkit_1uri_1response_1get_1content_1length_FUNC); + return rc; +} +#endif + #ifndef NO__1webkit_1uri_1response_1get_1mime_1type JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1uri_1response_1get_1mime_1type) (JNIEnv *env, jclass that, jintLong arg0) @@ -2200,6 +2360,26 @@ JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1web_1context_1get_1default } #endif +#ifndef NO__1webkit_1web_1context_1get_1type +JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1web_1context_1get_1type) + (JNIEnv *env, jclass that) +{ + jintLong rc = 0; + WebKitGTK_NATIVE_ENTER(env, that, _1webkit_1web_1context_1get_1type_FUNC); +/* + rc = (jintLong)webkit_web_context_get_type(); +*/ + { + WebKitGTK_LOAD_FUNCTION(fp, webkit_web_context_get_type) + if (fp) { + rc = (jintLong)((jintLong (CALLING_CONVENTION*)())fp)(); + } + } + WebKitGTK_NATIVE_EXIT(env, that, _1webkit_1web_1context_1get_1type_FUNC); + return rc; +} +#endif + #ifndef NO__1webkit_1web_1context_1set_1favicon_1database_1directory JNIEXPORT jintLong JNICALL WebKitGTK_NATIVE(_1webkit_1web_1context_1set_1favicon_1database_1directory) (JNIEnv *env, jclass that, jintLong arg0, jintLong arg1) diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.c b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.c index 95a217975e..bd41410426 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.c +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.c @@ -93,11 +93,18 @@ char * WebKitGTK_nativeFunctionNames[] = { "_1webkit_1download_1cancel", "_1webkit_1download_1get_1current_1size", "_1webkit_1download_1get_1network_1request", + "_1webkit_1download_1get_1received_1data_1length", + "_1webkit_1download_1get_1request", + "_1webkit_1download_1get_1response", "_1webkit_1download_1get_1status", "_1webkit_1download_1get_1suggested_1filename", "_1webkit_1download_1get_1total_1size", + "_1webkit_1download_1get_1type", "_1webkit_1download_1get_1uri", + "_1webkit_1download_1get_1web_1view", "_1webkit_1download_1new", + "_1webkit_1download_1set_1allow_1overwrite", + "_1webkit_1download_1set_1destination", "_1webkit_1download_1set_1destination_1uri", "_1webkit_1download_1start", "_1webkit_1favicon_1database_1set_1path", @@ -127,10 +134,12 @@ char * WebKitGTK_nativeFunctionNames[] = { "_1webkit_1uri_1request_1get_1http_1headers", "_1webkit_1uri_1request_1get_1uri", "_1webkit_1uri_1request_1new", + "_1webkit_1uri_1response_1get_1content_1length", "_1webkit_1uri_1response_1get_1mime_1type", "_1webkit_1user_1content_1manager_1new", "_1webkit_1user_1content_1manager_1register_1script_1message_1handler", "_1webkit_1web_1context_1get_1default", + "_1webkit_1web_1context_1get_1type", "_1webkit_1web_1context_1set_1favicon_1database_1directory", "_1webkit_1web_1data_1source_1get_1data", "_1webkit_1web_1data_1source_1get_1encoding", diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.h b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.h index 5488aaf42d..bbbcb1300d 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.h +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/library/webkitgtk_stats.h @@ -103,11 +103,18 @@ typedef enum { _1webkit_1download_1cancel_FUNC, _1webkit_1download_1get_1current_1size_FUNC, _1webkit_1download_1get_1network_1request_FUNC, + _1webkit_1download_1get_1received_1data_1length_FUNC, + _1webkit_1download_1get_1request_FUNC, + _1webkit_1download_1get_1response_FUNC, _1webkit_1download_1get_1status_FUNC, _1webkit_1download_1get_1suggested_1filename_FUNC, _1webkit_1download_1get_1total_1size_FUNC, + _1webkit_1download_1get_1type_FUNC, _1webkit_1download_1get_1uri_FUNC, + _1webkit_1download_1get_1web_1view_FUNC, _1webkit_1download_1new_FUNC, + _1webkit_1download_1set_1allow_1overwrite_FUNC, + _1webkit_1download_1set_1destination_FUNC, _1webkit_1download_1set_1destination_1uri_FUNC, _1webkit_1download_1start_FUNC, _1webkit_1favicon_1database_1set_1path_FUNC, @@ -137,10 +144,12 @@ typedef enum { _1webkit_1uri_1request_1get_1http_1headers_FUNC, _1webkit_1uri_1request_1get_1uri_FUNC, _1webkit_1uri_1request_1new_FUNC, + _1webkit_1uri_1response_1get_1content_1length_FUNC, _1webkit_1uri_1response_1get_1mime_1type_FUNC, _1webkit_1user_1content_1manager_1new_FUNC, _1webkit_1user_1content_1manager_1register_1script_1message_1handler_FUNC, _1webkit_1web_1context_1get_1default_FUNC, + _1webkit_1web_1context_1get_1type_FUNC, _1webkit_1web_1context_1set_1favicon_1database_1directory_FUNC, _1webkit_1web_1data_1source_1get_1data_FUNC, _1webkit_1web_1data_1source_1get_1encoding_FUNC, diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java index 4dfd67b8b2..0b58b7c1a5 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/browser/WebKit.java @@ -68,6 +68,7 @@ class WebKit extends WebBrowser { static long /*int*/ PostString, WebViewType; static boolean IsWebKit14orNewer; static Map<LONG, LONG> WindowMappings = new HashMap<> (); + static Map<LONG, Integer> webKitDownloadStatus = new HashMap<> (); // Webkit2 static final String ABOUT_BLANK = "about:blank"; //$NON-NLS-1$ static final String CLASSNAME_EXTERNAL = "External"; //$NON-NLS-1$ @@ -121,6 +122,9 @@ class WebKit extends WebBrowser { static final int MOUSE_TARGET_CHANGED = 18; static final int CONTEXT_MENU = 19; static final int AUTHENTICATE = 20; + static final int DECIDE_DESTINATION = 21; // webkit2 only. + static final int FAILED = 22; // webkit2 only. + static final int FINISHED = 23; // webkit2 only. static final String KEY_CHECK_SUBWINDOW = "org.eclipse.swt.internal.control.checksubwindow"; //$NON-NLS-1$ @@ -554,7 +558,13 @@ static long /*int*/ JSDOMEventProc (long /*int*/ arg0, long /*int*/ event, long } static long /*int*/ Proc (long /*int*/ handle, long /*int*/ user_data) { - Browser browser = FindBrowser (handle); + long /*int*/ webView = handle; + + if (WEBKIT2 && OS.G_TYPE_CHECK_INSTANCE_TYPE (handle, WebKitGTK.webkit_download_get_type ())) { + webView = WebKitGTK.webkit_download_get_web_view(handle); + } + + Browser browser = FindBrowser (webView); if (browser == null) return 0; WebKit webkit = (WebKit)browser.webBrowser; return webkit.webViewProc (handle, user_data); @@ -562,6 +572,7 @@ static long /*int*/ Proc (long /*int*/ handle, long /*int*/ user_data) { static long /*int*/ Proc (long /*int*/ handle, long /*int*/ arg0, long /*int*/ user_data) { long /*int*/ webView = 0; + boolean indirectWebView = false; // Behave as if handle were a WebKitWebView (Webkit2 only) if (OS.G_TYPE_CHECK_INSTANCE_TYPE (handle, WebKitGTK.webkit_web_view_get_type ())) { webView = handle; } else if (OS.G_TYPE_CHECK_INSTANCE_TYPE (handle, WebKitGTK.webkit_web_frame_get_type ())) { @@ -570,6 +581,19 @@ static long /*int*/ Proc (long /*int*/ handle, long /*int*/ arg0, long /*int*/ u } else { webView = WebKitGTK.webkit_web_frame_get_web_view (handle); // webkit1 only. } + } else if (WEBKIT2 && OS.G_TYPE_CHECK_INSTANCE_TYPE (handle, WebKitGTK.webkit_web_context_get_type ())) { + /* + * There is no API to determine WebKitWebView from a WebKitWebContext in WEBKIT2. + * Therefore, we pass the WebKitWebView in user_data field only when the handle + * is a WebKitWebContext. We then restore user_data to DOWNLOAD_REQUESTED to + * ensure the corresponding function gets called. + */ + webView = user_data; + user_data = DOWNLOAD_REQUESTED; + indirectWebView = true; + } else if (WEBKIT2 && OS.G_TYPE_CHECK_INSTANCE_TYPE (handle, WebKitGTK.webkit_download_get_type ())) { + webView = WebKitGTK.webkit_download_get_web_view(handle); + indirectWebView = true; } else { return 0; } @@ -579,7 +603,7 @@ static long /*int*/ Proc (long /*int*/ handle, long /*int*/ arg0, long /*int*/ u Browser browser = FindBrowser (webView); if (browser == null) return 0; WebKit webkit = (WebKit)browser.webBrowser; - if (webView == handle) { + if (webView == handle || indirectWebView) { return webkit.webViewProc (handle, arg0, user_data); } else { return webkit.webFrameProc (handle, arg0, user_data); @@ -713,6 +737,7 @@ long /*int*/ webViewProc (long /*int*/ handle, long /*int*/ user_data) { switch ((int)/*64*/user_data) { case CLOSE_WEB_VIEW: return webkit_close_web_view (handle); case WEB_VIEW_READY: return webkit_web_view_ready (handle); + case FINISHED: return webkit_download_finished (handle); // Webkit2 only. default: return 0; } } @@ -721,6 +746,7 @@ long /*int*/ webViewProc (long /*int*/ handle, long /*int*/ arg0, long /*int*/ u switch ((int)/*64*/user_data) { case CREATE_WEB_VIEW: return webkit_create_web_view (handle, arg0); case DOWNLOAD_REQUESTED: return webkit_download_requested (handle, arg0); + case DECIDE_DESTINATION: return webkit_download_decide_destination(handle, arg0); //Webkit2 only. case NOTIFY_LOAD_STATUS: return webkit_notify_load_status (handle, arg0); // Webkit1 case LOAD_CHANGED: return webkit_load_changed (handle, (int) arg0, user_data); case NOTIFY_PROGRESS: return webkit_notify_progress (handle, arg0); @@ -728,6 +754,7 @@ long /*int*/ webViewProc (long /*int*/ handle, long /*int*/ arg0, long /*int*/ u case POPULATE_POPUP: return webkit_populate_popup (handle, arg0); case STATUS_BAR_TEXT_CHANGED: return webkit_status_bar_text_changed (handle, arg0); // Webkit1 only. case AUTHENTICATE: return webkit_authenticate (handle, arg0); // Webkit2 only. + case FAILED: return webkit_download_failed (handle, arg0); // Webkit2 only. default: return 0; } } @@ -858,7 +885,7 @@ public void create (Composite parent, int style) { OS.g_signal_connect (webView, WebKitGTK.load_changed, Proc3.getAddress (), LOAD_CHANGED); OS.g_signal_connect (webView, WebKitGTK.ready_to_show, Proc2.getAddress (), WEB_VIEW_READY); OS.g_signal_connect (webView, WebKitGTK.decide_policy, Proc4.getAddress (), DECIDE_POLICY); - OS.g_signal_connect (WebKitGTK.webkit_web_context_get_default(), WebKitGTK.download_started, Proc3.getAddress (), DOWNLOAD_REQUESTED); + OS.g_signal_connect (WebKitGTK.webkit_web_context_get_default(), WebKitGTK.download_started, Proc3.getAddress (), this.webView); OS.g_signal_connect (webView, WebKitGTK.mouse_target_changed, Proc4.getAddress (), MOUSE_TARGET_CHANGED); OS.g_signal_connect (webView, WebKitGTK.context_menu, Proc5.getAddress (), CONTEXT_MENU); OS.g_signal_connect (webView, WebKitGTK.notify_estimated_load_progress, Proc3.getAddress (), NOTIFY_PROGRESS); @@ -2057,6 +2084,11 @@ void onResize (Event e) { } void openDownloadWindow (final long /*int*/ webkitDownload) { + assert WEBKIT1 : WebKitGTK.Webkit1AssertMsg; + openDownloadWindow(webkitDownload, null); +} + +void openDownloadWindow (final long /*int*/ webkitDownload, final String suggested_filename) { final Shell shell = new Shell (); String msg = Compatibility.getMessage ("SWT_FileDownload"); //$NON-NLS-1$ shell.setText (msg); @@ -2066,14 +2098,26 @@ void openDownloadWindow (final long /*int*/ webkitDownload) { gridLayout.verticalSpacing = 20; shell.setLayout (gridLayout); - long /*int*/ name = WebKitGTK.webkit_download_get_suggested_filename (webkitDownload); - int length = C.strlen (name); + String nameString; + if (WEBKIT1) { + long /*int*/ name = WebKitGTK.webkit_download_get_suggested_filename (webkitDownload); + int length = C.strlen (name); + byte[] bytes = new byte[length]; + C.memmove (bytes, name, length); + nameString = new String (Converter.mbcsToWcs (bytes)); + } else { + nameString = suggested_filename; + } + + long /*int*/ url; + if (WEBKIT1) { + url = WebKitGTK.webkit_download_get_uri (webkitDownload); + } else { + long /*int*/ request = WebKitGTK.webkit_download_get_request(webkitDownload); + url = WebKitGTK.webkit_uri_request_get_uri(request); + } + int length = C.strlen (url); byte[] bytes = new byte[length]; - C.memmove (bytes, name, length); - String nameString = new String (Converter.mbcsToWcs (bytes)); - long /*int*/ url = WebKitGTK.webkit_download_get_uri (webkitDownload); - length = C.strlen (url); - bytes = new byte[length]; C.memmove (bytes, url, length); String urlString = new String (Converter.mbcsToWcs (bytes)); msg = Compatibility.getMessage ("SWT_Download_Location", new Object[] {nameString, urlString}); //$NON-NLS-1$ @@ -2098,7 +2142,12 @@ void openDownloadWindow (final long /*int*/ webkitDownload) { data = new GridData (); data.horizontalAlignment = GridData.CENTER; cancel.setLayoutData (data); - final Listener cancelListener = event -> WebKitGTK.webkit_download_cancel (webkitDownload); + final Listener cancelListener = event -> { + if (WEBKIT2) { + webKitDownloadStatus.put(new LONG(webkitDownload), WebKitGTK.WEBKIT_DOWNLOAD_STATUS_CANCELLED); + } + WebKitGTK.webkit_download_cancel (webkitDownload); + }; cancel.addListener (SWT.Selection, cancelListener); OS.g_object_ref (webkitDownload); @@ -2107,11 +2156,19 @@ void openDownloadWindow (final long /*int*/ webkitDownload) { display.timerExec (INTERVAL, new Runnable () { @Override public void run () { - int status = WebKitGTK.webkit_download_get_status (webkitDownload); + int status = 0; // 0 allows download window to continue + if (WEBKIT1) { + status = WebKitGTK.webkit_download_get_status (webkitDownload); + } else { + status = webKitDownloadStatus.containsKey(new LONG(webkitDownload)) ? webKitDownloadStatus.get(new LONG(webkitDownload)) : 0; + } if (shell.isDisposed () || status == WebKitGTK.WEBKIT_DOWNLOAD_STATUS_FINISHED || status == WebKitGTK.WEBKIT_DOWNLOAD_STATUS_CANCELLED) { shell.dispose (); display.timerExec (-1, this); OS.g_object_unref (webkitDownload); + if (WEBKIT2) { + webKitDownloadStatus.remove(new LONG(webkitDownload)); + } return; } if (status == WebKitGTK.WEBKIT_DOWNLOAD_STATUS_ERROR) { @@ -2120,11 +2177,22 @@ void openDownloadWindow (final long /*int*/ webkitDownload) { OS.g_object_unref (webkitDownload); cancel.removeListener (SWT.Selection, cancelListener); cancel.addListener (SWT.Selection, event -> shell.dispose ()); + if (WEBKIT2) { + webKitDownloadStatus.remove(new LONG(webkitDownload)); + } return; } - long current = WebKitGTK.webkit_download_get_current_size (webkitDownload) / 1024L; - long total = WebKitGTK.webkit_download_get_total_size (webkitDownload) / 1024L; + long current = 0; + long total = 0; + if (WEBKIT1) { + current = WebKitGTK.webkit_download_get_current_size (webkitDownload) / 1024L; + total = WebKitGTK.webkit_download_get_total_size (webkitDownload) / 1024L; + } else { + current = WebKitGTK.webkit_download_get_received_data_length(webkitDownload) / 1024L; + long /*int*/ response = WebKitGTK.webkit_download_get_response(webkitDownload); + total = WebKitGTK.webkit_uri_response_get_content_length(response) / 1024L; + } String message = Compatibility.getMessage ("SWT_Download_Status", new Object[] {new Long(current), new Long(total)}); //$NON-NLS-1$ statusLabel.setText (message); display.timerExec (INTERVAL, this); @@ -2345,42 +2413,88 @@ long /*int*/ webkit_create_web_view (long /*int*/ web_view, long /*int*/ frame) } long /*int*/ webkit_download_requested (long /*int*/ web_view, long /*int*/ download) { - long /*int*/ name = WebKitGTK.webkit_download_get_suggested_filename (download); - int length = C.strlen (name); - byte[] bytes = new byte[length]; - C.memmove (bytes, name, length); - final String nameString = new String (Converter.mbcsToWcs (bytes)); + if (WEBKIT1) { + long /*int*/ name = WebKitGTK.webkit_download_get_suggested_filename (download); + int length = C.strlen (name); + byte[] bytes = new byte[length]; + C.memmove (bytes, name, length); + final String nameString = new String (Converter.mbcsToWcs (bytes)); - final long /*int*/ request = WebKitGTK.webkit_download_get_network_request (download); - OS.g_object_ref (request); + final long /*int*/ request = WebKitGTK.webkit_download_get_network_request (download); + OS.g_object_ref (request); - /* - * As of WebKitGTK 1.8.x attempting to show a FileDialog in this callback causes - * a hang. The workaround is to open it asynchronously with a new download. - */ - browser.getDisplay ().asyncExec (() -> { - if (!browser.isDisposed ()) { - FileDialog dialog = new FileDialog (browser.getShell (), SWT.SAVE); - dialog.setFileName (nameString); - String title = Compatibility.getMessage ("SWT_FileDownload"); //$NON-NLS-1$ - dialog.setText (title); - String path = dialog.open (); - if (path != null) { - path = URI_FILEROOT + path; - long /*int*/ newDownload = WebKitGTK.webkit_download_new (request); - byte[] uriBytes = Converter.wcsToMbcs (path, true); - WebKitGTK.webkit_download_set_destination_uri (newDownload, uriBytes); - openDownloadWindow (newDownload); - WebKitGTK.webkit_download_start (newDownload); - OS.g_object_unref (newDownload); + /* + * As of WebKitGTK 1.8.x attempting to show a FileDialog in this callback causes + * a hang. The workaround is to open it asynchronously with a new download. + */ + browser.getDisplay ().asyncExec (() -> { + if (!browser.isDisposed ()) { + FileDialog dialog = new FileDialog (browser.getShell (), SWT.SAVE); + dialog.setFileName (nameString); + String title = Compatibility.getMessage ("SWT_FileDownload"); //$NON-NLS-1$ + dialog.setText (title); + String path = dialog.open (); + if (path != null) { + path = URI_FILEROOT + path; + long /*int*/ newDownload = WebKitGTK.webkit_download_new (request); + byte[] uriBytes = Converter.wcsToMbcs (path, true); + WebKitGTK.webkit_download_set_destination_uri (newDownload, uriBytes); + openDownloadWindow (newDownload); + WebKitGTK.webkit_download_start (newDownload); + OS.g_object_unref (newDownload); + } } - } - OS.g_object_unref (request); - }); + OS.g_object_unref (request); + }); + } else { + OS._g_signal_connect(download, WebKitGTK.decide_destination, Proc3.getAddress(), DECIDE_DESTINATION); + OS._g_signal_connect(download, WebKitGTK.failed, Proc3.getAddress(), FAILED); + OS._g_signal_connect(download, WebKitGTK.finished, Proc2.getAddress(), FINISHED); + } return 1; } +long /*int*/ webkit_download_decide_destination(long /*int*/ download, long /*int*/ suggested_filename) { + assert WEBKIT2 : WebKitGTK.Webkit2AssertMsg; + final String fileName = getString(suggested_filename); + + if (!browser.isDisposed ()) { + FileDialog dialog = new FileDialog (browser.getShell (), SWT.SAVE); + dialog.setFileName (fileName); + String title = Compatibility.getMessage ("SWT_FileDownload"); //$NON-NLS-1$ + dialog.setText (title); + String path = dialog.open (); + if (path != null) { + path = URI_FILEROOT + path; + byte[] uriBytes = Converter.wcsToMbcs (path, true); + WebKitGTK.webkit_download_set_allow_overwrite (download, true); + WebKitGTK.webkit_download_set_destination (download, uriBytes); + openDownloadWindow (download, fileName); + } + } + + return 0; +} + +long /*int*/ webkit_download_finished(long /*int*/ download) { + assert WEBKIT2 : WebKitGTK.Webkit2AssertMsg; + // A failed signal may have been recorded prior. The finish signal is now being called. + if (!webKitDownloadStatus.containsKey(new LONG(download))) { + webKitDownloadStatus.put(new LONG(download), WebKitGTK.WEBKIT_DOWNLOAD_STATUS_FINISHED); + } + return 0; +} + +long /*int*/ webkit_download_failed(long /*int*/ download, long /*int*/ error) { + assert WEBKIT2 : WebKitGTK.Webkit2AssertMsg; + // A cancel may have been issued resulting in this signal call. Preserve the original cause. + if (!webKitDownloadStatus.containsKey(new LONG(download))) { + webKitDownloadStatus.put(new LONG(download), WebKitGTK.WEBKIT_DOWNLOAD_STATUS_ERROR); + } + return 0; +} + /** * Webkit2 only. WebkitWebView mouse-target-changed * - void user_function (WebKitWebView *web_view, WebKitHitTestResult *hit_test_result, guint modifiers, gpointer user_data) diff --git a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/internal/webkit/WebKitGTK.java b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/internal/webkit/WebKitGTK.java index 701cebc669..d4e8b50fc0 100644 --- a/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/internal/webkit/WebKitGTK.java +++ b/bundles/org.eclipse.swt/Eclipse SWT WebKit/gtk/org/eclipse/swt/internal/webkit/WebKitGTK.java @@ -90,8 +90,11 @@ public class WebKitGTK extends C { public static final byte[] create = ascii ("create"); // $NON-NLS-1$ public static final byte[] create_web_view = ascii ("create-web-view"); // $NON-NLS-1$ public static final byte[] decide_policy = ascii ("decide-policy"); // $NON-NLS-1$ + public static final byte[] decide_destination = ascii ("decide-destination"); // $NON-NLS-1$ // Webkit2 public static final byte[] download_requested = ascii ("download-requested"); // $NON-NLS-1$ - public static final byte[] download_started = ascii ("download-started"); // $NON-NLS-1$ + public static final byte[] download_started = ascii ("download-started"); // $NON-NLS-1$ // Webkit2 + public static final byte[] failed = ascii ("failed"); // $NON-NLS-1$ // Webkit2 + public static final byte[] finished = ascii ("finished"); // $NON-NLS-1$ // Webkit2 public static final byte[] hovering_over_link = ascii ("hovering-over-link"); // $NON-NLS-1$ // Webkit1 -> StatusTextListener.changed() public static final byte[] mouse_target_changed = ascii ("mouse-target-changed"); // $NON-NLS-1$ // Webkit2 -> StatusTextListener.changed() @@ -756,6 +759,18 @@ public static final void webkit_credential_free (long /*int*/ credential) { } /** @method flags=dynamic */ +public static final native long /*int*/ _webkit_web_context_get_type (); +public static final long /*int*/ webkit_web_context_get_type () { + assert WEBKIT2 : Webkit2AssertMsg; + lock.lock(); + try { + return _webkit_web_context_get_type (); + } finally { + lock.unlock(); + } +} + +/** @method flags=dynamic */ public static final native long /*int*/ _webkit_credential_new (byte[] username, byte[] password, int persistence); public static final long /*int*/ webkit_credential_new (byte[] username, byte[] password, int persistence) { assert WEBKIT2 : Webkit2AssertMsg; @@ -905,7 +920,6 @@ public static final void webkit_download_cancel (long /*int*/ download) { public static final native long _webkit_download_get_current_size (long /*int*/ download); public static final long webkit_download_get_current_size (long /*int*/ download) { assert WEBKIT1 : Webkit1AssertMsg; - //TODO - guard from being called on webkit2. lock.lock(); try { return _webkit_download_get_current_size (download); @@ -915,10 +929,21 @@ public static final long webkit_download_get_current_size (long /*int*/ download } /** @method flags=dynamic */ +public static final native long _webkit_download_get_received_data_length (long /*int*/ download); +public static final long webkit_download_get_received_data_length (long /*int*/ download) { + assert WEBKIT2 : Webkit2AssertMsg; + lock.lock(); + try { + return _webkit_download_get_received_data_length (download); + } finally { + lock.unlock(); + } +} + +/** @method flags=dynamic */ public static final native long /*int*/ _webkit_download_get_network_request (long /*int*/ download); public static final long /*int*/ webkit_download_get_network_request (long /*int*/ download) { assert WEBKIT1 : Webkit1AssertMsg; - //TODO - guard from being called on webkit2. lock.lock(); try { return _webkit_download_get_network_request (download); @@ -931,7 +956,6 @@ public static final long /*int*/ webkit_download_get_network_request (long /*int public static final native int _webkit_download_get_status (long /*int*/ download); public static final int webkit_download_get_status (long /*int*/ download) { assert WEBKIT1 : Webkit1AssertMsg; - //TODO - guard from being called on webkit2. lock.lock(); try { return _webkit_download_get_status (download); @@ -944,7 +968,6 @@ public static final int webkit_download_get_status (long /*int*/ download) { public static final native long /*int*/ _webkit_download_get_suggested_filename (long /*int*/ download); public static final long /*int*/ webkit_download_get_suggested_filename (long /*int*/ download) { assert WEBKIT1 : Webkit1AssertMsg; - //TODO - guard from being called on webkit2. lock.lock(); try { return _webkit_download_get_suggested_filename (download); @@ -954,10 +977,33 @@ public static final long /*int*/ webkit_download_get_suggested_filename (long /* } /** @method flags=dynamic */ +public static final native long /*int*/ _webkit_download_get_request (long /*int*/ download); +public static final long /*int*/ webkit_download_get_request (long /*int*/ download) { + assert WEBKIT2 : Webkit2AssertMsg; + lock.lock(); + try { + return _webkit_download_get_request (download); + } finally { + lock.unlock(); + } +} + +/** @method flags=dynamic */ +public static final native long /*int*/ _webkit_download_get_response (long /*int*/ download); +public static final long /*int*/ webkit_download_get_response (long /*int*/ download) { + assert WEBKIT2 : Webkit2AssertMsg; + lock.lock(); + try { + return _webkit_download_get_response (download); + } finally { + lock.unlock(); + } +} + +/** @method flags=dynamic */ public static final native long _webkit_download_get_total_size (long /*int*/ download); public static final long webkit_download_get_total_size (long /*int*/ download) { assert WEBKIT1 : Webkit1AssertMsg; - //TODO - guard from being called on webkit2. lock.lock(); try { return _webkit_download_get_total_size (download); @@ -967,10 +1013,33 @@ public static final long webkit_download_get_total_size (long /*int*/ download) } /** @method flags=dynamic */ +public static final native long /*int*/ _webkit_download_get_type (); +public static final long /*int*/ webkit_download_get_type () { + assert WEBKIT2 : Webkit2AssertMsg; + lock.lock(); + try { + return _webkit_download_get_type (); + } finally { + lock.unlock(); + } +} + +/** @method flags=dynamic */ +public static final native long _webkit_uri_response_get_content_length (long /*int*/ response); +public static final long webkit_uri_response_get_content_length (long /*int*/ response) { + assert WEBKIT2 : Webkit2AssertMsg; + lock.lock(); + try { + return _webkit_uri_response_get_content_length (response); + } finally { + lock.unlock(); + } +} + +/** @method flags=dynamic */ public static final native long /*int*/ _webkit_download_get_uri (long /*int*/ download); public static final long /*int*/ webkit_download_get_uri (long /*int*/ download) { assert WEBKIT1 : Webkit1AssertMsg; - //TODO - guard from being called on webkit2. lock.lock(); try { return _webkit_download_get_uri (download); @@ -980,10 +1049,21 @@ public static final long /*int*/ webkit_download_get_uri (long /*int*/ download) } /** @method flags=dynamic */ +public static final native long /*int*/ _webkit_download_get_web_view (long /*int*/ download); +public static final long /*int*/ webkit_download_get_web_view (long /*int*/ download) { + assert WEBKIT2 : Webkit2AssertMsg; + lock.lock(); + try { + return _webkit_download_get_web_view (download); + } finally { + lock.unlock(); + } +} + +/** @method flags=dynamic */ public static final native long /*int*/ _webkit_download_new (long /*int*/ request); public static final long /*int*/ webkit_download_new (long /*int*/ request) { assert WEBKIT1 : Webkit1AssertMsg; - //TODO - guard from being called on webkit2. lock.lock(); try { return _webkit_download_new (request); @@ -993,10 +1073,21 @@ public static final long /*int*/ webkit_download_new (long /*int*/ request) { } /** @method flags=dynamic */ +public static final native void _webkit_download_set_allow_overwrite (long /*int*/ download, boolean allowed); +public static final void webkit_download_set_allow_overwrite (long /*int*/ download, boolean allowed) { + assert WEBKIT2 : Webkit2AssertMsg; + lock.lock(); + try { + _webkit_download_set_allow_overwrite (download, allowed); + } finally { + lock.unlock(); + } +} + +/** @method flags=dynamic */ public static final native void _webkit_download_set_destination_uri (long /*int*/ download, byte[] destination_uri); public static final void webkit_download_set_destination_uri (long /*int*/ download, byte[] destination_uri) { assert WEBKIT1 : Webkit1AssertMsg; - //TODO - guard from being called on webkit2. lock.lock(); try { _webkit_download_set_destination_uri (download, destination_uri); @@ -1006,10 +1097,21 @@ public static final void webkit_download_set_destination_uri (long /*int*/ downl } /** @method flags=dynamic */ +public static final native void _webkit_download_set_destination (long /*int*/ download, byte[] destination_uri); +public static final void webkit_download_set_destination (long /*int*/ download, byte[] destination_uri) { + assert WEBKIT2 : Webkit2AssertMsg; + lock.lock(); + try { + _webkit_download_set_destination (download, destination_uri); + } finally { + lock.unlock(); + } +} + +/** @method flags=dynamic */ public static final native void _webkit_download_start (long /*int*/ download); public static final void webkit_download_start (long /*int*/ download) { assert WEBKIT1 : Webkit1AssertMsg; - //TODO - guard from being called on webkit2. lock.lock(); try { _webkit_download_start (download); diff --git a/tests/org.eclipse.swt.tests.gtk/Bug Snippets/org/eclipse/swt/tests/gtk/snippets/Bug525946_DownloadFunction.java b/tests/org.eclipse.swt.tests.gtk/Bug Snippets/org/eclipse/swt/tests/gtk/snippets/Bug525946_DownloadFunction.java new file mode 100644 index 0000000000..95c2e1c0af --- /dev/null +++ b/tests/org.eclipse.swt.tests.gtk/Bug Snippets/org/eclipse/swt/tests/gtk/snippets/Bug525946_DownloadFunction.java @@ -0,0 +1,32 @@ +package org.eclipse.swt.tests.gtk.snippets; + +import org.eclipse.swt.SWT; +import org.eclipse.swt.browser.Browser; +import org.eclipse.swt.layout.FillLayout; +import org.eclipse.swt.widgets.Display; +import org.eclipse.swt.widgets.Shell; + +/* + * Title: Bug 459462 - [WebKit] Implement Download functionality + * How to run: launch snippet + * Bug description: Download functionality doesn't work on WebKit2. + * Expected results: Download functionality now works on WebKit2. + * GTK version(s): GTK3.x + */ + +public class Bug525946_DownloadFunction { +public static void main(String[] args) { +final Display display = new Display(); +final Shell shell = new Shell(display); +shell.setBounds(10, 10, 400, 400); +shell.setLayout(new FillLayout()); +final Browser browser = new Browser(shell, SWT.NONE); +browser.setUrl("http://download.eclipse.org/tools/orbit/downloads/drops/R20170516192513/orbit-buildrepo-R20170516192513.zip"); +shell.open(); +while (!shell.isDisposed()) { +if (!display.readAndDispatch()) display.sleep(); +} +shell.dispose(); +display.dispose(); +} +}
\ No newline at end of file |
