• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 #include "mojo/public/cpp/bindings/sync_call_restrictions.h"
6 
7 #if ENABLE_SYNC_CALL_RESTRICTIONS
8 
9 #include "base/lazy_instance.h"
10 #include "base/logging.h"
11 #include "base/threading/thread_local.h"
12 #include "mojo/public/c/system/core.h"
13 
14 namespace mojo {
15 
16 namespace {
17 
18 class SyncCallSettings {
19  public:
20   static SyncCallSettings* current();
21 
allowed() const22   bool allowed() const {
23     return scoped_allow_count_ > 0 || system_defined_value_;
24   }
25 
IncreaseScopedAllowCount()26   void IncreaseScopedAllowCount() { scoped_allow_count_++; }
DecreaseScopedAllowCount()27   void DecreaseScopedAllowCount() {
28     DCHECK_LT(0u, scoped_allow_count_);
29     scoped_allow_count_--;
30   }
31 
32  private:
33   SyncCallSettings();
34   ~SyncCallSettings();
35 
36   bool system_defined_value_ = true;
37   size_t scoped_allow_count_ = 0;
38 };
39 
40 base::LazyInstance<base::ThreadLocalPointer<SyncCallSettings>>
41     g_sync_call_settings = LAZY_INSTANCE_INITIALIZER;
42 
43 // static
current()44 SyncCallSettings* SyncCallSettings::current() {
45   SyncCallSettings* result = g_sync_call_settings.Pointer()->Get();
46   if (!result) {
47     result = new SyncCallSettings();
48     DCHECK_EQ(result, g_sync_call_settings.Pointer()->Get());
49   }
50   return result;
51 }
52 
SyncCallSettings()53 SyncCallSettings::SyncCallSettings() {
54   MojoResult result = MojoGetProperty(MOJO_PROPERTY_TYPE_SYNC_CALL_ALLOWED,
55                                       &system_defined_value_);
56   DCHECK_EQ(MOJO_RESULT_OK, result);
57 
58   DCHECK(!g_sync_call_settings.Pointer()->Get());
59   g_sync_call_settings.Pointer()->Set(this);
60 }
61 
~SyncCallSettings()62 SyncCallSettings::~SyncCallSettings() {
63   g_sync_call_settings.Pointer()->Set(nullptr);
64 }
65 
66 }  // namespace
67 
68 // static
AssertSyncCallAllowed()69 void SyncCallRestrictions::AssertSyncCallAllowed() {
70   if (!SyncCallSettings::current()->allowed()) {
71       LOG(FATAL) << "Mojo sync calls are not allowed in this process because "
72                  << "they can lead to jank and deadlock. If you must make an "
73                  << "exception, please see "
74                  << "SyncCallRestrictions::ScopedAllowSyncCall and consult "
75                  << "mojo/OWNERS.";
76   }
77 }
78 
79 // static
IncreaseScopedAllowCount()80 void SyncCallRestrictions::IncreaseScopedAllowCount() {
81   SyncCallSettings::current()->IncreaseScopedAllowCount();
82 }
83 
84 // static
DecreaseScopedAllowCount()85 void SyncCallRestrictions::DecreaseScopedAllowCount() {
86   SyncCallSettings::current()->DecreaseScopedAllowCount();
87 }
88 
89 }  // namespace mojo
90 
91 #endif  // ENABLE_SYNC_CALL_RESTRICTIONS
92