From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Shelley Vohr <shelley.vohr@gmail.com>
Date: Thu, 20 Aug 2020 10:55:48 -0700
Subject: fix: properly honor printing page ranges

The print ranges in Chromium's print job settings were not being properly
plumbed through to PMPrintSettings on mcOS. This fixes that by setting
them should they exist.

This will be upstreamed.

diff --git a/printing/printing_context_mac.h b/printing/printing_context_mac.h
index 0fb5c91b8abcdd7e674251bafebfc2c51044ef77..8c134bae25afeb0dbbb6e33182f053bb34e2f978 100644
--- a/printing/printing_context_mac.h
+++ b/printing/printing_context_mac.h
@@ -83,6 +83,10 @@ class COMPONENT_EXPORT(PRINTING) PrintingContextMac : public PrintingContext {
   // Returns true if the orientation was set.
   bool SetOrientationIsLandscape(bool landscape);
 
+  // Set the page range in native print info object.
+  // Returns true if the range was set.
+  bool SetPrintRangeInPrintSettings(const PageRanges& ranges);
+
   // Sets duplex mode in PMPrintSettings.
   // Returns true if duplex mode is set.
   bool SetDuplexModeInPrintSettings(mojom::DuplexMode mode);
diff --git a/printing/printing_context_mac.mm b/printing/printing_context_mac.mm
index 9f80fe6f10515849dd02d580db9852e6fbbbaa30..67f5b76a8141857ba02abd806341f06b07a4ebdc 100644
--- a/printing/printing_context_mac.mm
+++ b/printing/printing_context_mac.mm
@@ -190,7 +190,8 @@ PMPaper MatchPaper(CFArrayRef paper_list,
         !SetCollateInPrintSettings(settings_->collate()) ||
         !SetDuplexModeInPrintSettings(settings_->duplex_mode()) ||
         !SetOutputColor(static_cast<int>(settings_->color())) ||
-        !SetResolution(settings_->dpi_size())) {
+        !SetResolution(settings_->dpi_size()) ||
+        !SetPrintRangeInPrintSettings(settings_->ranges()) ) {
       return OnError();
     }
   }
@@ -343,6 +344,22 @@ PMPaper MatchPaper(CFArrayRef paper_list,
   return PMSetCopies(print_settings, copies, false) == noErr;
 }
 
+bool PrintingContextMac::SetPrintRangeInPrintSettings(const PageRanges& ranges) {
+  // Default is already NSPrintAllPages - we can safely bail.
+  if (ranges.empty())
+    return true;
+
+  auto* print_settings =
+      static_cast<PMPrintSettings>([print_info_.get() PMPrintSettings]);
+
+  // macOS does not allow multiple ranges, so pluck the first.
+  auto range = ranges.front();
+  bool set_first_page = PMSetFirstPage(print_settings, range.from + 1, false) == noErr;
+  bool set_last_page = PMSetLastPage(print_settings, range.to + 1, false) == noErr;
+
+  return set_first_page && set_last_page;
+}
+
 bool PrintingContextMac::SetCollateInPrintSettings(bool collate) {
   PMPrintSettings print_settings =
       static_cast<PMPrintSettings>([print_info_.get() PMPrintSettings]);
diff --git a/printing/printing_context_system_dialog_win.cc b/printing/printing_context_system_dialog_win.cc
index 891e9574625bfbaf2a00eeeb54a20834a2a5fa21..4f47ad753c7593c83fdfd832a9d4a53d2094becf 100644
--- a/printing/printing_context_system_dialog_win.cc
+++ b/printing/printing_context_system_dialog_win.cc
@@ -53,14 +53,28 @@ void PrintingContextSystemDialogWin::AskUserForSettings(
   PRINTPAGERANGE ranges[32];
   dialog_options.nStartPage = START_PAGE_GENERAL;
   if (max_pages) {
-    // Default initialize to print all the pages.
     memset(ranges, 0, sizeof(ranges));
-    ranges[0].nFromPage = 1;
-    ranges[0].nToPage = max_pages;
-    dialog_options.nPageRanges = 1;
-    dialog_options.nMaxPageRanges = base::size(ranges);
+
+    auto page_ranges = settings_->ranges();
+    if (!page_ranges.empty()) {
+      for (size_t i = 0; i < page_ranges.size(); i++) {
+        auto range = page_ranges[i];
+        ranges[i].nFromPage = range.from + 1;
+        ranges[i].nToPage = range.to + 1;
+      }
+      dialog_options.nPageRanges = page_ranges.size();
+
+      // Ensure the Pages radio button is selected.
+      dialog_options.Flags |= PD_PAGENUMS;
+    } else {
+      ranges[0].nFromPage = 1;
+      ranges[0].nToPage = max_pages;
+      dialog_options.nPageRanges = 1;
+    }
+
     dialog_options.nMinPage = 1;
     dialog_options.nMaxPage = max_pages;
+    dialog_options.nMaxPageRanges = base::size(ranges);
     dialog_options.lpPageRanges = ranges;
   } else {
     // No need to bother, we don't know how many pages are available.
diff --git a/ui/gtk/printing/print_dialog_gtk.cc b/ui/gtk/printing/print_dialog_gtk.cc
index 62108f0eb91fd04235d29a5e010aa600f76f8288..0e21b30dbe3f6daca9dce6d2b89b063c13d044ee 100644
--- a/ui/gtk/printing/print_dialog_gtk.cc
+++ b/ui/gtk/printing/print_dialog_gtk.cc
@@ -238,6 +238,24 @@ void PrintDialogGtk::UpdateSettings(
 
   gtk_print_settings_set_n_copies(gtk_settings_, settings->copies());
   gtk_print_settings_set_collate(gtk_settings_, settings->collate());
+
+  auto print_ranges = settings->ranges();
+  if (!print_ranges.empty()) {
+    // Tell the system that we only intend to print a subset of pages.
+    gtk_print_settings_set_print_pages(gtk_settings_, GTK_PRINT_PAGES_RANGES);
+
+    GtkPageRange* ranges;
+    ranges = g_new(GtkPageRange, print_ranges.size());
+    for (size_t i = 0; i < print_ranges.size(); i++) {
+      auto range = print_ranges[i];
+      ranges[i].start = range.from;
+      ranges[i].end = range.to;
+    }
+
+    gtk_print_settings_set_page_ranges(gtk_settings_, ranges, 1);
+    g_free(ranges);
+  }
+
   if (settings->dpi_horizontal() > 0 && settings->dpi_vertical() > 0) {
     gtk_print_settings_set_resolution_xy(
         gtk_settings_, settings->dpi_horizontal(), settings->dpi_vertical());
