Coverage Report

Created: 2018-09-25 14:53

/src/mozilla-central/security/sandbox/chromium/base/bind_internal.h
Line
Count
Source (jump to first uncovered line)
1
// Copyright (c) 2011 The Chromium Authors. All rights reserved.
2
// Use of this source code is governed by a BSD-style license that can be
3
// found in the LICENSE file.
4
5
#ifndef BASE_BIND_INTERNAL_H_
6
#define BASE_BIND_INTERNAL_H_
7
8
#include <stddef.h>
9
10
#include <tuple>
11
#include <type_traits>
12
13
#include "base/bind_helpers.h"
14
#include "base/callback_internal.h"
15
#include "base/memory/raw_scoped_refptr_mismatch_checker.h"
16
#include "base/memory/weak_ptr.h"
17
#include "base/template_util.h"
18
#include "base/tuple.h"
19
#include "build/build_config.h"
20
21
namespace base {
22
namespace internal {
23
24
// See base/callback.h for user documentation.
25
//
26
//
27
// CONCEPTS:
28
//  Functor -- A movable type representing something that should be called.
29
//             All function pointers and Callback<> are functors even if the
30
//             invocation syntax differs.
31
//  RunType -- A function type (as opposed to function _pointer_ type) for
32
//             a Callback<>::Run().  Usually just a convenience typedef.
33
//  (Bound)Args -- A set of types that stores the arguments.
34
//
35
// Types:
36
//  ForceVoidReturn<> -- Helper class for translating function signatures to
37
//                       equivalent forms with a "void" return type.
38
//  FunctorTraits<> -- Type traits used to determine the correct RunType and
39
//                     invocation manner for a Functor.  This is where function
40
//                     signature adapters are applied.
41
//  InvokeHelper<> -- Take a Functor + arguments and actully invokes it.
42
//                    Handle the differing syntaxes needed for WeakPtr<>
43
//                    support.  This is separate from Invoker to avoid creating
44
//                    multiple version of Invoker<>.
45
//  Invoker<> -- Unwraps the curried parameters and executes the Functor.
46
//  BindState<> -- Stores the curried parameters, and is the main entry point
47
//                 into the Bind() system.
48
49
template <typename Callable,
50
          typename Signature = decltype(&Callable::operator())>
51
struct ExtractCallableRunTypeImpl;
52
53
template <typename Callable, typename R, typename... Args>
54
struct ExtractCallableRunTypeImpl<Callable, R(Callable::*)(Args...) const> {
55
  using Type = R(Args...);
56
};
57
58
// Evaluated to RunType of the given callable type.
59
// Example:
60
//   auto f = [](int, char*) { return 0.1; };
61
//   ExtractCallableRunType<decltype(f)>
62
//   is evaluated to
63
//   double(int, char*);
64
template <typename Callable>
65
using ExtractCallableRunType =
66
    typename ExtractCallableRunTypeImpl<Callable>::Type;
67
68
// IsConvertibleToRunType<Functor> is std::true_type if |Functor| has operator()
69
// and convertible to the corresponding function pointer. Otherwise, it's
70
// std::false_type.
71
// Example:
72
//   IsConvertibleToRunType<void(*)()>::value is false.
73
//
74
//   struct Foo {};
75
//   IsConvertibleToRunType<void(Foo::*)()>::value is false.
76
//
77
//   auto f = []() {};
78
//   IsConvertibleToRunType<decltype(f)>::value is true.
79
//
80
//   int i = 0;
81
//   auto g = [i]() {};
82
//   IsConvertibleToRunType<decltype(g)>::value is false.
83
template <typename Functor, typename SFINAE = void>
84
struct IsConvertibleToRunType : std::false_type {};
85
86
template <typename Callable>
87
struct IsConvertibleToRunType<Callable, void_t<decltype(&Callable::operator())>>
88
    : std::is_convertible<Callable, ExtractCallableRunType<Callable>*> {};
89
90
// HasRefCountedTypeAsRawPtr selects true_type when any of the |Args| is a raw
91
// pointer to a RefCounted type.
92
// Implementation note: This non-specialized case handles zero-arity case only.
93
// Non-zero-arity cases should be handled by the specialization below.
94
template <typename... Args>
95
struct HasRefCountedTypeAsRawPtr : std::false_type {};
96
97
// Implementation note: Select true_type if the first parameter is a raw pointer
98
// to a RefCounted type. Otherwise, skip the first parameter and check rest of
99
// parameters recursively.
100
template <typename T, typename... Args>
101
struct HasRefCountedTypeAsRawPtr<T, Args...>
102
    : std::conditional<NeedsScopedRefptrButGetsRawPtr<T>::value,
103
                       std::true_type,
104
                       HasRefCountedTypeAsRawPtr<Args...>>::type {};
105
106
// ForceVoidReturn<>
107
//
108
// Set of templates that support forcing the function return type to void.
109
template <typename Sig>
110
struct ForceVoidReturn;
111
112
template <typename R, typename... Args>
113
struct ForceVoidReturn<R(Args...)> {
114
  using RunType = void(Args...);
115
};
116
117
// FunctorTraits<>
118
//
119
// See description at top of file.
120
template <typename Functor, typename SFINAE>
121
struct FunctorTraits;
122
123
// For a callable type that is convertible to the corresponding function type.
124
// This specialization is intended to allow binding captureless lambdas by
125
// base::Bind(), based on the fact that captureless lambdas can be convertible
126
// to the function type while capturing lambdas can't.
127
template <typename Functor>
128
struct FunctorTraits<
129
    Functor,
130
    typename std::enable_if<IsConvertibleToRunType<Functor>::value>::type> {
131
  using RunType = ExtractCallableRunType<Functor>;
132
  static constexpr bool is_method = false;
133
  static constexpr bool is_nullable = false;
134
135
  template <typename... RunArgs>
136
  static ExtractReturnType<RunType>
137
  Invoke(const Functor& functor, RunArgs&&... args) {
138
    return functor(std::forward<RunArgs>(args)...);
139
  }
140
};
141
142
// For functions.
143
template <typename R, typename... Args>
144
struct FunctorTraits<R (*)(Args...)> {
145
  using RunType = R(Args...);
146
  static constexpr bool is_method = false;
147
  static constexpr bool is_nullable = true;
148
149
  template <typename... RunArgs>
150
0
  static R Invoke(R (*function)(Args...), RunArgs&&... args) {
151
0
    return function(std::forward<RunArgs>(args)...);
152
0
  }
153
};
154
155
#if defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
156
157
// For functions.
158
template <typename R, typename... Args>
159
struct FunctorTraits<R(__stdcall*)(Args...)> {
160
  using RunType = R(Args...);
161
  static constexpr bool is_method = false;
162
  static constexpr bool is_nullable = true;
163
164
  template <typename... RunArgs>
165
  static R Invoke(R(__stdcall* function)(Args...), RunArgs&&... args) {
166
    return function(std::forward<RunArgs>(args)...);
167
  }
168
};
169
170
// For functions.
171
template <typename R, typename... Args>
172
struct FunctorTraits<R(__fastcall*)(Args...)> {
173
  using RunType = R(Args...);
174
  static constexpr bool is_method = false;
175
  static constexpr bool is_nullable = true;
176
177
  template <typename... RunArgs>
178
  static R Invoke(R(__fastcall* function)(Args...), RunArgs&&... args) {
179
    return function(std::forward<RunArgs>(args)...);
180
  }
181
};
182
183
#endif  // defined(OS_WIN) && !defined(ARCH_CPU_X86_64)
184
185
// For methods.
186
template <typename R, typename Receiver, typename... Args>
187
struct FunctorTraits<R (Receiver::*)(Args...)> {
188
  using RunType = R(Receiver*, Args...);
189
  static constexpr bool is_method = true;
190
  static constexpr bool is_nullable = true;
191
192
  template <typename ReceiverPtr, typename... RunArgs>
193
  static R Invoke(R (Receiver::*method)(Args...),
194
                  ReceiverPtr&& receiver_ptr,
195
                  RunArgs&&... args) {
196
    return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
197
  }
198
};
199
200
// For const methods.
201
template <typename R, typename Receiver, typename... Args>
202
struct FunctorTraits<R (Receiver::*)(Args...) const> {
203
  using RunType = R(const Receiver*, Args...);
204
  static constexpr bool is_method = true;
205
  static constexpr bool is_nullable = true;
206
207
  template <typename ReceiverPtr, typename... RunArgs>
208
  static R Invoke(R (Receiver::*method)(Args...) const,
209
                  ReceiverPtr&& receiver_ptr,
210
                  RunArgs&&... args) {
211
    return ((*receiver_ptr).*method)(std::forward<RunArgs>(args)...);
212
  }
213
};
214
215
// For IgnoreResults.
216
template <typename T>
217
struct FunctorTraits<IgnoreResultHelper<T>> : FunctorTraits<T> {
218
  using RunType =
219
      typename ForceVoidReturn<typename FunctorTraits<T>::RunType>::RunType;
220
221
  template <typename IgnoreResultType, typename... RunArgs>
222
  static void Invoke(IgnoreResultType&& ignore_result_helper,
223
                     RunArgs&&... args) {
224
    FunctorTraits<T>::Invoke(
225
        std::forward<IgnoreResultType>(ignore_result_helper).functor_,
226
        std::forward<RunArgs>(args)...);
227
  }
228
};
229
230
// For OnceCallbacks.
231
template <typename R, typename... Args>
232
struct FunctorTraits<OnceCallback<R(Args...)>> {
233
  using RunType = R(Args...);
234
  static constexpr bool is_method = false;
235
  static constexpr bool is_nullable = true;
236
237
  template <typename CallbackType, typename... RunArgs>
238
  static R Invoke(CallbackType&& callback, RunArgs&&... args) {
239
    DCHECK(!callback.is_null());
240
    return std::forward<CallbackType>(callback).Run(
241
        std::forward<RunArgs>(args)...);
242
  }
243
};
244
245
// For RepeatingCallbacks.
246
template <typename R, typename... Args>
247
struct FunctorTraits<RepeatingCallback<R(Args...)>> {
248
  using RunType = R(Args...);
249
  static constexpr bool is_method = false;
250
  static constexpr bool is_nullable = true;
251
252
  template <typename CallbackType, typename... RunArgs>
253
  static R Invoke(CallbackType&& callback, RunArgs&&... args) {
254
    DCHECK(!callback.is_null());
255
    return std::forward<CallbackType>(callback).Run(
256
        std::forward<RunArgs>(args)...);
257
  }
258
};
259
260
template <typename Functor>
261
using MakeFunctorTraits = FunctorTraits<typename std::decay<Functor>::type>;
262
263
// InvokeHelper<>
264
//
265
// There are 2 logical InvokeHelper<> specializations: normal, WeakCalls.
266
//
267
// The normal type just calls the underlying runnable.
268
//
269
// WeakCalls need special syntax that is applied to the first argument to check
270
// if they should no-op themselves.
271
template <bool is_weak_call, typename ReturnType>
272
struct InvokeHelper;
273
274
template <typename ReturnType>
275
struct InvokeHelper<false, ReturnType> {
276
  template <typename Functor, typename... RunArgs>
277
0
  static inline ReturnType MakeItSo(Functor&& functor, RunArgs&&... args) {
278
0
    using Traits = MakeFunctorTraits<Functor>;
279
0
    return Traits::Invoke(std::forward<Functor>(functor),
280
0
                          std::forward<RunArgs>(args)...);
281
0
  }
282
};
283
284
template <typename ReturnType>
285
struct InvokeHelper<true, ReturnType> {
286
  // WeakCalls are only supported for functions with a void return type.
287
  // Otherwise, the function result would be undefined if the the WeakPtr<>
288
  // is invalidated.
289
  static_assert(std::is_void<ReturnType>::value,
290
                "weak_ptrs can only bind to methods without return values");
291
292
  template <typename Functor, typename BoundWeakPtr, typename... RunArgs>
293
  static inline void MakeItSo(Functor&& functor,
294
                              BoundWeakPtr&& weak_ptr,
295
                              RunArgs&&... args) {
296
    if (!weak_ptr)
297
      return;
298
    using Traits = MakeFunctorTraits<Functor>;
299
    Traits::Invoke(std::forward<Functor>(functor),
300
                   std::forward<BoundWeakPtr>(weak_ptr),
301
                   std::forward<RunArgs>(args)...);
302
  }
303
};
304
305
// Invoker<>
306
//
307
// See description at the top of the file.
308
template <typename StorageType, typename UnboundRunType>
309
struct Invoker;
310
311
template <typename StorageType, typename R, typename... UnboundArgs>
312
struct Invoker<StorageType, R(UnboundArgs...)> {
313
  static R RunOnce(BindStateBase* base, UnboundArgs&&... unbound_args) {
314
    // Local references to make debugger stepping easier. If in a debugger,
315
    // you really want to warp ahead and step through the
316
    // InvokeHelper<>::MakeItSo() call below.
317
    StorageType* storage = static_cast<StorageType*>(base);
318
    static constexpr size_t num_bound_args =
319
        std::tuple_size<decltype(storage->bound_args_)>::value;
320
    return RunImpl(std::move(storage->functor_),
321
                   std::move(storage->bound_args_),
322
                   MakeIndexSequence<num_bound_args>(),
323
                   std::forward<UnboundArgs>(unbound_args)...);
324
  }
325
326
0
  static R Run(BindStateBase* base, UnboundArgs&&... unbound_args) {
327
0
    // Local references to make debugger stepping easier. If in a debugger,
328
0
    // you really want to warp ahead and step through the
329
0
    // InvokeHelper<>::MakeItSo() call below.
330
0
    const StorageType* storage = static_cast<StorageType*>(base);
331
0
    static constexpr size_t num_bound_args =
332
0
        std::tuple_size<decltype(storage->bound_args_)>::value;
333
0
    return RunImpl(storage->functor_, storage->bound_args_,
334
0
                   MakeIndexSequence<num_bound_args>(),
335
0
                   std::forward<UnboundArgs>(unbound_args)...);
336
0
  }
337
338
 private:
339
  template <typename Functor, typename BoundArgsTuple, size_t... indices>
340
  static inline R RunImpl(Functor&& functor,
341
                          BoundArgsTuple&& bound,
342
                          IndexSequence<indices...>,
343
0
                          UnboundArgs&&... unbound_args) {
344
0
    static constexpr bool is_method = MakeFunctorTraits<Functor>::is_method;
345
0
346
0
    using DecayedArgsTuple = typename std::decay<BoundArgsTuple>::type;
347
0
    static constexpr bool is_weak_call =
348
0
        IsWeakMethod<is_method,
349
0
                     typename std::tuple_element<
350
0
                         indices,
351
0
                         DecayedArgsTuple>::type...>::value;
352
0
353
0
    return InvokeHelper<is_weak_call, R>::MakeItSo(
354
0
        std::forward<Functor>(functor),
355
0
        Unwrap(std::get<indices>(std::forward<BoundArgsTuple>(bound)))...,
356
0
        std::forward<UnboundArgs>(unbound_args)...);
357
0
  }
358
};
359
360
// Extracts necessary type info from Functor and BoundArgs.
361
// Used to implement MakeUnboundRunType, BindOnce and BindRepeating.
362
template <typename Functor, typename... BoundArgs>
363
struct BindTypeHelper {
364
  static constexpr size_t num_bounds = sizeof...(BoundArgs);
365
  using FunctorTraits = MakeFunctorTraits<Functor>;
366
367
  // Example:
368
  //   When Functor is `double (Foo::*)(int, const std::string&)`, and BoundArgs
369
  //   is a template pack of `Foo*` and `int16_t`:
370
  //    - RunType is `double(Foo*, int, const std::string&)`,
371
  //    - ReturnType is `double`,
372
  //    - RunParamsList is `TypeList<Foo*, int, const std::string&>`,
373
  //    - BoundParamsList is `TypeList<Foo*, int>`,
374
  //    - UnboundParamsList is `TypeList<const std::string&>`,
375
  //    - BoundArgsList is `TypeList<Foo*, int16_t>`,
376
  //    - UnboundRunType is `double(const std::string&)`.
377
  using RunType = typename FunctorTraits::RunType;
378
  using ReturnType = ExtractReturnType<RunType>;
379
380
  using RunParamsList = ExtractArgs<RunType>;
381
  using BoundParamsList = TakeTypeListItem<num_bounds, RunParamsList>;
382
  using UnboundParamsList = DropTypeListItem<num_bounds, RunParamsList>;
383
384
  using BoundArgsList = TypeList<BoundArgs...>;
385
386
  using UnboundRunType = MakeFunctionType<ReturnType, UnboundParamsList>;
387
};
388
389
template <typename Functor>
390
typename std::enable_if<FunctorTraits<Functor>::is_nullable, bool>::type
391
0
IsNull(const Functor& functor) {
392
0
  return !functor;
393
0
}
394
395
template <typename Functor>
396
typename std::enable_if<!FunctorTraits<Functor>::is_nullable, bool>::type
397
IsNull(const Functor&) {
398
  return false;
399
}
400
401
// Used by ApplyCancellationTraits below.
402
template <typename Functor, typename BoundArgsTuple, size_t... indices>
403
bool ApplyCancellationTraitsImpl(const Functor& functor,
404
                                 const BoundArgsTuple& bound_args,
405
                                 IndexSequence<indices...>) {
406
  return CallbackCancellationTraits<Functor, BoundArgsTuple>::IsCancelled(
407
      functor, std::get<indices>(bound_args)...);
408
}
409
410
// Relays |base| to corresponding CallbackCancellationTraits<>::Run(). Returns
411
// true if the callback |base| represents is canceled.
412
template <typename BindStateType>
413
bool ApplyCancellationTraits(const BindStateBase* base) {
414
  const BindStateType* storage = static_cast<const BindStateType*>(base);
415
  static constexpr size_t num_bound_args =
416
      std::tuple_size<decltype(storage->bound_args_)>::value;
417
  return ApplyCancellationTraitsImpl(
418
      storage->functor_, storage->bound_args_,
419
      MakeIndexSequence<num_bound_args>());
420
};
421
422
// BindState<>
423
//
424
// This stores all the state passed into Bind().
425
template <typename Functor, typename... BoundArgs>
426
struct BindState final : BindStateBase {
427
  using IsCancellable = std::integral_constant<
428
      bool,
429
      CallbackCancellationTraits<Functor,
430
                                 std::tuple<BoundArgs...>>::is_cancellable>;
431
432
  template <typename ForwardFunctor, typename... ForwardBoundArgs>
433
  explicit BindState(BindStateBase::InvokeFuncStorage invoke_func,
434
                     ForwardFunctor&& functor,
435
                     ForwardBoundArgs&&... bound_args)
436
      // IsCancellable is std::false_type if
437
      // CallbackCancellationTraits<>::IsCancelled returns always false.
438
      // Otherwise, it's std::true_type.
439
      : BindState(IsCancellable{},
440
                  invoke_func,
441
                  std::forward<ForwardFunctor>(functor),
442
0
                  std::forward<ForwardBoundArgs>(bound_args)...) {
443
0
  }
444
445
  Functor functor_;
446
  std::tuple<BoundArgs...> bound_args_;
447
448
 private:
449
  template <typename ForwardFunctor, typename... ForwardBoundArgs>
450
  explicit BindState(std::true_type,
451
                     BindStateBase::InvokeFuncStorage invoke_func,
452
                     ForwardFunctor&& functor,
453
                     ForwardBoundArgs&&... bound_args)
454
      : BindStateBase(invoke_func,
455
                      &Destroy,
456
                      &ApplyCancellationTraits<BindState>),
457
        functor_(std::forward<ForwardFunctor>(functor)),
458
        bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
459
    DCHECK(!IsNull(functor_));
460
  }
461
462
  template <typename ForwardFunctor, typename... ForwardBoundArgs>
463
  explicit BindState(std::false_type,
464
                     BindStateBase::InvokeFuncStorage invoke_func,
465
                     ForwardFunctor&& functor,
466
                     ForwardBoundArgs&&... bound_args)
467
      : BindStateBase(invoke_func, &Destroy),
468
        functor_(std::forward<ForwardFunctor>(functor)),
469
0
        bound_args_(std::forward<ForwardBoundArgs>(bound_args)...) {
470
0
    DCHECK(!IsNull(functor_));
471
0
  }
472
473
  ~BindState() {}
474
475
0
  static void Destroy(const BindStateBase* self) {
476
0
    delete static_cast<const BindState*>(self);
477
0
  }
478
};
479
480
// Used to implement MakeBindStateType.
481
template <bool is_method, typename Functor, typename... BoundArgs>
482
struct MakeBindStateTypeImpl;
483
484
template <typename Functor, typename... BoundArgs>
485
struct MakeBindStateTypeImpl<false, Functor, BoundArgs...> {
486
  static_assert(!HasRefCountedTypeAsRawPtr<
487
                    typename std::decay<BoundArgs>::type...>::value,
488
                "A parameter is a refcounted type and needs scoped_refptr.");
489
  using Type = BindState<typename std::decay<Functor>::type,
490
                         typename std::decay<BoundArgs>::type...>;
491
};
492
493
template <typename Functor>
494
struct MakeBindStateTypeImpl<true, Functor> {
495
  using Type = BindState<typename std::decay<Functor>::type>;
496
};
497
498
template <typename Functor, typename Receiver, typename... BoundArgs>
499
struct MakeBindStateTypeImpl<true, Functor, Receiver, BoundArgs...> {
500
  static_assert(
501
      !std::is_array<typename std::remove_reference<Receiver>::type>::value,
502
      "First bound argument to a method cannot be an array.");
503
  static_assert(!HasRefCountedTypeAsRawPtr<
504
                    typename std::decay<BoundArgs>::type...>::value,
505
                "A parameter is a refcounted type and needs scoped_refptr.");
506
507
 private:
508
  using DecayedReceiver = typename std::decay<Receiver>::type;
509
510
 public:
511
  using Type = BindState<
512
      typename std::decay<Functor>::type,
513
      typename std::conditional<
514
          std::is_pointer<DecayedReceiver>::value,
515
          scoped_refptr<typename std::remove_pointer<DecayedReceiver>::type>,
516
          DecayedReceiver>::type,
517
      typename std::decay<BoundArgs>::type...>;
518
};
519
520
template <typename Functor, typename... BoundArgs>
521
using MakeBindStateType =
522
    typename MakeBindStateTypeImpl<MakeFunctorTraits<Functor>::is_method,
523
                                   Functor,
524
                                   BoundArgs...>::Type;
525
526
}  // namespace internal
527
528
// Returns a RunType of bound functor.
529
// E.g. MakeUnboundRunType<R(A, B, C), A, B> is evaluated to R(C).
530
template <typename Functor, typename... BoundArgs>
531
using MakeUnboundRunType =
532
    typename internal::BindTypeHelper<Functor, BoundArgs...>::UnboundRunType;
533
534
}  // namespace base
535
536
#endif  // BASE_BIND_INTERNAL_H_