1 // Copyright (c) 2012 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_THREADING_THREAD_RESTRICTIONS_H_
6 #define BASE_THREADING_THREAD_RESTRICTIONS_H_
7 
8 #include "base/base_export.h"
9 #include "base/gtest_prod_util.h"
10 #include "base/location.h"
11 #include "base/logging.h"
12 #include "base/macros.h"
13 
14 // -----------------------------------------------------------------------------
15 // Usage documentation
16 // -----------------------------------------------------------------------------
17 //
18 // Overview:
19 // This file exposes functions to ban and allow certain slow operations
20 // on a per-thread basis. To annotate *usage* of such slow operations, refer to
21 // scoped_blocking_call.h instead.
22 //
23 // Specific allowances that can be controlled in this file are:
24 // - Blocking call: Refers to any call that causes the calling thread to wait
25 //   off-CPU. It includes but is not limited to calls that wait on synchronous
26 //   file I/O operations: read or write a file from disk, interact with a pipe
27 //   or a socket, rename or delete a file, enumerate files in a directory, etc.
28 //   Acquiring a low contention lock is not considered a blocking call.
29 //
30 // - Waiting on a //base sync primitive: Refers to calling one of these methods:
31 //   - base::WaitableEvent::*Wait*
32 //   - base::ConditionVariable::*Wait*
33 //   - base::Process::WaitForExit*
34 //
35 // - Long CPU work: Refers to any code that takes more than 100 ms to
36 //   run when there is no CPU contention and no hard page faults and therefore,
37 //   is not suitable to run on a thread required to keep the browser responsive
38 //   (where jank could be visible to the user).
39 //
40 // The following disallowance functions are offered:
41 //  - DisallowBlocking(): Disallows blocking calls on the current thread.
42 //  - DisallowBaseSyncPrimitives(): Disallows waiting on a //base sync primitive
43 //    on the current thread.
44 //  - DisallowUnresponsiveTasks() Disallows blocking calls, waiting on a //base
45 //    sync primitive, and long cpu work on the current thread.
46 //
47 // In addition, scoped-allowance mechanisms are offered to make an exception
48 // within a scope for a behavior that is normally disallowed.
49 //  - ScopedAllowBlocking(ForTesting): Allows blocking calls.
50 //  - ScopedAllowBaseSyncPrimitives(ForTesting)(OutsideBlockingScope): Allow
51 //    waiting on a //base sync primitive. The OutsideBlockingScope suffix allows
52 //    uses in a scope where blocking is also disallowed.
53 //
54 // Avoid using allowances outside of unit tests. In unit tests, use allowances
55 // with the suffix "ForTesting".
56 //
57 // Prefer making blocking calls from tasks posted to base::ThreadPoolInstance
58 // with base::MayBlock().
59 //
60 // Instead of waiting on a WaitableEvent or a ConditionVariable, prefer putting
61 // the work that should happen after the wait in a continuation callback and
62 // post it from where the WaitableEvent or ConditionVariable would have been
63 // signaled. If something needs to be scheduled after many tasks have executed,
64 // use base::BarrierClosure.
65 //
66 // On Windows, join processes asynchronously using base::win::ObjectWatcher.
67 //
68 // Where unavoidable, put ScopedAllow* instances in the narrowest scope possible
69 // in the caller making the blocking call but no further down. For example: if a
70 // Cleanup() method needs to do a blocking call, document Cleanup() as blocking
71 // and add a ScopedAllowBlocking instance in callers that can't avoid making
72 // this call from a context where blocking is banned, as such:
73 //
74 //   void Client::MyMethod() {
75 //     (...)
76 //     {
77 //       // Blocking is okay here because XYZ.
78 //       ScopedAllowBlocking allow_blocking;
79 //       my_foo_->Cleanup();
80 //     }
81 //     (...)
82 //   }
83 //
84 //   // This method can block.
85 //   void Foo::Cleanup() {
86 //     // Do NOT add the ScopedAllowBlocking in Cleanup() directly as that hides
87 //     // its blocking nature from unknowing callers and defeats the purpose of
88 //     // these checks.
89 //     FlushStateToDisk();
90 //   }
91 //
92 // Note: In rare situations where the blocking call is an implementation detail
93 // (i.e. the impl makes a call that invokes AssertBlockingAllowed() but it
94 // somehow knows that in practice this will not block), it might be okay to hide
95 // the ScopedAllowBlocking instance in the impl with a comment explaining why
96 // that's okay.
97 
98 class BrowserProcessImpl;
99 class HistogramSynchronizer;
100 class KeyStorageLinux;
101 class NativeBackendKWallet;
102 class NativeDesktopMediaList;
103 
104 namespace android_webview {
105 class AwFormDatabaseService;
106 class CookieManager;
107 class ScopedAllowInitGLBindings;
108 class VizCompositorThreadRunnerWebView;
109 }
110 namespace audio {
111 class OutputDevice;
112 }
113 namespace blink {
114 class RTCVideoDecoderAdapter;
115 class RTCVideoEncoder;
116 class SourceStream;
117 class VideoFrameResourceProvider;
118 class WorkerThread;
119 namespace scheduler {
120 class WorkerThread;
121 }
122 }
123 namespace cc {
124 class CompletionEvent;
125 class TileTaskManagerImpl;
126 }
127 namespace chromeos {
128 class BlockingMethodCaller;
129 class MojoUtils;
130 namespace system {
131 class StatisticsProviderImpl;
132 }
133 }
134 namespace chrome_browser_net {
135 class Predictor;
136 }
137 namespace chrome_cleaner {
138 class SystemReportComponent;
139 }
140 namespace content {
141 class BrowserGpuChannelHostFactory;
142 class BrowserMainLoop;
143 class BrowserProcessSubThread;
144 class BrowserShutdownProfileDumper;
145 class BrowserTestBase;
146 class CategorizedWorkerPool;
147 class DesktopCaptureDevice;
148 class InProcessUtilityThread;
149 class NestedMessagePumpAndroid;
150 class RenderProcessHostImpl;
151 class RenderWidgetHostViewMac;
152 class RTCVideoDecoder;
153 class SandboxHostLinux;
154 class ScopedAllowWaitForDebugURL;
155 class ServiceWorkerContextClient;
156 class SoftwareOutputDeviceMus;
157 class SynchronousCompositor;
158 class SynchronousCompositorHost;
159 class SynchronousCompositorSyncCallBridge;
160 class TextInputClientMac;
161 class WebContentsViewMac;
162 }  // namespace content
163 namespace cronet {
164 class CronetPrefsManager;
165 class CronetURLRequestContext;
166 }  // namespace cronet
167 namespace dbus {
168 class Bus;
169 }
170 namespace disk_cache {
171 class BackendImpl;
172 class InFlightIO;
173 }
174 namespace functions {
175 class ExecScriptScopedAllowBaseSyncPrimitives;
176 }
177 namespace history_report {
178 class HistoryReportJniBridge;
179 }
180 namespace gpu {
181 class GpuChannelHost;
182 }
183 namespace leveldb_env {
184 class DBTracker;
185 }
186 namespace media {
187 class AudioInputDevice;
188 class AudioOutputDevice;
189 class BlockingUrlProtocol;
190 class PaintCanvasVideoRenderer;
191 }
192 namespace memory_instrumentation {
193 class OSMetrics;
194 }
195 namespace midi {
196 class TaskService;  // https://crbug.com/796830
197 }
198 namespace module_installer {
199 class ScopedAllowModulePakLoad;
200 }
201 namespace mojo {
202 class CoreLibraryInitializer;
203 class SyncCallRestrictions;
204 namespace core {
205 class ScopedIPCSupport;
206 }
207 }
208 namespace printing {
209 class PrintJobWorker;
210 class PrinterQuery;
211 }
212 namespace rlz_lib {
213 class FinancialPing;
214 }
215 namespace syncer {
216 class GetLocalChangesRequest;
217 class HttpBridge;
218 class ModelSafeWorker;
219 }
220 namespace ui {
221 class CommandBufferClientImpl;
222 class CommandBufferLocal;
223 class DrmThreadProxy;
224 class GpuState;
225 }
226 namespace weblayer {
227 class BrowserContextImpl;
228 class BrowserProcess;
229 class ProfileImpl;
230 class WebLayerPathProvider;
231 }
232 namespace net {
233 class MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives;
234 class MultiThreadedProxyResolverScopedAllowJoinOnIO;
235 class NetworkChangeNotifierMac;
236 class NetworkConfigWatcherMacThread;
237 namespace internal {
238 class AddressTrackerLinux;
239 }
240 }
241 
242 namespace proxy_resolver {
243 class ScopedAllowThreadJoinForProxyResolverV8Tracing;
244 }
245 
246 namespace remoting {
247 class AutoThread;
248 namespace protocol {
249 class ScopedAllowThreadJoinForWebRtcTransport;
250 }
251 }
252 
253 namespace resource_coordinator {
254 class TabManagerDelegate;
255 }
256 
257 namespace service_manager {
258 class ServiceProcessLauncher;
259 }
260 
261 namespace shell_integration_linux {
262 class LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
263 }
264 
265 namespace ui {
266 class WindowResizeHelperMac;
267 }
268 
269 namespace viz {
270 class HostGpuMemoryBufferManager;
271 }
272 
273 namespace vr {
274 class VrShell;
275 }
276 
277 namespace web {
278 class WebMainLoop;
279 class WebSubThread;
280 }
281 
282 namespace webrtc {
283 class DesktopConfigurationMonitor;
284 }
285 
286 namespace base {
287 
288 namespace sequence_manager {
289 namespace internal {
290 class TaskQueueImpl;
291 }
292 }  // namespace sequence_manager
293 
294 namespace android {
295 class JavaHandlerThread;
296 }
297 
298 namespace internal {
299 class JobTaskSource;
300 class TaskTracker;
301 }
302 
303 class AdjustOOMScoreHelper;
304 class FileDescriptorWatcher;
305 class FilePath;
306 class GetAppOutputScopedAllowBaseSyncPrimitives;
307 class ScopedAllowThreadRecallForStackSamplingProfiler;
308 class SimpleThread;
309 class StackSamplingProfiler;
310 class Thread;
311 
312 bool PathProviderWin(int, FilePath*);
313 
314 #if DCHECK_IS_ON()
315 #define INLINE_IF_DCHECK_IS_OFF BASE_EXPORT
316 #define EMPTY_BODY_IF_DCHECK_IS_OFF
317 #else
318 #define INLINE_IF_DCHECK_IS_OFF inline
319 
320 // The static_assert() eats follow-on semicolons. `= default` would work
321 // too, but it makes clang realize that all the Scoped classes are no-ops in
322 // non-dcheck builds and it starts emitting many -Wunused-variable warnings.
323 #define EMPTY_BODY_IF_DCHECK_IS_OFF \
324   {}                                \
325   static_assert(true, "")
326 #endif
327 
328 namespace internal {
329 
330 // Asserts that blocking calls are allowed in the current scope. This is an
331 // internal call, external code should use ScopedBlockingCall instead, which
332 // serves as a precise annotation of the scope that may/will block.
333 INLINE_IF_DCHECK_IS_OFF void AssertBlockingAllowed()
334     EMPTY_BODY_IF_DCHECK_IS_OFF;
335 
336 }  // namespace internal
337 
338 // Disallows blocking on the current thread.
339 INLINE_IF_DCHECK_IS_OFF void DisallowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
340 
341 // Disallows blocking calls within its scope.
342 class BASE_EXPORT ScopedDisallowBlocking {
343  public:
344   ScopedDisallowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
345   ~ScopedDisallowBlocking() EMPTY_BODY_IF_DCHECK_IS_OFF;
346 
347  private:
348 #if DCHECK_IS_ON()
349   const bool was_disallowed_;
350 #endif
351 
352   DISALLOW_COPY_AND_ASSIGN(ScopedDisallowBlocking);
353 };
354 
355 class BASE_EXPORT ScopedAllowBlocking {
356  private:
357   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest, ScopedAllowBlocking);
358   friend class ScopedAllowBlockingForTesting;
359 
360   // This can only be instantiated by friends. Use ScopedAllowBlockingForTesting
361   // in unit tests to avoid the friend requirement.
362   friend class AdjustOOMScoreHelper;
363   friend class StackSamplingProfiler;
364   friend class android_webview::ScopedAllowInitGLBindings;
365   friend class chromeos::MojoUtils;  // http://crbug.com/1055467
366   friend class content::BrowserProcessSubThread;
367   friend class content::RenderProcessHostImpl;
368   friend class content::RenderWidgetHostViewMac;  // http://crbug.com/121917
369   friend class content::WebContentsViewMac;
370   friend class cronet::CronetPrefsManager;
371   friend class cronet::CronetURLRequestContext;
372   friend class memory_instrumentation::OSMetrics;
373   friend class module_installer::ScopedAllowModulePakLoad;
374   friend class mojo::CoreLibraryInitializer;
375   friend class printing::PrintJobWorker;
376   friend class resource_coordinator::TabManagerDelegate;  // crbug.com/778703
377   friend class web::WebSubThread;
378   friend class weblayer::BrowserContextImpl;
379   friend class weblayer::BrowserProcess;
380   friend class weblayer::ProfileImpl;
381   friend class weblayer::WebLayerPathProvider;
382 
383   friend bool PathProviderWin(int, FilePath*);
384 
385   ScopedAllowBlocking(const Location& from_here = Location::Current());
386   ~ScopedAllowBlocking();
387 
388 #if DCHECK_IS_ON()
389   const bool was_disallowed_;
390 #endif
391 
392   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBlocking);
393 };
394 
395 class ScopedAllowBlockingForTesting {
396  public:
ScopedAllowBlockingForTesting()397   ScopedAllowBlockingForTesting() {}
~ScopedAllowBlockingForTesting()398   ~ScopedAllowBlockingForTesting() {}
399 
400  private:
401 #if DCHECK_IS_ON()
402   ScopedAllowBlocking scoped_allow_blocking_;
403 #endif
404 
405   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBlockingForTesting);
406 };
407 
408 INLINE_IF_DCHECK_IS_OFF void DisallowBaseSyncPrimitives()
409     EMPTY_BODY_IF_DCHECK_IS_OFF;
410 
411 class BASE_EXPORT ScopedAllowBaseSyncPrimitives {
412  private:
413   // This can only be instantiated by friends. Use
414   // ScopedAllowBaseSyncPrimitivesForTesting in unit tests to avoid the friend
415   // requirement.
416   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
417                            ScopedAllowBaseSyncPrimitives);
418   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
419                            ScopedAllowBaseSyncPrimitivesResetsState);
420   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
421                            ScopedAllowBaseSyncPrimitivesWithBlockingDisallowed);
422 
423   // Allowed usage:
424   friend class SimpleThread;
425   friend class base::GetAppOutputScopedAllowBaseSyncPrimitives;
426   friend class blink::SourceStream;
427   friend class blink::WorkerThread;
428   friend class blink::scheduler::WorkerThread;
429   friend class chrome_cleaner::SystemReportComponent;
430   friend class content::BrowserMainLoop;
431   friend class content::BrowserProcessSubThread;
432   friend class content::ServiceWorkerContextClient;
433   friend class functions::ExecScriptScopedAllowBaseSyncPrimitives;
434   friend class history_report::HistoryReportJniBridge;
435   friend class internal::TaskTracker;
436   friend class leveldb_env::DBTracker;
437   friend class media::BlockingUrlProtocol;
438   friend class mojo::core::ScopedIPCSupport;
439   friend class net::MultiThreadedCertVerifierScopedAllowBaseSyncPrimitives;
440   friend class rlz_lib::FinancialPing;
441   friend class shell_integration_linux::
442       LaunchXdgUtilityScopedAllowBaseSyncPrimitives;
443   friend class syncer::HttpBridge;
444   friend class syncer::GetLocalChangesRequest;
445   friend class syncer::ModelSafeWorker;
446   friend class webrtc::DesktopConfigurationMonitor;
447 
448   // Usage that should be fixed:
449   friend class ::NativeBackendKWallet;            // http://crbug.com/125331
450   friend class ::chromeos::system::
451       StatisticsProviderImpl;                      // http://crbug.com/125385
452   friend class content::TextInputClientMac;        // http://crbug.com/121917
453   friend class blink::VideoFrameResourceProvider;  // http://crbug.com/878070
454 
455   ScopedAllowBaseSyncPrimitives() EMPTY_BODY_IF_DCHECK_IS_OFF;
456   ~ScopedAllowBaseSyncPrimitives() EMPTY_BODY_IF_DCHECK_IS_OFF;
457 
458 #if DCHECK_IS_ON()
459   const bool was_disallowed_;
460 #endif
461 
462   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBaseSyncPrimitives);
463 };
464 
465 class BASE_EXPORT ScopedAllowBaseSyncPrimitivesOutsideBlockingScope {
466  private:
467   // This can only be instantiated by friends. Use
468   // ScopedAllowBaseSyncPrimitivesForTesting in unit tests to avoid the friend
469   // requirement.
470   FRIEND_TEST_ALL_PREFIXES(ThreadRestrictionsTest,
471                            ScopedAllowBaseSyncPrimitivesOutsideBlockingScope);
472   FRIEND_TEST_ALL_PREFIXES(
473       ThreadRestrictionsTest,
474       ScopedAllowBaseSyncPrimitivesOutsideBlockingScopeResetsState);
475 
476   // Allowed usage:
477   friend class ::BrowserProcessImpl;  // http://crbug.com/125207
478   friend class ::KeyStorageLinux;
479   friend class ::NativeDesktopMediaList;
480   friend class android::JavaHandlerThread;
481   friend class android_webview::
482       AwFormDatabaseService;  // http://crbug.com/904431
483   friend class android_webview::CookieManager;
484   friend class android_webview::VizCompositorThreadRunnerWebView;
485   friend class audio::OutputDevice;
486   friend class base::sequence_manager::internal::TaskQueueImpl;
487   friend class base::FileDescriptorWatcher;
488   friend class base::internal::JobTaskSource;
489   friend class base::ScopedAllowThreadRecallForStackSamplingProfiler;
490   friend class base::StackSamplingProfiler;
491   friend class blink::RTCVideoDecoderAdapter;
492   friend class blink::RTCVideoEncoder;
493   friend class cc::TileTaskManagerImpl;
494   friend class content::CategorizedWorkerPool;
495   friend class content::DesktopCaptureDevice;
496   friend class content::InProcessUtilityThread;
497   friend class content::RTCVideoDecoder;
498   friend class content::SandboxHostLinux;
499   friend class content::ScopedAllowWaitForDebugURL;
500   friend class content::SynchronousCompositor;
501   friend class content::SynchronousCompositorHost;
502   friend class content::SynchronousCompositorSyncCallBridge;
503   friend class media::AudioInputDevice;
504   friend class media::AudioOutputDevice;
505   friend class media::PaintCanvasVideoRenderer;
506   friend class mojo::SyncCallRestrictions;
507   friend class net::NetworkConfigWatcherMacThread;
508   friend class ui::DrmThreadProxy;
509   friend class viz::HostGpuMemoryBufferManager;
510   friend class vr::VrShell;
511 
512   // Usage that should be fixed:
513   friend class ::chromeos::BlockingMethodCaller;  // http://crbug.com/125360
514   friend class base::Thread;                      // http://crbug.com/918039
515   friend class cc::CompletionEvent;               // http://crbug.com/902653
516   friend class content::
517       BrowserGpuChannelHostFactory;                 // http://crbug.com/125248
518   friend class dbus::Bus;                           // http://crbug.com/125222
519   friend class disk_cache::BackendImpl;             // http://crbug.com/74623
520   friend class disk_cache::InFlightIO;              // http://crbug.com/74623
521   friend class gpu::GpuChannelHost;                 // http://crbug.com/125264
522   friend class remoting::protocol::
523       ScopedAllowThreadJoinForWebRtcTransport;      // http://crbug.com/660081
524   friend class midi::TaskService;                   // https://crbug.com/796830
525   friend class net::internal::AddressTrackerLinux;  // http://crbug.com/125097
526   friend class net::
527       MultiThreadedProxyResolverScopedAllowJoinOnIO;  // http://crbug.com/69710
528   friend class net::NetworkChangeNotifierMac;         // http://crbug.com/125097
529   friend class printing::PrinterQuery;                 // http://crbug.com/66082
530   friend class proxy_resolver::
531       ScopedAllowThreadJoinForProxyResolverV8Tracing;  // http://crbug.com/69710
532   friend class remoting::AutoThread;  // https://crbug.com/944316
533   // Not used in production yet, https://crbug.com/844078.
534   friend class service_manager::ServiceProcessLauncher;
535   friend class ui::WindowResizeHelperMac;  // http://crbug.com/902829
536 
537   ScopedAllowBaseSyncPrimitivesOutsideBlockingScope(
538       const Location& from_here = Location::Current());
539 
540   ~ScopedAllowBaseSyncPrimitivesOutsideBlockingScope();
541 
542 #if DCHECK_IS_ON()
543   const bool was_disallowed_;
544 #endif
545 
546   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBaseSyncPrimitivesOutsideBlockingScope);
547 };
548 
549 // Allow base-sync-primitives in tests, doesn't require explicit friend'ing like
550 // ScopedAllowBaseSyncPrimitives-types aimed at production do.
551 // Note: For WaitableEvents in the test logic, base::TestWaitableEvent is
552 // exposed as a convenience to avoid the need for
553 // ScopedAllowBaseSyncPrimitivesForTesting.
554 class BASE_EXPORT ScopedAllowBaseSyncPrimitivesForTesting {
555  public:
556   ScopedAllowBaseSyncPrimitivesForTesting() EMPTY_BODY_IF_DCHECK_IS_OFF;
557   ~ScopedAllowBaseSyncPrimitivesForTesting() EMPTY_BODY_IF_DCHECK_IS_OFF;
558 
559  private:
560 #if DCHECK_IS_ON()
561   const bool was_disallowed_;
562 #endif
563 
564   DISALLOW_COPY_AND_ASSIGN(ScopedAllowBaseSyncPrimitivesForTesting);
565 };
566 
567 // Counterpart to base::DisallowUnresponsiveTasks() for tests to allow them to
568 // block their thread after it was banned.
569 class BASE_EXPORT ScopedAllowUnresponsiveTasksForTesting {
570  public:
571   ScopedAllowUnresponsiveTasksForTesting() EMPTY_BODY_IF_DCHECK_IS_OFF;
572   ~ScopedAllowUnresponsiveTasksForTesting() EMPTY_BODY_IF_DCHECK_IS_OFF;
573 
574  private:
575 #if DCHECK_IS_ON()
576   const bool was_disallowed_base_sync_;
577   const bool was_disallowed_blocking_;
578   const bool was_disallowed_cpu_;
579 #endif
580 
581   DISALLOW_COPY_AND_ASSIGN(ScopedAllowUnresponsiveTasksForTesting);
582 };
583 
584 namespace internal {
585 
586 // Asserts that waiting on a //base sync primitive is allowed in the current
587 // scope.
588 INLINE_IF_DCHECK_IS_OFF void AssertBaseSyncPrimitivesAllowed()
589     EMPTY_BODY_IF_DCHECK_IS_OFF;
590 
591 // Resets all thread restrictions on the current thread.
592 INLINE_IF_DCHECK_IS_OFF void ResetThreadRestrictionsForTesting()
593     EMPTY_BODY_IF_DCHECK_IS_OFF;
594 
595 }  // namespace internal
596 
597 // Asserts that running long CPU work is allowed in the current scope.
598 INLINE_IF_DCHECK_IS_OFF void AssertLongCPUWorkAllowed()
599     EMPTY_BODY_IF_DCHECK_IS_OFF;
600 
601 INLINE_IF_DCHECK_IS_OFF void DisallowUnresponsiveTasks()
602     EMPTY_BODY_IF_DCHECK_IS_OFF;
603 
604 class BASE_EXPORT ThreadRestrictions {
605  public:
606   // Constructing a ScopedAllowIO temporarily allows IO for the current
607   // thread.  Doing this is almost certainly always incorrect.
608   //
609   // DEPRECATED. Use ScopedAllowBlocking(ForTesting).
610   class BASE_EXPORT ScopedAllowIO {
611    public:
612     ScopedAllowIO(const Location& from_here = Location::Current());
613     ~ScopedAllowIO();
614 
615    private:
616 #if DCHECK_IS_ON()
617     const bool was_allowed_;
618 #endif
619 
620     DISALLOW_COPY_AND_ASSIGN(ScopedAllowIO);
621   };
622 
623 #if DCHECK_IS_ON()
624   // Set whether the current thread to make IO calls.
625   // Threads start out in the *allowed* state.
626   // Returns the previous value.
627   //
628   // DEPRECATED. Use ScopedAllowBlocking(ForTesting) or ScopedDisallowBlocking.
629   static bool SetIOAllowed(bool allowed);
630 
631   // Set whether the current thread can use singletons.  Returns the previous
632   // value.
633   static bool SetSingletonAllowed(bool allowed);
634 
635   // Check whether the current thread is allowed to use singletons (Singleton /
636   // LazyInstance).  DCHECKs if not.
637   static void AssertSingletonAllowed();
638 
639   // Disable waiting on the current thread. Threads start out in the *allowed*
640   // state. Returns the previous value.
641   //
642   // DEPRECATED. Use DisallowBaseSyncPrimitives.
643   static void DisallowWaiting();
644 #else
645   // Inline the empty definitions of these functions so that they can be
646   // compiled out.
SetIOAllowed(bool allowed)647   static bool SetIOAllowed(bool allowed) { return true; }
SetSingletonAllowed(bool allowed)648   static bool SetSingletonAllowed(bool allowed) { return true; }
AssertSingletonAllowed()649   static void AssertSingletonAllowed() {}
DisallowWaiting()650   static void DisallowWaiting() {}
651 #endif
652 
653  private:
654   // DO NOT ADD ANY OTHER FRIEND STATEMENTS.
655   // BEGIN ALLOWED USAGE.
656   friend class content::BrowserMainLoop;
657   friend class content::BrowserShutdownProfileDumper;
658   friend class content::BrowserTestBase;
659   friend class content::ScopedAllowWaitForDebugURL;
660   friend class ::HistogramSynchronizer;
661   friend class internal::TaskTracker;
662   friend class web::WebMainLoop;
663   friend class MessagePumpDefault;
664   friend class PlatformThread;
665   friend class ui::CommandBufferClientImpl;
666   friend class ui::CommandBufferLocal;
667   friend class ui::GpuState;
668 
669   // END ALLOWED USAGE.
670   // BEGIN USAGE THAT NEEDS TO BE FIXED.
671   friend class chrome_browser_net::Predictor;     // http://crbug.com/78451
672 #if !defined(OFFICIAL_BUILD)
673   friend class content::SoftwareOutputDeviceMus;  // Interim non-production code
674 #endif
675 // END USAGE THAT NEEDS TO BE FIXED.
676 
677 #if DCHECK_IS_ON()
678   // DEPRECATED. Use ScopedAllowBaseSyncPrimitives.
679   static bool SetWaitAllowed(bool allowed);
680 #else
SetWaitAllowed(bool allowed)681   static bool SetWaitAllowed(bool allowed) { return true; }
682 #endif
683 
684   DISALLOW_IMPLICIT_CONSTRUCTORS(ThreadRestrictions);
685 };
686 
687 #undef INLINE_IF_DCHECK_IS_OFF
688 #undef EMPTY_BODY_IF_DCHECK_IS_OFF
689 
690 }  // namespace base
691 
692 #endif  // BASE_THREADING_THREAD_RESTRICTIONS_H_
693