| OLD | NEW |
| (Empty) |
| 1 // Copyright 2015 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 "ipc/attachment_broker_privileged.h" | |
| 6 | |
| 7 #include <algorithm> | |
| 8 #include <memory> | |
| 9 | |
| 10 #include "base/bind.h" | |
| 11 #include "base/lazy_instance.h" | |
| 12 #include "base/location.h" | |
| 13 #include "base/memory/ptr_util.h" | |
| 14 #include "base/metrics/histogram_macros.h" | |
| 15 #include "build/build_config.h" | |
| 16 #include "ipc/ipc_endpoint.h" | |
| 17 | |
| 18 #if defined(OS_WIN) | |
| 19 #include "ipc/attachment_broker_privileged_win.h" | |
| 20 #endif | |
| 21 | |
| 22 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
| 23 #include <mach/mach.h> | |
| 24 | |
| 25 #include "base/process/port_provider_mac.h" | |
| 26 #include "ipc/attachment_broker_privileged_mac.h" | |
| 27 #endif | |
| 28 | |
| 29 namespace IPC { | |
| 30 | |
| 31 namespace { | |
| 32 | |
| 33 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
| 34 | |
| 35 // A fake port provider that does nothing. Intended for single process unit | |
| 36 // tests. | |
| 37 class FakePortProvider : public base::PortProvider { | |
| 38 mach_port_t TaskForPid(base::ProcessHandle process) const override { | |
| 39 DCHECK_EQ(process, getpid()); | |
| 40 return mach_task_self(); | |
| 41 } | |
| 42 }; | |
| 43 | |
| 44 base::LazyInstance<FakePortProvider>::Leaky | |
| 45 g_fake_port_provider = LAZY_INSTANCE_INITIALIZER; | |
| 46 | |
| 47 // Passed as a constructor parameter to AttachmentBrokerPrivilegedMac. | |
| 48 base::PortProvider* g_port_provider = nullptr; | |
| 49 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | |
| 50 | |
| 51 // On platforms that support attachment brokering, returns a new instance of | |
| 52 // a platform-specific attachment broker. Otherwise returns |nullptr|. | |
| 53 // The caller takes ownership of the newly created instance, and is | |
| 54 // responsible for ensuring that the attachment broker lives longer than | |
| 55 // every IPC::Channel. The new instance automatically registers itself as the | |
| 56 // global attachment broker. | |
| 57 std::unique_ptr<AttachmentBrokerPrivileged> CreateBroker() { | |
| 58 #if defined(OS_WIN) | |
| 59 return base::WrapUnique(new IPC::AttachmentBrokerPrivilegedWin); | |
| 60 #elif defined(OS_MACOSX) && !defined(OS_IOS) | |
| 61 return base::MakeUnique<IPC::AttachmentBrokerPrivilegedMac>(g_port_provider); | |
| 62 #else | |
| 63 return nullptr; | |
| 64 #endif | |
| 65 } | |
| 66 | |
| 67 // This class is wrapped in a LazyInstance to ensure that its constructor is | |
| 68 // only called once. The constructor creates an attachment broker and sets it as | |
| 69 // the global broker. | |
| 70 class AttachmentBrokerMakeOnce { | |
| 71 public: | |
| 72 AttachmentBrokerMakeOnce() : attachment_broker_(CreateBroker()) {} | |
| 73 | |
| 74 private: | |
| 75 std::unique_ptr<IPC::AttachmentBrokerPrivileged> attachment_broker_; | |
| 76 }; | |
| 77 | |
| 78 base::LazyInstance<AttachmentBrokerMakeOnce>::Leaky | |
| 79 g_attachment_broker_make_once = LAZY_INSTANCE_INITIALIZER; | |
| 80 | |
| 81 } // namespace | |
| 82 | |
| 83 AttachmentBrokerPrivileged::AttachmentBrokerPrivileged() { | |
| 84 IPC::AttachmentBroker::SetGlobal(this); | |
| 85 } | |
| 86 | |
| 87 AttachmentBrokerPrivileged::~AttachmentBrokerPrivileged() { | |
| 88 IPC::AttachmentBroker::SetGlobal(nullptr); | |
| 89 } | |
| 90 | |
| 91 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
| 92 // static | |
| 93 void AttachmentBrokerPrivileged::CreateBrokerIfNeeded( | |
| 94 base::PortProvider* provider) { | |
| 95 g_port_provider = provider; | |
| 96 g_attachment_broker_make_once.Get(); | |
| 97 } | |
| 98 #else | |
| 99 // static | |
| 100 void AttachmentBrokerPrivileged::CreateBrokerIfNeeded() { | |
| 101 g_attachment_broker_make_once.Get(); | |
| 102 } | |
| 103 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | |
| 104 | |
| 105 // static | |
| 106 void AttachmentBrokerPrivileged::CreateBrokerForSingleProcessTests() { | |
| 107 #if defined(OS_MACOSX) && !defined(OS_IOS) | |
| 108 CreateBrokerIfNeeded(&g_fake_port_provider.Get()); | |
| 109 #else | |
| 110 CreateBrokerIfNeeded(); | |
| 111 #endif // defined(OS_MACOSX) && !defined(OS_IOS) | |
| 112 } | |
| 113 | |
| 114 void AttachmentBrokerPrivileged::RegisterCommunicationChannel( | |
| 115 Endpoint* endpoint, | |
| 116 scoped_refptr<base::SingleThreadTaskRunner> runner) { | |
| 117 base::AutoLock auto_lock(*get_lock()); | |
| 118 endpoint->SetAttachmentBrokerEndpoint(true); | |
| 119 auto it = std::find_if(endpoints_.begin(), endpoints_.end(), | |
| 120 [endpoint](const EndpointRunnerPair& pair) { | |
| 121 return pair.first == endpoint; | |
| 122 }); | |
| 123 DCHECK(endpoints_.end() == it); | |
| 124 endpoints_.push_back(std::make_pair(endpoint, runner)); | |
| 125 } | |
| 126 | |
| 127 void AttachmentBrokerPrivileged::DeregisterCommunicationChannel( | |
| 128 Endpoint* endpoint) { | |
| 129 base::AutoLock auto_lock(*get_lock()); | |
| 130 auto it = std::find_if(endpoints_.begin(), endpoints_.end(), | |
| 131 [endpoint](const EndpointRunnerPair& pair) { | |
| 132 return pair.first == endpoint; | |
| 133 }); | |
| 134 if (it != endpoints_.end()) | |
| 135 endpoints_.erase(it); | |
| 136 } | |
| 137 | |
| 138 bool AttachmentBrokerPrivileged::IsPrivilegedBroker() { | |
| 139 return true; | |
| 140 } | |
| 141 | |
| 142 AttachmentBrokerPrivileged::EndpointRunnerPair | |
| 143 AttachmentBrokerPrivileged::GetSenderWithProcessId(base::ProcessId id) { | |
| 144 get_lock()->AssertAcquired(); | |
| 145 auto it = std::find_if(endpoints_.begin(), endpoints_.end(), | |
| 146 [id](const EndpointRunnerPair& pair) { | |
| 147 return pair.first->GetPeerPID() == id; | |
| 148 }); | |
| 149 if (it == endpoints_.end()) | |
| 150 return std::make_pair(nullptr, nullptr); | |
| 151 return *it; | |
| 152 } | |
| 153 | |
| 154 void AttachmentBrokerPrivileged::SendMessageToEndpoint(EndpointRunnerPair pair, | |
| 155 Message* message) { | |
| 156 if (!pair.second || pair.second->BelongsToCurrentThread()) { | |
| 157 pair.first->Send(message); | |
| 158 } else { | |
| 159 pair.second->PostTask( | |
| 160 FROM_HERE, | |
| 161 base::Bind(&AttachmentBrokerPrivileged::SendMessageToEndpoint, | |
| 162 base::Unretained(this), pair, message)); | |
| 163 } | |
| 164 } | |
| 165 | |
| 166 void AttachmentBrokerPrivileged::LogError(UMAError error) { | |
| 167 UMA_HISTOGRAM_ENUMERATION( | |
| 168 "IPC.AttachmentBrokerPrivileged.BrokerAttachmentError", error, ERROR_MAX); | |
| 169 } | |
| 170 | |
| 171 } // namespace IPC | |
| OLD | NEW |