Skip to content

Commit

Permalink
scanning: Add a wrapper for CancelScan
Browse files Browse the repository at this point in the history
The current CancelScan method only works when there is exactly one scan
active at a time.  This is the use-case for the current scan app.  The
new documentScan API allows multiple scans at the same time, each one
having a unique job handle.  Add a wrapper to call the CancelScan method
using this job handle (via the CancelScanRequest message from the
lorgnette protobuf API).

Bug: b:297435346
Change-Id: Ifd73174f085211793ef880e15ac1865a7d51d321
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/4926573
Reviewed-by: Benjamin Gordon <bmgordon@chromium.org>
Commit-Queue: Nathan Muggli <nmuggli@google.com>
Cr-Commit-Position: refs/heads/main@{#1209475}
  • Loading branch information
nmuggli authored and Chromium LUCI CQ committed Oct 13, 2023
1 parent aea0516 commit ed4f83c
Show file tree
Hide file tree
Showing 10 changed files with 263 additions and 25 deletions.
12 changes: 12 additions & 0 deletions chrome/browser/ash/scanning/fake_lorgnette_scanner_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,13 @@ void FakeLorgnetteScannerManager::CancelScan(CancelCallback cancel_callback) {
FROM_HERE, base::BindOnce(std::move(cancel_callback), true));
}

void FakeLorgnetteScannerManager::CancelScan(
const lorgnette::CancelScanRequest& request,
CancelScanCallback callback) {
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), cancel_scan_response_));
}

void FakeLorgnetteScannerManager::SetGetScannerNamesResponse(
const std::vector<std::string>& scanner_names) {
scanner_names_ = scanner_names;
Expand Down Expand Up @@ -210,4 +217,9 @@ void FakeLorgnetteScannerManager::SetScanResponse(
scan_data_ = scan_data;
}

void FakeLorgnetteScannerManager::SetCancelScanResponse(
const absl::optional<lorgnette::CancelScanResponse>& response) {
cancel_scan_response_ = response;
}

} // namespace ash
7 changes: 7 additions & 0 deletions chrome/browser/ash/scanning/fake_lorgnette_scanner_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,8 @@ class FakeLorgnetteScannerManager final : public LorgnetteScannerManager {
PageCallback page_callback,
CompletionCallback completion_callback) override;
void CancelScan(CancelCallback cancel_callback) override;
void CancelScan(const lorgnette::CancelScanRequest& request,
CancelScanCallback callback) override;

// Sets the response returned by GetScannerNames().
void SetGetScannerNamesResponse(
Expand Down Expand Up @@ -79,6 +81,10 @@ class FakeLorgnetteScannerManager final : public LorgnetteScannerManager {
void SetScanResponse(
const absl::optional<std::vector<std::string>>& scan_data);

// Sets the response returned by CancelScan().
void SetCancelScanResponse(
const absl::optional<lorgnette::CancelScanResponse>& response);

private:
std::vector<std::string> scanner_names_;
absl::optional<lorgnette::ListScannersResponse> list_scanners_response_;
Expand All @@ -88,6 +94,7 @@ class FakeLorgnetteScannerManager final : public LorgnetteScannerManager {
absl::optional<lorgnette::StartPreparedScanResponse>
start_prepared_scan_response_;
absl::optional<lorgnette::ReadScanDataResponse> read_scan_data_response_;
absl::optional<lorgnette::CancelScanResponse> cancel_scan_response_;
absl::optional<std::vector<std::string>> scan_data_;
};

Expand Down
15 changes: 15 additions & 0 deletions chrome/browser/ash/scanning/lorgnette_scanner_manager.cc
Original file line number Diff line number Diff line change
Expand Up @@ -287,6 +287,15 @@ class LorgnetteScannerManagerImpl final : public LorgnetteScannerManager {
GetLorgnetteManagerClient()->CancelScan(std::move(cancel_callback));
}

// LorgnetteScannerManager:
void CancelScan(const lorgnette::CancelScanRequest& request,
CancelScanCallback callback) override {
GetLorgnetteManagerClient()->CancelScan(
request,
base::BindOnce(&LorgnetteScannerManagerImpl::OnCancelScanResponse,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

private:
// Called when scanners are detected by a ScannerDetector.
void OnScannersDetected(std::vector<Scanner> scanners) {
Expand Down Expand Up @@ -513,6 +522,12 @@ class LorgnetteScannerManagerImpl final : public LorgnetteScannerManager {
std::move(callback).Run(response);
}

void OnCancelScanResponse(
CancelScanCallback callback,
absl::optional<lorgnette::CancelScanResponse> response) {
std::move(callback).Run(response);
}

// Uses |response| and zeroconf_scanners_ to rebuild deduped_scanners_.
void RebuildDedupedScanners(
absl::optional<lorgnette::ListScannersResponse> response) {
Expand Down
8 changes: 8 additions & 0 deletions chrome/browser/ash/scanning/lorgnette_scanner_manager.h
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,8 @@ class LorgnetteScannerManager : public KeyedService {
using CompletionCallback =
base::OnceCallback<void(lorgnette::ScanFailureMode failure_mode)>;
using CancelCallback = base::OnceCallback<void(bool success)>;
using CancelScanCallback = base::OnceCallback<void(
const absl::optional<lorgnette::CancelScanResponse>& response)>;

~LorgnetteScannerManager() override = default;

Expand Down Expand Up @@ -109,6 +111,12 @@ class LorgnetteScannerManager : public KeyedService {
// Request to cancel the currently running scan job. This function makes the
// assumption that LorgnetteManagerClient only has one scan running at a time.
virtual void CancelScan(CancelCallback cancel_callback) = 0;

// Request to cancel the scan specified by the JobHandle in |request| and
// return the result using the provided |callback|. If an error occurs,
// absl::nullopt is returned in the callback.
virtual void CancelScan(const lorgnette::CancelScanRequest& request,
CancelScanCallback callback) = 0;
};

} // namespace ash
Expand Down
39 changes: 39 additions & 0 deletions chrome/browser/ash/scanning/lorgnette_scanner_manager_unittest.cc
Original file line number Diff line number Diff line change
Expand Up @@ -292,6 +292,15 @@ class LorgnetteScannerManagerTest : public testing::Test {
base::Unretained(this)));
}

// Calls LorgnetteScannerManager::CancelScan() with a CancelScanRequest and
// binds a callback to process the result.
void CancelScanJob() {
lorgnette_scanner_manager_->CancelScan(
lorgnette::CancelScanRequest(),
base::BindOnce(&LorgnetteScannerManagerTest::CancelScanJobCallback,
base::Unretained(this)));
}

// Runs all tasks until the ThreadPool's non-delayed queues are empty.
void CompleteTasks() { task_environment_.RunUntilIdle(); }

Expand Down Expand Up @@ -341,6 +350,10 @@ class LorgnetteScannerManagerTest : public testing::Test {
lorgnette::ScanFailureMode failure_mode() const { return failure_mode_; }
bool cancel_scan_success() const { return cancel_scan_success_; }

absl::optional<lorgnette::CancelScanResponse> cancel_scan_response() const {
return cancel_scan_response_;
}

private:
// Handles the result of calling LorgnetteScannerManager::GetScannerNames().
void GetScannerNamesCallback(std::vector<std::string> scanner_names) {
Expand Down Expand Up @@ -404,6 +417,14 @@ class LorgnetteScannerManagerTest : public testing::Test {
run_loop_->Quit();
}

// Handles completion of LorgnetteScannerManager::CancelScan() when called
// with a CancelScanRequest.
void CancelScanJobCallback(
const absl::optional<lorgnette::CancelScanResponse>& response) {
cancel_scan_response_ = response;
run_loop_->Quit();
}

base::test::TaskEnvironment task_environment_;

std::unique_ptr<base::RunLoop> run_loop_;
Expand All @@ -424,6 +445,7 @@ class LorgnetteScannerManagerTest : public testing::Test {
lorgnette::ScanFailureMode failure_mode_ =
lorgnette::SCAN_FAILURE_MODE_NO_FAILURE;
bool cancel_scan_success_ = false;
absl::optional<lorgnette::CancelScanResponse> cancel_scan_response_;
std::vector<std::string> scan_data_;
};

Expand Down Expand Up @@ -1012,4 +1034,21 @@ TEST_F(LorgnetteScannerManagerTest, CancelScan) {
EXPECT_TRUE(cancel_scan_success());
}

// Test canceling a scan by JobHandle.
TEST_F(LorgnetteScannerManagerTest, CancelScanByJobHandle) {
lorgnette::JobHandle job_handle;
job_handle.set_token("job-handle-token");

lorgnette::CancelScanResponse response;
response.set_success(true);
response.set_result(lorgnette::OPERATION_RESULT_SUCCESS);
*response.mutable_job_handle() = std::move(job_handle);

GetLorgnetteManagerClient()->SetCancelScanResponse(response);
CancelScanJob();
WaitForResult();
ASSERT_TRUE(cancel_scan_response());
EXPECT_THAT(response, EqualsProto(cancel_scan_response().value()));
}

} // namespace ash
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,13 @@ void FakeLorgnetteManagerClient::CancelScan(
FROM_HERE, base::BindOnce(std::move(completion_callback), true));
}

void FakeLorgnetteManagerClient::CancelScan(
const lorgnette::CancelScanRequest& request,
chromeos::DBusMethodCallback<lorgnette::CancelScanResponse> callback) {
base::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), cancel_scan_response_));
}

void FakeLorgnetteManagerClient::StartScannerDiscovery(
const lorgnette::StartScannerDiscoveryRequest& request,
base::RepeatingCallback<void(lorgnette::ScannerListChangedSignal)>
Expand Down Expand Up @@ -153,4 +160,9 @@ void FakeLorgnetteManagerClient::SetScanResponse(
scan_response_ = scan_response;
}

void FakeLorgnetteManagerClient::SetCancelScanResponse(
const absl::optional<lorgnette::CancelScanResponse>& response) {
cancel_scan_response_ = response;
}

} // namespace ash
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,9 @@ class COMPONENT_EXPORT(LORGNETTE_MANAGER) FakeLorgnetteManagerClient
override;
void CancelScan(
chromeos::VoidDBusMethodCallback completion_callback) override;
void CancelScan(const lorgnette::CancelScanRequest& request,
chromeos::DBusMethodCallback<lorgnette::CancelScanResponse>
callback) override;
void StartScannerDiscovery(
const lorgnette::StartScannerDiscoveryRequest& request,
base::RepeatingCallback<void(lorgnette::ScannerListChangedSignal)>
Expand Down Expand Up @@ -99,6 +102,10 @@ class COMPONENT_EXPORT(LORGNETTE_MANAGER) FakeLorgnetteManagerClient
void SetReadScanDataResponse(
const absl::optional<lorgnette::ReadScanDataResponse>& response);

// Sets the response returned by CancelScan().
void SetCancelScanResponse(
const absl::optional<lorgnette::CancelScanResponse>& response);

private:
absl::optional<lorgnette::ListScannersResponse> list_scanners_response_;
absl::optional<lorgnette::ScannerCapabilities> capabilities_response_;
Expand All @@ -107,6 +114,7 @@ class COMPONENT_EXPORT(LORGNETTE_MANAGER) FakeLorgnetteManagerClient
absl::optional<lorgnette::StartPreparedScanResponse>
start_prepared_scan_response_;
absl::optional<lorgnette::ReadScanDataResponse> read_scan_data_response_;
absl::optional<lorgnette::CancelScanResponse> cancel_scan_response_;
absl::optional<std::vector<std::string>> scan_response_;
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -211,6 +211,24 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
std::move(cancel_callback)));
}

void CancelScan(const lorgnette::CancelScanRequest& request,
chromeos::DBusMethodCallback<lorgnette::CancelScanResponse>
callback) override {
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::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(callback), absl::nullopt));
return;
}
lorgnette_daemon_proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&LorgnetteManagerClientImpl::OnCancelScanJobResponse,
weak_ptr_factory_.GetWeakPtr(), std::move(callback)));
}

void StartScannerDiscovery(
const lorgnette::StartScannerDiscoveryRequest& request,
base::RepeatingCallback<void(lorgnette::ScannerListChangedSignal)>
Expand Down Expand Up @@ -445,23 +463,12 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
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::SingleThreadTaskRunner::GetCurrentDefault()->PostTask(
FROM_HERE, base::BindOnce(std::move(cancel_callback), false));
return;
}

ScanJobState& state = scan_job_state_.begin()->second;
state.cancel_callback = std::move(cancel_callback);

lorgnette_daemon_proxy_->CallMethod(
&method_call, dbus::ObjectProxy::TIMEOUT_USE_DEFAULT,
base::BindOnce(&LorgnetteManagerClientImpl::OnCancelScanResponse,
weak_ptr_factory_.GetWeakPtr(), uuid));
CancelScan(request,
base::BindOnce(&LorgnetteManagerClientImpl::OnCancelScanResponse,
weak_ptr_factory_.GetWeakPtr(), uuid));
}

// Called when ListScanners completes.
Expand Down Expand Up @@ -652,8 +659,9 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
std::move(callback).Run(response_proto);
}

void OnCancelScanResponse(const std::string& scan_uuid,
dbus::Response* response) {
void OnCancelScanResponse(
const std::string& scan_uuid,
absl::optional<lorgnette::CancelScanResponse> response) {
DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
// If the cancel completed and the scan job has been erased, there's no work
// to do.
Expand All @@ -672,22 +680,35 @@ class LorgnetteManagerClientImpl : public LorgnetteManagerClient {
return;
}

// If the cancel request failed, report the cancel as failed via the
// callback. Otherwise, wait for the cancel to complete.
if (!response->success()) {
LOG(ERROR) << "Cancelling scan failed: " << response->failure_reason();
std::move(state.cancel_callback).Run(false);
return;
}
}

// Handles the response received after calling CancelScan with a
// CancelScanRequest.
void OnCancelScanJobResponse(
chromeos::DBusMethodCallback<lorgnette::CancelScanResponse> callback,
dbus::Response* response) {
if (!response) {
LOG(ERROR) << "Failed to obtain CancelScanResponse";
std::move(callback).Run(absl::nullopt);
return;
}

lorgnette::CancelScanResponse response_proto;
dbus::MessageReader reader(response);
if (!reader.PopArrayOfBytesAsProto(&response_proto)) {
LOG(ERROR) << "Failed to decode CancelScanResponse proto";
std::move(state.cancel_callback).Run(false);
std::move(callback).Run(absl::nullopt);
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()) {
LOG(ERROR) << "Cancelling scan failed: "
<< response_proto.failure_reason();
std::move(state.cancel_callback).Run(false);
return;
}
std::move(callback).Run(response_proto);
}

// Called when a response to a GetNextImage request is received from
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,6 +111,12 @@ class COMPONENT_EXPORT(LORGNETTE_MANAGER) LorgnetteManagerClient
// scan running at a time.
virtual void CancelScan(chromeos::VoidDBusMethodCallback cancel_callback) = 0;

// Cancels a scan specified by the JobHandle in |request| and returns the
// result using the provided |callback|.
virtual void CancelScan(
const lorgnette::CancelScanRequest& request,
chromeos::DBusMethodCallback<lorgnette::CancelScanResponse> callback) = 0;

// Starts a new scanner discovery session. A handle to the session is
// returned in the response. While the session is active, device update
// callbacks will be made.
Expand Down

0 comments on commit ed4f83c

Please sign in to comment.