[webkit-gtk] File chooser signal backported to WebKit1

Daniel Drake dsd at laptop.org
Tue May 22 15:32:06 PDT 2012


In Sugar, we need to override the file chooser used for file uploads.
This is now possible with WebKit2 (thanks!)
https://bugs.webkit.org/show_bug.cgi?id=78491

However OLPC is shipping WebKit1 right now. We'll move to WebKit2 shortly,
but we need a temporary solution for right now.

So I've backported the signal and API to WebKit1, and tested it.
I have removed the API around filtering mime types and so on, which wasn't
implemented anyway in the hardcoded filechooser popup.

I'm trying to follow the webkit contributing page to post this to bugzilla
but without success. I can't complete the svn/git checkouts, probably due to
my slow connection in Nicaragua struggling with the sheer size of WebKit.

Would anyone be willing to run the check-webkit-style program for me (if
appropriate) and prepare-ChangeLog to get this in a format appropriate
for submission?

Thanks
Daniel


---
 Source/WebKit/gtk/GNUmakefile.am                   |    4 +
 .../WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp  |   36 +----
 Source/WebKit/gtk/docs/webkitgtk-docs.sgml         |    1 +
 Source/WebKit/gtk/docs/webkitgtk-sections.txt      |   21 +++
 Source/WebKit/gtk/docs/webkitgtk.types             |    1 +
 .../WebKit/gtk/webkit/webkitfilechooserrequest.cpp |  180 ++++++++++++++++++++
 .../WebKit/gtk/webkit/webkitfilechooserrequest.h   |   65 +++++++
 .../gtk/webkit/webkitfilechooserrequestprivate.h   |   30 ++++
 Source/WebKit/gtk/webkit/webkitwebview.cpp         |   76 ++++++++
 Source/WebKit/gtk/webkit/webkitwebview.h           |    3 +
 Source/WebKit/gtk/webkit/webkitwebviewprivate.h    |    2 +
 11 files changed, 386 insertions(+), 33 deletions(-)
 create mode 100644 Source/WebKit/gtk/webkit/webkitfilechooserrequest.cpp
 create mode 100644 Source/WebKit/gtk/webkit/webkitfilechooserrequest.h
 create mode 100644 Source/WebKit/gtk/webkit/webkitfilechooserrequestprivate.h

diff --git a/Source/WebKit/gtk/GNUmakefile.am b/Source/WebKit/gtk/GNUmakefile.am
index 2d5ad0a..ff28dd9 100644
--- a/Source/WebKit/gtk/GNUmakefile.am
+++ b/Source/WebKit/gtk/GNUmakefile.am
@@ -114,6 +114,7 @@ webkitgtk_static_h_api += \
 	$(srcdir)/Source/WebKit/gtk/webkit/webkitdownload.h \
 	$(srcdir)/Source/WebKit/gtk/webkit/webkiterror.h \
 	$(srcdir)/Source/WebKit/gtk/webkit/webkitfavicondatabase.h \
+	$(srcdir)/Source/WebKit/gtk/webkit/webkitfilechooserrequest.h \
 	$(srcdir)/Source/WebKit/gtk/webkit/webkitgeolocationpolicydecision.h \
 	$(srcdir)/Source/WebKit/gtk/webkit/webkitglobals.h \
 	$(srcdir)/Source/WebKit/gtk/webkit/webkithittestresult.h \
@@ -220,6 +221,9 @@ webkitgtk_sources += \
 	Source/WebKit/gtk/webkit/webkiterror.cpp \
 	Source/WebKit/gtk/webkit/webkitfavicondatabase.cpp \
 	Source/WebKit/gtk/webkit/webkitfavicondatabaseprivate.h \
+	Source/WebKit/gtk/webkit/webkitfilechooserrequest.cpp \
+	Source/WebKit/gtk/webkit/webkitfilechooserrequest.h \
+	Source/WebKit/gtk/webkit/webkitfilechooserrequestprivate.h \
 	Source/WebKit/gtk/webkit/webkitgeolocationpolicydecision.cpp \
 	Source/WebKit/gtk/webkit/webkitgeolocationpolicydecisionprivate.h \
 	Source/WebKit/gtk/webkit/webkitglobals.cpp \
diff --git a/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp b/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp
index 655bf78..07f0e38 100644
--- a/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp
+++ b/Source/WebKit/gtk/WebCoreSupport/ChromeClientGtk.cpp
@@ -55,6 +55,7 @@
 #include "WebKitDOMBinding.h"
 #include "WebKitDOMHTMLElementPrivate.h"
 #include "WindowFeatures.h"
+#include "webkitfilechooserrequestprivate.h"
 #include "webkitgeolocationpolicydecision.h"
 #include "webkitgeolocationpolicydecisionprivate.h"
 #include "webkitnetworkrequest.h"
@@ -815,39 +816,8 @@ void ChromeClient::reachedApplicationCacheOriginQuota(SecurityOrigin*, int64_t)
 void ChromeClient::runOpenPanel(Frame*, PassRefPtr<FileChooser> prpFileChooser)
 {
     RefPtr<FileChooser> chooser = prpFileChooser;
-
-    GtkWidget* toplevel = gtk_widget_get_toplevel(GTK_WIDGET(m_webView));
-    if (!widgetIsOnscreenToplevelWindow(toplevel))
-        toplevel = 0;
-
-    GtkWidget* dialog = gtk_file_chooser_dialog_new(_("Upload File"),
-                                                    toplevel ? GTK_WINDOW(toplevel) : 0,
-                                                    GTK_FILE_CHOOSER_ACTION_OPEN,
-                                                    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
-                                                    GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
-                                                    NULL);
-
-    gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), chooser->settings().allowsMultipleFiles);
-
-    if (gtk_dialog_run(GTK_DIALOG(dialog)) == GTK_RESPONSE_ACCEPT) {
-        if (gtk_file_chooser_get_select_multiple(GTK_FILE_CHOOSER(dialog))) {
-            GOwnPtr<GSList> filenames(gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)));
-            Vector<String> names;
-            for (GSList* item = filenames.get() ; item ; item = item->next) {
-                if (!item->data)
-                    continue;
-                names.append(filenameToString(static_cast<char*>(item->data)));
-                g_free(item->data);
-            }
-            chooser->chooseFiles(names);
-        } else {
-            gchar* filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(dialog));
-            if (filename)
-                chooser->chooseFile(filenameToString(filename));
-            g_free(filename);
-        }
-    }
-    gtk_widget_destroy(dialog);
+    GRefPtr<WebKitFileChooserRequest> request = adoptGRef(webkit_file_chooser_request_create(chooser));
+    webkit_web_view_run_file_chooser_request(m_webView, request.get());
 }
 
 void ChromeClient::loadIconForFiles(const Vector<WTF::String>& filenames, WebCore::FileIconLoader* loader)
diff --git a/Source/WebKit/gtk/docs/webkitgtk-docs.sgml b/Source/WebKit/gtk/docs/webkitgtk-docs.sgml
index b4eb26d..7210652 100644
--- a/Source/WebKit/gtk/docs/webkitgtk-docs.sgml
+++ b/Source/WebKit/gtk/docs/webkitgtk-docs.sgml
@@ -41,6 +41,7 @@
     <xi:include href="xml/webkiticondatabase.xml"/>
     <xi:include href="xml/webkitspellchecker.xml"/>
     <xi:include href="xml/webkitfavicondatabase.xml"/>
+    <xi:include href="xml/webkitfilechooserrequest.xml"/>
   </chapter>
 
   <chapter>
diff --git a/Source/WebKit/gtk/docs/webkitgtk-sections.txt b/Source/WebKit/gtk/docs/webkitgtk-sections.txt
index c97489b..3cc7e4e 100644
--- a/Source/WebKit/gtk/docs/webkitgtk-sections.txt
+++ b/Source/WebKit/gtk/docs/webkitgtk-sections.txt
@@ -703,6 +703,27 @@ WebKitFaviconDatabasePrivate
 </SECTION>
 
 <SECTION>
+<FILE>webkitfilechooserrequest</FILE>
+WebKitFileChooserRequest
+webkit_file_chooser_request_get_select_multiple
+webkit_file_chooser_request_select_files
+webkit_file_chooser_request_cancel
+
+<SUBSECTION Standard>
+WebKitFileChooserRequestClass
+WEBKIT_TYPE_FILE_CHOOSER_REQUEST
+WEBKIT_FILE_CHOOSER_REQUEST
+WEBKIT_IS_FILE_CHOOSER_REQUEST
+WEBKIT_FILE_CHOOSER_REQUEST_CLASS
+WEBKIT_IS_FILE_CHOOSER_REQUEST_CLASS
+WEBKIT_FILE_CHOOSER_REQUEST_GET_CLASS
+
+<SUBSECTION Private>
+WebKitFileChooserRequestPrivate
+webkit_file_chooser_request_get_type
+</SECTION>
+
+<SECTION>
 <FILE>webkitdefines</FILE>
 WEBKIT_API
 WEBKITGTK_API_VERSION
diff --git a/Source/WebKit/gtk/docs/webkitgtk.types b/Source/WebKit/gtk/docs/webkitgtk.types
index 2be1a8c..8049b5c 100644
--- a/Source/WebKit/gtk/docs/webkitgtk.types
+++ b/Source/WebKit/gtk/docs/webkitgtk.types
@@ -1,6 +1,7 @@
 #include <webkit/webkit.h>
 webkit_download_get_type
 webkit_favicon_database_get_type
+webkit_file_chooser_request_get_type
 webkit_geolocation_policy_decision_get_type
 webkit_hit_test_result_get_type
 webkit_icon_database_get_type
diff --git a/Source/WebKit/gtk/webkit/webkitfilechooserrequest.cpp b/Source/WebKit/gtk/webkit/webkitfilechooserrequest.cpp
new file mode 100644
index 0000000..f7d0a4f
--- /dev/null
+++ b/Source/WebKit/gtk/webkit/webkitfilechooserrequest.cpp
@@ -0,0 +1,180 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#include "config.h"
+#include "webkitfilechooserrequest.h"
+
+#include "webkitfilechooserrequestprivate.h"
+#include "webkitglobalsprivate.h"
+#include "FileChooser.h"
+#include "FileSystem.h"
+#include <glib/gi18n-lib.h>
+#include <wtf/gobject/GOwnPtr.h>
+#include <wtf/gobject/GRefPtr.h>
+#include <wtf/text/CString.h>
+
+using namespace WebCore;
+
+/**
+ * SECTION: WebKitFileChooserRequest
+ * @Short_description: A request to open a file chooser
+ * @Title: WebKitFileChooserRequest
+ * @See_also: #WebKitWebView
+ *
+ * Whenever the user interacts with an <input type='file' />
+ * HTML element, WebKit will need to show a dialog to choose one or
+ * more files to be uploaded to the server along with the rest of the
+ * form data. For that to happen in a general way, instead of just
+ * opening a #GtkFileChooserDialog (which might be not desirable in
+ * some cases, which could prefer to use their own file chooser
+ * dialog), WebKit will fire the #WebKitWebView::run-file-chooser
+ * signal with a #WebKitFileChooserRequest object, which will allow
+ * the client application to specify the files to be selected, to
+ * inspect the details of the request (e.g. if multiple selection
+ * should be allowed) and to cancel the request, in case nothing was
+ * selected.
+ *
+ * In case the client application does not wish to handle this signal,
+ * WebKit will provide a default handler which will asynchronously run
+ * a regular #GtkFileChooserDialog for the user to interact with.
+ */
+G_DEFINE_TYPE(WebKitFileChooserRequest, webkit_file_chooser_request, G_TYPE_OBJECT)
+
+struct _WebKitFileChooserRequestPrivate {
+    RefPtr<FileChooser> chooser;
+};
+
+enum {
+    PROP_0,
+    PROP_SELECT_MULTIPLE,
+};
+
+static void webkit_file_chooser_request_init(WebKitFileChooserRequest* request)
+{
+    request->priv = G_TYPE_INSTANCE_GET_PRIVATE(request, WEBKIT_TYPE_FILE_CHOOSER_REQUEST, WebKitFileChooserRequestPrivate);
+    new (request->priv) WebKitFileChooserRequestPrivate();
+}
+
+static void webkit_file_chooser_request_finalize(GObject* object)
+{
+    WebKitFileChooserRequest* request = WEBKIT_FILE_CHOOSER_REQUEST(object);
+
+    request->priv->~WebKitFileChooserRequestPrivate();
+    G_OBJECT_CLASS(webkit_file_chooser_request_parent_class)->finalize(object);
+}
+
+static void webkit_file_chooser_request_get_property(GObject* object, guint propId, GValue* value, GParamSpec* paramSpec)
+{
+    WebKitFileChooserRequest* request = WEBKIT_FILE_CHOOSER_REQUEST(object);
+    switch (propId) {
+    case PROP_SELECT_MULTIPLE:
+        g_value_set_boolean(value, webkit_file_chooser_request_get_select_multiple(request));
+        break;
+    default:
+        G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propId, paramSpec);
+        break;
+    }
+}
+
+static void webkit_file_chooser_request_class_init(WebKitFileChooserRequestClass* requestClass)
+{
+    GObjectClass* objectClass = G_OBJECT_CLASS(requestClass);
+    objectClass->finalize = webkit_file_chooser_request_finalize;
+    objectClass->get_property = webkit_file_chooser_request_get_property;
+    g_type_class_add_private(requestClass, sizeof(WebKitFileChooserRequestPrivate));
+
+    /**
+     * WebKitFileChooserRequest:select-multiple:
+     *
+     * Whether the file chooser should allow selecting multiple
+     * files. See
+     * webkit_file_chooser_request_get_select_multiple() for
+     * more details.
+     */
+    g_object_class_install_property(objectClass,
+                                    PROP_SELECT_MULTIPLE,
+                                    g_param_spec_boolean("select-multiple",
+                                                       _("Select multiple files"),
+                                                       _("Whether the file chooser should allow selecting multiple files"),
+                                                       FALSE,
+                                                       WEBKIT_PARAM_READABLE));
+}
+
+WebKitFileChooserRequest* webkit_file_chooser_request_create(RefPtr<FileChooser> chooser)
+{
+    WebKitFileChooserRequest* request = WEBKIT_FILE_CHOOSER_REQUEST(g_object_new(WEBKIT_TYPE_FILE_CHOOSER_REQUEST, NULL));
+    request->priv->chooser = chooser;
+    return request;
+}
+
+/**
+ * webkit_file_chooser_request_get_select_multiple:
+ * @request: a #WebKitFileChooserRequest
+ *
+ * Determine whether the file chooser associated to this
+ * #WebKitFileChooserRequest should allow selecting multiple files,
+ * which depends on the HTML input element having a 'multiple'
+ * attribute defined.
+ *
+ * Returns: %TRUE if the file chooser should allow selecting multiple files or %FALSE otherwise.
+ */
+gboolean webkit_file_chooser_request_get_select_multiple(WebKitFileChooserRequest* request)
+{
+    g_return_val_if_fail(WEBKIT_IS_FILE_CHOOSER_REQUEST(request), FALSE);
+	return request->priv->chooser->settings().allowsMultipleFiles;
+}
+
+/**
+ * webkit_file_chooser_request_select_files:
+ * @request: a #WebKitFileChooserRequest
+ * @files: (array zero-terminated=1) (transfer none): a
+ * %NULL-terminated array of strings, containing paths to local files.
+ *
+ * Ask WebKit to select local files for upload and complete the
+ * request.
+ */
+void webkit_file_chooser_request_select_files(WebKitFileChooserRequest* request, const gchar* const* files)
+{
+    g_return_if_fail(WEBKIT_IS_FILE_CHOOSER_REQUEST(request));
+    g_return_if_fail(files);
+
+    Vector<String> names;
+
+    for (int i = 0; files[i]; i++)
+        names.append(filenameToString(files[i]));
+
+    request->priv->chooser->chooseFiles(names);
+}
+
+/**
+ * webkit_file_chooser_request_cancel:
+ * @request: a #WebKitFileChooserRequest
+ *
+ * Ask WebKit to cancel the request. It's important to do this in case
+ * no selection has been made in the client, otherwise the request
+ * won't be properly completed and the browser will keep the request
+ * pending forever, which might cause the browser to hang.
+ */
+void webkit_file_chooser_request_cancel(WebKitFileChooserRequest* request)
+{
+    /*
+     * Stub only; for API compatibility with WebKit2's gobject bindings.
+     * Not needed for WebKit1.
+     */
+}
diff --git a/Source/WebKit/gtk/webkit/webkitfilechooserrequest.h b/Source/WebKit/gtk/webkit/webkitfilechooserrequest.h
new file mode 100644
index 0000000..1d46f31
--- /dev/null
+++ b/Source/WebKit/gtk/webkit/webkitfilechooserrequest.h
@@ -0,0 +1,65 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef webkitfilechooserrequest_h
+#define webkitfilechooserrequest_h
+
+#include <gtk/gtk.h>
+#include <webkit/webkitdefines.h>
+
+G_BEGIN_DECLS
+
+#define WEBKIT_TYPE_FILE_CHOOSER_REQUEST            (webkit_file_chooser_request_get_type())
+#define WEBKIT_FILE_CHOOSER_REQUEST(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), WEBKIT_TYPE_FILE_CHOOSER_REQUEST, WebKitFileChooserRequest))
+#define WEBKIT_FILE_CHOOSER_REQUEST_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass),  WEBKIT_TYPE_FILE_CHOOSER_REQUEST, WebKitFileChooserRequestClass))
+#define WEBKIT_IS_FILE_CHOOSER_REQUEST(obj)         (G_TYPE_CHECK_INSTANCE_TYPE((obj), WEBKIT_TYPE_FILE_CHOOSER_REQUEST))
+#define WEBKIT_IS_FILE_CHOOSER_REQUEST_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),  WEBKIT_TYPE_FILE_CHOOSER_REQUEST))
+#define WEBKIT_FILE_CHOOSER_REQUEST_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS((obj),  WEBKIT_TYPE_FILE_CHOOSER_REQUEST, WebKitFileChooserRequestClass))
+
+typedef struct _WebKitFileChooserRequest        WebKitFileChooserRequest;
+typedef struct _WebKitFileChooserRequestClass   WebKitFileChooserRequestClass;
+typedef struct _WebKitFileChooserRequestPrivate WebKitFileChooserRequestPrivate;
+
+struct _WebKitFileChooserRequest {
+    GObject parent;
+
+    /*< private >*/
+    WebKitFileChooserRequestPrivate *priv;
+};
+
+struct _WebKitFileChooserRequestClass {
+    GObjectClass parent_class;
+};
+
+WEBKIT_API GType
+webkit_file_chooser_request_get_type                  (void);
+
+WEBKIT_API gboolean
+webkit_file_chooser_request_get_select_multiple   (WebKitFileChooserRequest *request);
+
+WEBKIT_API void
+webkit_file_chooser_request_select_files          (WebKitFileChooserRequest *request,
+                                                   const gchar * const      *files);
+
+WEBKIT_API void
+webkit_file_chooser_request_cancel                (WebKitFileChooserRequest *request);
+
+G_END_DECLS
+
+#endif
diff --git a/Source/WebKit/gtk/webkit/webkitfilechooserrequestprivate.h b/Source/WebKit/gtk/webkit/webkitfilechooserrequestprivate.h
new file mode 100644
index 0000000..da00e30
--- /dev/null
+++ b/Source/WebKit/gtk/webkit/webkitfilechooserrequestprivate.h
@@ -0,0 +1,30 @@
+/*
+ * Copyright (C) 2012 Igalia S.L.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * along with this library; see the file COPYING.LIB.  If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#ifndef webkitfilechooserrequestprivate_h
+#define webkitfilechooserrequestprivate_h
+
+#include "FileChooser.h"
+#include "webkitfilechooserrequest.h"
+
+using namespace WebCore;
+
+WebKitFileChooserRequest* webkit_file_chooser_request_create(RefPtr<FileChooser> chooser);
+
+#endif
diff --git a/Source/WebKit/gtk/webkit/webkitwebview.cpp b/Source/WebKit/gtk/webkit/webkitwebview.cpp
index 300ea8c..6029b3a 100644
--- a/Source/WebKit/gtk/webkit/webkitwebview.cpp
+++ b/Source/WebKit/gtk/webkit/webkitwebview.cpp
@@ -221,6 +221,7 @@ enum {
     ENTERING_FULLSCREEN,
     LEAVING_FULLSCREEN,
     CONTEXT_MENU,
+    RUN_FILE_CHOOSER,
 
     LAST_SIGNAL
 };
@@ -1300,6 +1301,43 @@ static gboolean webkit_web_view_real_leaving_fullscreen(WebKitWebView* webView)
     return FALSE;
 }
 
+static void fileChooserDialogResponseCallback(GtkDialog* dialog, gint responseID, WebKitFileChooserRequest* request)
+{
+    GRefPtr<WebKitFileChooserRequest> adoptedRequest = adoptGRef(request);
+    if (responseID == GTK_RESPONSE_ACCEPT) {
+        GOwnPtr<GSList> filesList(gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER(dialog)));
+        GRefPtr<GPtrArray> filesArray = adoptGRef(g_ptr_array_new());
+        for (GSList* file = filesList.get(); file; file = g_slist_next(file))
+            g_ptr_array_add(filesArray.get(), file->data);
+        g_ptr_array_add(filesArray.get(), 0);
+        webkit_file_chooser_request_select_files(adoptedRequest.get(), reinterpret_cast<const gchar* const*>(filesArray->pdata));
+    } else
+        webkit_file_chooser_request_cancel(adoptedRequest.get());
+
+    gtk_widget_destroy(GTK_WIDGET(dialog));
+}
+
+static gboolean webkit_web_view_real_run_file_chooser(WebKitWebView* webView, WebKitFileChooserRequest* request)
+{
+    GtkWidget* toplevel = gtk_widget_get_toplevel(GTK_WIDGET(webView));
+    if (!widgetIsOnscreenToplevelWindow(toplevel))
+        toplevel = 0;
+
+    gboolean allowsMultipleSelection = webkit_file_chooser_request_get_select_multiple(request);
+    GtkWidget* dialog = gtk_file_chooser_dialog_new(allowsMultipleSelection ? _("Select Files") : _("Select File"),
+                                                    toplevel ? GTK_WINDOW(toplevel) : 0,
+                                                    GTK_FILE_CHOOSER_ACTION_OPEN,
+                                                    GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL,
+                                                    GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT,
+                                                    NULL);
+
+    gtk_file_chooser_set_select_multiple(GTK_FILE_CHOOSER(dialog), allowsMultipleSelection);
+    g_signal_connect(dialog, "response", G_CALLBACK(fileChooserDialogResponseCallback), g_object_ref(request));
+    gtk_widget_show(dialog);
+
+    return TRUE;
+}
+
 static void webkit_web_view_dispose(GObject* object)
 {
     WebKitWebView* webView = WEBKIT_WEB_VIEW(object);
@@ -2553,6 +2591,37 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
             G_TYPE_NONE, 1,
             WEBKIT_TYPE_WEB_FRAME);
 
+     /**
+     * WebKitWebView::run-file-chooser:
+     * @web_view: the #WebKitWebView on which the signal is emitted
+     * @request: a #WebKitFileChooserRequest
+     *
+     * This signal is emitted when the user interacts with a <input
+     * type='file' /> HTML element, requesting from WebKit to show
+     * a dialog to select one or more files to be uploaded. To let the
+     * application know the details of the file chooser, as well as to
+     * allow the client application to either cancel the request or
+     * perform an actual selection of files, the signal will pass an
+     * instance of the #WebKitFileChooserRequest in the @request
+     * argument.
+     *
+     * The default signal handler will asynchronously run a regular
+     * #GtkFileChooserDialog for the user to interact with.
+     *
+     * Returns: %TRUE to stop other handlers from being invoked for the event.
+     *   %FALSE to propagate the event further.
+     *
+     */
+    webkit_web_view_signals[RUN_FILE_CHOOSER] =
+        g_signal_new("run-file-chooser",
+                     G_TYPE_FROM_CLASS(webViewClass),
+                     G_SIGNAL_RUN_LAST,
+                     G_STRUCT_OFFSET(WebKitWebViewClass, run_file_chooser),
+                     g_signal_accumulator_true_handled, 0 /* accumulator data */,
+                     webkit_marshal_BOOLEAN__OBJECT,
+                     G_TYPE_BOOLEAN, 1, /* number of parameters */
+                     WEBKIT_TYPE_FILE_CHOOSER_REQUEST);
+
     webkit_web_view_signals[SHOULD_BEGIN_EDITING] = g_signal_new("should-begin-editing",
         G_TYPE_FROM_CLASS(webViewClass), static_cast<GSignalFlags>(G_SIGNAL_RUN_LAST | G_SIGNAL_ACTION),
         G_STRUCT_OFFSET(WebKitWebViewClass, should_allow_editing_action), g_signal_accumulator_first_wins, 0,
@@ -2862,6 +2931,7 @@ static void webkit_web_view_class_init(WebKitWebViewClass* webViewClass)
     webViewClass->should_allow_editing_action = webkit_web_view_real_should_allow_editing_action;
     webViewClass->entering_fullscreen = webkit_web_view_real_entering_fullscreen;
     webViewClass->leaving_fullscreen = webkit_web_view_real_leaving_fullscreen;
+    webViewClass->run_file_chooser = webkit_web_view_real_run_file_chooser;
 
     GObjectClass* objectClass = G_OBJECT_CLASS(webViewClass);
     objectClass->dispose = webkit_web_view_dispose;
@@ -3615,6 +3685,12 @@ GtkWidget* webkit_web_view_new(void)
     return GTK_WIDGET(webView);
 }
 
+void webkit_web_view_run_file_chooser_request(WebKitWebView* webView, WebKitFileChooserRequest* request)
+{
+    gboolean returnValue;
+    g_signal_emit(webView, webkit_web_view_signals[RUN_FILE_CHOOSER], 0, request, &returnValue);
+}
+
 // for internal use only
 void webkit_web_view_notify_ready(WebKitWebView* webView)
 {
diff --git a/Source/WebKit/gtk/webkit/webkitwebview.h b/Source/WebKit/gtk/webkit/webkitwebview.h
index dc578d5..42911d0 100644
--- a/Source/WebKit/gtk/webkit/webkitwebview.h
+++ b/Source/WebKit/gtk/webkit/webkitwebview.h
@@ -32,6 +32,7 @@
 #include <webkit/webkitwebframe.h>
 #include <webkit/webkitwebhistoryitem.h>
 #include <webkit/webkitwebsettings.h>
+#include <webkit/webkitfilechooserrequest.h>
 
 G_BEGIN_DECLS
 
@@ -165,6 +166,8 @@ struct _WebKitWebViewClass {
     gboolean                   (* move_cursor)            (WebKitWebView        *web_view,
                                                            GtkMovementStep       step,
                                                            gint                  count);
+    gboolean                   (* run_file_chooser)       (WebKitWebView             *web_view,
+                                                           WebKitFileChooserRequest  *request);
 
     /*
      * internal
diff --git a/Source/WebKit/gtk/webkit/webkitwebviewprivate.h b/Source/WebKit/gtk/webkit/webkitwebviewprivate.h
index 0bc5a56..6a8d93a 100644
--- a/Source/WebKit/gtk/webkit/webkitwebviewprivate.h
+++ b/Source/WebKit/gtk/webkit/webkitwebviewprivate.h
@@ -124,6 +124,8 @@ GtkMenu* webkit_web_view_get_context_menu(WebKitWebView*);
 void webViewEnterFullscreen(WebKitWebView* webView, WebCore::Node*);
 void webViewExitFullscreen(WebKitWebView* webView);
 
+void webkit_web_view_run_file_chooser_request(WebKitWebView*, WebKitFileChooserRequest*);
+
 #if ENABLE(ICONDATABASE)
 void webkitWebViewRegisterForIconNotification(WebKitWebView*, bool shouldRegister);
 void webkitWebViewIconLoaded(WebKitFaviconDatabase*, const char* frameURI, WebKitWebView*);
-- 
1.5.3.8



More information about the webkit-gtk mailing list