initial import
[vuplus_webkit] / Source / WebKit / efl / ewk / ewk_protocol_handler_soup.cpp
1 /*
2     Copyright (C) 2011 ProFUSION embedded systems
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 "ewk_protocol_handler_soup.h"
22
23 #include "FrameLoaderClientEfl.h"
24 #include "FrameNetworkingContextEfl.h"
25 #include "ResourceHandle.h"
26 #include "ResourceHandleClient.h"
27 #include "ResourceHandleInternal.h"
28 #include "ewk_private.h"
29 #include <glib-object.h>
30 #include <glib.h>
31 #include <libsoup/soup-requester.h>
32 #include <libsoup/soup.h>
33
34 struct _EwkProtocolHandlerPrivate {
35     char* mime;
36     size_t bytesRead;
37 };
38
39 G_DEFINE_TYPE(EwkCustomProtocolHandler, ewk_custom_protocol_handler, SOUP_TYPE_REQUEST)
40
41 static char** schemes = 0;
42 static unsigned customProtocolAddedCount = 0;
43
44 static void ewk_custom_protocol_handler_init(EwkCustomProtocolHandler* customProtocolHandler)
45 {
46     customProtocolHandler->priv = G_TYPE_INSTANCE_GET_PRIVATE(customProtocolHandler, EWK_TYPE_CUSTOM_PROTOCOL_HANDLER,
47                                                               EwkProtocolHandlerPrivate);
48     EINA_SAFETY_ON_NULL_RETURN(customProtocolHandler->priv);
49
50     customProtocolHandler->priv->mime = 0;
51     customProtocolHandler->priv->bytesRead = 0;
52 }
53
54 static void ewk_custom_protocol_handler_finalize(GObject* obj)
55 {
56     EwkProtocolHandlerPrivate* priv  = G_TYPE_INSTANCE_GET_PRIVATE(obj, EWK_TYPE_CUSTOM_PROTOCOL_HANDLER,
57                                                                    EwkProtocolHandlerPrivate);
58     if (priv)
59         free(priv->mime);
60
61     G_OBJECT_CLASS(ewk_custom_protocol_handler_parent_class)->finalize(obj);
62 }
63
64 static gboolean ewk_custom_protocol_handler_check_uri(SoupRequest* request, SoupURI* uri, GError** error)
65 {
66     return TRUE;
67 }
68
69 static GInputStream* ewk_custom_protocol_handler_send(SoupRequest* request, GCancellable* cancellable, GError** error)
70 {
71     void* buffer;
72     char* mime = 0;
73     size_t bytesRead = 0;
74
75     WebCore::ResourceHandle* resource = static_cast<
76         WebCore::ResourceHandle*>(g_object_get_data(G_OBJECT(request), "webkit-resource"));
77     EINA_SAFETY_ON_NULL_RETURN_VAL(resource, 0);
78
79     const WebCore::FrameNetworkingContextEfl* frameContext = static_cast<
80         WebCore::FrameNetworkingContextEfl*>(resource->getInternal()->m_context.get());
81     EINA_SAFETY_ON_NULL_RETURN_VAL(frameContext, 0);
82
83     const WebCore::FrameLoaderClientEfl* frameLoaderClient = static_cast<
84         WebCore::FrameLoaderClientEfl*>(frameContext->coreFrame()->loader()->client());
85     EINA_SAFETY_ON_NULL_RETURN_VAL(frameLoaderClient, 0);
86
87     SoupURI* uri = soup_request_get_uri(request);
88     EINA_SAFETY_ON_NULL_RETURN_VAL(uri, 0);
89
90     EwkProtocolHandlerPrivate* priv = G_TYPE_INSTANCE_GET_PRIVATE(
91         reinterpret_cast<EwkCustomProtocolHandler*>(request),
92         EWK_TYPE_CUSTOM_PROTOCOL_HANDLER,
93         EwkProtocolHandlerPrivate);
94
95     EINA_SAFETY_ON_NULL_RETURN_VAL(priv, 0);
96
97
98     if (uri->path[0] == '/') {
99         buffer = ewk_view_protocol_handler_resource_get(frameLoaderClient->webView(),
100                                                         &bytesRead, &mime, uri->path + 1); // The path is always initialized with /.
101     } else
102         buffer = ewk_view_protocol_handler_resource_get(frameLoaderClient->webView(), &bytesRead, &mime, uri->host);
103
104     priv->bytesRead = bytesRead;
105     if (mime)
106         priv->mime = strdup(mime);
107
108     return g_memory_input_stream_new_from_data(buffer, bytesRead, free);
109 }
110
111 static goffset ewk_custom_protocol_handler_get_content_length(SoupRequest* request)
112 {
113     EwkProtocolHandlerPrivate* priv  = G_TYPE_INSTANCE_GET_PRIVATE(reinterpret_cast<EwkCustomProtocolHandler*>(request),
114                                                                    EWK_TYPE_CUSTOM_PROTOCOL_HANDLER,
115                                                                    EwkProtocolHandlerPrivate);
116     return (priv) ? priv->bytesRead : 0;
117 }
118
119 static const char* ewk_custom_protocol_handler_get_content_type(SoupRequest* request)
120 {
121     EwkProtocolHandlerPrivate* priv  = G_TYPE_INSTANCE_GET_PRIVATE(reinterpret_cast<EwkCustomProtocolHandler*>(request),
122                                                                    EWK_TYPE_CUSTOM_PROTOCOL_HANDLER,
123                                                                    EwkProtocolHandlerPrivate);
124     return (priv && priv->mime) ? priv->mime : "text/html";
125 }
126
127 static void ewk_custom_protocol_handler_class_init(EwkCustomProtocolHandlerClass* customProtocolHandlerClass)
128 {
129     GObjectClass* gobjectClass = G_OBJECT_CLASS(customProtocolHandlerClass);
130     SoupRequestClass* requestClass = SOUP_REQUEST_CLASS(customProtocolHandlerClass);
131
132     gobjectClass->finalize = ewk_custom_protocol_handler_finalize;
133     requestClass->schemes = const_cast<const char**>(schemes);
134     requestClass->check_uri = ewk_custom_protocol_handler_check_uri;
135     requestClass->send = ewk_custom_protocol_handler_send;
136     requestClass->get_content_length = ewk_custom_protocol_handler_get_content_length;
137     requestClass->get_content_type = ewk_custom_protocol_handler_get_content_type;
138
139     g_type_class_add_private(customProtocolHandlerClass, sizeof(EwkProtocolHandlerPrivate));
140 }
141
142 Eina_Bool ewk_custom_protocol_handler_soup_set(const char** protocols)
143 {
144     guint protocolsSize;
145     SoupSession* session = WebCore::ResourceHandle::defaultSession();
146     SoupSessionFeature* requester;
147
148     protocolsSize = g_strv_length(const_cast<gchar**>(protocols));
149
150     // This array must be null terminated.
151     EINA_SAFETY_ON_TRUE_RETURN_VAL(!protocolsSize || protocols[protocolsSize], EINA_FALSE);
152
153     requester = soup_session_get_feature(session, SOUP_TYPE_REQUESTER);
154     if (!requester) {
155         requester = SOUP_SESSION_FEATURE(soup_requester_new());
156         soup_session_add_feature(session, requester);
157         g_object_unref(requester);
158     }
159
160     if (soup_session_feature_has_feature(requester, EWK_TYPE_CUSTOM_PROTOCOL_HANDLER)) {
161         customProtocolAddedCount++;
162         return EINA_TRUE;
163     }
164
165     schemes = g_strdupv(const_cast<gchar**>(protocols));
166     if (!(schemes && soup_session_feature_add_feature(requester, EWK_TYPE_CUSTOM_PROTOCOL_HANDLER)))
167         return EINA_FALSE;
168
169     customProtocolAddedCount++;
170     return EINA_TRUE;
171 }
172
173 Eina_Bool ewk_custom_protocol_handler_soup_all_unset()
174 {
175     SoupSession* session = WebCore::ResourceHandle::defaultSession();
176     SoupSessionFeature* requester;
177
178     if (!customProtocolAddedCount)
179         return EINA_FALSE;
180
181     requester = soup_session_get_feature(session, SOUP_TYPE_REQUESTER);
182     if (!requester)
183         return EINA_FALSE;
184
185     if (!soup_session_feature_has_feature(requester, EWK_TYPE_CUSTOM_PROTOCOL_HANDLER))
186         return EINA_FALSE;
187
188     if (customProtocolAddedCount == 1) {
189         if (soup_session_feature_remove_feature(requester, EWK_TYPE_CUSTOM_PROTOCOL_HANDLER))
190             g_strfreev(schemes);
191         else
192             return EINA_FALSE;
193     }
194
195     customProtocolAddedCount--;
196     return EINA_TRUE;
197 }