Commit 0b930628 authored by Jesse Schettler's avatar Jesse Schettler Committed by Commit Bot

scanning: Run cancel callback when cancel completes

When a cancel completes, run the cancel callback instead of the
completion callback. This prevents clients from having to wait for and
handle two separate callbacks when canceling a scan.

Bug: 1059779
Change-Id: I80083a1aed002abbdbf117ddad527c531e32bfba
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2537052Reviewed-by: default avatarSteven Bennetts <stevenjb@chromium.org>
Commit-Queue: Jesse Schettler <jschettler@chromium.org>
Cr-Commit-Position: refs/heads/master@{#827441}
parent 114bc6ab
...@@ -96,13 +96,13 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient { ...@@ -96,13 +96,13 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
weak_ptr_factory_.GetWeakPtr(), std::move(state))); weak_ptr_factory_.GetWeakPtr(), std::move(state)));
} }
void CancelScan(VoidDBusMethodCallback completion_callback) override { void CancelScan(VoidDBusMethodCallback cancel_callback) override {
// Post the task to the proper sequence (since it requires access to // Post the task to the proper sequence (since it requires access to
// scan_job_state_). // scan_job_state_).
base::ThreadTaskRunnerHandle::Get()->PostTask( base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&LorgnetteManagerClientImpl::DoScanCancel, FROM_HERE, base::BindOnce(&LorgnetteManagerClientImpl::DoScanCancel,
weak_ptr_factory_.GetWeakPtr(), weak_ptr_factory_.GetWeakPtr(),
std::move(completion_callback))); std::move(cancel_callback)));
} }
protected: protected:
...@@ -188,13 +188,14 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient { ...@@ -188,13 +188,14 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
}; };
// The state tracked for an in-progress scan job. // The state tracked for an in-progress scan job.
// Contains callbacks used to report progress and job completion or failure, // Contains callbacks used to report job progress, completion, failure, or
// as well as a ScanDataReader which is responsible for reading from the pipe // cancellation, as well as a ScanDataReader which is responsible for reading
// of data into a string. // from the pipe of data into a string.
struct ScanJobState { struct ScanJobState {
VoidDBusMethodCallback completion_callback; VoidDBusMethodCallback completion_callback;
base::RepeatingCallback<void(uint32_t, uint32_t)> progress_callback; base::RepeatingCallback<void(uint32_t, uint32_t)> progress_callback;
base::RepeatingCallback<void(std::string, uint32_t)> page_callback; base::RepeatingCallback<void(std::string, uint32_t)> page_callback;
VoidDBusMethodCallback cancel_callback;
std::unique_ptr<ScanDataReader> scan_data_reader; std::unique_ptr<ScanDataReader> scan_data_reader;
}; };
...@@ -235,12 +236,12 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient { ...@@ -235,12 +236,12 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
// Helper method to actually perform scan cancellation. // Helper method to actually perform scan cancellation.
// We use this method since the scan cancel logic requires that we are running // We use this method since the scan cancel logic requires that we are running
// on the proper sequence. // on the proper sequence.
void DoScanCancel(VoidDBusMethodCallback callback) { void DoScanCancel(VoidDBusMethodCallback cancel_callback) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
if (scan_job_state_.size() == 0) { if (scan_job_state_.size() == 0) {
LOG(ERROR) << "No active scan job to cancel."; LOG(ERROR) << "No active scan job to cancel.";
base::ThreadTaskRunnerHandle::Get()->PostTask( base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), false)); FROM_HERE, base::BindOnce(std::move(cancel_callback), false));
return; return;
} }
...@@ -249,7 +250,7 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient { ...@@ -249,7 +250,7 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
if (scan_job_state_.size() > 1) { if (scan_job_state_.size() > 1) {
LOG(ERROR) << "Multiple scan jobs running; not clear which to cancel."; LOG(ERROR) << "Multiple scan jobs running; not clear which to cancel.";
base::ThreadTaskRunnerHandle::Get()->PostTask( base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), false)); FROM_HERE, base::BindOnce(std::move(cancel_callback), false));
return; return;
} }
...@@ -264,14 +265,17 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient { ...@@ -264,14 +265,17 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
if (!writer.AppendProtoAsArrayOfBytes(request)) { if (!writer.AppendProtoAsArrayOfBytes(request)) {
LOG(ERROR) << "Failed to encode CancelScanRequest protobuf"; LOG(ERROR) << "Failed to encode CancelScanRequest protobuf";
base::ThreadTaskRunnerHandle::Get()->PostTask( base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), false)); FROM_HERE, base::BindOnce(std::move(cancel_callback), false));
return; return;
} }
ScanJobState& state = scan_job_state_.begin()->second;
state.cancel_callback = std::move(cancel_callback);
lorgnette_daemon_proxy_->CallMethod( lorgnette_daemon_proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT, &method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&LorgnetteManagerClientImpl::OnCancelScanResponse, base::BindOnce(&LorgnetteManagerClientImpl::OnCancelScanResponse,
weak_ptr_factory_.GetWeakPtr(), std::move(callback))); weak_ptr_factory_.GetWeakPtr(), uuid));
} }
// Called when ListScanners completes. // Called when ListScanners completes.
...@@ -372,12 +376,20 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient { ...@@ -372,12 +376,20 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
GetNextImage(response_proto.scan_uuid()); GetNextImage(response_proto.scan_uuid());
} }
void OnCancelScanResponse(VoidDBusMethodCallback callback, void OnCancelScanResponse(const std::string& scan_uuid,
dbus::Response* response) { dbus::Response* response) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// If the cancel completed and the scan job has been erased, there's no work
// to do.
auto it = scan_job_state_.find(scan_uuid);
if (it == scan_job_state_.end())
return;
ScanJobState& state = it->second;
DCHECK(!state.cancel_callback.is_null());
if (!response) { if (!response) {
LOG(ERROR) << "Failed to obtain CancelScanResponse"; LOG(ERROR) << "Failed to obtain CancelScanResponse";
std::move(callback).Run(false); std::move(state.cancel_callback).Run(false);
return; return;
} }
...@@ -385,18 +397,18 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient { ...@@ -385,18 +397,18 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
dbus::MessageReader reader(response); dbus::MessageReader reader(response);
if (!reader.PopArrayOfBytesAsProto(&response_proto)) { if (!reader.PopArrayOfBytesAsProto(&response_proto)) {
LOG(ERROR) << "Failed to decode CancelScanResponse proto"; LOG(ERROR) << "Failed to decode CancelScanResponse proto";
std::move(callback).Run(false); std::move(state.cancel_callback).Run(false);
return; return;
} }
// If the cancel request failed, report the cancel as failed via the
// callback. Otherwise, wait for the cancel to complete.
if (!response_proto.success()) { if (!response_proto.success()) {
LOG(ERROR) << "Cancelling scan failed: " LOG(ERROR) << "Cancelling scan failed: "
<< response_proto.failure_reason(); << response_proto.failure_reason();
std::move(callback).Run(false); std::move(state.cancel_callback).Run(false);
return; return;
} }
std::move(callback).Run(true);
} }
// Called when a response to a GetNextImage request is received from // Called when a response to a GetNextImage request is received from
...@@ -467,7 +479,9 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient { ...@@ -467,7 +479,9 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
} else if (signal_proto.state() == lorgnette::SCAN_STATE_CANCELLED) { } else if (signal_proto.state() == lorgnette::SCAN_STATE_CANCELLED) {
VLOG(1) << "Scan job " << signal_proto.scan_uuid() VLOG(1) << "Scan job " << signal_proto.scan_uuid()
<< " has been cancelled."; << " has been cancelled.";
std::move(state.completion_callback).Run(false); if (!state.cancel_callback.is_null())
std::move(state.cancel_callback).Run(true);
scan_job_state_.erase(signal_proto.scan_uuid()); scan_job_state_.erase(signal_proto.scan_uuid());
} }
} }
......
...@@ -59,15 +59,16 @@ class COMPONENT_EXPORT(LORGNETTE_MANAGER) LorgnetteManagerClient ...@@ -59,15 +59,16 @@ class COMPONENT_EXPORT(LORGNETTE_MANAGER) LorgnetteManagerClient
// Requests that lorgnette cancel the currently running scan job. // Requests that lorgnette cancel the currently running scan job.
// When this function returns, that guarantees that cancelling has been // When this function returns, that guarantees that cancelling has been
// requested, but the cancelled scan may not be completely terminated yet. // requested, but the cancelled scan is not completely terminated until
// |cancel_callback| reports a successful result.
// //
// Once CancelScan returns, it is safe to request another scan, because // Once CancelScan() returns, it is safe to request another scan, because
// lorgnette will prevent access to a device until the previous scan job has // lorgnette will prevent access to a device until the previous scan job has
// released it. // released it.
// //
// This function makes the assumption that LorgnetteManagerClient only has one // This function makes the assumption that LorgnetteManagerClient only has one
// scan running at a time. // scan running at a time.
virtual void CancelScan(VoidDBusMethodCallback completion_callback) = 0; virtual void CancelScan(VoidDBusMethodCallback cancel_callback) = 0;
// Factory function, creates a new instance and returns ownership. // Factory function, creates a new instance and returns ownership.
// For normal usage, access the singleton via DBusThreadManager::Get(). // For normal usage, access the singleton via DBusThreadManager::Get().
......
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