Commit 0dd38b8f authored by Gavin Williams's avatar Gavin Williams Committed by Commit Bot

scanning: Add CancelScan to Scanning mojo and ScanService

This change adds CancelScan to the Scanning mojo then calls it from
ScanService.

In ScanService, when the cancel completes and OnCancelCompleted is
called, OnScanCompleted will not be called afterwards. And the same
vice versa, if a cancel is requested but the scan finishes first and
calls OnScanCompleted, we will not then call OnCancelCompleted.

Bug: 1059779
Change-Id: Iabea43d9498f41d3f42633c2ac8601f27f3ec81e
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2533193
Commit-Queue: Gavin Williams <gavinwill@chromium.org>
Reviewed-by: default avatarJesse Schettler <jschettler@chromium.org>
Reviewed-by: default avatarDaniel Cheng <dcheng@chromium.org>
Cr-Commit-Position: refs/heads/master@{#827535}
parent ea88a8bd
......@@ -90,7 +90,12 @@ void ScanService::StartScan(
return;
}
scan_job_observer_.reset();
scan_job_observer_.Bind(std::move(observer));
// Unretained is safe here, because `this` owns `scan_job_observer_`, and no
// reply callbacks will be invoked once the mojo::Remote is destroyed.
scan_job_observer_.set_disconnect_handler(
base::BindOnce(&ScanService::CancelScan, base::Unretained(this)));
base::Time::Now().LocalExplode(&start_time_);
save_failed_ = false;
......@@ -106,6 +111,11 @@ void ScanService::StartScan(
std::move(callback).Run(true);
}
void ScanService::CancelScan() {
lorgnette_scanner_manager_->CancelScan(base::BindOnce(
&ScanService::OnCancelCompleted, weak_ptr_factory_.GetWeakPtr()));
}
void ScanService::BindInterface(
mojo::PendingReceiver<mojo_ipc::ScanService> pending_receiver) {
receiver_.Bind(std::move(pending_receiver));
......@@ -159,7 +169,6 @@ void ScanService::OnScannerCapabilitiesReceived(
void ScanService::OnProgressPercentReceived(uint32_t progress_percent,
uint32_t page_number) {
DCHECK_LE(progress_percent, kMaxProgressPercent);
DCHECK(scan_job_observer_.is_connected());
scan_job_observer_->OnPageProgress(page_number, progress_percent);
}
......@@ -171,7 +180,6 @@ void ScanService::OnPageReceived(const base::FilePath& scan_to_path,
// vector.
// In case the last reported progress percent was less than 100, send one
// final progress event before the page complete event.
DCHECK(scan_job_observer_.is_connected());
scan_job_observer_->OnPageProgress(page_number, kMaxProgressPercent);
scan_job_observer_->OnPageComplete(
std::vector<uint8_t>(scanned_image.begin(), scanned_image.end()));
......@@ -208,9 +216,11 @@ void ScanService::OnPageReceived(const base::FilePath& scan_to_path,
}
void ScanService::OnScanCompleted(bool success) {
DCHECK(scan_job_observer_.is_connected());
scan_job_observer_->OnScanComplete(success && !save_failed_);
scan_job_observer_.reset();
}
void ScanService::OnCancelCompleted(bool success) {
scan_job_observer_->OnCancelComplete(success);
}
bool ScanService::FilePathSupported(const base::FilePath& file_path) {
......
......@@ -48,6 +48,7 @@ class ScanService : public scanning::mojom::ScanService, public KeyedService {
scanning::mojom::ScanSettingsPtr settings,
mojo::PendingRemote<scanning::mojom::ScanJobObserver> observer,
StartScanCallback callback) override;
void CancelScan() override;
// Binds receiver_ by consuming |pending_receiver|.
void BindInterface(
......@@ -90,6 +91,10 @@ class ScanService : public scanning::mojom::ScanService, public KeyedService {
// Processes the final result of calling LorgnetteScannerManager::Scan().
void OnScanCompleted(bool success);
// Processes the final result of calling
// LorgnetteScannerManager::CancelScan().
void OnCancelCompleted(bool success);
// TODO(jschettler): Replace this with a generic helper function when one is
// available.
// Determines whether the service supports saving scanned images to
......
......@@ -88,6 +88,10 @@ class FakeScanJobObserver : public mojo_ipc::ScanJobObserver {
void OnScanComplete(bool success) override { scan_success_ = success; }
void OnCancelComplete(bool success) override {
cancel_scan_success_ = success;
}
// Creates a pending remote that can be passed in calls to
// ScanService::StartScan().
mojo::PendingRemote<mojo_ipc::ScanJobObserver> GenerateRemote() {
......@@ -104,10 +108,14 @@ class FakeScanJobObserver : public mojo_ipc::ScanJobObserver {
return progress_ == 100 && page_complete_ && scan_success_;
}
// Returns true if the cancel scan request completed successfully.
bool cancel_scan_success() const { return cancel_scan_success_; }
private:
uint32_t progress_ = 0;
bool page_complete_ = false;
bool scan_success_ = false;
bool cancel_scan_success_ = false;
mojo::Receiver<mojo_ipc::ScanJobObserver> receiver_{this};
};
......@@ -152,6 +160,12 @@ class ScanServiceTest : public testing::Test {
return success;
}
// Performs a cancel scan request.
void CancelScan() {
scan_service_remote_->CancelScan();
scan_service_remote_.FlushForTesting();
}
protected:
base::ScopedTempDir temp_dir_;
FakeLorgnetteScannerManager fake_lorgnette_scanner_manager_;
......@@ -295,4 +309,21 @@ TEST_F(ScanServiceTest, Scan) {
}
}
// Test that canceling sends an update to the observer OnCancelComplete().
TEST_F(ScanServiceTest, CancelScanBeforeScanCompletes) {
fake_lorgnette_scanner_manager_.SetGetScannerNamesResponse(
{kFirstTestScannerName});
fake_lorgnette_scanner_manager_.SetScanResponse("TestData");
auto scanners = GetScanners();
ASSERT_EQ(scanners.size(), 1u);
scan_service_.SetMyFilesPathForTesting(temp_dir_.GetPath());
mojo_ipc::ScanSettings settings;
settings.scan_to_path = temp_dir_.GetPath();
Scan(scanners[0]->id, settings.Clone());
CancelScan();
EXPECT_TRUE(fake_scan_job_observer_.cancel_scan_success());
}
} // namespace chromeos
......@@ -206,6 +206,10 @@ class FakeScanService {
resolve({success: true});
});
}
cancelScan() {
this.methodCalled('cancelScan');
}
}
export function scanningAppTest() {
......
......@@ -105,6 +105,10 @@ interface ScanJobObserver {
// Called when the scan is complete. |success| indicates whether the scan
// completed successfully.
OnScanComplete(bool success);
// Called when canceling the current scan job is complete. |success|
// indicates whether the scan job was cancelled successfully.
OnCancelComplete(bool success);
};
// Interface used to obtain information about and interact with connected
......@@ -127,4 +131,8 @@ interface ScanService {
// |observer|. |success| indicates whether the scan started successfully.
StartScan(mojo_base.mojom.UnguessableToken scanner_id, ScanSettings settings,
pending_remote<ScanJobObserver> observer) => (bool success);
// Attempts to cancel the currently running scan job. The success of the
// cancel attempt is reported through the ScanJobObserver.
CancelScan();
};
......@@ -386,6 +386,12 @@ Polymer({
return this.i18n(fileSavedText);
},
/**
* Overrides chromeos.scanning.mojom.ScanJobObserverInterface.
* @param {boolean} success
*/
onCancelComplete(success) {},
/**
* Sets the app state if the state transition is allowed.
* @param {!AppState} newState
......
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