Commit a2f6e394 authored by Fletcher Woodruff's avatar Fletcher Woodruff Committed by Commit Bot

scanner: add CancelScan to LorgnetteManagerClient

Add a function to cancel the currently running scan job to
LorgnetteManagerClient. Has the limitation that it only works when one
scan is running.

Bug: b:171821976
Change-Id: Ib60cb27477ee6c26110655dbdd1a408795774585
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2523437
Commit-Queue: Fletcher Woodruff <fletcherw@chromium.org>
Reviewed-by: default avatarJesse Schettler <jschettler@chromium.org>
Cr-Commit-Position: refs/heads/master@{#825688}
parent 0a5ea084
......@@ -62,6 +62,12 @@ void FakeLorgnetteManagerClient::StartScan(
scan_response_ = base::nullopt;
}
void FakeLorgnetteManagerClient::CancelScan(
VoidDBusMethodCallback completion_callback) {
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(completion_callback), true));
}
void FakeLorgnetteManagerClient::SetListScannersResponse(
const base::Optional<lorgnette::ListScannersResponse>&
list_scanners_response) {
......
......@@ -38,6 +38,7 @@ class COMPONENT_EXPORT(LORGNETTE_MANAGER) FakeLorgnetteManagerClient
base::RepeatingCallback<void(std::string, uint32_t)> page_callback,
base::RepeatingCallback<void(uint32_t, uint32_t)> progress_callback)
override;
void CancelScan(VoidDBusMethodCallback completion_callback) override;
// Sets the response returned by ListScanners().
void SetListScannersResponse(
......
......@@ -96,6 +96,15 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
weak_ptr_factory_.GetWeakPtr(), std::move(state)));
}
void CancelScan(VoidDBusMethodCallback completion_callback) override {
// Post the task to the proper sequence (since it requires access to
// scan_job_state_).
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&LorgnetteManagerClientImpl::DoScanCancel,
weak_ptr_factory_.GetWeakPtr(),
std::move(completion_callback)));
}
protected:
void Init(dbus::Bus* bus) override {
lorgnette_daemon_proxy_ =
......@@ -223,6 +232,48 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
weak_ptr_factory_.GetWeakPtr(), uuid));
}
// Helper method to actually perform scan cancellation.
// We use this method since the scan cancel logic requires that we are running
// on the proper sequence.
void DoScanCancel(VoidDBusMethodCallback callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (scan_job_state_.size() == 0) {
LOG(ERROR) << "No active scan job to cancel.";
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), false));
return;
}
// A more robust implementation would pass a scan job identifier to callers
// of StartScan() so they could request cancellation of a particular scan.
if (scan_job_state_.size() > 1) {
LOG(ERROR) << "Multiple scan jobs running; not clear which to cancel.";
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), false));
return;
}
std::string uuid = scan_job_state_.begin()->first;
lorgnette::CancelScanRequest request;
request.set_scan_uuid(uuid);
dbus::MethodCall method_call(lorgnette::kManagerServiceInterface,
lorgnette::kCancelScanMethod);
dbus::MessageWriter writer(&method_call);
if (!writer.AppendProtoAsArrayOfBytes(request)) {
LOG(ERROR) << "Failed to encode CancelScanRequest protobuf";
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), false));
return;
}
lorgnette_daemon_proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&LorgnetteManagerClientImpl::OnCancelScanResponse,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}
// Called when ListScanners completes.
void OnListScanners(
DBusMethodCallback<lorgnette::ListScannersResponse> callback,
......@@ -321,6 +372,33 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
GetNextImage(response_proto.scan_uuid());
}
void OnCancelScanResponse(VoidDBusMethodCallback callback,
dbus::Response* response) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (!response) {
LOG(ERROR) << "Failed to obtain CancelScanResponse";
std::move(callback).Run(false);
return;
}
lorgnette::CancelScanResponse response_proto;
dbus::MessageReader reader(response);
if (!reader.PopArrayOfBytesAsProto(&response_proto)) {
LOG(ERROR) << "Failed to decode CancelScanResponse proto";
std::move(callback).Run(false);
return;
}
if (!response_proto.success()) {
LOG(ERROR) << "Cancelling scan failed: "
<< response_proto.failure_reason();
std::move(callback).Run(false);
return;
}
std::move(callback).Run(true);
}
// Called when a response to a GetNextImage request is received from
// lorgnette. Handles stopping the scan if the request failed.
void OnGetNextImageResponse(std::string uuid, dbus::Response* response) {
......@@ -386,6 +464,11 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
} else if (signal_proto.state() == lorgnette::SCAN_STATE_IN_PROGRESS &&
!state.progress_callback.is_null()) {
state.progress_callback.Run(signal_proto.progress(), signal_proto.page());
} else if (signal_proto.state() == lorgnette::SCAN_STATE_CANCELLED) {
VLOG(1) << "Scan job " << signal_proto.scan_uuid()
<< " has been cancelled.";
std::move(state.completion_callback).Run(false);
scan_job_state_.erase(signal_proto.scan_uuid());
}
}
......
......@@ -57,6 +57,18 @@ class COMPONENT_EXPORT(LORGNETTE_MANAGER) LorgnetteManagerClient
base::RepeatingCallback<void(std::string, uint32_t)> page_callback,
base::RepeatingCallback<void(uint32_t, uint32_t)> progress_callback) = 0;
// Requests that lorgnette cancel the currently running scan job.
// When this function returns, that guarantees that cancelling has been
// requested, but the cancelled scan may not be completely terminated yet.
//
// Once CancelScan returns, it is safe to request another scan, because
// lorgnette will prevent access to a device until the previous scan job has
// released it.
//
// This function makes the assumption that LorgnetteManagerClient only has one
// scan running at a time.
virtual void CancelScan(VoidDBusMethodCallback completion_callback) = 0;
// Factory function, creates a new instance and returns ownership.
// For normal usage, access the singleton via DBusThreadManager::Get().
static std::unique_ptr<LorgnetteManagerClient> Create();
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment