|
113 | 113 | #include "ui/gfx/font_render_params.h"
|
114 | 114 | #endif
|
115 | 115 |
|
116 |
| -#if BUILDFLAG(ENABLE_PRINTING) |
117 |
| -#include "chrome/browser/printing/print_view_manager_basic.h" |
118 |
| -#include "components/printing/common/print_messages.h" |
119 |
| -#endif |
120 |
| - |
121 | 116 | #if BUILDFLAG(ENABLE_ELECTRON_EXTENSIONS)
|
122 | 117 | #include "shell/browser/extensions/atom_extension_web_contents_observer.h"
|
123 | 118 | #endif
|
@@ -313,6 +308,35 @@ void OnCapturePageDone(util::Promise promise, const SkBitmap& bitmap) {
|
313 | 308 | promise.Resolve(gfx::Image::CreateFrom1xBitmap(bitmap));
|
314 | 309 | }
|
315 | 310 |
|
| 311 | +#if BUILDFLAG(ENABLE_PRINTING) |
| 312 | +// This will return false if no printer with the provided device_name can be |
| 313 | +// found on the network. We need to check this because Chromium does not do |
| 314 | +// sanity checking of device_name validity and so will crash on invalid names. |
| 315 | +bool IsDeviceNameValid(const base::string16& device_name) { |
| 316 | +#if defined(OS_MACOSX) |
| 317 | + base::ScopedCFTypeRef<CFStringRef> new_printer_id( |
| 318 | + base::SysUTF16ToCFStringRef(device_name)); |
| 319 | + PMPrinter new_printer = PMPrinterCreateFromPrinterID(new_printer_id.get()); |
| 320 | + bool printer_exists = new_printer != nullptr; |
| 321 | + PMRelease(new_printer); |
| 322 | + return printer_exists; |
| 323 | +#elif defined(OS_WIN) |
| 324 | + printing::ScopedPrinterHandle printer; |
| 325 | + return printer.OpenPrinterWithName(device_name.c_str()); |
| 326 | +#endif |
| 327 | + return true; |
| 328 | +} |
| 329 | + |
| 330 | +base::string16 GetDefaultPrinterAsync() { |
| 331 | + base::ScopedBlockingCall scoped_blocking_call(FROM_HERE, |
| 332 | + base::BlockingType::MAY_BLOCK); |
| 333 | + |
| 334 | + scoped_refptr<printing::PrintBackend> backend = |
| 335 | + printing::PrintBackend::CreateInstance(nullptr); |
| 336 | + std::string printer_name = backend->GetDefaultPrinterName(); |
| 337 | + return base::UTF8ToUTF16(printer_name); |
| 338 | +} |
| 339 | +#endif |
316 | 340 | } // namespace
|
317 | 341 |
|
318 | 342 | WebContents::WebContents(v8::Isolate* isolate,
|
@@ -1647,6 +1671,30 @@ bool WebContents::IsCurrentlyAudible() {
|
1647 | 1671 | }
|
1648 | 1672 |
|
1649 | 1673 | #if BUILDFLAG(ENABLE_PRINTING)
|
| 1674 | +void WebContents::OnGetDefaultPrinter( |
| 1675 | + base::DictionaryValue print_settings, |
| 1676 | + printing::CompletionCallback print_callback, |
| 1677 | + base::string16 device_name, |
| 1678 | + bool silent, |
| 1679 | + base::string16 default_printer) { |
| 1680 | + base::string16 printer_name = |
| 1681 | + device_name.empty() ? default_printer : device_name; |
| 1682 | + print_settings.SetStringKey(printing::kSettingDeviceName, printer_name); |
| 1683 | + |
| 1684 | + auto* print_view_manager = |
| 1685 | + printing::PrintViewManagerBasic::FromWebContents(web_contents()); |
| 1686 | + auto* focused_frame = web_contents()->GetFocusedFrame(); |
| 1687 | + auto* rfh = focused_frame && focused_frame->HasSelection() |
| 1688 | + ? focused_frame |
| 1689 | + : web_contents()->GetMainFrame(); |
| 1690 | + |
| 1691 | + print_view_manager->PrintNow( |
| 1692 | + rfh, |
| 1693 | + std::make_unique<PrintMsg_PrintPages>(rfh->GetRoutingID(), silent, |
| 1694 | + std::move(print_settings)), |
| 1695 | + std::move(print_callback)); |
| 1696 | +} |
| 1697 | + |
1650 | 1698 | void WebContents::Print(mate::Arguments* args) {
|
1651 | 1699 | mate::Dictionary options = mate::Dictionary::CreateEmpty(args->isolate());
|
1652 | 1700 | base::DictionaryValue settings;
|
@@ -1710,11 +1758,15 @@ void WebContents::Print(mate::Arguments* args) {
|
1710 | 1758 | options.Get("landscape", &landscape);
|
1711 | 1759 | settings.SetBoolean(printing::kSettingLandscape, landscape);
|
1712 | 1760 |
|
1713 |
| - // We set the default to empty string here and only update |
1714 |
| - // if at the Chromium level if it's non-empty |
| 1761 | + // We set the default to the system's default printer and only update |
| 1762 | + // if at the Chromium level if the user overrides. |
| 1763 | + // Printer device name as opened by the OS. |
1715 | 1764 | base::string16 device_name;
|
1716 | 1765 | options.Get("deviceName", &device_name);
|
1717 |
| - settings.SetString(printing::kSettingDeviceName, device_name); |
| 1766 | + if (!device_name.empty() && !IsDeviceNameValid(device_name)) { |
| 1767 | + args->ThrowError("webContents.print(): Invalid deviceName provided."); |
| 1768 | + return; |
| 1769 | + } |
1718 | 1770 |
|
1719 | 1771 | int scale_factor = 100;
|
1720 | 1772 | options.Get("scaleFactor", &scale_factor);
|
@@ -1781,16 +1833,13 @@ void WebContents::Print(mate::Arguments* args) {
|
1781 | 1833 | settings.SetInteger(printing::kSettingDpiVertical, dpi);
|
1782 | 1834 | }
|
1783 | 1835 |
|
1784 |
| - auto* print_view_manager = |
1785 |
| - printing::PrintViewManagerBasic::FromWebContents(web_contents()); |
1786 |
| - auto* focused_frame = web_contents()->GetFocusedFrame(); |
1787 |
| - auto* rfh = focused_frame && focused_frame->HasSelection() |
1788 |
| - ? focused_frame |
1789 |
| - : web_contents()->GetMainFrame(); |
1790 |
| - print_view_manager->PrintNow(rfh, |
1791 |
| - std::make_unique<PrintMsg_PrintPages>( |
1792 |
| - rfh->GetRoutingID(), silent, settings), |
1793 |
| - std::move(callback)); |
| 1836 | + base::PostTaskAndReplyWithResult( |
| 1837 | + FROM_HERE, |
| 1838 | + {base::ThreadPool(), base::MayBlock(), base::TaskPriority::USER_BLOCKING}, |
| 1839 | + base::BindOnce(&GetDefaultPrinterAsync), |
| 1840 | + base::BindOnce(&WebContents::OnGetDefaultPrinter, |
| 1841 | + weak_factory_.GetWeakPtr(), std::move(settings), |
| 1842 | + std::move(callback), device_name, silent)); |
1794 | 1843 | }
|
1795 | 1844 |
|
1796 | 1845 | std::vector<printing::PrinterBasicInfo> WebContents::GetPrinterList() {
|
|
0 commit comments