[GLIB] Use GUniquePtr instead of GOwnPtr
[WebKit-https.git] / Source / WebKit2 / UIProcess / API / gtk / WebKitURISchemeRequest.cpp
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 Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 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 "WebKitURISchemeRequest.h"
22
23 #include "APIData.h"
24 #include "WebKitURISchemeRequestPrivate.h"
25 #include "WebKitWebContextPrivate.h"
26 #include "WebKitWebView.h"
27 #include "WebPageProxy.h"
28 #include "WebSoupRequestManagerProxy.h"
29 #include <WebCore/GUniquePtrSoup.h>
30 #include <WebCore/ResourceError.h>
31 #include <libsoup/soup.h>
32 #include <wtf/gobject/GOwnPtr.h>
33 #include <wtf/gobject/GRefPtr.h>
34 #include <wtf/text/CString.h>
35
36 using namespace WebKit;
37
38 /**
39  * SECTION: WebKitURISchemeRequest
40  * @Short_description: Represents a URI scheme request
41  * @Title: WebKitURISchemeRequest
42  *
43  * If you register a particular URI scheme in a #WebKitWebContext,
44  * using webkit_web_context_register_uri_scheme(), you have to provide
45  * a #WebKitURISchemeRequestCallback. After that, when a URI request
46  * is made with that particular scheme, your callback will be
47  * called. There you will be able to access properties such as the
48  * scheme, the URI and path, and the #WebKitWebView that initiated the
49  * request, and also finish the request with
50  * webkit_uri_scheme_request_finish().
51  *
52  */
53
54 static const unsigned int gReadBufferSize = 8192;
55
56 struct _WebKitURISchemeRequestPrivate {
57     WebKitWebContext* webContext;
58     RefPtr<WebSoupRequestManagerProxy> webRequestManager;
59     RefPtr<WebPageProxy> initiatingPage;
60     uint64_t requestID;
61     CString uri;
62     GUniquePtr<SoupURI> soupURI;
63
64     GRefPtr<GInputStream> stream;
65     uint64_t streamLength;
66     GRefPtr<GCancellable> cancellable;
67     char readBuffer[gReadBufferSize];
68     uint64_t bytesRead;
69     CString mimeType;
70 };
71
72 WEBKIT_DEFINE_TYPE(WebKitURISchemeRequest, webkit_uri_scheme_request, G_TYPE_OBJECT)
73
74 static void webkit_uri_scheme_request_class_init(WebKitURISchemeRequestClass* requestClass)
75 {
76 }
77
78 WebKitURISchemeRequest* webkitURISchemeRequestCreate(WebKitWebContext* webContext, WebSoupRequestManagerProxy* webRequestManager, API::URL* webURL, WebPageProxy* initiatingPage, uint64_t requestID)
79 {
80     WebKitURISchemeRequest* request = WEBKIT_URI_SCHEME_REQUEST(g_object_new(WEBKIT_TYPE_URI_SCHEME_REQUEST, NULL));
81     request->priv->webContext = webContext;
82     request->priv->webRequestManager = webRequestManager;
83     request->priv->uri = webURL->string().utf8();
84     request->priv->initiatingPage = initiatingPage;
85     request->priv->requestID = requestID;
86     return request;
87 }
88
89 uint64_t webkitURISchemeRequestGetID(WebKitURISchemeRequest* request)
90 {
91     return request->priv->requestID;
92 }
93
94 void webkitURISchemeRequestCancel(WebKitURISchemeRequest* request)
95 {
96     if (request->priv->cancellable.get())
97         g_cancellable_cancel(request->priv->cancellable.get());
98 }
99
100 /**
101  * webkit_uri_scheme_request_get_scheme:
102  * @request: a #WebKitURISchemeRequest
103  *
104  * Get the URI scheme of @request
105  *
106  * Returns: the URI scheme of @request
107  */
108 const char* webkit_uri_scheme_request_get_scheme(WebKitURISchemeRequest* request)
109 {
110     g_return_val_if_fail(WEBKIT_IS_URI_SCHEME_REQUEST(request), 0);
111
112     if (!request->priv->soupURI)
113         request->priv->soupURI.reset(soup_uri_new(request->priv->uri.data()));
114     return request->priv->soupURI->scheme;
115 }
116
117 /**
118  * webkit_uri_scheme_request_get_uri:
119  * @request: a #WebKitURISchemeRequest
120  *
121  * Get the URI of @request
122  *
123  * Returns: the full URI of @request
124  */
125 const char* webkit_uri_scheme_request_get_uri(WebKitURISchemeRequest* request)
126 {
127     g_return_val_if_fail(WEBKIT_IS_URI_SCHEME_REQUEST(request), 0);
128
129     return request->priv->uri.data();
130 }
131
132 /**
133  * webkit_uri_scheme_request_get_path:
134  * @request: a #WebKitURISchemeRequest
135  *
136  * Get the URI path of @request
137  *
138  * Returns: the URI path of @request
139  */
140 const char* webkit_uri_scheme_request_get_path(WebKitURISchemeRequest* request)
141 {
142     g_return_val_if_fail(WEBKIT_IS_URI_SCHEME_REQUEST(request), 0);
143
144     if (!request->priv->soupURI)
145         request->priv->soupURI.reset(soup_uri_new(request->priv->uri.data()));
146     return request->priv->soupURI->path;
147 }
148
149 /**
150  * webkit_uri_scheme_request_get_web_view:
151  * @request: a #WebKitURISchemeRequest
152  *
153  * Get the #WebKitWebView that initiated the request.
154  *
155  * Returns: (transfer none): the #WebKitWebView that initiated @request.
156  */
157 WebKitWebView* webkit_uri_scheme_request_get_web_view(WebKitURISchemeRequest* request)
158 {
159     g_return_val_if_fail(WEBKIT_IS_URI_SCHEME_REQUEST(request), 0);
160
161     return WEBKIT_WEB_VIEW(request->priv->initiatingPage->viewWidget());
162 }
163
164 static void webkitURISchemeRequestReadCallback(GInputStream* inputStream, GAsyncResult* result, WebKitURISchemeRequest* schemeRequest)
165 {
166     GRefPtr<WebKitURISchemeRequest> request = adoptGRef(schemeRequest);
167     GOwnPtr<GError> error;
168     gssize bytesRead = g_input_stream_read_finish(inputStream, result, &error.outPtr());
169     if (bytesRead == -1) {
170         webkit_uri_scheme_request_finish_error(request.get(), error.get());
171         return;
172     }
173
174     WebKitURISchemeRequestPrivate* priv = request->priv;
175     RefPtr<API::Data> webData = API::Data::create(reinterpret_cast<const unsigned char*>(priv->readBuffer), bytesRead);
176     if (!priv->bytesRead) {
177         // First chunk read. In case of empty reply an empty API::Data is sent to the WebProcess.
178         priv->webRequestManager->didHandleURIRequest(webData.get(), priv->streamLength, String::fromUTF8(priv->mimeType.data()), priv->requestID);
179     } else if (bytesRead || (!bytesRead && !priv->streamLength)) {
180         // Subsequent chunk read. We only send an empty API::Data to the WebProcess when stream length is unknown.
181         priv->webRequestManager->didReceiveURIRequestData(webData.get(), priv->requestID);
182     }
183
184     if (!bytesRead) {
185         webkitWebContextDidFinishURIRequest(request->priv->webContext, request->priv->requestID);
186         return;
187     }
188
189     priv->bytesRead += bytesRead;
190     g_input_stream_read_async(inputStream, priv->readBuffer, gReadBufferSize, G_PRIORITY_DEFAULT, priv->cancellable.get(),
191                               reinterpret_cast<GAsyncReadyCallback>(webkitURISchemeRequestReadCallback), g_object_ref(request.get()));
192 }
193
194 /**
195  * webkit_uri_scheme_request_finish:
196  * @request: a #WebKitURISchemeRequest
197  * @stream: a #GInputStream to read the contents of the request
198  * @stream_length: the length of the stream or -1 if not known
199  * @mime_type: (allow-none): the content type of the stream or %NULL if not known
200  *
201  * Finish a #WebKitURISchemeRequest by setting the contents of the request and its mime type.
202  */
203 void webkit_uri_scheme_request_finish(WebKitURISchemeRequest* request, GInputStream* inputStream, gint64 streamLength, const gchar* mimeType)
204 {
205     g_return_if_fail(WEBKIT_IS_URI_SCHEME_REQUEST(request));
206     g_return_if_fail(G_IS_INPUT_STREAM(inputStream));
207     g_return_if_fail(streamLength == -1 || streamLength >= 0);
208
209     request->priv->stream = inputStream;
210     // We use -1 in the API for consistency with soup when the content length is not known, but 0 internally.
211     request->priv->streamLength = streamLength == -1 ? 0 : streamLength;
212     request->priv->cancellable = adoptGRef(g_cancellable_new());
213     request->priv->bytesRead = 0;
214     request->priv->mimeType = mimeType;
215     g_input_stream_read_async(inputStream, request->priv->readBuffer, gReadBufferSize, G_PRIORITY_DEFAULT, request->priv->cancellable.get(),
216                               reinterpret_cast<GAsyncReadyCallback>(webkitURISchemeRequestReadCallback), g_object_ref(request));
217 }
218
219 /**
220  * webkit_uri_scheme_request_finish_error:
221  * @request: a #WebKitURISchemeRequest
222  * @error: a #GError that will be passed to the #WebKitWebView
223  *
224  * Finish a #WebKitURISchemeRequest with a #GError.
225  *
226  * Since: 2.2
227  */
228 void webkit_uri_scheme_request_finish_error(WebKitURISchemeRequest* request, GError* error)
229 {
230     g_return_if_fail(WEBKIT_IS_URI_SCHEME_REQUEST(request));
231     g_return_if_fail(error);
232
233     WebKitURISchemeRequestPrivate* priv = request->priv;
234
235     WebCore::ResourceError resourceError(g_quark_to_string(error->domain), error->code, priv->uri.data(), String::fromUTF8(error->message));
236     priv->webRequestManager->didFailURIRequest(resourceError, priv->requestID);
237
238     webkitWebContextDidFinishURIRequest(priv->webContext, priv->requestID);
239 }