Commit d00ff1d2 authored by Alan Screen's avatar Alan Screen Committed by Chromium LUCI CQ

Add GetPrinterSemanticCapsAndDefaults to print backend service

Incorporate support for retrieving a printer's semantic capabilities
and defaults from the utility service instead of within the browser
process.  This protects the browser from potential crashes as well as
reducing jank by not having the UI thread blocked waiting on the call
to return.

Bug: 809738
Change-Id: I900939877679fe09a245b4796e6b1bb0110eec71
Reviewed-on: https://chromium-review.googlesource.com/c/chromium/src/+/2441668Reviewed-by: default avatarMartin Barbella <mbarbella@chromium.org>
Reviewed-by: default avatarRebekah Potter <rbpotter@chromium.org>
Reviewed-by: default avatarDaniel Hosseinian <dhoss@chromium.org>
Commit-Queue: Alan Screen <awscreen@chromium.org>
Cr-Commit-Position: refs/heads/master@{#834557}
parent 31d81cce
......@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include <stdint.h>
#include <memory>
#include <string>
#include <utility>
......@@ -27,6 +29,9 @@ namespace printing {
namespace {
constexpr char kDefaultPrinterName[] = "default-test-printer";
constexpr char kInvalidPrinterName[] = "invalid-test-printer";
constexpr int32_t kCopiesMax = 123;
} // namespace
......@@ -82,8 +87,12 @@ class PrintBackendBrowserTest : public InProcessBrowserTest {
/*printer_status=*/0, /*is_default=*/true,
/*options=*/PrinterBasicInfoOptions{});
// Only explicitly specify capabilities that we pay attention to in the
// tests.
auto default_caps = std::make_unique<PrinterSemanticCapsAndDefaults>();
default_caps->copies_max = kCopiesMax;
print_backend_service_->test_print_backend_->AddValidPrinter(
kDefaultPrinterName, nullptr, std::move(printer_info));
kDefaultPrinterName, std::move(default_caps), std::move(printer_info));
}
// Public callbacks used by tests.
......@@ -94,17 +103,26 @@ class PrintBackendBrowserTest : public InProcessBrowserTest {
CheckForQuit();
}
void OnDidGetPrinterSemanticCapsAndDefaults(
base::Optional<PrinterSemanticCapsAndDefaults>* capture_printer_caps,
const base::Optional<PrinterSemanticCapsAndDefaults>& printer_caps) {
*capture_printer_caps = printer_caps;
CheckForQuit();
}
// The following are helper functions for having a wait loop in the test and
// exit when expected messages are received.
// exit when expected messages are received. Expect to only have to wait for
// one message.
void WaitUntilCallbackReceived() {
if (received_message_) {
// Callback happened before even needing to wait.
return;
// If callback happened before getting here, then no need to wait.
if (!received_message_) {
base::RunLoop run_loop;
quit_callback_ = run_loop.QuitClosure();
run_loop.Run();
}
base::RunLoop run_loop;
quit_callback_ = run_loop.QuitClosure();
run_loop.Run();
// Reset for possible subsequent test.
received_message_ = false;
}
void CheckForQuit() {
......@@ -130,6 +148,7 @@ class PrintBackendBrowserTest : public InProcessBrowserTest {
// without having performed initialization.
IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest, FailWithoutInit) {
base::Optional<std::string> default_printer_name;
base::Optional<PrinterSemanticCapsAndDefaults> printer_caps;
// Safe to use base::Unretained(this) since waiting locally on the callback
// forces a shorter lifetime than `this`.
......@@ -138,6 +157,14 @@ IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest, FailWithoutInit) {
base::Unretained(this), &default_printer_name));
WaitUntilCallbackReceived();
EXPECT_FALSE(default_printer_name.has_value());
GetPrintBackendService()->GetPrinterSemanticCapsAndDefaults(
kDefaultPrinterName,
base::BindOnce(
&PrintBackendBrowserTest::OnDidGetPrinterSemanticCapsAndDefaults,
base::Unretained(this), &printer_caps));
WaitUntilCallbackReceived();
EXPECT_FALSE(printer_caps.has_value());
}
IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest, GetDefaultPrinterName) {
......@@ -155,4 +182,31 @@ IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest, GetDefaultPrinterName) {
EXPECT_EQ(default_printer_name.value(), kDefaultPrinterName);
}
IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest,
GetPrinterSemanticCapsAndDefaults) {
base::Optional<PrinterSemanticCapsAndDefaults> printer_caps;
DoInitAndSetupTestData();
// Safe to use base::Unretained(this) since waiting locally on the callback
// forces a shorter lifetime than `this`.
GetPrintBackendService()->GetPrinterSemanticCapsAndDefaults(
kDefaultPrinterName,
base::BindOnce(
&PrintBackendBrowserTest::OnDidGetPrinterSemanticCapsAndDefaults,
base::Unretained(this), &printer_caps));
WaitUntilCallbackReceived();
EXPECT_TRUE(printer_caps.has_value());
EXPECT_EQ(printer_caps->copies_max, kCopiesMax);
// Requesting for an invalid printer should not return capabilities.
GetPrintBackendService()->GetPrinterSemanticCapsAndDefaults(
kInvalidPrinterName,
base::BindOnce(
&PrintBackendBrowserTest::OnDidGetPrinterSemanticCapsAndDefaults,
base::Unretained(this), &printer_caps));
WaitUntilCallbackReceived();
EXPECT_FALSE(printer_caps.has_value());
}
} // namespace printing
......@@ -37,4 +37,25 @@ void PrintBackendServiceImpl::GetDefaultPrinterName(
std::move(callback).Run(print_backend_->GetDefaultPrinterName());
}
void PrintBackendServiceImpl::GetPrinterSemanticCapsAndDefaults(
const std::string& printer_name,
mojom::PrintBackendService::GetPrinterSemanticCapsAndDefaultsCallback
callback) {
if (!print_backend_) {
std::move(callback).Run(base::nullopt);
return;
}
PrinterSemanticCapsAndDefaults printer_caps;
const bool result = print_backend_->GetPrinterSemanticCapsAndDefaults(
printer_name, &printer_caps);
if (!result) {
DLOG(ERROR) << "GetPrinterSemanticCapsAndDefaults failed, last error is "
<< logging::GetLastSystemErrorCode();
std::move(callback).Run(base::nullopt);
return;
}
std::move(callback).Run(std::move(printer_caps));
}
} // namespace printing
......@@ -30,12 +30,18 @@ class PrintBackendServiceImpl : public mojom::PrintBackendService {
using GetDefaultPrinterCallback =
base::OnceCallback<void(const base::Optional<std::string>& printer_name)>;
using GetPrinterSemanticCapsAndDefaultsCallback = base::OnceCallback<void(
base::Optional<PrinterSemanticCapsAndDefaults> printer_caps)>;
// mojom::PrintBackendService implementation:
void Init(const std::string& locale) override;
void GetDefaultPrinterName(
mojom::PrintBackendService::GetDefaultPrinterNameCallback callback)
override;
void GetPrinterSemanticCapsAndDefaults(
const std::string& printer_name,
mojom::PrintBackendService::GetPrinterSemanticCapsAndDefaultsCallback
callback) override;
scoped_refptr<PrintBackend> print_backend_;
......
......@@ -36,6 +36,7 @@ mojom("mojom") {
if (is_win || is_mac || is_linux || is_chromeos) {
sources += [ "print_backend_service.mojom" ]
deps += [ "//printing/backend/mojom" ]
}
cpp_typemaps = [
......
......@@ -4,6 +4,8 @@
module printing.mojom;
import "printing/backend/mojom/print_backend.mojom";
// The main interface to Chrome's Print Backend Service, which performs
// printer queries and commands to operating system printer drivers in an
// isolated process.
......@@ -16,4 +18,9 @@ interface PrintBackendService {
// No value for `printer_name` is provided if there is a failure.
GetDefaultPrinterName()
=> (string? printer_name);
// Gets the semantic capabilities and defaults for a specific printer.
// No value provided for `printer_caps` if there is a failure.
GetPrinterSemanticCapsAndDefaults(string printer_name)
=> (PrinterSemanticCapsAndDefaults? printer_caps);
};
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