security/sandbox/chromium/base/bind_helpers.h

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     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.
     5 // This defines a set of argument wrappers and related factory methods that
     6 // can be used specify the refcounting and reference semantics of arguments
     7 // that are bound by the Bind() function in base/bind.h.
     8 //
     9 // It also defines a set of simple functions and utilities that people want
    10 // when using Callback<> and Bind().
    11 //
    12 //
    13 // ARGUMENT BINDING WRAPPERS
    14 //
    15 // The wrapper functions are base::Unretained(), base::Owned(), bass::Passed(),
    16 // base::ConstRef(), and base::IgnoreResult().
    17 //
    18 // Unretained() allows Bind() to bind a non-refcounted class, and to disable
    19 // refcounting on arguments that are refcounted objects.
    20 //
    21 // Owned() transfers ownership of an object to the Callback resulting from
    22 // bind; the object will be deleted when the Callback is deleted.
    23 //
    24 // Passed() is for transferring movable-but-not-copyable types (eg. scoped_ptr)
    25 // through a Callback. Logically, this signifies a destructive transfer of
    26 // the state of the argument into the target function.  Invoking
    27 // Callback::Run() twice on a Callback that was created with a Passed()
    28 // argument will CHECK() because the first invocation would have already
    29 // transferred ownership to the target function.
    30 //
    31 // ConstRef() allows binding a constant reference to an argument rather
    32 // than a copy.
    33 //
    34 // IgnoreResult() is used to adapt a function or Callback with a return type to
    35 // one with a void return. This is most useful if you have a function with,
    36 // say, a pesky ignorable bool return that you want to use with PostTask or
    37 // something else that expect a Callback with a void return.
    38 //
    39 // EXAMPLE OF Unretained():
    40 //
    41 //   class Foo {
    42 //    public:
    43 //     void func() { cout << "Foo:f" << endl; }
    44 //   };
    45 //
    46 //   // In some function somewhere.
    47 //   Foo foo;
    48 //   Closure foo_callback =
    49 //       Bind(&Foo::func, Unretained(&foo));
    50 //   foo_callback.Run();  // Prints "Foo:f".
    51 //
    52 // Without the Unretained() wrapper on |&foo|, the above call would fail
    53 // to compile because Foo does not support the AddRef() and Release() methods.
    54 //
    55 //
    56 // EXAMPLE OF Owned():
    57 //
    58 //   void foo(int* arg) { cout << *arg << endl }
    59 //
    60 //   int* pn = new int(1);
    61 //   Closure foo_callback = Bind(&foo, Owned(pn));
    62 //
    63 //   foo_callback.Run();  // Prints "1"
    64 //   foo_callback.Run();  // Prints "1"
    65 //   *n = 2;
    66 //   foo_callback.Run();  // Prints "2"
    67 //
    68 //   foo_callback.Reset();  // |pn| is deleted.  Also will happen when
    69 //                          // |foo_callback| goes out of scope.
    70 //
    71 // Without Owned(), someone would have to know to delete |pn| when the last
    72 // reference to the Callback is deleted.
    73 //
    74 //
    75 // EXAMPLE OF ConstRef():
    76 //
    77 //   void foo(int arg) { cout << arg << endl }
    78 //
    79 //   int n = 1;
    80 //   Closure no_ref = Bind(&foo, n);
    81 //   Closure has_ref = Bind(&foo, ConstRef(n));
    82 //
    83 //   no_ref.Run();  // Prints "1"
    84 //   has_ref.Run();  // Prints "1"
    85 //
    86 //   n = 2;
    87 //   no_ref.Run();  // Prints "1"
    88 //   has_ref.Run();  // Prints "2"
    89 //
    90 // Note that because ConstRef() takes a reference on |n|, |n| must outlive all
    91 // its bound callbacks.
    92 //
    93 //
    94 // EXAMPLE OF IgnoreResult():
    95 //
    96 //   int DoSomething(int arg) { cout << arg << endl; }
    97 //
    98 //   // Assign to a Callback with a void return type.
    99 //   Callback<void(int)> cb = Bind(IgnoreResult(&DoSomething));
   100 //   cb->Run(1);  // Prints "1".
   101 //
   102 //   // Prints "1" on |ml|.
   103 //   ml->PostTask(FROM_HERE, Bind(IgnoreResult(&DoSomething), 1);
   104 //
   105 //
   106 // EXAMPLE OF Passed():
   107 //
   108 //   void TakesOwnership(scoped_ptr<Foo> arg) { }
   109 //   scoped_ptr<Foo> CreateFoo() { return scoped_ptr<Foo>(new Foo()); }
   110 //
   111 //   scoped_ptr<Foo> f(new Foo());
   112 //
   113 //   // |cb| is given ownership of Foo(). |f| is now NULL.
   114 //   // You can use f.Pass() in place of &f, but it's more verbose.
   115 //   Closure cb = Bind(&TakesOwnership, Passed(&f));
   116 //
   117 //   // Run was never called so |cb| still owns Foo() and deletes
   118 //   // it on Reset().
   119 //   cb.Reset();
   120 //
   121 //   // |cb| is given a new Foo created by CreateFoo().
   122 //   cb = Bind(&TakesOwnership, Passed(CreateFoo()));
   123 //
   124 //   // |arg| in TakesOwnership() is given ownership of Foo(). |cb|
   125 //   // no longer owns Foo() and, if reset, would not delete Foo().
   126 //   cb.Run();  // Foo() is now transferred to |arg| and deleted.
   127 //   cb.Run();  // This CHECK()s since Foo() already been used once.
   128 //
   129 // Passed() is particularly useful with PostTask() when you are transferring
   130 // ownership of an argument into a task, but don't necessarily know if the
   131 // task will always be executed. This can happen if the task is cancellable
   132 // or if it is posted to a MessageLoopProxy.
   133 //
   134 //
   135 // SIMPLE FUNCTIONS AND UTILITIES.
   136 //
   137 //   DoNothing() - Useful for creating a Closure that does nothing when called.
   138 //   DeletePointer<T>() - Useful for creating a Closure that will delete a
   139 //                        pointer when invoked. Only use this when necessary.
   140 //                        In most cases MessageLoop::DeleteSoon() is a better
   141 //                        fit.
   143 #ifndef BASE_BIND_HELPERS_H_
   144 #define BASE_BIND_HELPERS_H_
   146 #include "base/basictypes.h"
   147 #include "base/callback.h"
   148 #include "base/memory/weak_ptr.h"
   149 #include "base/template_util.h"
   151 namespace base {
   152 namespace internal {
   154 // Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T
   155 // for the existence of AddRef() and Release() functions of the correct
   156 // signature.
   157 //
   158 // http://en.wikipedia.org/wiki/Substitution_failure_is_not_an_error
   159 // http://stackoverflow.com/questions/257288/is-it-possible-to-write-a-c-template-to-check-for-a-functions-existence
   160 // http://stackoverflow.com/questions/4358584/sfinae-approach-comparison
   161 // http://stackoverflow.com/questions/1966362/sfinae-to-check-for-inherited-member-functions
   162 //
   163 // The last link in particular show the method used below.
   164 //
   165 // For SFINAE to work with inherited methods, we need to pull some extra tricks
   166 // with multiple inheritance.  In the more standard formulation, the overloads
   167 // of Check would be:
   168 //
   169 //   template <typename C>
   170 //   Yes NotTheCheckWeWant(Helper<&C::TargetFunc>*);
   171 //
   172 //   template <typename C>
   173 //   No NotTheCheckWeWant(...);
   174 //
   175 //   static const bool value = sizeof(NotTheCheckWeWant<T>(0)) == sizeof(Yes);
   176 //
   177 // The problem here is that template resolution will not match
   178 // C::TargetFunc if TargetFunc does not exist directly in C.  That is, if
   179 // TargetFunc in inherited from an ancestor, &C::TargetFunc will not match,
   180 // |value| will be false.  This formulation only checks for whether or
   181 // not TargetFunc exist directly in the class being introspected.
   182 //
   183 // To get around this, we play a dirty trick with multiple inheritance.
   184 // First, We create a class BaseMixin that declares each function that we
   185 // want to probe for.  Then we create a class Base that inherits from both T
   186 // (the class we wish to probe) and BaseMixin.  Note that the function
   187 // signature in BaseMixin does not need to match the signature of the function
   188 // we are probing for; thus it's easiest to just use void(void).
   189 //
   190 // Now, if TargetFunc exists somewhere in T, then &Base::TargetFunc has an
   191 // ambiguous resolution between BaseMixin and T.  This lets us write the
   192 // following:
   193 //
   194 //   template <typename C>
   195 //   No GoodCheck(Helper<&C::TargetFunc>*);
   196 //
   197 //   template <typename C>
   198 //   Yes GoodCheck(...);
   199 //
   200 //   static const bool value = sizeof(GoodCheck<Base>(0)) == sizeof(Yes);
   201 //
   202 // Notice here that the variadic version of GoodCheck() returns Yes here
   203 // instead of No like the previous one. Also notice that we calculate |value|
   204 // by specializing GoodCheck() on Base instead of T.
   205 //
   206 // We've reversed the roles of the variadic, and Helper overloads.
   207 // GoodCheck(Helper<&C::TargetFunc>*), when C = Base, fails to be a valid
   208 // substitution if T::TargetFunc exists. Thus GoodCheck<Base>(0) will resolve
   209 // to the variadic version if T has TargetFunc.  If T::TargetFunc does not
   210 // exist, then &C::TargetFunc is not ambiguous, and the overload resolution
   211 // will prefer GoodCheck(Helper<&C::TargetFunc>*).
   212 //
   213 // This method of SFINAE will correctly probe for inherited names, but it cannot
   214 // typecheck those names.  It's still a good enough sanity check though.
   215 //
   216 // Works on gcc-4.2, gcc-4.4, and Visual Studio 2008.
   217 //
   218 // TODO(ajwong): Move to ref_counted.h or template_util.h when we've vetted
   219 // this works well.
   220 //
   221 // TODO(ajwong): Make this check for Release() as well.
   222 // See http://crbug.com/82038.
   223 template <typename T>
   224 class SupportsAddRefAndRelease {
   225   typedef char Yes[1];
   226   typedef char No[2];
   228   struct BaseMixin {
   229     void AddRef();
   230   };
   232 // MSVC warns when you try to use Base if T has a private destructor, the
   233 // common pattern for refcounted types. It does this even though no attempt to
   234 // instantiate Base is made.  We disable the warning for this definition.
   235 #if defined(OS_WIN)
   236 #pragma warning(push)
   237 #pragma warning(disable:4624)
   238 #endif
   239   struct Base : public T, public BaseMixin {
   240   };
   241 #if defined(OS_WIN)
   242 #pragma warning(pop)
   243 #endif
   245   template <void(BaseMixin::*)(void)> struct Helper {};
   247   template <typename C>
   248   static No& Check(Helper<&C::AddRef>*);
   250   template <typename >
   251   static Yes& Check(...);
   253  public:
   254   static const bool value = sizeof(Check<Base>(0)) == sizeof(Yes);
   255 };
   257 // Helpers to assert that arguments of a recounted type are bound with a
   258 // scoped_refptr.
   259 template <bool IsClasstype, typename T>
   260 struct UnsafeBindtoRefCountedArgHelper : false_type {
   261 };
   263 template <typename T>
   264 struct UnsafeBindtoRefCountedArgHelper<true, T>
   265     : integral_constant<bool, SupportsAddRefAndRelease<T>::value> {
   266 };
   268 template <typename T>
   269 struct UnsafeBindtoRefCountedArg : false_type {
   270 };
   272 template <typename T>
   273 struct UnsafeBindtoRefCountedArg<T*>
   274     : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> {
   275 };
   277 template <typename T>
   278 class HasIsMethodTag {
   279   typedef char Yes[1];
   280   typedef char No[2];
   282   template <typename U>
   283   static Yes& Check(typename U::IsMethod*);
   285   template <typename U>
   286   static No& Check(...);
   288  public:
   289   static const bool value = sizeof(Check<T>(0)) == sizeof(Yes);
   290 };
   292 template <typename T>
   293 class UnretainedWrapper {
   294  public:
   295   explicit UnretainedWrapper(T* o) : ptr_(o) {}
   296   T* get() const { return ptr_; }
   297  private:
   298   T* ptr_;
   299 };
   301 template <typename T>
   302 class ConstRefWrapper {
   303  public:
   304   explicit ConstRefWrapper(const T& o) : ptr_(&o) {}
   305   const T& get() const { return *ptr_; }
   306  private:
   307   const T* ptr_;
   308 };
   310 template <typename T>
   311 struct IgnoreResultHelper {
   312   explicit IgnoreResultHelper(T functor) : functor_(functor) {}
   314   T functor_;
   315 };
   317 template <typename T>
   318 struct IgnoreResultHelper<Callback<T> > {
   319   explicit IgnoreResultHelper(const Callback<T>& functor) : functor_(functor) {}
   321   const Callback<T>& functor_;
   322 };
   324 // An alternate implementation is to avoid the destructive copy, and instead
   325 // specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to
   326 // a class that is essentially a scoped_ptr<>.
   327 //
   328 // The current implementation has the benefit though of leaving ParamTraits<>
   329 // fully in callback_internal.h as well as avoiding type conversions during
   330 // storage.
   331 template <typename T>
   332 class OwnedWrapper {
   333  public:
   334   explicit OwnedWrapper(T* o) : ptr_(o) {}
   335   ~OwnedWrapper() { delete ptr_; }
   336   T* get() const { return ptr_; }
   337   OwnedWrapper(const OwnedWrapper& other) {
   338     ptr_ = other.ptr_;
   339     other.ptr_ = NULL;
   340   }
   342  private:
   343   mutable T* ptr_;
   344 };
   346 // PassedWrapper is a copyable adapter for a scoper that ignores const.
   347 //
   348 // It is needed to get around the fact that Bind() takes a const reference to
   349 // all its arguments.  Because Bind() takes a const reference to avoid
   350 // unnecessary copies, it is incompatible with movable-but-not-copyable
   351 // types; doing a destructive "move" of the type into Bind() would violate
   352 // the const correctness.
   353 //
   354 // This conundrum cannot be solved without either C++11 rvalue references or
   355 // a O(2^n) blowup of Bind() templates to handle each combination of regular
   356 // types and movable-but-not-copyable types.  Thus we introduce a wrapper type
   357 // that is copyable to transmit the correct type information down into
   358 // BindState<>. Ignoring const in this type makes sense because it is only
   359 // created when we are explicitly trying to do a destructive move.
   360 //
   361 // Two notes:
   362 //  1) PassedWrapper supports any type that has a "Pass()" function.
   363 //     This is intentional. The whitelisting of which specific types we
   364 //     support is maintained by CallbackParamTraits<>.
   365 //  2) is_valid_ is distinct from NULL because it is valid to bind a "NULL"
   366 //     scoper to a Callback and allow the Callback to execute once.
   367 template <typename T>
   368 class PassedWrapper {
   369  public:
   370   explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {}
   371   PassedWrapper(const PassedWrapper& other)
   372       : is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) {
   373   }
   374   T Pass() const {
   375     CHECK(is_valid_);
   376     is_valid_ = false;
   377     return scoper_.Pass();
   378   }
   380  private:
   381   mutable bool is_valid_;
   382   mutable T scoper_;
   383 };
   385 // Unwrap the stored parameters for the wrappers above.
   386 template <typename T>
   387 struct UnwrapTraits {
   388   typedef const T& ForwardType;
   389   static ForwardType Unwrap(const T& o) { return o; }
   390 };
   392 template <typename T>
   393 struct UnwrapTraits<UnretainedWrapper<T> > {
   394   typedef T* ForwardType;
   395   static ForwardType Unwrap(UnretainedWrapper<T> unretained) {
   396     return unretained.get();
   397   }
   398 };
   400 template <typename T>
   401 struct UnwrapTraits<ConstRefWrapper<T> > {
   402   typedef const T& ForwardType;
   403   static ForwardType Unwrap(ConstRefWrapper<T> const_ref) {
   404     return const_ref.get();
   405   }
   406 };
   408 template <typename T>
   409 struct UnwrapTraits<scoped_refptr<T> > {
   410   typedef T* ForwardType;
   411   static ForwardType Unwrap(const scoped_refptr<T>& o) { return o.get(); }
   412 };
   414 template <typename T>
   415 struct UnwrapTraits<WeakPtr<T> > {
   416   typedef const WeakPtr<T>& ForwardType;
   417   static ForwardType Unwrap(const WeakPtr<T>& o) { return o; }
   418 };
   420 template <typename T>
   421 struct UnwrapTraits<OwnedWrapper<T> > {
   422   typedef T* ForwardType;
   423   static ForwardType Unwrap(const OwnedWrapper<T>& o) {
   424     return o.get();
   425   }
   426 };
   428 template <typename T>
   429 struct UnwrapTraits<PassedWrapper<T> > {
   430   typedef T ForwardType;
   431   static T Unwrap(PassedWrapper<T>& o) {
   432     return o.Pass();
   433   }
   434 };
   436 // Utility for handling different refcounting semantics in the Bind()
   437 // function.
   438 template <bool is_method, typename T>
   439 struct MaybeRefcount;
   441 template <typename T>
   442 struct MaybeRefcount<false, T> {
   443   static void AddRef(const T&) {}
   444   static void Release(const T&) {}
   445 };
   447 template <typename T, size_t n>
   448 struct MaybeRefcount<false, T[n]> {
   449   static void AddRef(const T*) {}
   450   static void Release(const T*) {}
   451 };
   453 template <typename T>
   454 struct MaybeRefcount<true, T> {
   455   static void AddRef(const T&) {}
   456   static void Release(const T&) {}
   457 };
   459 template <typename T>
   460 struct MaybeRefcount<true, T*> {
   461   static void AddRef(T* o) { o->AddRef(); }
   462   static void Release(T* o) { o->Release(); }
   463 };
   465 // No need to additionally AddRef() and Release() since we are storing a
   466 // scoped_refptr<> inside the storage object already.
   467 template <typename T>
   468 struct MaybeRefcount<true, scoped_refptr<T> > {
   469   static void AddRef(const scoped_refptr<T>& o) {}
   470   static void Release(const scoped_refptr<T>& o) {}
   471 };
   473 template <typename T>
   474 struct MaybeRefcount<true, const T*> {
   475   static void AddRef(const T* o) { o->AddRef(); }
   476   static void Release(const T* o) { o->Release(); }
   477 };
   479 // IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a
   480 // method.  It is used internally by Bind() to select the correct
   481 // InvokeHelper that will no-op itself in the event the WeakPtr<> for
   482 // the target object is invalidated.
   483 //
   484 // P1 should be the type of the object that will be received of the method.
   485 template <bool IsMethod, typename P1>
   486 struct IsWeakMethod : public false_type {};
   488 template <typename T>
   489 struct IsWeakMethod<true, WeakPtr<T> > : public true_type {};
   491 template <typename T>
   492 struct IsWeakMethod<true, ConstRefWrapper<WeakPtr<T> > > : public true_type {};
   494 }  // namespace internal
   496 template <typename T>
   497 static inline internal::UnretainedWrapper<T> Unretained(T* o) {
   498   return internal::UnretainedWrapper<T>(o);
   499 }
   501 template <typename T>
   502 static inline internal::ConstRefWrapper<T> ConstRef(const T& o) {
   503   return internal::ConstRefWrapper<T>(o);
   504 }
   506 template <typename T>
   507 static inline internal::OwnedWrapper<T> Owned(T* o) {
   508   return internal::OwnedWrapper<T>(o);
   509 }
   511 // We offer 2 syntaxes for calling Passed().  The first takes a temporary and
   512 // is best suited for use with the return value of a function. The second
   513 // takes a pointer to the scoper and is just syntactic sugar to avoid having
   514 // to write Passed(scoper.Pass()).
   515 template <typename T>
   516 static inline internal::PassedWrapper<T> Passed(T scoper) {
   517   return internal::PassedWrapper<T>(scoper.Pass());
   518 }
   519 template <typename T>
   520 static inline internal::PassedWrapper<T> Passed(T* scoper) {
   521   return internal::PassedWrapper<T>(scoper->Pass());
   522 }
   524 template <typename T>
   525 static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) {
   526   return internal::IgnoreResultHelper<T>(data);
   527 }
   529 template <typename T>
   530 static inline internal::IgnoreResultHelper<Callback<T> >
   531 IgnoreResult(const Callback<T>& data) {
   532   return internal::IgnoreResultHelper<Callback<T> >(data);
   533 }
   535 BASE_EXPORT void DoNothing();
   537 template<typename T>
   538 void DeletePointer(T* obj) {
   539   delete obj;
   540 }
   542 }  // namespace base
   544 #endif  // BASE_BIND_HELPERS_H_

mercurial