~ubuntu-branches/ubuntu/precise/telepathy-glib/precise

« back to all changes in this revision

Viewing changes to telepathy-glib/channel.c

  • Committer: Bazaar Package Importer
  • Author(s): Adam Conrad
  • Date: 2011-06-22 16:29:01 UTC
  • mfrom: (1.6.28 upstream)
  • Revision ID: james.westby@ubuntu.com-20110622162901-tc492ifcn229lmkh
Tags: 0.15.2-2
Cherry-pick upstream fix to increase timeout of the contact-lists
test on slower architectures like armel, mips, and mipsel.

Show diffs side-by-side

added added

removed removed

Lines of Context:
100
100
  PROP_REQUESTED,
101
101
  PROP_INITIATOR_HANDLE,
102
102
  PROP_INITIATOR_IDENTIFIER,
 
103
  PROP_PASSWORD_NEEDED,
103
104
  N_PROPS
104
105
};
105
106
 
450
451
    case PROP_INITIATOR_IDENTIFIER:
451
452
      g_value_set_string (value, tp_channel_get_initiator_identifier (self));
452
453
      break;
 
454
    case PROP_PASSWORD_NEEDED:
 
455
      g_value_set_boolean (value, tp_channel_password_needed (self));
 
456
      break;
453
457
    default:
454
458
      G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
455
459
      break;
1337
1341
  ((GObjectClass *) tp_channel_parent_class)->finalize (object);
1338
1342
}
1339
1343
 
 
1344
static void
 
1345
got_password_flags_cb (TpChannel *self,
 
1346
    guint password_flags,
 
1347
    const GError *error,
 
1348
    gpointer user_data,
 
1349
    GObject *weak_object)
 
1350
{
 
1351
  GSimpleAsyncResult *result = user_data;
 
1352
 
 
1353
  if (error != NULL)
 
1354
    {
 
1355
      DEBUG ("Failed to get password flags: %s", error->message);
 
1356
    }
 
1357
  else
 
1358
    {
 
1359
      self->priv->password_flags = password_flags;
 
1360
 
 
1361
      if (tp_channel_password_needed (self))
 
1362
        {
 
1363
          /* password-needed is FALSE by default */
 
1364
          g_object_notify (G_OBJECT (self), "password-needed");
 
1365
        }
 
1366
    }
 
1367
 
 
1368
  g_simple_async_result_complete (result);
 
1369
}
 
1370
 
 
1371
static void
 
1372
password_flags_changed_cb (TpChannel *self,
 
1373
    guint added,
 
1374
    guint removed,
 
1375
    gpointer user_data,
 
1376
    GObject *weak_object)
 
1377
{
 
1378
  gboolean was_needed, needed;
 
1379
 
 
1380
  was_needed = tp_channel_password_needed (self);
 
1381
 
 
1382
  self->priv->password_flags |= added;
 
1383
  self->priv->password_flags ^= removed;
 
1384
 
 
1385
  needed = tp_channel_password_needed (self);
 
1386
 
 
1387
  if (was_needed != needed)
 
1388
    g_object_notify (G_OBJECT (self), "password-needed");
 
1389
}
 
1390
 
 
1391
static void
 
1392
tp_channel_prepare_password_async (TpProxy *proxy,
 
1393
    const TpProxyFeature *feature,
 
1394
    GAsyncReadyCallback callback,
 
1395
    gpointer user_data)
 
1396
{
 
1397
  TpChannel *self = (TpChannel *) proxy;
 
1398
  GSimpleAsyncResult *result;
 
1399
 
 
1400
  result = g_simple_async_result_new ((GObject *) proxy, callback, user_data,
 
1401
      tp_channel_prepare_password_async);
 
1402
 
 
1403
  tp_cli_channel_interface_password_connect_to_password_flags_changed (self,
 
1404
      password_flags_changed_cb, self, NULL, G_OBJECT (self), NULL);
 
1405
 
 
1406
  tp_cli_channel_interface_password_call_get_password_flags (self, -1,
 
1407
      got_password_flags_cb, result, g_object_unref, G_OBJECT (self));
 
1408
}
 
1409
 
 
1410
 
1340
1411
enum {
1341
1412
    FEAT_CORE,
1342
1413
    FEAT_GROUP,
1343
1414
    FEAT_CHAT_STATES,
 
1415
    FEAT_PASSWORD,
1344
1416
    N_FEAT
1345
1417
};
1346
1418
 
1349
1421
{
1350
1422
  static TpProxyFeature features[N_FEAT + 1] = { { 0 } };
1351
1423
  static GQuark need_chat_states[2] = {0, 0};
 
1424
  static GQuark need_password[2] = {0, 0};
1352
1425
 
1353
1426
  if (G_LIKELY (features[0].name != 0))
1354
1427
    return features;
1364
1437
  need_chat_states[0] = TP_IFACE_QUARK_CHANNEL_INTERFACE_CHAT_STATE;
1365
1438
  features[FEAT_CHAT_STATES].interfaces_needed = need_chat_states;
1366
1439
 
 
1440
  features[FEAT_PASSWORD].name = TP_CHANNEL_FEATURE_PASSWORD;
 
1441
  features[FEAT_PASSWORD].prepare_async =
 
1442
    tp_channel_prepare_password_async;
 
1443
  need_password[0] = TP_IFACE_QUARK_CHANNEL_INTERFACE_PASSWORD;
 
1444
  features[FEAT_PASSWORD].interfaces_needed = need_password;
 
1445
 
1367
1446
  /* assert that the terminator at the end is there */
1368
1447
  g_assert (features[N_FEAT].name == 0);
1369
1448
 
1602
1681
      param_spec);
1603
1682
 
1604
1683
  /**
 
1684
   * TpChannel:password-needed:
 
1685
   *
 
1686
   * If %TRUE, tp_channel_provide_password_async() has to be called
 
1687
   * to be able to join the channel.
 
1688
   *
 
1689
   * This is not guaranteed to be meaningful until tp_proxy_prepare_async() has
 
1690
   * finished preparing %TP_CHANNEL_FEATURE_PASSWORD; until then, it may return
 
1691
   * %FALSE even if the channel is actually protected by a password.
 
1692
   * Preparing %TP_CHANNEL_FEATURE_PASSWORD also ensures that the
 
1693
   * notify::password-needed signal will be fired when this property changes.
 
1694
   *
 
1695
   * Since: 0.15.2
 
1696
   */
 
1697
  param_spec = g_param_spec_boolean ("password-needed",
 
1698
      "Password needed",
 
1699
      "Password neede to join the channel",
 
1700
      FALSE,
 
1701
      G_PARAM_READABLE | G_PARAM_STATIC_STRINGS);
 
1702
  g_object_class_install_property (object_class, PROP_PASSWORD_NEEDED,
 
1703
      param_spec);
 
1704
 
 
1705
  /**
1605
1706
   * TpChannel::group-flags-changed:
1606
1707
   * @self: a channel
1607
1708
   * @added: #TpChannelGroupFlags which are newly set
2141
2242
{
2142
2243
  GSimpleAsyncResult *result = user_data;
2143
2244
 
2144
 
  if (error != NULL)
 
2245
  if (tp_proxy_get_invalidated (channel) != NULL &&
 
2246
      error != NULL)
2145
2247
    {
2146
 
      DEBUG ("RemoveMembersWithDetails() with self handle failed: %s",
2147
 
          error->message);
2148
 
 
2149
 
      if (tp_proxy_get_invalidated (channel) != NULL)
2150
 
        {
2151
 
          DEBUG ("Proxy has been invalidated; succeed");
2152
 
          goto succeed;
2153
 
        }
2154
 
 
2155
 
      DEBUG ("Close channel then");
 
2248
      DEBUG ("RemoveMembersWithDetails() with self handle failed; call Close()"
 
2249
          " %s", error->message);
2156
2250
 
2157
2251
      tp_cli_channel_call_close (channel, -1, channel_close_cb, result,
2158
2252
          NULL, NULL);
2159
2253
      return;
2160
2254
    }
2161
2255
 
2162
 
 DEBUG ("RemoveMembersWithDetails() succeeded");
2163
 
 
2164
 
succeed:
2165
2256
  g_simple_async_result_complete (result);
2166
2257
  g_object_unref (result);
2167
2258
}
2382
2473
{
2383
2474
  _tp_implement_finish_void (self, tp_channel_close_async)
2384
2475
}
 
2476
 
 
2477
static void
 
2478
channel_destroy_cb (TpChannel *channel,
 
2479
    const GError *error,
 
2480
    gpointer user_data,
 
2481
    GObject *weak_object)
 
2482
{
 
2483
  GSimpleAsyncResult *result = user_data;
 
2484
 
 
2485
  if (tp_proxy_get_invalidated (channel) == NULL &&
 
2486
      error != NULL)
 
2487
    {
 
2488
      DEBUG ("Destroy() failed; call Close(): %s", error->message);
 
2489
 
 
2490
      tp_cli_channel_call_close (channel, -1, channel_close_cb, result,
 
2491
          NULL, NULL);
 
2492
      return;
 
2493
    }
 
2494
 
 
2495
  g_simple_async_result_complete (result);
 
2496
  g_object_unref (result);
 
2497
}
 
2498
 
 
2499
/**
 
2500
 * tp_channel_destroy_async:
 
2501
 * @self: a #TpChannel
 
2502
 * @callback: a callback to call when we left the channel
 
2503
 * @user_data: data to pass to @callback
 
2504
 *
 
2505
 * Destroy channel @self.
 
2506
 * If @self doesn't implement #TP_IFACE_QUARK_CHANNEL_INTERFACE_DESTROYABLE
 
2507
 * or if for any reason we can't destroy the channel, we close it.
 
2508
 *
 
2509
 * When the channel has been destroyed or closed, @callback will be called.
 
2510
 * You can then call tp_channel_destroy_finish() to get the result of
 
2511
 * the operation.
 
2512
 *
 
2513
 * Since: 0.15.2
 
2514
 */
 
2515
void
 
2516
tp_channel_destroy_async (TpChannel *self,
 
2517
    GAsyncReadyCallback callback,
 
2518
    gpointer user_data)
 
2519
{
 
2520
  GSimpleAsyncResult *result;
 
2521
 
 
2522
  g_return_if_fail (TP_IS_CHANNEL (self));
 
2523
 
 
2524
  result = g_simple_async_result_new (G_OBJECT (self), callback,
 
2525
      user_data, tp_channel_destroy_async);
 
2526
 
 
2527
  if (tp_proxy_is_prepared (self, TP_CHANNEL_FEATURE_CORE) &&
 
2528
      !tp_proxy_has_interface_by_id (self,
 
2529
        TP_IFACE_QUARK_CHANNEL_INTERFACE_DESTROYABLE))
 
2530
    {
 
2531
      DEBUG ("Channel doesn't implement Destroy; fallback to Close()");
 
2532
 
 
2533
      tp_cli_channel_call_close (self, -1, channel_close_cb, result,
 
2534
          NULL, NULL);
 
2535
      return;
 
2536
    }
 
2537
 
 
2538
  tp_cli_channel_interface_destroyable_call_destroy (self, -1,
 
2539
      channel_destroy_cb, result, NULL, NULL);
 
2540
}
 
2541
 
 
2542
/**
 
2543
 * tp_channel_destroy_finish:
 
2544
 * @self: a #TpChannel
 
2545
 * @result: a #GAsyncResult
 
2546
 * @error: a #GError to fill
 
2547
 *
 
2548
 * Finishes to leave a channel.
 
2549
 *
 
2550
 * Returns: %TRUE if the channel has been destroyed or closed; %FALSE otherwise
 
2551
 *
 
2552
 * Since: 0.15.2
 
2553
 */
 
2554
gboolean
 
2555
tp_channel_destroy_finish (TpChannel *self,
 
2556
    GAsyncResult *result,
 
2557
    GError **error)
 
2558
{
 
2559
  _tp_implement_finish_void (self, tp_channel_destroy_async)
 
2560
}
 
2561
 
 
2562
/**
 
2563
 * TP_CHANNEL_FEATURE_PASSWORD:
 
2564
 *
 
2565
 * Expands to a call to a function that returns a quark representing the
 
2566
 * password feature on a #TpChannel.
 
2567
 *
 
2568
 * When this feature is prepared, tp_channel_password_needed() and the
 
2569
 * #TpChannel:password-needed property become useful.
 
2570
 *
 
2571
 * One can ask for a feature to be prepared using the
 
2572
 * tp_proxy_prepare_async() function, and waiting for it to callback.
 
2573
 *
 
2574
 * Since: 0.15.2
 
2575
 */
 
2576
 
 
2577
GQuark
 
2578
tp_channel_get_feature_quark_password (void)
 
2579
{
 
2580
  return g_quark_from_static_string ("tp-channel-feature-password");
 
2581
}
 
2582
 
 
2583
/**
 
2584
 * tp_channel_password_needed:
 
2585
 * @self: a #TpChannel
 
2586
 *
 
2587
 * Return the #TpChannel:password-needed property
 
2588
 *
 
2589
 * Returns: the value of #TpChannel:password-needed
 
2590
 *
 
2591
 * Since: 0.15.2
 
2592
 */
 
2593
gboolean
 
2594
tp_channel_password_needed (TpChannel *self)
 
2595
{
 
2596
  return self->priv->password_flags & TP_CHANNEL_PASSWORD_FLAG_PROVIDE;
 
2597
}
 
2598
 
 
2599
static void
 
2600
provide_password_cb (TpChannel *self,
 
2601
    gboolean correct,
 
2602
    const GError *error,
 
2603
    gpointer user_data,
 
2604
    GObject *weak_object)
 
2605
{
 
2606
  GSimpleAsyncResult *result = user_data;
 
2607
 
 
2608
  if (error != NULL)
 
2609
    {
 
2610
      g_simple_async_result_set_from_error (result, error);
 
2611
    }
 
2612
  else if (!correct)
 
2613
    {
 
2614
      DEBUG ("Wrong password provided for %s", tp_proxy_get_object_path (self));
 
2615
 
 
2616
      g_simple_async_result_set_error (result, TP_ERRORS,
 
2617
          TP_ERROR_AUTHENTICATION_FAILED, "Password was not correct");
 
2618
    }
 
2619
 
 
2620
  g_simple_async_result_complete (result);
 
2621
}
 
2622
 
 
2623
/**
 
2624
 * tp_channel_provide_password_async:
 
2625
 * @self: a #TpChannel
 
2626
 * @password: the password
 
2627
 * @callback: a callback to call when @password has been provided
 
2628
 * @user_data: data to pass to @callback
 
2629
 *
 
2630
 * Provide @password so that @self can be joined.
 
2631
 * This function must be called with the correct password in order for
 
2632
 * channel joining to proceed if the TpChannel:password-needed property
 
2633
 * is set.
 
2634
 *
 
2635
 * Once the password has been provided, @callback will be
 
2636
 * called. You can then call tp_channel_provide_password_finish()
 
2637
 * to get the result of the operation.
 
2638
 *
 
2639
 * Since: 0.15.2
 
2640
 */
 
2641
void
 
2642
tp_channel_provide_password_async (TpChannel *self,
 
2643
    const gchar *password,
 
2644
    GAsyncReadyCallback callback,
 
2645
    gpointer user_data)
 
2646
{
 
2647
  GSimpleAsyncResult *result;
 
2648
 
 
2649
  g_return_if_fail (TP_IS_CHANNEL (self));
 
2650
 
 
2651
  result = g_simple_async_result_new (G_OBJECT (self), callback,
 
2652
      user_data, tp_channel_provide_password_async);
 
2653
 
 
2654
  tp_cli_channel_interface_password_call_provide_password (self, -1, password,
 
2655
      provide_password_cb, result, g_object_unref, G_OBJECT (self));
 
2656
}
 
2657
 
 
2658
/**
 
2659
 * tp_channel_provide_password_finish:
 
2660
 * @self: a #TpChannel
 
2661
 * @result: a #GAsyncResult
 
2662
 * @error: a #GError to fill
 
2663
 *
 
2664
 * Finishes to provide a password. If the password was rejected, the operation
 
2665
 * fails with #TP_ERROR_AUTHENTICATION_FAILED.
 
2666
 *
 
2667
 * Returns: %TRUE if the password has been provided and accepted,
 
2668
 * %FALSE otherwise.
 
2669
 *
 
2670
 * Since: 0.15.2
 
2671
 */
 
2672
gboolean
 
2673
tp_channel_provide_password_finish (TpChannel *self,
 
2674
    GAsyncResult *result,
 
2675
    GError **error)
 
2676
{
 
2677
  _tp_implement_finish_void (self, tp_channel_provide_password_async);
 
2678
}