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.h" | |
6 | |
7 #include <algorithm> | |
8 | |
9 #include "base/bind.h" | |
10 #include "base/location.h" | |
11 #include "base/sequenced_task_runner.h" | |
12 | |
13 namespace { | |
14 IPC::AttachmentBroker* g_attachment_broker = nullptr; | |
15 } | |
16 | |
17 namespace IPC { | |
18 | |
19 // static | |
20 void AttachmentBroker::SetGlobal(AttachmentBroker* broker) { | |
21 g_attachment_broker = broker; | |
22 } | |
23 | |
24 // static | |
25 AttachmentBroker* AttachmentBroker::GetGlobal() { | |
26 return g_attachment_broker; | |
27 } | |
28 | |
29 AttachmentBroker::AttachmentBroker() : last_unique_id_(0) {} | |
30 AttachmentBroker::~AttachmentBroker() {} | |
31 | |
32 bool AttachmentBroker::GetAttachmentWithId( | |
33 BrokerableAttachment::AttachmentId id, | |
34 scoped_refptr<BrokerableAttachment>* out_attachment) { | |
35 base::AutoLock auto_lock(*get_lock()); | |
36 for (AttachmentVector::iterator it = attachments_.begin(); | |
37 it != attachments_.end(); ++it) { | |
38 if ((*it)->GetIdentifier() == id) { | |
39 *out_attachment = *it; | |
40 attachments_.erase(it); | |
41 return true; | |
42 } | |
43 } | |
44 return false; | |
45 } | |
46 | |
47 void AttachmentBroker::AddObserver( | |
48 AttachmentBroker::Observer* observer, | |
49 const scoped_refptr<base::SequencedTaskRunner>& runner) { | |
50 base::AutoLock auto_lock(*get_lock()); | |
51 auto it = std::find_if(observers_.begin(), observers_.end(), | |
52 [observer](const ObserverInfo& info) { | |
53 return info.observer == observer; | |
54 }); | |
55 if (it == observers_.end()) { | |
56 ObserverInfo info; | |
57 info.observer = observer; | |
58 info.runner = runner; | |
59 info.unique_id = ++last_unique_id_; | |
60 observers_.push_back(info); | |
61 | |
62 // Give the observer a chance to handle attachments that arrived while the | |
63 // observer was handling the message that caused it to register, but our | |
64 // mutex was not yet locked. | |
65 for (const auto& attachment : attachments_) { | |
66 info.runner->PostTask( | |
67 FROM_HERE, | |
68 base::Bind(&AttachmentBroker::NotifyObserver, base::Unretained(this), | |
69 info.unique_id, attachment->GetIdentifier())); | |
70 } | |
71 } | |
72 } | |
73 | |
74 void AttachmentBroker::RemoveObserver(AttachmentBroker::Observer* observer) { | |
75 base::AutoLock auto_lock(*get_lock()); | |
76 auto it = std::find_if(observers_.begin(), observers_.end(), | |
77 [observer](const ObserverInfo& info) { | |
78 return info.observer == observer; | |
79 }); | |
80 if (it != observers_.end()) | |
81 observers_.erase(it); | |
82 } | |
83 | |
84 void AttachmentBroker::RegisterCommunicationChannel( | |
85 Endpoint* endpoint, | |
86 scoped_refptr<base::SingleThreadTaskRunner> runner) { | |
87 NOTREACHED(); | |
88 } | |
89 | |
90 void AttachmentBroker::DeregisterCommunicationChannel(Endpoint* endpoint) { | |
91 NOTREACHED(); | |
92 } | |
93 | |
94 void AttachmentBroker::RegisterBrokerCommunicationChannel(Endpoint* endpoint) { | |
95 NOTREACHED(); | |
96 } | |
97 | |
98 void AttachmentBroker::DeregisterBrokerCommunicationChannel( | |
99 Endpoint* endpoint) { | |
100 NOTREACHED(); | |
101 } | |
102 | |
103 void AttachmentBroker::ReceivedPeerPid(base::ProcessId peer_pid) { | |
104 NOTREACHED(); | |
105 } | |
106 | |
107 bool AttachmentBroker::IsPrivilegedBroker() { | |
108 NOTREACHED(); | |
109 return false; | |
110 } | |
111 | |
112 void AttachmentBroker::HandleReceivedAttachment( | |
113 const scoped_refptr<BrokerableAttachment>& attachment) { | |
114 { | |
115 base::AutoLock auto_lock(*get_lock()); | |
116 attachments_.push_back(attachment); | |
117 } | |
118 NotifyObservers(attachment->GetIdentifier()); | |
119 } | |
120 | |
121 void AttachmentBroker::NotifyObservers( | |
122 const BrokerableAttachment::AttachmentId& id) { | |
123 base::AutoLock auto_lock(*get_lock()); | |
124 | |
125 // Dispatch notifications onto the appropriate task runners. This has two | |
126 // effects: | |
127 // 1. Ensures that the notification is posted from the right task runner. | |
128 // 2. Avoids any complications from re-entrant functions, since one of the | |
129 // observers may be halfway through processing some messages. | |
130 for (const auto& info : observers_) { | |
131 info.runner->PostTask( | |
132 FROM_HERE, base::Bind(&AttachmentBroker::NotifyObserver, | |
133 base::Unretained(this), info.unique_id, id)); | |
134 } | |
135 } | |
136 | |
137 void AttachmentBroker::NotifyObserver( | |
138 int unique_id, | |
139 const BrokerableAttachment::AttachmentId& id) { | |
140 Observer* observer = nullptr; | |
141 { | |
142 // Check that the same observer is still registered. | |
143 base::AutoLock auto_lock(*get_lock()); | |
144 auto it = std::find_if(observers_.begin(), observers_.end(), | |
145 [unique_id](const ObserverInfo& info) { | |
146 return info.unique_id == unique_id; | |
147 }); | |
148 if (it == observers_.end()) | |
149 return; | |
150 observer = it->observer; | |
151 } | |
152 | |
153 observer->ReceivedBrokerableAttachmentWithId(id); | |
154 } | |
155 | |
156 AttachmentBroker::ObserverInfo::ObserverInfo() {} | |
157 AttachmentBroker::ObserverInfo::ObserverInfo(const ObserverInfo& other) = | |
158 default; | |
159 AttachmentBroker::ObserverInfo::~ObserverInfo() {} | |
160 | |
161 } // namespace IPC | |
OLD | NEW |