1 // Copyright 2016 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 MOJO_PUBLIC_CPP_BINDINGS_SYNC_CALL_RESTRICTIONS_H_ 6 #define MOJO_PUBLIC_CPP_BINDINGS_SYNC_CALL_RESTRICTIONS_H_ 7 8 #include "base/macros.h" 9 #include "base/threading/thread_restrictions.h" 10 #include "mojo/public/cpp/bindings/bindings_export.h" 11 12 #if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON)) 13 #define ENABLE_SYNC_CALL_RESTRICTIONS 1 14 #else 15 #define ENABLE_SYNC_CALL_RESTRICTIONS 0 16 #endif 17 18 namespace leveldb { 19 class LevelDBMojoProxy; 20 } 21 22 namespace ui { 23 class Gpu; 24 } 25 26 namespace views { 27 class ClipboardMus; 28 } 29 30 namespace mojo { 31 32 // In some processes, sync calls are disallowed. For example, in the browser 33 // process we don't want any sync calls to child processes for performance, 34 // security and stability reasons. SyncCallRestrictions helps to enforce such 35 // rules. 36 // 37 // Before processing a sync call, the bindings call 38 // SyncCallRestrictions::AssertSyncCallAllowed() to check whether sync calls are 39 // allowed. By default, it is determined by the mojo system property 40 // MOJO_PROPERTY_SYNC_CALL_ALLOWED. If the default setting says no but you have 41 // a very compelling reason to disregard that (which should be very very rare), 42 // you can override it by constructing a ScopedAllowSyncCall object, which 43 // allows making sync calls on the current thread during its lifetime. 44 class MOJO_CPP_BINDINGS_EXPORT SyncCallRestrictions { 45 public: 46 #if ENABLE_SYNC_CALL_RESTRICTIONS 47 // Checks whether the current thread is allowed to make sync calls, and causes 48 // a DCHECK if not. 49 static void AssertSyncCallAllowed(); 50 #else 51 // Inline the empty definitions of functions so that they can be compiled out. 52 static void AssertSyncCallAllowed() {} 53 #endif 54 55 private: 56 // DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to mojo/OWNERS first. 57 // BEGIN ALLOWED USAGE. 58 friend class ui::Gpu; // http://crbug.com/620058 59 // LevelDBMojoProxy makes same-process sync calls from the DB thread. 60 friend class leveldb::LevelDBMojoProxy; 61 // END ALLOWED USAGE. 62 63 // BEGIN USAGE THAT NEEDS TO BE FIXED. 64 // In the non-mus case, we called blocking OS functions in the ui::Clipboard 65 // implementation which weren't caught by sync call restrictions. Our blocking 66 // calls to mus, however, are. 67 friend class views::ClipboardMus; 68 // END USAGE THAT NEEDS TO BE FIXED. 69 70 #if ENABLE_SYNC_CALL_RESTRICTIONS 71 static void IncreaseScopedAllowCount(); 72 static void DecreaseScopedAllowCount(); 73 #else IncreaseScopedAllowCount()74 static void IncreaseScopedAllowCount() {} DecreaseScopedAllowCount()75 static void DecreaseScopedAllowCount() {} 76 #endif 77 78 // If a process is configured to disallow sync calls in general, constructing 79 // a ScopedAllowSyncCall object temporarily allows making sync calls on the 80 // current thread. Doing this is almost always incorrect, which is why we 81 // limit who can use this through friend. If you find yourself needing to use 82 // this, talk to mojo/OWNERS. 83 class ScopedAllowSyncCall { 84 public: ScopedAllowSyncCall()85 ScopedAllowSyncCall() { IncreaseScopedAllowCount(); } ~ScopedAllowSyncCall()86 ~ScopedAllowSyncCall() { DecreaseScopedAllowCount(); } 87 88 private: 89 #if ENABLE_SYNC_CALL_RESTRICTIONS 90 base::ThreadRestrictions::ScopedAllowWait allow_wait_; 91 #endif 92 93 DISALLOW_COPY_AND_ASSIGN(ScopedAllowSyncCall); 94 }; 95 96 DISALLOW_IMPLICIT_CONSTRUCTORS(SyncCallRestrictions); 97 }; 98 99 } // namespace mojo 100 101 #endif // MOJO_PUBLIC_CPP_BINDINGS_SYNC_CALL_RESTRICTIONS_H_ 102