Open Bug 825287 Opened 13 years ago Updated 20 days ago

No way to set global printer preferences

Categories

(Core :: Printing: Setup, defect)

defect

Tracking

()

REOPENED

People

(Reporter: mkaply, Assigned: mkaply)

Details

Attachments

(1 file)

Currently all printer preferences are printer specific. So for instance, if you want to change the left header, the preference is: printer_PRINTERNAME.print_headerleft What this means is that there is no way for an administrator or company to set global print preferences without knowing the specific printer name. There should be a way to set global printer preferences that are used when no settings have been specified. And these should be overridden by the user then changing the preferences.
I have noticed for example print.print_headerleft in about:config as well as user_pref("printer_Print_to_File.print_headerleft", ""); After configuring the print dialog to be --blank--. My problem is that although setting these values, the print dialog does not persist with the saved preferences. They keep getting reset to their defaults!
Sorry for the noise. The solution is indeed as Mike says, is to know the printer name. printer_Print_to_File.* or print.* won't suffice. Here is an example I'm using with a customer who has named their printer Ricoh. http://ppd.webconverger.com/2013/ricoh.js
Per policy at https://wiki.mozilla.org/Bug_Triage/Projects/Bug_Handling/Bug_Husbandry#Inactive_Bugs. If this bug is not an enhancement request or a bug not present in a supported release of Firefox, then it may be reopened.
Status: NEW → RESOLVED
Closed: 8 years ago
Resolution: --- → INACTIVE
Status: RESOLVED → REOPENED
Resolution: INACTIVE → ---
Severity: normal → S3

There are two reasonable angles on this, and I want to record the narrower one here since the broader one (bug 1691283, adding a policy.json wildcard) has stalled on print-team priorities rather than technical objections.

The narrower fix lives entirely inside nsPrintSettingsService and doesn't touch policy, the print UI, or the pref system: when reading a per-printer pref, fall back to the same pref without the printer_<name>. qualifier. That gives administrators (and user.js authors) a single place to set defaults — print.print_shrink_to_fit, print.print_headerleft, etc. — which apply to every printer until the user overrides for a specific one. Writes stay per-printer, so user customization for a given printer continues to work exactly as today.

The change is contained in the GET*PREF macros in widget/nsPrintSettingsService.cpp::ReadPrefs. Sketch (untested, intent only):

#define GETBOOLPREF(_prefname, _retval)                                     \
  (NS_SUCCEEDED(Preferences::GetBool(                                       \
       GetPrefName(_prefname, aPrinterName), _retval)) ||                   \
   (!aPrinterName.IsEmpty() && NS_SUCCEEDED(Preferences::GetBool(           \
       GetPrefName(_prefname, EmptyString()), _retval))))

#define GETSTRPREF(_prefname, _retval)                                      \
  (NS_SUCCEEDED(Preferences::GetString(                                     \
       GetPrefName(_prefname, aPrinterName), _retval)) ||                   \
   (!aPrinterName.IsEmpty() && NS_SUCCEEDED(Preferences::GetString(         \
       GetPrefName(_prefname, EmptyString()), _retval))))

#define GETINTPREF(_prefname, _retval)                                      \
  (NS_SUCCEEDED(Preferences::GetInt(                                        \
       GetPrefName(_prefname, aPrinterName), _retval)) ||                   \
   (!aPrinterName.IsEmpty() && NS_SUCCEEDED(Preferences::GetInt(            \
       GetPrefName(_prefname, EmptyString()), _retval))))

#define GETDBLPREF(_prefname, _retval)                                      \
  (NS_SUCCEEDED(ReadPrefDouble(                                             \
       GetPrefName(_prefname, aPrinterName), _retval)) ||                   \
   (!aPrinterName.IsEmpty() && NS_SUCCEEDED(ReadPrefDouble(                 \
       GetPrefName(_prefname, EmptyString()), _retval))))

Properties of this approach:

  • Additive. Existing per-printer prefs continue to win over the generic value.
  • No policy-engine changes, no new wildcard semantics — Preferences policy already supports setting print.foo directly.
  • The existing in-tree comment at line 274 ("It is either print.attr_name or print.printer_HPLasr5.attr_name") implies this is what the code was supposed to do; this brings the behavior in line with the comment.
  • Review path is widget/print backend, not policy or UI, which sidesteps the priority conflict that stalled bug 1691283.

Not taking this myself right now, but recording the patch so it's not lost. Happy to hand off to anyone who picks it up, or revisit when I have a cycle.

Walked the code more carefully and the picture is more nuanced than my earlier sketch suggested.

nsPrintSettingsService::InitPrintSettingsFromPrefs already does a two-pass read: it calls ReadPrefs first with an empty printer name (which GetPrefName turns into print.<attr>) and then again with the actual printer name (print.printer_<NAME>.<attr>). The empty-name pass is intentionally masked to nsIPrintSettings::kGlobalSettings, which today covers headers (left/center/right), footers (left/center/right), edges, reversed, in-color, BG colors, BG images, and shrink-to-fit. So for those flags, global prefs like print.print_headerleft are read on every print and apply as defaults when there's no per-printer override.

I confirmed this in about:config — the global print.print_edge_* and print.print_header*/print.print_footer* prefs already exist and are read.

The real problem isn't read-side, it's write-side. WritePrefs always writes the per-printer pref (print.printer_<NAME>.print_headerleft) on every save, regardless of whether the value matches the global default. So:

  1. Admin sets print.print_headerleft="ACME" globally (via policies.json, user.js, or enterprise policy).
  2. First print uses ACME (global wins because no per-printer pref exists yet).
  3. WritePrefs writes print.printer_<NAME>.print_headerleft="ACME" (copied from the in-memory settings).
  4. From then on, the per-printer pref shadows the global. If the user later changes the header in the print dialog and prints, the per-printer pref diverges from ACME and the admin's value is lost for that printer.
  5. Locking the global via policy doesn't help — Firefox still writes the per-printer pref, and the read order prefers it over the global.

Cleanest fix on the write side: don't write the per-printer pref if its value equals the corresponding global pref. Pref tree stays clean, the global keeps winning indefinitely, and per-printer prefs only materialize when a user genuinely chose a different value for that specific printer.

Sketch for the WritePrefs macros (each Preferences::Set* call site for a GetPrefName(_prefname, aPrinterName) target):

// Helper, conceptual:
template <typename T>
void SetPerPrinterPref(const char* attr, const nsAString& printer, T value) {
  // If value matches the global default, don't write a per-printer override.
  T globalVal;
  if (NS_SUCCEEDED(Preferences::Get<T>(GetPrefName(attr, EmptyString()),
                                       &globalVal)) &&
      globalVal == value) {
    // Optionally also Preferences::ClearUser on the per-printer name so a
    // previously-saved divergent value gets cleaned up.
    Preferences::ClearUser(GetPrefName(attr, printer));
    return;
  }
  Preferences::Set(GetPrefName(attr, printer), value);
}

…and route the kGlobalSettings-masked branches of WritePrefs through that helper instead of writing unconditionally.

Properties:

  • Admin-set globals stop getting clobbered. Existing per-printer prefs that match the global get cleared on next save, which converges the pref tree toward "only divergent values are stored per-printer."
  • No new IDL, no new read path, no semantic change for kGlobalSettings flags users already customize per-printer.
  • Settings outside kGlobalSettings (paper size, duplex, orientation, page delay, margins, scaling) are unaffected — they remain per-printer-only, which is the right default since paper-size and margins are physically tied to a specific printer.

If admin override for those non-kGlobalSettings flags is also wanted (paper, duplex, etc.), that's a separate decision about whether they should move into kGlobalSettings, with caveats about surprising users on multi-printer setups. Worth a follow-up bug rather than expanding scope here.

Not taking this myself right now, but recording so it's not lost.

When print.<attr> is locked, per-printer print.printer_<NAME>.<attr>
prefs must not override it on read or be written on save. Also clears
stale per-printer prefs that match an unlocked global, so admin-set
defaults keep applying after the first print. Covers the kGlobalSettings
attributes plus duplex.

Assignee: nobody → mozilla
Attachment #9594905 - Attachment description: WIP: Bug 825287 - Honor locked global print prefs across per-printer overrides → Bug 825287 - Honor global print prefs across per-printer overrides. r?emilio
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: