~mhr3/+junk/grilo-fix-1236637

« back to all changes in this revision

Viewing changes to libs/net/grl-net-wc.c

  • Committer: Package Import Robot
  • Author(s): Alberto Garcia
  • Date: 2012-05-24 18:05:32 UTC
  • mfrom: (1.1.4)
  • Revision ID: package-import@ubuntu.com-20120524180532-ccftaeh72upen313
Tags: 0.1.19-1
* New upstream release.
* Build using Vala 0.16:
  - debian/control: update build dependencies.
  - debian/rules: install Vala API files in /usr/share/vala/vapi.
  - debian/libgrilo-0.1-dev.install: update path of Vala API files.
* Create a new libgrilo-0.1-bin package and move grl-inspect-0.1 there.
  - debian/rules: rename manpage to match the binary name.
* Drop libgrilo-0.1-0.shlibs and use dh_makeshlibs to generate a shlibs
  file.
* Multi-arch support:
  - debian/compat: set compatibility level to 9.
  - debian/control: build depend on debhelper >= 9.
  - debian/control: Add Multi-Arch and Pre-Depends fields to
    libgrilo-0.1-0.
  - debian/libgrilo-0.1-{0,dev}.install: replace usr/lib/ with
    usr/lib/*/.
  - bump shlibs to 0.1.19 and break grilo-plugins-0.1 << 0.1.19.
* libgrilo-0.1-{0,bin}.lintian-overrides: ignore the
  hardening-no-stackprotector warning, Grilo does not use character
  arrays on the stack.
* debian/copyright: update copyright years and add section for Debian
  files.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
 
 * Copyright (C) 2010 Igalia S.L.
 
2
 * Copyright (C) 2010, 2011 Igalia S.L.
3
3
 *
4
4
 * Contact: Iago Toral Quiroga <itoral@igalia.com>
5
5
 *
39
39
#include <string.h>
40
40
#include <libsoup/soup.h>
41
41
 
42
 
#ifdef LIBSOUP_WITH_CACHE
43
 
/* Using the cache feature requires to use the unstable API */
44
 
#define LIBSOUP_USE_UNSTABLE_REQUEST_API
45
 
#define BUFFER_SIZE (50*1024)
46
 
#include <libsoup/soup-cache.h>
47
 
#include <libsoup/soup-requester.h>
48
 
#include <libsoup/soup-request-http.h>
49
 
#endif
50
 
 
51
42
#include <grilo.h>
52
43
#include "grl-net-wc.h"
 
44
#include "grl-net-private.h"
53
45
 
54
46
#define GRL_LOG_DOMAIN_DEFAULT wc_log_domain
55
 
GRL_LOG_DOMAIN_STATIC(wc_log_domain);
 
47
GRL_LOG_DOMAIN(wc_log_domain);
56
48
 
57
49
enum {
58
50
  PROP_0,
60
52
  PROP_THROTTLING,
61
53
  PROP_CACHE,
62
54
  PROP_CACHE_SIZE,
 
55
  PROP_USER_AGENT,
63
56
};
64
57
 
65
58
#define GRL_NET_WC_GET_PRIVATE(object)                  \
67
60
                               GRL_TYPE_NET_WC,         \
68
61
                               GrlNetWcPrivate))
69
62
 
70
 
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
71
 
static SoupCache *cache = NULL;
72
 
static void cache_down(GrlNetWc *self);
73
 
#endif
74
 
 
75
 
static guint cache_size;
76
 
 
77
 
typedef struct _RequestClosure RequestClosure;
78
 
 
79
 
struct _GrlNetWcPrivate {
80
 
  SoupSession *session;
81
 
  SoupLoggerLogLevel log_level;
82
 
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
83
 
  SoupRequester *requester;
84
 
  SoupCache *cache;
85
 
  gchar *previous_data;
86
 
#endif
87
 
  guint cache_size;
88
 
  guint throttling;
89
 
  GTimeVal last_request;
90
 
  GQueue *pending; /* closure queue for delayed requests */
91
 
};
92
 
 
93
 
struct _RequestClosure {
94
 
  GrlNetWc *self;
95
 
  char *url;
96
 
  GAsyncResult *result;
97
 
  GCancellable *cancellable;
98
 
  guint source_id;
99
 
};
100
 
 
101
 
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
102
 
typedef struct {
103
 
  SoupRequest *request;
104
 
  gchar *buffer;
105
 
  gsize length;
106
 
  gsize offset;
107
 
} RequestResult;
108
 
#endif
109
 
 
110
63
GQuark
111
64
grl_net_wc_error_quark (void)
112
65
{
193
146
                                                      G_PARAM_READWRITE |
194
147
                                                      G_PARAM_CONSTRUCT |
195
148
                                                      G_PARAM_STATIC_STRINGS));
 
149
  /**
 
150
   * GrlNetWc::user-agent
 
151
   *
 
152
   * User agent identifier.
 
153
   */
 
154
  g_object_class_install_property (g_klass,
 
155
                                   PROP_USER_AGENT,
 
156
                                   g_param_spec_string ("user-agent",
 
157
                                                        "User Agent",
 
158
                                                        "User agent identifier",
 
159
                                                        NULL,
 
160
                                                        G_PARAM_READWRITE |
 
161
                                                        G_PARAM_CONSTRUCT |
 
162
                                                        G_PARAM_STATIC_STRINGS));
 
163
}
 
164
 
 
165
/*
 
166
 * use-thread-context is available for libsoup-2.4 >= 2.39.0
 
167
 * We check in run-time if it's available
 
168
 */
 
169
static void
 
170
set_thread_context (GrlNetWc *self)
 
171
{
 
172
    GrlNetWcPrivate *priv = self->priv;
 
173
    GObjectClass *klass = G_OBJECT_GET_CLASS (priv->session);
 
174
    GParamSpec *spec = g_object_class_find_property (klass,
 
175
                                                     "use-thread-context");
 
176
    if (spec)
 
177
      g_object_set (priv->session, "use-thread-context", TRUE, NULL);
196
178
}
197
179
 
198
180
static void
204
186
 
205
187
  wc->priv->session = soup_session_async_new ();
206
188
  wc->priv->pending = g_queue_new ();
207
 
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
208
 
  wc->priv->requester = soup_requester_new();
209
 
  soup_session_add_feature (wc->priv->session,
210
 
                            SOUP_SESSION_FEATURE (wc->priv->requester));
211
 
#endif
 
189
 
 
190
  set_thread_context (wc);
 
191
  init_requester (wc);
212
192
}
213
193
 
214
194
static void
218
198
 
219
199
  wc = GRL_NET_WC (object);
220
200
  grl_net_wc_flush_delayed_requests (wc);
221
 
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
 
201
 
222
202
  cache_down (wc);
223
 
  g_free (wc->priv->previous_data);
224
 
  g_object_unref (wc->priv->requester);
225
 
#endif
 
203
  finalize_requester (wc);
 
204
 
226
205
  g_queue_free (wc->priv->pending);
227
206
  g_object_unref (wc->priv->session);
228
207
 
252
231
  case PROP_CACHE_SIZE:
253
232
    grl_net_wc_set_cache_size (wc, g_value_get_uint (value));
254
233
    break;
 
234
  case PROP_USER_AGENT:
 
235
    g_object_set (G_OBJECT (wc->priv->session),
 
236
                  "user-agent", g_value_get_string (value),
 
237
                  NULL);
 
238
    break;
255
239
  default:
256
240
    G_OBJECT_WARN_INVALID_PROPERTY_ID (wc, propid, pspec);
257
241
  }
275
259
    g_value_set_uint (value, wc->priv->throttling);
276
260
    break;
277
261
  case PROP_CACHE:
278
 
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
279
 
    g_value_set_boolean (value, wc->priv->cache != NULL);
280
 
#else
281
 
    g_value_set_boolean (value, FALSE);
282
 
#endif
 
262
    g_value_set_boolean(value, cache_is_available (wc));
283
263
    break;
284
264
  case PROP_CACHE_SIZE:
285
 
    g_value_set_uint (value, wc->priv->cache_size);
 
265
    g_value_set_uint (value, cache_get_size (wc));
 
266
    break;
 
267
  case PROP_USER_AGENT:
 
268
    g_object_get_property (G_OBJECT (wc->priv->session), "user_agent", value);
286
269
    break;
287
270
  default:
288
271
    G_OBJECT_WARN_INVALID_PROPERTY_ID (wc, propid, pspec);
289
272
  }
290
273
}
291
274
 
292
 
static inline void
293
 
parse_error (guint status,
294
 
             const gchar *reason,
295
 
             const gchar *response,
296
 
             GSimpleAsyncResult *result)
297
 
{
298
 
  if (!response || *response == '\0')
299
 
    response = reason;
300
 
 
301
 
  switch (status) {
302
 
  case SOUP_STATUS_CANT_RESOLVE:
303
 
  case SOUP_STATUS_CANT_CONNECT:
304
 
  case SOUP_STATUS_SSL_FAILED:
305
 
  case SOUP_STATUS_IO_ERROR:
306
 
    g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
307
 
                                     GRL_NET_WC_ERROR_NETWORK_ERROR,
308
 
                                     "Cannot connect to the server");
309
 
    return;
310
 
  case SOUP_STATUS_CANT_RESOLVE_PROXY:
311
 
  case SOUP_STATUS_CANT_CONNECT_PROXY:
312
 
    g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
313
 
                                     GRL_NET_WC_ERROR_PROXY_ERROR,
314
 
                                     "Cannot connect to the proxy server");
315
 
    return;
316
 
  case SOUP_STATUS_INTERNAL_SERVER_ERROR: /* 500 */
317
 
  case SOUP_STATUS_MALFORMED:
318
 
  case SOUP_STATUS_BAD_REQUEST: /* 400 */
319
 
    g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
320
 
                                     GRL_NET_WC_ERROR_PROTOCOL_ERROR,
321
 
                                     "Invalid request URI or header: %s",
322
 
                                     response);
323
 
    return;
324
 
  case SOUP_STATUS_UNAUTHORIZED: /* 401 */
325
 
  case SOUP_STATUS_FORBIDDEN: /* 403 */
326
 
    g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
327
 
                                     GRL_NET_WC_ERROR_AUTHENTICATION_REQUIRED,
328
 
                                     "Authentication required: %s", response);
329
 
    return;
330
 
  case SOUP_STATUS_NOT_FOUND: /* 404 */
331
 
    g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
332
 
                                     GRL_NET_WC_ERROR_NOT_FOUND,
333
 
                                     "The requested resource was not found: %s",
334
 
                                     response);
335
 
    return;
336
 
  case SOUP_STATUS_CONFLICT: /* 409 */
337
 
  case SOUP_STATUS_PRECONDITION_FAILED: /* 412 */
338
 
    g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
339
 
                                     GRL_NET_WC_ERROR_CONFLICT,
340
 
                                     "The entry has been modified since it was downloaded: %s",
341
 
                                     response);
342
 
    return;
343
 
  case SOUP_STATUS_CANCELLED:
344
 
    g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
345
 
                                     GRL_NET_WC_ERROR_CANCELLED,
346
 
                                     "Operation was cancelled");
347
 
    return;
348
 
  default:
349
 
    g_message ("Unhandled status: %s", soup_status_get_phrase (status));
350
 
  }
351
 
}
352
 
 
353
 
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
354
 
static void
355
 
read_async_cb (GObject *source, GAsyncResult *res, gpointer user_data)
356
 
{
357
 
  GSimpleAsyncResult *result;
358
 
  RequestResult *rr;
359
 
  SoupMessage *msg;
360
 
  GError *error = NULL;
361
 
  gsize to_read;
362
 
  gssize s;
363
 
 
364
 
  result = G_SIMPLE_ASYNC_RESULT (user_data);
365
 
  rr = g_simple_async_result_get_op_res_gpointer (result);
366
 
 
367
 
  s = g_input_stream_read_finish (G_INPUT_STREAM (source), res, &error);
368
 
  if (s > 0) {
369
 
    /* Continue reading */
370
 
    rr->offset += s;
371
 
    to_read = rr->length - rr->offset;
372
 
    if (!to_read) {
373
 
      /* Buffer is not enough; we need to assign more space */
374
 
      rr->length *= 2;
375
 
      rr->buffer = g_renew (gchar, rr->buffer, rr->length);
376
 
      to_read = rr->length - rr->offset;
377
 
    }
378
 
    g_input_stream_read_async (G_INPUT_STREAM (source), rr->buffer + rr->offset, to_read, G_PRIORITY_DEFAULT, NULL, read_async_cb, user_data);
379
 
    return;
380
 
  }
381
 
 
382
 
  /* Put the end of string */
383
 
  rr->buffer[rr->offset] = '\0';
384
 
 
385
 
  g_input_stream_close (G_INPUT_STREAM (source), NULL, NULL);
386
 
 
387
 
  if (error) {
388
 
    if (error->code == G_IO_ERROR_CANCELLED) {
389
 
      g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
390
 
                                       GRL_NET_WC_ERROR_CANCELLED,
391
 
                                       "Operation was cancelled");
392
 
    } else {
393
 
      g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
394
 
                                       GRL_NET_WC_ERROR_UNAVAILABLE,
395
 
                                       "Data not available");
396
 
    }
397
 
    g_error_free (error);
398
 
 
399
 
    g_simple_async_result_complete (result);
400
 
    g_object_unref (result);
401
 
    return;
402
 
  }
403
 
 
404
 
  msg = soup_request_http_get_message (SOUP_REQUEST_HTTP (rr->request));
405
 
 
406
 
  if (msg) {
407
 
    if (msg->status_code != SOUP_STATUS_OK) {
408
 
      parse_error (msg->status_code,
409
 
                   msg->reason_phrase,
410
 
                   msg->response_body->data,
411
 
                   G_SIMPLE_ASYNC_RESULT (user_data));
412
 
      g_object_unref (msg);
413
 
    }
414
 
  }
415
 
 
416
 
  g_simple_async_result_complete (result);
417
 
  g_object_unref (result);
418
 
}
419
 
 
420
 
static void
421
 
reply_cb (GObject *source, GAsyncResult *res, gpointer user_data)
422
 
{
423
 
  GSimpleAsyncResult *result = G_SIMPLE_ASYNC_RESULT (user_data);
424
 
  RequestResult *rr = g_simple_async_result_get_op_res_gpointer (result);
425
 
  GError *error = NULL;
426
 
 
427
 
  GInputStream *in = soup_request_send_finish (rr->request, res, &error);
428
 
 
429
 
  if (error != NULL) {
430
 
    g_simple_async_result_set_error (result, GRL_NET_WC_ERROR,
431
 
                                     GRL_NET_WC_ERROR_UNAVAILABLE,
432
 
                                     "Data not available");
433
 
    g_error_free (error);
434
 
 
435
 
    g_simple_async_result_complete (result);
436
 
    g_object_unref (result);
437
 
    return;
438
 
  }
439
 
 
440
 
  rr->length = soup_request_get_content_length (rr->request) + 1;
441
 
  if (rr->length == 1) {
442
 
    rr->length = BUFFER_SIZE;
443
 
  }
444
 
  rr->buffer = g_new (gchar, rr->length);
445
 
  g_input_stream_read_async (in, rr->buffer, rr->length, G_PRIORITY_DEFAULT, NULL, read_async_cb, user_data);
446
 
}
447
 
 
448
 
#else
449
 
 
450
 
static void
451
 
reply_cb (SoupSession *session,
452
 
          SoupMessage *msg,
453
 
          gpointer user_data)
454
 
{
455
 
  GSimpleAsyncResult *result;
456
 
  gulong cancel_signal;
457
 
 
458
 
  cancel_signal = GPOINTER_TO_UINT (g_object_get_data (G_OBJECT (msg),
459
 
                                                       "cancel-signal"));
460
 
  if (cancel_signal) {
461
 
    GCancellable *cancellable;
462
 
 
463
 
    cancellable = g_object_get_data (G_OBJECT (msg), "cancellable");
464
 
    g_signal_handler_disconnect (cancellable, cancel_signal);
465
 
  }
466
 
 
467
 
  result = G_SIMPLE_ASYNC_RESULT (user_data);
468
 
 
469
 
  if (msg->status_code != SOUP_STATUS_OK) {
470
 
    parse_error (msg->status_code,
471
 
                 msg->reason_phrase,
472
 
                 msg->response_body->data,
473
 
                 result);
474
 
  }
475
 
 
476
 
  g_simple_async_result_complete (result);
477
 
  g_object_unref (result);
478
 
}
479
 
 
480
 
static void
481
 
message_cancel_cb (GCancellable *cancellable,
482
 
                   SoupMessage *msg)
483
 
{
484
 
  if (msg)
485
 
    soup_session_cancel_message (g_object_get_data (G_OBJECT (msg), "session"),
486
 
                                 msg, SOUP_STATUS_CANCELLED);
487
 
 
488
 
}
489
 
#endif
490
 
 
491
 
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
492
 
static void
493
 
get_url_now (GrlNetWc *self,
494
 
             const char *url,
495
 
             GAsyncResult *result,
496
 
             GCancellable *cancellable)
497
 
{
498
 
  RequestResult *rr = g_slice_new0 (RequestResult);
499
 
 
500
 
  g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result),
501
 
                                             rr,
502
 
                                             NULL);
503
 
 
504
 
  rr->request = soup_requester_request (self->priv->requester, url, NULL);
505
 
 
506
 
  soup_request_send_async (rr->request, cancellable, reply_cb, result);
507
 
}
508
 
 
509
 
#else
510
 
 
511
 
static void
512
 
get_url_now (GrlNetWc *self,
513
 
             const char *url,
514
 
             GAsyncResult *result,
515
 
             GCancellable *cancellable)
516
 
{
517
 
  SoupMessage *msg;
518
 
  gulong cancel_signal;
519
 
 
520
 
  msg = soup_message_new (SOUP_METHOD_GET, url);
521
 
 
522
 
  if (!msg) {
523
 
    g_simple_async_result_set_error (G_SIMPLE_ASYNC_RESULT (result),
524
 
                                     GRL_NET_WC_ERROR,
525
 
                                     GRL_NET_WC_ERROR_PROTOCOL_ERROR,
526
 
                                     "Malformed URL: %s", url);
527
 
    g_simple_async_result_complete_in_idle (G_SIMPLE_ASYNC_RESULT (result));
528
 
    g_object_unref (result);
529
 
 
530
 
    return;
531
 
  }
532
 
 
533
 
  g_simple_async_result_set_op_res_gpointer (G_SIMPLE_ASYNC_RESULT (result),
534
 
                                             msg, NULL);
535
 
 
536
 
  cancel_signal = 0;
537
 
  if (cancellable) {
538
 
    g_object_set_data (G_OBJECT (msg),
539
 
                       "cancellable",
540
 
                       cancellable);
541
 
    cancel_signal = g_signal_connect (cancellable,
542
 
                                      "cancelled",
543
 
                                      G_CALLBACK (message_cancel_cb),
544
 
                                      msg);
545
 
  }
546
 
 
547
 
  g_object_set_data (G_OBJECT (msg),
548
 
                     "cancel-signal",
549
 
                     GUINT_TO_POINTER (cancel_signal));
550
 
  g_object_set_data_full (G_OBJECT (msg),
551
 
                          "session",
552
 
                          g_object_ref (self->priv->session),
553
 
                          g_object_unref);
554
 
 
555
 
  soup_session_queue_message (self->priv->session,
556
 
                              msg,
557
 
                              reply_cb,
558
 
                              result);
559
 
}
560
 
#endif
 
275
struct request_clos {
 
276
  GrlNetWc *self;
 
277
  char *url;
 
278
  GAsyncResult *result;
 
279
  GCancellable *cancellable;
 
280
  guint source_id;
 
281
};
561
282
 
562
283
static gboolean
563
284
get_url_delayed (gpointer user_data)
564
285
{
565
 
  RequestClosure *c, *d;
566
 
 
567
 
  c = (RequestClosure *) user_data;
568
 
  d = g_queue_pop_tail (c->self->priv->pending);
569
 
 
570
 
  g_assert (c == d);
571
 
 
572
 
  get_url_now (c->self,
573
 
               c->url,
574
 
               G_ASYNC_RESULT (c->result),
575
 
               c->cancellable);
 
286
  struct request_clos *c = (struct request_clos *) user_data;
 
287
 
 
288
  /* validation */
 
289
  {
 
290
    GrlNetWcPrivate *priv = c->self->priv;
 
291
    struct request_clos *d = g_queue_pop_tail (priv->pending);
 
292
    g_assert (c == d);
 
293
  }
 
294
 
 
295
  get_url_now (c->self, c->url, c->result, c->cancellable);
576
296
 
577
297
  g_free (c->url);
578
298
  g_free (c);
586
306
         GAsyncResult *result,
587
307
         GCancellable *cancellable)
588
308
{
 
309
  guint id;
589
310
  GTimeVal now;
590
 
 
 
311
  struct request_clos *c;
 
312
  GrlNetWcPrivate *priv = self->priv;
591
313
 
592
314
  g_get_current_time (&now);
593
 
  if (now.tv_sec - self->priv->last_request.tv_sec > self->priv->throttling) {
594
 
    get_url_now (self, url, G_ASYNC_RESULT (result), cancellable);
595
 
    g_get_current_time (&self->priv->last_request);
596
 
  } else {
597
 
    RequestClosure *c;
598
 
    guint id;
599
 
 
600
 
    GRL_DEBUG ("delaying web request");
601
 
 
602
 
    /* closure */
603
 
    c = g_new (RequestClosure, 1);
604
 
    c->self = self;
605
 
    c->url = g_strdup (url);
606
 
    c->result = result;
607
 
    c->cancellable = cancellable;
608
 
 
609
 
    self->priv->last_request.tv_sec += self->priv->throttling;
610
 
    id = g_timeout_add_seconds (self->priv->last_request.tv_sec - now.tv_sec,
611
 
                                get_url_delayed, c);
612
 
 
613
 
    c->source_id = id;
614
 
    g_queue_push_head (self->priv->pending, c);
615
 
  }
616
 
}
617
 
 
618
 
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
619
 
static void
620
 
update_cache_size ()
621
 
{
622
 
  guint size_in_bytes = cache_size * 1024 * 1024;
623
 
  soup_cache_set_max_size (cache, size_in_bytes);
624
 
}
625
 
 
626
 
static void
627
 
cache_down (GrlNetWc *self)
628
 
{
629
 
  soup_session_remove_feature (self->priv->session,
630
 
                               SOUP_SESSION_FEATURE (self->priv->cache));
631
 
  g_object_unref (self->priv->cache);
632
 
  self->priv->cache = NULL;
633
 
}
634
 
 
635
 
static void
636
 
cache_up (GrlNetWc *self)
637
 
{
638
 
  if (!cache) {
639
 
    gchar *cache_dir = g_build_filename (g_get_user_cache_dir (),
640
 
                                         g_get_prgname (),
641
 
                                         "grilo",
642
 
                                         NULL);
643
 
    cache = soup_cache_new (cache_dir, SOUP_CACHE_SINGLE_USER);
644
 
    update_cache_size ();
645
 
    g_free (cache_dir);
646
 
  }
647
 
 
648
 
  self->priv->cache = g_object_ref (cache);
649
 
  soup_session_add_feature (self->priv->session,
650
 
                            SOUP_SESSION_FEATURE (self->priv->cache));
651
 
}
652
 
#endif
 
315
 
 
316
  if ((now.tv_sec - priv->last_request.tv_sec) > priv->throttling) {
 
317
    get_url_now (self, url, result, cancellable);
 
318
    g_get_current_time (&priv->last_request);
 
319
 
 
320
    return;
 
321
  }
 
322
 
 
323
  GRL_DEBUG ("delaying web request");
 
324
 
 
325
  /* closure */
 
326
  c = g_new (struct request_clos, 1);
 
327
  c->self = self;
 
328
  c->url = g_strdup (url);
 
329
  c->result = result;
 
330
  c->cancellable = cancellable;
 
331
 
 
332
  priv->last_request.tv_sec += priv->throttling;
 
333
  id = g_timeout_add_seconds (priv->last_request.tv_sec - now.tv_sec,
 
334
                              get_url_delayed, c);
 
335
  c->source_id = id;
 
336
 
 
337
  g_queue_push_head (self->priv->pending, c);
 
338
}
653
339
 
654
340
/**
655
341
 * grl_net_wc_new:
725
411
  g_warn_if_fail (g_simple_async_result_get_source_tag (res) ==
726
412
                  grl_net_wc_request_async);
727
413
 
 
414
  void *op = g_simple_async_result_get_op_res_gpointer (res);
 
415
 
728
416
  if (g_simple_async_result_propagate_error (res, error) == TRUE) {
729
417
    ret = FALSE;
730
418
    goto end_func;
731
419
  }
732
420
 
733
 
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
734
 
  RequestResult *rr = g_simple_async_result_get_op_res_gpointer (res);
735
 
 
736
 
  if (self->priv->previous_data) {
737
 
    g_free (self->priv->previous_data);
738
 
  }
739
 
 
740
 
  self->priv->previous_data = rr->buffer;
741
 
 
742
 
  if (content) {
743
 
    *content = self->priv->previous_data;
744
 
  } else {
745
 
    g_free (rr->buffer);
746
 
  }
747
 
 
748
 
  if (length) {
749
 
    *length = rr->offset;
750
 
  }
751
 
 
752
 
  g_object_unref (rr->request);
753
 
  g_slice_free (RequestResult, rr);
754
 
 
755
 
#else
756
 
  SoupMessage *msg = (SoupMessage *) g_simple_async_result_get_op_res_gpointer (res);
757
 
 
758
 
  if (content != NULL)
759
 
    *content = (gchar *) msg->response_body->data;
760
 
  if (length != NULL)
761
 
    *length = (gsize) msg->response_body->length;
762
 
#endif
 
421
  get_content(self, op, content, length);
763
422
 
764
423
end_func:
 
424
  free_op_res (op);
 
425
 
765
426
  return ret;
766
427
}
767
428
 
838
499
{
839
500
  g_return_if_fail (GRL_IS_NET_WC (self));
840
501
 
841
 
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
842
 
  if (use_cache) {
843
 
    if (self->priv->cache) {
844
 
      return;
845
 
    }
846
 
 
 
502
  if (use_cache)
847
503
    cache_up (self);
848
 
 
849
 
  } else {
850
 
    if (self->priv->cache) {
851
 
      cache_down (self);
852
 
    }
853
 
  }
854
 
#else
855
 
  GRL_WARNING ("Cache not supported");
856
 
#endif
 
504
  else
 
505
    cache_down (self);
857
506
}
858
507
 
859
508
/**
872
521
{
873
522
  g_return_if_fail (GRL_IS_NET_WC (self));
874
523
 
875
 
  if (self->priv->cache_size == size) {
876
 
    return;
877
 
  }
878
 
 
879
 
  /* Change the global cache size */
880
 
  cache_size -= self->priv->cache_size;
881
 
  self->priv->cache_size = size;
882
 
  cache_size += self->priv->cache_size;
883
 
 
884
 
#ifdef LIBSOUP_USE_UNSTABLE_REQUEST_API
885
 
  if (self->priv->cache) {
886
 
    update_cache_size ();
887
 
  }
888
 
#endif
 
524
  cache_set_size (self, size);
889
525
}
890
526
 
891
527
/**
897
533
void
898
534
grl_net_wc_flush_delayed_requests (GrlNetWc *self)
899
535
{
900
 
  RequestClosure *c;
901
 
 
902
 
  while ((c = g_queue_pop_head (self->priv->pending))) {
 
536
  g_return_if_fail (GRL_IS_NET_WC (self));
 
537
 
 
538
  GrlNetWcPrivate *priv = self->priv;
 
539
  struct request_clos *c;
 
540
 
 
541
  while ((c = g_queue_pop_head (priv->pending))) {
903
542
    g_source_remove (c->source_id);
904
543
    g_object_unref (c->cancellable);
905
544
    g_free (c->url);
906
545
    g_free (c);
907
546
  }
908
547
 
909
 
  g_get_current_time (&self->priv->last_request);
 
548
  g_get_current_time (&priv->last_request);
910
549
}