blob: aabe92e774204b540f825334060a40f7ec4e1b17 [file] [log] [blame]
// Copyright 2021 The Chromium OS Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <memory>
#include <string>
#include <utility>
#include <base/bind.h>
#include <base/logging.h>
#include <base/memory/scoped_refptr.h>
#include <base/strings/string_number_conversions.h>
#include <base/strings/string_piece.h>
#include <dbus/bus.h>
#include <dbus/object_path.h>
#include <dbus/message.h>
#include <chromeos/dbus/service_constants.h>
#include "missive/dbus/upload_client.h"
#include "missive/proto/interface.pb.h"
#include "missive/proto/record.pb.h"
#include "missive/util/status.h"
#include "missive/util/statusor.h"
namespace reporting {
UploadClient::UploadClient(scoped_refptr<dbus::Bus> bus,
dbus::ObjectProxy* chrome_proxy)
: bus_(bus), chrome_proxy_(chrome_proxy) {}
UploadClient::~UploadClient() = default;
// static
scoped_refptr<UploadClient> UploadClient::Create() {
dbus::Bus::Options options;
options.bus_type = dbus::Bus::SYSTEM;
// Despite being a base::RefCountedThreadSafe object, dbus::Bus doesn't follow
// the normal pattern of creation. The constructor is public and this is the
// standard usage.
scoped_refptr<dbus::Bus> bus(new dbus::Bus(options));
CHECK(bus->Connect());
CHECK(bus->SetUpAsyncOperations());
dbus::ObjectProxy* chrome_proxy = bus->GetObjectProxy(
chromeos::kChromeReportingServiceName,
dbus::ObjectPath(chromeos::kChromeReportingServicePath));
CHECK(chrome_proxy);
return Create(bus, chrome_proxy);
}
// static
scoped_refptr<UploadClient> UploadClient::Create(
scoped_refptr<dbus::Bus> bus, dbus::ObjectProxy* chrome_proxy) {
return base::WrapRefCounted(new UploadClient(bus, chrome_proxy));
}
void UploadClient::SendEncryptedRecords(
std::unique_ptr<std::vector<EncryptedRecord>> records,
const bool need_encryption_keys,
HandleUploadResponseCallback response_callback) {
// Build the request.
UploadEncryptedRecordRequest request;
for (const auto& record : *records) {
request.add_encrypted_record()->CheckTypeAndMergeFrom(record);
}
request.set_need_encryption_keys(need_encryption_keys);
// Make the call to Chrome
dbus::MethodCall call(
chromeos::kChromeReportingServiceInterface,
chromeos::kChromeReportingServiceUploadEncryptedRecordMethod);
dbus::MessageWriter writer(&call);
if (!writer.AppendProtoAsArrayOfBytes(request)) {
Status status(error::UNKNOWN,
"MessageWriter was unable to append the request.");
LOG(ERROR) << status;
std::move(response_callback).Run(status);
return;
}
chrome_proxy_->CallMethod(
&call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&UploadClient::HandleUploadEncryptedRecordResponse,
weak_ptr_factory_.GetWeakPtr(),
std::move(response_callback)));
}
void UploadClient::HandleUploadEncryptedRecordResponse(
HandleUploadResponseCallback response_callback,
dbus::Response* response) const {
dbus::MessageReader reader(response);
UploadEncryptedRecordResponse response_proto;
if (!reader.PopArrayOfBytesAsProto(&response_proto)) {
std::move(response_callback)
.Run(Status(error::INTERNAL, "Response was not parseable."));
return;
}
std::move(response_callback).Run(std::move(response_proto));
}
} // namespace reporting