lorgnette: Obtain port access for pixma backend

The pixma backend needs port access to probe for scanners before
connecting to and interacting with a specific device. Obtain port access
when using the pixma backend to get scanner capabilities or perform a
scan.

BUG=b:162323255
TEST=Use lorgnette_cli with a pixma scanner connected via WiFi

Change-Id: I399017c82040e5421e28e3695d78d751d202e1b4
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/2324004
Tested-by: Jesse Schettler <jschettler@chromium.org>
Reviewed-by: Fletcher Woodruff <fletcherw@chromium.org>
Reviewed-by: Benjamin Gordon <bmgordon@chromium.org>
Commit-Queue: Jesse Schettler <jschettler@chromium.org>
diff --git a/lorgnette/manager.cc b/lorgnette/manager.cc
index 196689b..1ce2f60 100644
--- a/lorgnette/manager.cc
+++ b/lorgnette/manager.cc
@@ -247,6 +247,21 @@
   }
 }
 
+// Uses |firwewall_manager| to request port access if |device_name| corresponds
+// to a SANE backend that needs the access when connecting to a device. The
+// caller should keep the returned object alive as long as port access is
+// needed.
+base::ScopedClosureRunner RequestPortAccessIfNeeded(
+    const std::string& device_name, FirewallManager* firewall_manager) {
+  if (BackendFromDeviceName(device_name) != kPixma)
+    return base::ScopedClosureRunner();
+
+  firewall_manager->RequestScannerPortAccess();
+  return base::ScopedClosureRunner(
+      base::BindOnce([](FirewallManager* fm) { fm->ReleaseAllPortsAccess(); },
+                     firewall_manager));
+}
+
 }  // namespace
 
 const char Manager::kMetricScanRequested[] = "DocumentScan.ScanRequested";
@@ -351,6 +366,8 @@
     return false;
   }
 
+  base::ScopedClosureRunner release_ports =
+      RequestPortAccessIfNeeded(device_name, firewall_manager_.get());
   std::unique_ptr<SaneDevice> device =
       sane_client_->ConnectToDevice(error, device_name);
   if (!device)
@@ -531,6 +548,8 @@
 
   LOG(INFO) << "Scanning image from device " << request.device_name();
 
+  base::ScopedClosureRunner release_ports =
+      RequestPortAccessIfNeeded(request.device_name(), firewall_manager_.get());
   std::unique_ptr<SaneDevice> device =
       sane_client_->ConnectToDevice(error, request.device_name());
   if (!device) {