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 @@ ...@@ -2,6 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
#include <stdint.h>
#include <memory> #include <memory>
#include <string> #include <string>
#include <utility> #include <utility>
...@@ -27,6 +29,9 @@ namespace printing { ...@@ -27,6 +29,9 @@ namespace printing {
namespace { namespace {
constexpr char kDefaultPrinterName[] = "default-test-printer"; constexpr char kDefaultPrinterName[] = "default-test-printer";
constexpr char kInvalidPrinterName[] = "invalid-test-printer";
constexpr int32_t kCopiesMax = 123;
} // namespace } // namespace
...@@ -82,8 +87,12 @@ class PrintBackendBrowserTest : public InProcessBrowserTest { ...@@ -82,8 +87,12 @@ class PrintBackendBrowserTest : public InProcessBrowserTest {
/*printer_status=*/0, /*is_default=*/true, /*printer_status=*/0, /*is_default=*/true,
/*options=*/PrinterBasicInfoOptions{}); /*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( 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. // Public callbacks used by tests.
...@@ -94,19 +103,28 @@ class PrintBackendBrowserTest : public InProcessBrowserTest { ...@@ -94,19 +103,28 @@ class PrintBackendBrowserTest : public InProcessBrowserTest {
CheckForQuit(); CheckForQuit();
} }
// The following are helper functions for having a wait loop in the test and void OnDidGetPrinterSemanticCapsAndDefaults(
// exit when expected messages are received. base::Optional<PrinterSemanticCapsAndDefaults>* capture_printer_caps,
void WaitUntilCallbackReceived() { const base::Optional<PrinterSemanticCapsAndDefaults>& printer_caps) {
if (received_message_) { *capture_printer_caps = printer_caps;
// Callback happened before even needing to wait. CheckForQuit();
return;
} }
// The following are helper functions for having a wait loop in the test and
// exit when expected messages are received. Expect to only have to wait for
// one message.
void WaitUntilCallbackReceived() {
// If callback happened before getting here, then no need to wait.
if (!received_message_) {
base::RunLoop run_loop; base::RunLoop run_loop;
quit_callback_ = run_loop.QuitClosure(); quit_callback_ = run_loop.QuitClosure();
run_loop.Run(); run_loop.Run();
} }
// Reset for possible subsequent test.
received_message_ = false;
}
void CheckForQuit() { void CheckForQuit() {
received_message_ = true; received_message_ = true;
if (quit_callback_) if (quit_callback_)
...@@ -130,6 +148,7 @@ class PrintBackendBrowserTest : public InProcessBrowserTest { ...@@ -130,6 +148,7 @@ class PrintBackendBrowserTest : public InProcessBrowserTest {
// without having performed initialization. // without having performed initialization.
IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest, FailWithoutInit) { IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest, FailWithoutInit) {
base::Optional<std::string> default_printer_name; base::Optional<std::string> default_printer_name;
base::Optional<PrinterSemanticCapsAndDefaults> printer_caps;
// Safe to use base::Unretained(this) since waiting locally on the callback // Safe to use base::Unretained(this) since waiting locally on the callback
// forces a shorter lifetime than `this`. // forces a shorter lifetime than `this`.
...@@ -138,6 +157,14 @@ IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest, FailWithoutInit) { ...@@ -138,6 +157,14 @@ IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest, FailWithoutInit) {
base::Unretained(this), &default_printer_name)); base::Unretained(this), &default_printer_name));
WaitUntilCallbackReceived(); WaitUntilCallbackReceived();
EXPECT_FALSE(default_printer_name.has_value()); 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) { IN_PROC_BROWSER_TEST_F(PrintBackendBrowserTest, GetDefaultPrinterName) {
...@@ -155,4 +182,31 @@ 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); 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 } // namespace printing
...@@ -37,4 +37,25 @@ void PrintBackendServiceImpl::GetDefaultPrinterName( ...@@ -37,4 +37,25 @@ void PrintBackendServiceImpl::GetDefaultPrinterName(
std::move(callback).Run(print_backend_->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 } // namespace printing
...@@ -30,12 +30,18 @@ class PrintBackendServiceImpl : public mojom::PrintBackendService { ...@@ -30,12 +30,18 @@ class PrintBackendServiceImpl : public mojom::PrintBackendService {
using GetDefaultPrinterCallback = using GetDefaultPrinterCallback =
base::OnceCallback<void(const base::Optional<std::string>& printer_name)>; base::OnceCallback<void(const base::Optional<std::string>& printer_name)>;
using GetPrinterSemanticCapsAndDefaultsCallback = base::OnceCallback<void(
base::Optional<PrinterSemanticCapsAndDefaults> printer_caps)>;
// mojom::PrintBackendService implementation: // mojom::PrintBackendService implementation:
void Init(const std::string& locale) override; void Init(const std::string& locale) override;
void GetDefaultPrinterName( void GetDefaultPrinterName(
mojom::PrintBackendService::GetDefaultPrinterNameCallback callback) mojom::PrintBackendService::GetDefaultPrinterNameCallback callback)
override; override;
void GetPrinterSemanticCapsAndDefaults(
const std::string& printer_name,
mojom::PrintBackendService::GetPrinterSemanticCapsAndDefaultsCallback
callback) override;
scoped_refptr<PrintBackend> print_backend_; scoped_refptr<PrintBackend> print_backend_;
......
...@@ -36,6 +36,7 @@ mojom("mojom") { ...@@ -36,6 +36,7 @@ mojom("mojom") {
if (is_win || is_mac || is_linux || is_chromeos) { if (is_win || is_mac || is_linux || is_chromeos) {
sources += [ "print_backend_service.mojom" ] sources += [ "print_backend_service.mojom" ]
deps += [ "//printing/backend/mojom" ]
} }
cpp_typemaps = [ cpp_typemaps = [
......
...@@ -4,6 +4,8 @@ ...@@ -4,6 +4,8 @@
module printing.mojom; module printing.mojom;
import "printing/backend/mojom/print_backend.mojom";
// The main interface to Chrome's Print Backend Service, which performs // The main interface to Chrome's Print Backend Service, which performs
// printer queries and commands to operating system printer drivers in an // printer queries and commands to operating system printer drivers in an
// isolated process. // isolated process.
...@@ -16,4 +18,9 @@ interface PrintBackendService { ...@@ -16,4 +18,9 @@ interface PrintBackendService {
// No value for `printer_name` is provided if there is a failure. // No value for `printer_name` is provided if there is a failure.
GetDefaultPrinterName() GetDefaultPrinterName()
=> (string? printer_name); => (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