blob: c608918dfbf9afe4ca94f4b5b3a67dfc68ce1d73 [file] [log] [blame]
// Copyright 2016 The Chromium Authors
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#ifndef MOJO_PUBLIC_CPP_BINDINGS_SYNC_CALL_RESTRICTIONS_H_
#define MOJO_PUBLIC_CPP_BINDINGS_SYNC_CALL_RESTRICTIONS_H_
#include "base/component_export.h"
#include "base/threading/thread_restrictions.h"
#include "build/build_config.h"
#if (!defined(NDEBUG) || defined(DCHECK_ALWAYS_ON))
#define ENABLE_SYNC_CALL_RESTRICTIONS 1
#else
#define ENABLE_SYNC_CALL_RESTRICTIONS 0
#endif
namespace chromecast {
class CastCdmOriginProvider;
} // namespace chromecast
namespace chromeos {
class ChromeOsCdmFactory;
} // namespace chromeos
namespace content {
class AndroidOverlaySyncHelper;
#if BUILDFLAG(IS_WIN)
class DCOMPTextureFactory;
#endif
} // namespace content
namespace gpu {
class CommandBufferProxyImpl;
class GpuChannelHost;
class SharedImageInterfaceProxy;
} // namespace gpu
namespace ui {
class Compositor;
} // namespace ui
namespace viz {
class GpuHostImpl;
class HostFrameSinkManager;
class HostGpuMemoryBufferManager;
} // namespace viz
#if BUILDFLAG(IS_MAC)
namespace web_app {
class WebAppShortcutCopierSyncCallHelper;
} // namespace web_app
#endif
namespace mojo {
class ScopedAllowSyncCallForTesting;
// In some processes, sync calls are disallowed. For example, in the browser
// process we don't want any sync calls to child processes for performance,
// security and stability reasons. SyncCallRestrictions helps to enforce such
// rules.
//
// Before processing a sync call, the bindings call
// SyncCallRestrictions::AssertSyncCallAllowed() to check whether sync calls are
// allowed. By default sync calls are allowed but they may be globally
// disallowed within a process by calling DisallowSyncCall().
//
// If globally disallowed but you but you have a very compelling reason to
// disregard that (which should be very very rare), you can override it by
// constructing a ScopedAllowSyncCall object which allows making sync calls on
// the current sequence during its lifetime.
class COMPONENT_EXPORT(MOJO_CPP_BINDINGS) SyncCallRestrictions {
public:
SyncCallRestrictions() = delete;
SyncCallRestrictions(const SyncCallRestrictions&) = delete;
SyncCallRestrictions& operator=(const SyncCallRestrictions&) = delete;
#if ENABLE_SYNC_CALL_RESTRICTIONS
// Checks whether the current sequence is allowed to make sync calls, and
// causes a DCHECK if not.
static void AssertSyncCallAllowed();
// Disables sync calls within the calling process. Any caller who wishes to
// make sync calls once this has been invoked must do so within the extent of
// a ScopedAllowSyncCall or ScopedAllowSyncCallForTesting.
static void DisallowSyncCall();
#else
// Inline the empty definitions of functions so that they can be compiled out.
static void AssertSyncCallAllowed() {}
static void DisallowSyncCall() {}
#endif
// Globally disables sync call interrupts. This means that all sync calls in
// the current process will be strictly blocking until a reply is received,
// and no incoming sync calls can dispatch on the blocking thread in interim.
static void DisableSyncCallInterrupts();
// Used only in tests to re-enable sync call interrupts after disabling them.
static void EnableSyncCallInterruptsForTesting();
// Indicates whether sync call interrupts are enabled in the calling process.
// They're enabled by default, so any sync message that isn't marked [Sync]
// may have its blocking call interrupted to dispatch other incoming sync
// IPCs which target the blocking thread.
static bool AreSyncCallInterruptsEnabled();
private:
// DO NOT ADD ANY OTHER FRIEND STATEMENTS, talk to mojo/OWNERS first.
// BEGIN ALLOWED USAGE.
// SynchronousCompositorHost is used for Android webview.
friend class content::SynchronousCompositorHost;
friend class mojo::ScopedAllowSyncCallForTesting;
friend class viz::GpuHostImpl;
// For destroying the GL context/surface that draw to a platform window before
// the platform window is destroyed.
friend class viz::HostFrameSinkManager;
friend class viz::HostGpuMemoryBufferManager;
// For preventing frame swaps of wrong size during resize on Windows.
// (https://crbug.com/811945)
friend class ui::Compositor;
// For calling sync mojo API to get cdm origin in the ChromeOS GPU process.
// Migrating to async is non-trivial and has not been prioritized.
// (http://crbug.com/368792274)
friend class chromeos::ChromeOsCdmFactory;
// For calling sync mojo API to get cdm origin. The service and the client are
// running in the same process, so it won't block anything.
// TODO(159346933) Remove once the origin isolation logic is moved outside of
// cast media service.
friend class chromecast::CastCdmOriginProvider;
// Android requires synchronous processing when overlay surfaces are
// destroyed, else behavior is undefined.
friend class content::AndroidOverlaySyncHelper;
// GPU client code uses a few sync IPCs, grandfathered in from legacy IPC.
friend class gpu::GpuChannelHost;
friend class gpu::CommandBufferProxyImpl;
friend class gpu::SharedImageInterfaceProxy;
#if BUILDFLAG(IS_WIN)
friend class content::DCOMPTextureFactory;
#endif
#if BUILDFLAG(IS_MAC)
friend class web_app::WebAppShortcutCopierSyncCallHelper;
#endif
// END ALLOWED USAGE.
#if ENABLE_SYNC_CALL_RESTRICTIONS
static void IncreaseScopedAllowCount();
static void DecreaseScopedAllowCount();
#else
static void IncreaseScopedAllowCount() {}
static void DecreaseScopedAllowCount() {}
#endif
// If a process is configured to disallow sync calls in general, constructing
// a ScopedAllowSyncCall object temporarily allows making sync calls on the
// current sequence. Doing this is almost always incorrect, which is why we
// limit who can use this through friend. If you find yourself needing to use
// this, talk to mojo/OWNERS.
class ScopedAllowSyncCall {
public:
ScopedAllowSyncCall() { IncreaseScopedAllowCount(); }
ScopedAllowSyncCall(const ScopedAllowSyncCall&) = delete;
ScopedAllowSyncCall& operator=(const ScopedAllowSyncCall&) = delete;
~ScopedAllowSyncCall() { DecreaseScopedAllowCount(); }
private:
base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait_;
};
};
class ScopedAllowSyncCallForTesting {
public:
ScopedAllowSyncCallForTesting() {}
ScopedAllowSyncCallForTesting(const ScopedAllowSyncCallForTesting&) = delete;
ScopedAllowSyncCallForTesting& operator=(
const ScopedAllowSyncCallForTesting&) = delete;
~ScopedAllowSyncCallForTesting() {}
private:
SyncCallRestrictions::ScopedAllowSyncCall scoped_allow_sync_call_;
};
} // namespace mojo
#endif // MOJO_PUBLIC_CPP_BINDINGS_SYNC_CALL_RESTRICTIONS_H_