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