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 class ChromeSelectFileDialogFactory; 19 20 namespace sync_preferences { 21 class PrefServiceSyncable; 22 } 23 24 namespace content { 25 class BlinkTestController; 26 } 27 28 namespace display { 29 class ForwardingDisplayDelegate; 30 } 31 32 namespace leveldb { 33 class LevelDBMojoProxy; 34 } 35 36 namespace prefs { 37 class PersistentPrefStoreClient; 38 } 39 40 namespace ui { 41 class ClipboardClient; 42 class HostContextFactoryPrivate; 43 } // namespace ui 44 45 namespace viz { 46 class HostFrameSinkManager; 47 } 48 49 namespace mojo { 50 class ScopedAllowSyncCallForTesting; 51 52 // In some processes, sync calls are disallowed. For example, in the browser 53 // process we don't want any sync calls to child processes for performance, 54 // security and stability reasons. SyncCallRestrictions helps to enforce such 55 // rules. 56 // 57 // Before processing a sync call, the bindings call 58 // SyncCallRestrictions::AssertSyncCallAllowed() to check whether sync calls are 59 // allowed. By default sync calls are allowed but they may be globally 60 // disallowed within a process by calling DisallowSyncCall(). 61 // 62 // If globally disallowed but you but you have a very compelling reason to 63 // disregard that (which should be very very rare), you can override it by 64 // constructing a ScopedAllowSyncCall object which allows making sync calls on 65 // the current sequence during its lifetime. 66 class MOJO_CPP_BINDINGS_EXPORT SyncCallRestrictions { 67 public: 68 #if ENABLE_SYNC_CALL_RESTRICTIONS 69 // Checks whether the current sequence is allowed to make sync calls, and 70 // causes a DCHECK if not. 71 static void AssertSyncCallAllowed(); 72 73 // Disables sync calls within the calling process. Any caller who wishes to 74 // make sync calls once this has been invoked must do so within the extent of 75 // a ScopedAllowSyncCall or ScopedAllowSyncCallForTesting. 76 static void DisallowSyncCall(); 77 78 #else 79 // Inline the empty definitions of functions so that they can be compiled out. 80 static void AssertSyncCallAllowed() {} 81 static void DisallowSyncCall() {} 82 #endif 83 84 private: 85 // DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to mojo/OWNERS first. 86 // BEGIN ALLOWED USAGE. 87 // SynchronousCompositorHost is used for Android webview. 88 friend class content::SynchronousCompositorHost; 89 // LevelDBMojoProxy makes same-process sync calls from the DB thread. 90 friend class leveldb::LevelDBMojoProxy; 91 // Pref service connection is sync at startup. 92 friend class prefs::PersistentPrefStoreClient; 93 // Incognito pref service instances are created synchronously. 94 friend class sync_preferences::PrefServiceSyncable; 95 friend class mojo::ScopedAllowSyncCallForTesting; 96 // For file open and save dialogs created synchronously. 97 friend class ::ChromeSelectFileDialogFactory; 98 // For synchronous system clipboard access. 99 friend class ui::ClipboardClient; 100 // For destroying the GL context/surface that draw to a platform window before 101 // the platform window is destroyed. 102 friend class viz::HostFrameSinkManager; 103 // Allow for layout test pixel dumps. 104 friend class content::BlinkTestController; 105 // For preventing frame swaps of wrong size during resize on Windows. 106 // (https://crbug.com/811945) 107 friend class ui::HostContextFactoryPrivate; 108 // END ALLOWED USAGE. 109 110 // BEGIN USAGE THAT NEEDS TO BE FIXED. 111 // In ash::Shell::Init() it assumes that NativeDisplayDelegate will be 112 // synchronous at first. In mushrome ForwardingDisplayDelegate uses a 113 // synchronous call to get the display snapshots as a workaround. 114 friend class display::ForwardingDisplayDelegate; 115 // END USAGE THAT NEEDS TO BE FIXED. 116 117 #if ENABLE_SYNC_CALL_RESTRICTIONS 118 static void IncreaseScopedAllowCount(); 119 static void DecreaseScopedAllowCount(); 120 #else IncreaseScopedAllowCount()121 static void IncreaseScopedAllowCount() {} DecreaseScopedAllowCount()122 static void DecreaseScopedAllowCount() {} 123 #endif 124 125 // If a process is configured to disallow sync calls in general, constructing 126 // a ScopedAllowSyncCall object temporarily allows making sync calls on the 127 // current sequence. Doing this is almost always incorrect, which is why we 128 // limit who can use this through friend. If you find yourself needing to use 129 // this, talk to mojo/OWNERS. 130 class ScopedAllowSyncCall { 131 public: ScopedAllowSyncCall()132 ScopedAllowSyncCall() { IncreaseScopedAllowCount(); } ~ScopedAllowSyncCall()133 ~ScopedAllowSyncCall() { DecreaseScopedAllowCount(); } 134 135 private: 136 #if ENABLE_SYNC_CALL_RESTRICTIONS 137 base::ThreadRestrictions::ScopedAllowWait allow_wait_; 138 #endif 139 140 DISALLOW_COPY_AND_ASSIGN(ScopedAllowSyncCall); 141 }; 142 143 DISALLOW_IMPLICIT_CONSTRUCTORS(SyncCallRestrictions); 144 }; 145 146 class ScopedAllowSyncCallForTesting { 147 public: ScopedAllowSyncCallForTesting()148 ScopedAllowSyncCallForTesting() {} ~ScopedAllowSyncCallForTesting()149 ~ScopedAllowSyncCallForTesting() {} 150 151 private: 152 SyncCallRestrictions::ScopedAllowSyncCall scoped_allow_sync_call_; 153 154 DISALLOW_COPY_AND_ASSIGN(ScopedAllowSyncCallForTesting); 155 }; 156 157 } // namespace mojo 158 159 #endif // MOJO_PUBLIC_CPP_BINDINGS_SYNC_CALL_RESTRICTIONS_H_ 160