blob: 08692ab84df6ceebb271e5f8117f6fedb696133b [file] [log] [blame]
aviau039001d2016-09-29 16:39:05 -04001/*
Guillaume Roguez2a6150d2017-07-19 18:24:47 -04002 * Copyright (C) 2016-2017 Savoir-faire Linux Inc.
aviau039001d2016-09-29 16:39:05 -04003 * Author: Alexandre Viau <alexandre.viau@savoirfairelinux.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18 */
19
20#include "webkitchatcontainer.h"
21
22// GTK+ related
23#include <gtk/gtk.h>
aviau039001d2016-09-29 16:39:05 -040024#include <webkit2/webkit2.h>
25
26// Qt
27#include <QtCore/QJsonValue>
28#include <QtCore/QJsonObject>
29#include <QtCore/QJsonDocument>
30
31// LRC
32#include <media/textrecording.h>
33#include <globalinstances.h>
aviaufc213552016-11-01 12:39:39 -040034#include <contactmethod.h>
aviau039001d2016-09-29 16:39:05 -040035
36// Ring Client
37#include "native/pixbufmanipulator.h"
38#include "config.h"
39
40struct _WebKitChatContainer
41{
42 GtkBox parent;
43};
44
45struct _WebKitChatContainerClass
46{
47 GtkBoxClass parent_class;
48};
49
50typedef struct _WebKitChatContainerPrivate WebKitChatContainerPrivate;
51
52struct _WebKitChatContainerPrivate
53{
54 GtkWidget* webview_chat;
aviau32b8dd62016-11-02 00:36:57 -040055 GtkWidget* box_webview_chat;
aviau039001d2016-09-29 16:39:05 -040056
57 bool chatview_debug;
58
59 /* Array of javascript libraries to load. Used during initialization */
60 GList* js_libs_to_load;
61 gboolean js_libs_loaded;
62};
63
64G_DEFINE_TYPE_WITH_PRIVATE(WebKitChatContainer, webkit_chat_container, GTK_TYPE_BOX);
65
66#define WEBKIT_CHAT_CONTAINER_GET_PRIVATE(obj) (G_TYPE_INSTANCE_GET_PRIVATE ((obj), WEBKIT_CHAT_CONTAINER_TYPE, WebKitChatContainerPrivate))
67
68/* signals */
69enum {
70 READY,
AmarOkb4253242017-07-13 11:21:39 -040071 SEND_MESSAGE,
aviau039001d2016-09-29 16:39:05 -040072 LAST_SIGNAL
73};
74
75static guint webkit_chat_container_signals[LAST_SIGNAL] = { 0 };
76
Stepan Salenikovich1cf35e52017-05-03 16:12:11 -040077/* functions */
78static gboolean webview_crashed(WebKitChatContainer *self);
79
aviau039001d2016-09-29 16:39:05 -040080static void
81webkit_chat_container_dispose(GObject *object)
82{
83 G_OBJECT_CLASS(webkit_chat_container_parent_class)->dispose(object);
84}
85
86static void
87webkit_chat_container_init(WebKitChatContainer *view)
88{
89 gtk_widget_init_template(GTK_WIDGET(view));
90}
91
92static void
93webkit_chat_container_class_init(WebKitChatContainerClass *klass)
94{
95 G_OBJECT_CLASS(klass)->dispose = webkit_chat_container_dispose;
96
aviau039001d2016-09-29 16:39:05 -040097 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
98 "/cx/ring/RingGnome/webkitchatcontainer.ui");
99
aviau32b8dd62016-11-02 00:36:57 -0400100 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), WebKitChatContainer, box_webview_chat);
aviau039001d2016-09-29 16:39:05 -0400101
102 /* add signals */
103 webkit_chat_container_signals[READY] = g_signal_new("ready",
104 G_TYPE_FROM_CLASS(klass),
105 (GSignalFlags) (G_SIGNAL_RUN_FIRST | G_SIGNAL_ACTION),
106 0,
107 nullptr,
108 nullptr,
109 g_cclosure_marshal_VOID__VOID,
110 G_TYPE_NONE, 0);
AmarOkb4253242017-07-13 11:21:39 -0400111
112 webkit_chat_container_signals[SEND_MESSAGE] = g_signal_new("send-message",
113 G_TYPE_FROM_CLASS(klass),
114 (GSignalFlags) (G_SIGNAL_RUN_LAST | G_SIGNAL_DETAILED),
115 0,
116 nullptr,
117 nullptr,
118 g_cclosure_marshal_VOID__STRING,
119 G_TYPE_NONE, 1, G_TYPE_STRING);
aviau039001d2016-09-29 16:39:05 -0400120}
121
122static gboolean
AmarOk748d6cd2017-07-18 12:23:42 -0400123webview_chat_context_menu(WebKitChatContainer *self,
124 WebKitContextMenu *menu,
125 GdkEvent *event,
126 WebKitHitTestResult *hit_test_result,
127 gpointer user_data)
aviau039001d2016-09-29 16:39:05 -0400128{
AmarOk748d6cd2017-07-18 12:23:42 -0400129 GList *items, *nextList;
130 for (items = webkit_context_menu_get_items(menu) ; items ; items = nextList) {
131 WebKitContextMenuAction action;
132 nextList = items->next;
133 auto item = (WebKitContextMenuItem*)items->data;
134 action = webkit_context_menu_item_get_stock_action(item);
135
136 if (action == WEBKIT_CONTEXT_MENU_ACTION_RELOAD ||
137 action == WEBKIT_CONTEXT_MENU_ACTION_GO_FORWARD ||
138 action == WEBKIT_CONTEXT_MENU_ACTION_GO_BACK ||
139 action == WEBKIT_CONTEXT_MENU_ACTION_STOP) {
140 webkit_context_menu_remove(menu, item);
141 }
142 }
143 return false;
aviau039001d2016-09-29 16:39:05 -0400144}
145
146QString
147message_index_to_json_message_object(const QModelIndex &idx)
148{
149 auto message = idx.data().value<QString>();
150 auto sender = idx.data(static_cast<int>(Media::TextRecording::Role::AuthorDisplayname)).value<QString>();
aviaufc213552016-11-01 12:39:39 -0400151 auto sender_contact_method = idx.data(static_cast<int>(Media::TextRecording::Role::ContactMethod)).value<ContactMethod*>();
aviau039001d2016-09-29 16:39:05 -0400152 auto timestamp = idx.data(static_cast<int>(Media::TextRecording::Role::Timestamp)).value<time_t>();
153 auto direction = idx.data(static_cast<int>(Media::TextRecording::Role::Direction)).value<Media::Media::Direction>();
154 auto message_id = idx.row();
155
aviaufc213552016-11-01 12:39:39 -0400156 QString sender_contact_method_str;
157 if(direction == Media::Media::Direction::IN)
158 {
159 sender_contact_method_str = QString(g_strdup_printf("%p", sender_contact_method));
160 }
161 else
162 {
163 sender_contact_method_str = "self";
164 }
165
aviau039001d2016-09-29 16:39:05 -0400166 QJsonObject message_object = QJsonObject();
167 message_object.insert("text", QJsonValue(message));
168 message_object.insert("id", QJsonValue(QString().setNum(message_id)));
169 message_object.insert("sender", QJsonValue(sender));
aviaufc213552016-11-01 12:39:39 -0400170 message_object.insert("sender_contact_method", QJsonValue(sender_contact_method_str));
aviau039001d2016-09-29 16:39:05 -0400171 message_object.insert("timestamp", QJsonValue((int) timestamp));
172 message_object.insert("direction", QJsonValue((direction == Media::Media::Direction::IN) ? "in" : "out"));
173
174 switch(idx.data(static_cast<int>(Media::TextRecording::Role::DeliveryStatus)).value<Media::TextRecording::Status>())
175 {
176 case Media::TextRecording::Status::FAILURE:
177 {
178 message_object.insert("delivery_status", QJsonValue("failure"));
179 break;
180 }
181 case Media::TextRecording::Status::COUNT__:
182 {
183 message_object.insert("delivery_status", QJsonValue("count__"));
184 break;
185 }
186 case Media::TextRecording::Status::SENDING:
187 {
188 message_object.insert("delivery_status", QJsonValue("sending"));
189 break;
190 }
191 case Media::TextRecording::Status::UNKNOWN:
192 {
193 message_object.insert("delivery_status", QJsonValue("unknown"));
194 break;
195 }
196 case Media::TextRecording::Status::READ:
197 {
198 message_object.insert("delivery_status", QJsonValue("read"));
199 break;
200 }
201 case Media::TextRecording::Status::SENT:
202 {
203 message_object.insert("delivery_status", QJsonValue("sent"));
204 break;
205 }
206 }
207
208 return QString(QJsonDocument(message_object).toJson(QJsonDocument::Compact));
209}
210
Stepan Salenikovichb52dbc52016-12-27 14:05:39 -0500211#if WEBKIT_CHECK_VERSION(2, 6, 0)
aviau039001d2016-09-29 16:39:05 -0400212static gboolean
213webview_chat_decide_policy (G_GNUC_UNUSED WebKitWebView *web_view,
214 WebKitPolicyDecision *decision,
215 WebKitPolicyDecisionType type)
216{
217 switch (type)
218 {
219 case WEBKIT_POLICY_DECISION_TYPE_NEW_WINDOW_ACTION:
220 case WEBKIT_POLICY_DECISION_TYPE_NAVIGATION_ACTION:
221 {
222 WebKitNavigationPolicyDecision* navigation_decision = WEBKIT_NAVIGATION_POLICY_DECISION(decision);
223 WebKitNavigationAction* navigation_action = webkit_navigation_policy_decision_get_navigation_action(navigation_decision);
224 WebKitNavigationType navigation_type = webkit_navigation_action_get_navigation_type(navigation_action);
225
226 switch (navigation_type)
227 {
228 case WEBKIT_NAVIGATION_TYPE_FORM_SUBMITTED:
229 case WEBKIT_NAVIGATION_TYPE_BACK_FORWARD:
230 case WEBKIT_NAVIGATION_TYPE_RELOAD:
231 case WEBKIT_NAVIGATION_TYPE_FORM_RESUBMITTED:
232 case WEBKIT_NAVIGATION_TYPE_OTHER:
233 {
234 /* make no decision */
235 return FALSE;
236
237 }
238 case WEBKIT_NAVIGATION_TYPE_LINK_CLICKED:
239 {
240 webkit_policy_decision_ignore(decision);
241
242 WebKitURIRequest* uri_request = webkit_navigation_action_get_request(navigation_action);
243 const gchar* uri = webkit_uri_request_get_uri(uri_request);
244
245 gtk_show_uri(NULL, uri, GDK_CURRENT_TIME, NULL);
246 }
247 }
248
249 webkit_policy_decision_ignore(decision);
250 break;
251 }
252 case WEBKIT_POLICY_DECISION_TYPE_RESPONSE:
253 {
254 //WebKitResponsePolicyDecision *response = WEBKIT_RESPONSE_POLICY_DECISION (decision);
255 //break;
256 return FALSE;
257 }
258 default:
259 {
260 /* Making no decision results in webkit_policy_decision_use(). */
261 return FALSE;
262 }
263 }
264 return TRUE;
265}
266#endif
267
AmarOkb4253242017-07-13 11:21:39 -0400268static gboolean
269webview_send_text(WebKitWebView *self,
270 WebKitScriptDialog *dialog,
271 gpointer user_data)
272{
273 auto message = webkit_script_dialog_get_message(dialog);
274 g_signal_emit(G_OBJECT(self), webkit_chat_container_signals[SEND_MESSAGE], 0, message);
275 return true;
276}
277
aviau039001d2016-09-29 16:39:05 -0400278static void
279javascript_library_loaded(WebKitWebView *webview_chat,
280 GAsyncResult *result,
281 WebKitChatContainer* self)
282{
283 g_return_if_fail(IS_WEBKIT_CHAT_CONTAINER(self));
284 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(self);
285
286 auto loaded_library = g_list_first(priv->js_libs_to_load);
287
288 GError *error = NULL;
289 WebKitJavascriptResult* js_result = webkit_web_view_run_javascript_from_gresource_finish(webview_chat, result, &error);
290 if (!js_result) {
291 g_warning("Error loading %s: %s", (const gchar*) loaded_library->data, error->message);
292 g_error_free(error);
293 g_object_unref(self);
294 /* Stop loading view, most likely resulting in a blank page */
295 return;
296 }
297 webkit_javascript_result_unref(js_result);
298
299 priv->js_libs_to_load = g_list_remove(priv->js_libs_to_load, loaded_library->data);
300
301 if(g_list_length(priv->js_libs_to_load) > 0)
302 {
303 /* keep loading... */
304 webkit_web_view_run_javascript_from_gresource(
305 webview_chat,
306 (const gchar*) g_list_first(priv->js_libs_to_load)->data,
307 NULL,
308 (GAsyncReadyCallback) javascript_library_loaded,
309 self
310 );
311 }
312 else
313 {
314 priv->js_libs_loaded = TRUE;
315 g_signal_emit(G_OBJECT(self), webkit_chat_container_signals[READY], 0);
316
317 /* The view could now be deleted without causing a crash */
318 g_object_unref(self);
319 }
320}
321
322static void
323load_javascript_libs(WebKitWebView *webview_chat,
324 WebKitChatContainer* self)
325{
326 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(self);
327
328 /* Create the list of libraries to load */
aviau039001d2016-09-29 16:39:05 -0400329 priv->js_libs_to_load = g_list_append(priv->js_libs_to_load, (gchar*) "/cx/ring/RingGnome/linkify.js");
330 priv->js_libs_to_load = g_list_append(priv->js_libs_to_load, (gchar*) "/cx/ring/RingGnome/linkify-string.js");
331 priv->js_libs_to_load = g_list_append(priv->js_libs_to_load, (gchar*) "/cx/ring/RingGnome/linkify-html.js");
aviau039001d2016-09-29 16:39:05 -0400332
333 /* ref the chat view so that its not destroyed while we load
334 * we will unref in javascript_library_loaded
335 */
336 g_object_ref(self);
337
338 /* start loading */
339 webkit_web_view_run_javascript_from_gresource(
340 WEBKIT_WEB_VIEW(webview_chat),
341 (const gchar*) g_list_first(priv->js_libs_to_load)->data,
342 NULL,
343 (GAsyncReadyCallback) javascript_library_loaded,
344 self
345 );
346}
347
348static void
349webview_chat_load_changed(WebKitWebView *webview_chat,
350 WebKitLoadEvent load_event,
351 WebKitChatContainer* self)
352{
353 switch (load_event) {
354 case WEBKIT_LOAD_REDIRECTED:
355 {
356 g_warning("webview_chat load is being redirected, this should not happen");
357 }
358 case WEBKIT_LOAD_STARTED:
359 case WEBKIT_LOAD_COMMITTED:
360 {
361 break;
362 }
363 case WEBKIT_LOAD_FINISHED:
364 {
365 load_javascript_libs(webview_chat, self);
366 //TODO: disconnect? It shouldn't happen more than once
367 break;
368 }
369 }
370}
371
372static void
373build_view(WebKitChatContainer *view)
374{
375 g_return_if_fail(IS_WEBKIT_CHAT_CONTAINER(view));
376 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
377
aviau039001d2016-09-29 16:39:05 -0400378 priv->chatview_debug = FALSE;
379 auto ring_chatview_debug = g_getenv("RING_CHATVIEW_DEBUG");
380 if (ring_chatview_debug || g_strcmp0(ring_chatview_debug, "true") == 0)
381 {
382 priv->chatview_debug = TRUE;
383 }
384
aviau32b8dd62016-11-02 00:36:57 -0400385 /* Prepare WebKitUserContentManager */
386 WebKitUserContentManager* webkit_content_manager = webkit_user_content_manager_new();
387
388 WebKitUserStyleSheet* chatview_style_sheet = webkit_user_style_sheet_new(
389 (gchar*) g_bytes_get_data(
390 g_resources_lookup_data(
391 "/cx/ring/RingGnome/chatview.css",
392 G_RESOURCE_LOOKUP_FLAGS_NONE,
393 NULL
394 ),
395 NULL
396 ),
397 WEBKIT_USER_CONTENT_INJECT_ALL_FRAMES,
398 WEBKIT_USER_STYLE_LEVEL_USER,
399 NULL,
400 NULL
401 );
402 webkit_user_content_manager_add_style_sheet(webkit_content_manager, chatview_style_sheet);
403
404 /* Prepare WebKitSettings */
aviau039001d2016-09-29 16:39:05 -0400405 WebKitSettings* webkit_settings = webkit_settings_new_with_settings(
406 "enable-javascript", TRUE,
407 "enable-developer-extras", priv->chatview_debug,
408 "enable-java", FALSE,
409 "enable-plugins", FALSE,
410 "enable-site-specific-quirks", FALSE,
411 "enable-smooth-scrolling", TRUE,
412 NULL
413 );
aviau32b8dd62016-11-02 00:36:57 -0400414
415 /* Create the WebKitWebView */
416 priv->webview_chat = GTK_WIDGET(
417 webkit_web_view_new_with_user_content_manager(
418 webkit_content_manager
419 )
420 );
421
422 gtk_container_add(GTK_CONTAINER(priv->box_webview_chat), priv->webview_chat);
423 gtk_widget_show(priv->webview_chat);
424 gtk_widget_set_vexpand(GTK_WIDGET(priv->webview_chat), TRUE);
425 gtk_widget_set_hexpand(GTK_WIDGET(priv->webview_chat), TRUE);
426
427 /* Set the WebKitSettings */
aviau039001d2016-09-29 16:39:05 -0400428 webkit_web_view_set_settings(WEBKIT_WEB_VIEW(priv->webview_chat), webkit_settings);
429
430 g_signal_connect(priv->webview_chat, "load-changed", G_CALLBACK(webview_chat_load_changed), view);
431 g_signal_connect_swapped(priv->webview_chat, "context-menu", G_CALLBACK(webview_chat_context_menu), view);
AmarOkb4253242017-07-13 11:21:39 -0400432 g_signal_connect_swapped(priv->webview_chat, "script-dialog", G_CALLBACK(webview_send_text), view);
Stepan Salenikovichb52dbc52016-12-27 14:05:39 -0500433#if WEBKIT_CHECK_VERSION(2, 6, 0)
aviau039001d2016-09-29 16:39:05 -0400434 g_signal_connect(priv->webview_chat, "decide-policy", G_CALLBACK(webview_chat_decide_policy), view);
435#endif
436
437 GBytes* chatview_bytes = g_resources_lookup_data(
438 "/cx/ring/RingGnome/chatview.html",
439 G_RESOURCE_LOOKUP_FLAGS_NONE,
440 NULL
441 );
442
443 webkit_web_view_load_html(
444 WEBKIT_WEB_VIEW(priv->webview_chat),
445 (gchar*) g_bytes_get_data(chatview_bytes, NULL),
446 NULL
447 );
448
449 /* Now we wait for the load-changed event, before we
450 * start loading javascript libraries */
Stepan Salenikovich1cf35e52017-05-03 16:12:11 -0400451
452 /* handle web view crash */
453 g_signal_connect_swapped(priv->webview_chat, "web-process-crashed", G_CALLBACK(webview_crashed), view);
454}
455
456static gboolean
457webview_crashed(WebKitChatContainer *self)
458{
459 g_warning("Gtk Web Process crashed! Re-createing web view");
460
461 auto priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(self);
462
463 /* make sure we destroy previous WebView */
464 if (priv->webview_chat) {
465 gtk_widget_destroy(priv->webview_chat);
466 priv->webview_chat = nullptr;
467 }
468
469 build_view(self);
470
471 return G_SOURCE_CONTINUE;
aviau039001d2016-09-29 16:39:05 -0400472}
473
474GtkWidget *
475webkit_chat_container_new()
476{
477 gpointer view = g_object_new(WEBKIT_CHAT_CONTAINER_TYPE, NULL);
478
479 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
480 priv->js_libs_loaded = FALSE;
481
482 build_view(WEBKIT_CHAT_CONTAINER(view));
483
484 return (GtkWidget *)view;
485}
486
487void
aviaufc213552016-11-01 12:39:39 -0400488webkit_chat_container_clear_sender_images(WebKitChatContainer *view)
489{
490 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
491
492 webkit_web_view_run_javascript(
493 WEBKIT_WEB_VIEW(priv->webview_chat),
494 "ring.chatview.clearSenderImages()",
495 NULL,
496 NULL,
497 NULL
498 );
499}
500
501void
aviau039001d2016-09-29 16:39:05 -0400502webkit_chat_container_clear(WebKitChatContainer *view)
503{
504 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
505
506 webkit_web_view_run_javascript(
507 WEBKIT_WEB_VIEW(priv->webview_chat),
508 "ring.chatview.clearMessages()",
509 NULL,
510 NULL,
511 NULL
512 );
513
aviaufc213552016-11-01 12:39:39 -0400514 webkit_chat_container_clear_sender_images(view);
aviau039001d2016-09-29 16:39:05 -0400515}
516
517void
518webkit_chat_container_print_new_message(WebKitChatContainer *view, const QModelIndex &idx)
519{
520 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
521
Guillaume Roguez1820ba12017-03-28 16:30:36 -0400522 auto message_object = message_index_to_json_message_object(idx).toUtf8();
523 gchar* function_call = g_strdup_printf("ring.chatview.addMessage(%s);", message_object.constData());
aviau039001d2016-09-29 16:39:05 -0400524 webkit_web_view_run_javascript(
525 WEBKIT_WEB_VIEW(priv->webview_chat),
526 function_call,
527 NULL,
528 NULL,
529 NULL
530 );
531 g_free(function_call);
532}
533
534void
535webkit_chat_container_update_message(WebKitChatContainer *view, const QModelIndex &idx)
536{
537 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
538
Guillaume Roguez1820ba12017-03-28 16:30:36 -0400539 auto message_object = message_index_to_json_message_object(idx).toUtf8();
540 gchar* function_call = g_strdup_printf("ring.chatview.updateMessage(%s);", message_object.constData());
aviau039001d2016-09-29 16:39:05 -0400541 webkit_web_view_run_javascript(
542 WEBKIT_WEB_VIEW(priv->webview_chat),
543 function_call,
544 NULL,
545 NULL,
546 NULL
547 );
548 g_free(function_call);
549}
550
551void
aviaufc213552016-11-01 12:39:39 -0400552webkit_chat_container_set_sender_image(WebKitChatContainer *view, ContactMethod *sender_contact_method, QVariant sender_image)
aviau039001d2016-09-29 16:39:05 -0400553{
554 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
555
aviaufc213552016-11-01 12:39:39 -0400556 /* The sender_contact_method should be set to nullptr if the sender is self */
557 QString sender_contact_method_str;
558 if (sender_contact_method)
559 {
aviauac74ac32016-11-03 17:25:11 -0400560 sender_contact_method_str = QString().sprintf("%p", sender_contact_method);
aviaufc213552016-11-01 12:39:39 -0400561 }
562 else
563 {
564 sender_contact_method_str = "self";
565 }
566
aviau039001d2016-09-29 16:39:05 -0400567 auto sender_image_base64 = (QString) GlobalInstances::pixmapManipulator().toByteArray(sender_image).toBase64();
568
569 QJsonObject set_sender_image_object = QJsonObject();
aviaufc213552016-11-01 12:39:39 -0400570 set_sender_image_object.insert("sender_contact_method", QJsonValue(sender_contact_method_str));
aviau039001d2016-09-29 16:39:05 -0400571 set_sender_image_object.insert("sender_image", QJsonValue(sender_image_base64));
572
Stepan Salenikovich407dc412016-11-29 11:01:31 -0500573 auto set_sender_image_object_string = QString(QJsonDocument(set_sender_image_object).toJson(QJsonDocument::Compact));
aviau039001d2016-09-29 16:39:05 -0400574
Stepan Salenikovich407dc412016-11-29 11:01:31 -0500575 gchar* function_call = g_strdup_printf("ring.chatview.setSenderImage(%s);", set_sender_image_object_string.toUtf8().constData());
aviau039001d2016-09-29 16:39:05 -0400576 webkit_web_view_run_javascript(WEBKIT_WEB_VIEW(priv->webview_chat), function_call, NULL, NULL, NULL);
577 g_free(function_call);
578}
579
580gboolean
581webkit_chat_container_is_ready(WebKitChatContainer *view)
582{
583 WebKitChatContainerPrivate *priv = WEBKIT_CHAT_CONTAINER_GET_PRIVATE(view);
584 return priv->js_libs_loaded;
585}