Fixes bug in html_viewer that could lead to dropping interface requests
[chromium-blink-merge.git] / chromeos / dbus / shill_third_party_vpn_driver_client.cc
blob7a2832516a85ee914ff64141a0efd2f4306ee683
1 // Copyright 2014 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.
5 #include "chromeos/dbus/shill_third_party_vpn_driver_client.h"
7 #include "base/bind.h"
8 #include "base/stl_util.h"
9 #include "chromeos/dbus/shill_third_party_vpn_observer.h"
10 #include "dbus/bus.h"
11 #include "dbus/message.h"
12 #include "dbus/object_proxy.h"
13 #include "third_party/cros_system_api/dbus/service_constants.h"
15 namespace chromeos {
17 namespace {
19 const char* kSetParametersKeyList[] = {
20 shill::kAddressParameterThirdPartyVpn,
21 shill::kBroadcastAddressParameterThirdPartyVpn,
22 shill::kExclusionListParameterThirdPartyVpn,
23 shill::kInclusionListParameterThirdPartyVpn,
24 shill::kSubnetPrefixParameterThirdPartyVpn,
25 shill::kMtuParameterThirdPartyVpn,
26 shill::kDomainSearchParameterThirdPartyVpn,
27 shill::kDnsServersParameterThirdPartyVpn};
29 // The ShillThirdPartyVpnDriverClient implementation.
30 class ShillThirdPartyVpnDriverClientImpl
31 : public ShillThirdPartyVpnDriverClient {
32 public:
33 ShillThirdPartyVpnDriverClientImpl();
34 ~ShillThirdPartyVpnDriverClientImpl() override;
36 // ShillThirdPartyVpnDriverClient overrides
37 void AddShillThirdPartyVpnObserver(
38 const std::string& object_path_value,
39 ShillThirdPartyVpnObserver* observer) override;
41 void RemoveShillThirdPartyVpnObserver(
42 const std::string& object_path_value) override;
44 void SetParameters(
45 const std::string& object_path_value,
46 const base::DictionaryValue& parameters,
47 const ShillClientHelper::StringCallback& callback,
48 const ShillClientHelper::ErrorCallback& error_callback) override;
50 void UpdateConnectionState(
51 const std::string& object_path_value,
52 const uint32_t connection_state,
53 const base::Closure& callback,
54 const ShillClientHelper::ErrorCallback& error_callback) override;
56 void SendPacket(
57 const std::string& object_path_value,
58 const std::vector<char>& ip_packet,
59 const base::Closure& callback,
60 const ShillClientHelper::ErrorCallback& error_callback) override;
62 protected:
63 void Init(dbus::Bus* bus) override { bus_ = bus; }
65 ShillThirdPartyVpnDriverClient::TestInterface* GetTestInterface() override {
66 return nullptr;
69 private:
70 class HelperInfo {
71 public:
72 explicit HelperInfo(dbus::ObjectProxy* object_proxy);
74 ShillClientHelper* helper() { return &helper_; }
75 ShillThirdPartyVpnObserver* observer() { return observer_; }
77 void set_observer(ShillThirdPartyVpnObserver* observer) {
78 observer_ = observer;
81 base::WeakPtr<HelperInfo> GetWeakPtr() {
82 return weak_ptr_factory_.GetWeakPtr();
85 private:
86 ShillClientHelper helper_;
87 ShillThirdPartyVpnObserver* observer_;
89 base::WeakPtrFactory<HelperInfo> weak_ptr_factory_;
91 using HelperMap = std::map<std::string, HelperInfo*>;
93 static void OnPacketReceived(base::WeakPtr<HelperInfo> helper_info,
94 dbus::Signal* signal);
95 static void OnPlatformMessage(base::WeakPtr<HelperInfo> helper_info,
96 dbus::Signal* signal);
97 static void OnSignalConnected(const std::string& interface,
98 const std::string& signal,
99 bool success);
101 // Returns or creates the corresponding ShillClientHelper for the
102 // |object_path_value|.
103 ShillClientHelper* GetHelper(const std::string& object_path_value);
105 // Returns or creates the corresponding HelperInfo for the
106 // |object_path_value|.
107 HelperInfo* GetHelperInfo(const std::string& object_path_value);
109 // Returns the corresponding HelperInfo for the |object_path| if exists,
110 // nullptr if not.
111 HelperInfo* FindHelperInfo(const dbus::ObjectPath& object_path);
113 // Deletes the helper object corresponding to |object_path|.
114 void DeleteHelper(const dbus::ObjectPath& object_path);
116 dbus::Bus* bus_;
117 HelperMap helpers_;
118 std::set<std::string> valid_keys_;
120 DISALLOW_COPY_AND_ASSIGN(ShillThirdPartyVpnDriverClientImpl);
123 ShillThirdPartyVpnDriverClientImpl::HelperInfo::HelperInfo(
124 dbus::ObjectProxy* object_proxy)
125 : helper_(object_proxy), observer_(nullptr), weak_ptr_factory_(this) {
128 ShillThirdPartyVpnDriverClientImpl::ShillThirdPartyVpnDriverClientImpl()
129 : bus_(nullptr) {
130 for (uint32_t i = 0; i < arraysize(kSetParametersKeyList); ++i) {
131 valid_keys_.insert(kSetParametersKeyList[i]);
135 ShillThirdPartyVpnDriverClientImpl::~ShillThirdPartyVpnDriverClientImpl() {
136 for (auto& iter : helpers_) {
137 HelperInfo* helper_info = iter.second;
138 bus_->RemoveObjectProxy(
139 shill::kFlimflamServiceName,
140 helper_info->helper()->object_proxy()->object_path(),
141 base::Bind(&base::DoNothing));
142 delete helper_info;
146 void ShillThirdPartyVpnDriverClientImpl::AddShillThirdPartyVpnObserver(
147 const std::string& object_path_value,
148 ShillThirdPartyVpnObserver* observer) {
149 HelperInfo* helper_info = GetHelperInfo(object_path_value);
150 if (helper_info->observer()) {
151 LOG(ERROR) << "Observer exists for " << object_path_value;
152 return;
155 // TODO(kaliamoorthi): Remove the const_cast.
156 helper_info->set_observer(observer);
157 dbus::ObjectProxy* proxy =
158 const_cast<dbus::ObjectProxy*>(helper_info->helper()->object_proxy());
160 proxy->ConnectToSignal(
161 shill::kFlimflamThirdPartyVpnInterface, shill::kOnPlatformMessageFunction,
162 base::Bind(&ShillThirdPartyVpnDriverClientImpl::OnPlatformMessage,
163 helper_info->GetWeakPtr()),
164 base::Bind(&ShillThirdPartyVpnDriverClientImpl::OnSignalConnected));
166 proxy->ConnectToSignal(
167 shill::kFlimflamThirdPartyVpnInterface, shill::kOnPacketReceivedFunction,
168 base::Bind(&ShillThirdPartyVpnDriverClientImpl::OnPacketReceived,
169 helper_info->GetWeakPtr()),
170 base::Bind(&ShillThirdPartyVpnDriverClientImpl::OnSignalConnected));
173 void ShillThirdPartyVpnDriverClientImpl::RemoveShillThirdPartyVpnObserver(
174 const std::string& object_path_value) {
175 HelperInfo* helper_info = FindHelperInfo(dbus::ObjectPath(object_path_value));
176 if (!helper_info) {
177 LOG(ERROR) << "Unknown object_path_value " << object_path_value;
178 return;
181 CHECK(helper_info->observer());
182 helper_info->set_observer(nullptr);
183 DeleteHelper(dbus::ObjectPath(object_path_value));
186 void ShillThirdPartyVpnDriverClientImpl::DeleteHelper(
187 const dbus::ObjectPath& object_path) {
188 HelperInfo* helper_info = FindHelperInfo(dbus::ObjectPath(object_path));
189 if (!helper_info) {
190 LOG(ERROR) << "Unknown object_path " << object_path.value();
191 return;
194 bus_->RemoveObjectProxy(shill::kFlimflamServiceName, object_path,
195 base::Bind(&base::DoNothing));
196 helpers_.erase(helpers_.find(object_path.value()));
197 delete helper_info;
200 void ShillThirdPartyVpnDriverClientImpl::SetParameters(
201 const std::string& object_path_value,
202 const base::DictionaryValue& parameters,
203 const ShillClientHelper::StringCallback& callback,
204 const ShillClientHelper::ErrorCallback& error_callback) {
205 dbus::MethodCall method_call(shill::kFlimflamThirdPartyVpnInterface,
206 shill::kSetParametersFunction);
207 dbus::MessageWriter writer(&method_call);
208 dbus::MessageWriter array_writer(nullptr);
209 writer.OpenArray("{ss}", &array_writer);
210 for (base::DictionaryValue::Iterator it(parameters); !it.IsAtEnd();
211 it.Advance()) {
212 if (valid_keys_.find(it.key()) == valid_keys_.end()) {
213 LOG(WARNING) << "Unknown key " << it.key();
214 continue;
216 std::string value;
217 if (!it.value().GetAsString(&value)) {
218 LOG(WARNING) << "Non string value " << it.value();
219 continue;
221 dbus::MessageWriter entry_writer(nullptr);
222 array_writer.OpenDictEntry(&entry_writer);
223 entry_writer.AppendString(it.key());
224 entry_writer.AppendString(value);
225 array_writer.CloseContainer(&entry_writer);
227 writer.CloseContainer(&array_writer);
228 GetHelper(object_path_value)
229 ->CallStringMethodWithErrorCallback(&method_call, callback,
230 error_callback);
233 void ShillThirdPartyVpnDriverClientImpl::UpdateConnectionState(
234 const std::string& object_path_value,
235 const uint32_t connection_state,
236 const base::Closure& callback,
237 const ShillClientHelper::ErrorCallback& error_callback) {
238 dbus::MethodCall method_call(shill::kFlimflamThirdPartyVpnInterface,
239 shill::kUpdateConnectionStateFunction);
240 dbus::MessageWriter writer(&method_call);
241 writer.AppendUint32(connection_state);
242 GetHelper(object_path_value)
243 ->CallVoidMethodWithErrorCallback(&method_call, callback, error_callback);
246 void ShillThirdPartyVpnDriverClientImpl::SendPacket(
247 const std::string& object_path_value,
248 const std::vector<char>& ip_packet,
249 const base::Closure& callback,
250 const ShillClientHelper::ErrorCallback& error_callback) {
251 dbus::MethodCall method_call(shill::kFlimflamThirdPartyVpnInterface,
252 shill::kSendPacketFunction);
253 dbus::MessageWriter writer(&method_call);
254 static_assert(sizeof(uint8_t) == sizeof(char),
255 "Can't reinterpret ip_packet if char is not 8 bit large.");
256 writer.AppendArrayOfBytes(
257 reinterpret_cast<const uint8_t*>(vector_as_array(&ip_packet)),
258 ip_packet.size());
259 GetHelper(object_path_value)
260 ->CallVoidMethodWithErrorCallback(&method_call, callback, error_callback);
263 // static
264 void ShillThirdPartyVpnDriverClientImpl::OnPacketReceived(
265 base::WeakPtr<HelperInfo> helper_info,
266 dbus::Signal* signal) {
267 if (!helper_info || !helper_info->observer())
268 return;
270 dbus::MessageReader reader(signal);
271 const uint8_t* data = nullptr;
272 size_t length = 0;
273 if (reader.PopArrayOfBytes(&data, &length)) {
274 helper_info->observer()->OnPacketReceived(
275 std::vector<char>(data, data + length));
279 // static
280 void ShillThirdPartyVpnDriverClientImpl::OnPlatformMessage(
281 base::WeakPtr<HelperInfo> helper_info,
282 dbus::Signal* signal) {
283 if (!helper_info || !helper_info->observer())
284 return;
286 dbus::MessageReader reader(signal);
287 uint32_t platform_message = 0;
288 if (reader.PopUint32(&platform_message))
289 helper_info->observer()->OnPlatformMessage(platform_message);
292 // static
293 void ShillThirdPartyVpnDriverClientImpl::OnSignalConnected(
294 const std::string& interface,
295 const std::string& signal,
296 bool success) {
297 LOG_IF(ERROR, !success) << "Connect to " << interface << " " << signal
298 << " failed.";
301 ShillClientHelper* ShillThirdPartyVpnDriverClientImpl::GetHelper(
302 const std::string& object_path_value) {
303 return GetHelperInfo(object_path_value)->helper();
306 ShillThirdPartyVpnDriverClientImpl::HelperInfo*
307 ShillThirdPartyVpnDriverClientImpl::FindHelperInfo(
308 const dbus::ObjectPath& object_path) {
309 HelperMap::iterator it = helpers_.find(object_path.value());
310 return (it != helpers_.end()) ? it->second : nullptr;
313 ShillThirdPartyVpnDriverClientImpl::HelperInfo*
314 ShillThirdPartyVpnDriverClientImpl::GetHelperInfo(
315 const std::string& object_path_value) {
316 dbus::ObjectPath object_path(object_path_value);
317 HelperInfo* helper_info = FindHelperInfo(object_path);
318 if (helper_info)
319 return helper_info;
321 // There is no helper for the profile, create it.
322 dbus::ObjectProxy* object_proxy =
323 bus_->GetObjectProxy(shill::kFlimflamServiceName, object_path);
324 helper_info = new HelperInfo(object_proxy);
325 helpers_[object_path_value] = helper_info;
326 return helper_info;
329 } // namespace
331 ShillThirdPartyVpnDriverClient::ShillThirdPartyVpnDriverClient() {
334 ShillThirdPartyVpnDriverClient::~ShillThirdPartyVpnDriverClient() {
337 // static
338 ShillThirdPartyVpnDriverClient* ShillThirdPartyVpnDriverClient::Create() {
339 return new ShillThirdPartyVpnDriverClientImpl();
342 } // namespace chromeos