Closed Bug 1669149 Opened 4 years ago Closed 3 years ago

Platform code changes to prepare to validate prefs against printer to improve performance

Categories

(Core :: Printing: Setup, enhancement, P1)

enhancement

Tracking

()

RESOLVED FIXED
96 Branch
Tracking Status
firefox96 --- fixed

People

(Reporter: bobowen, Assigned: bobowen)

References

(Blocks 2 open bugs)

Details

(Keywords: perf, Whiteboard: [print2020_v90][old-ui-])

Attachments

(7 files, 2 obsolete files)

47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
47 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review
48 bytes, text/x-phabricator-request
Details | Review

This is a sketch of an idea about how the PrintPreview API could be changed to improve performance and check settings against the printer.
It’s written as a change to the nsFrameLoader API, but could be done in frontend code, although some of the steps might need new platform APIs.
I don't know how the "Apply settings to printer" step works for CUPS printers or even if it is possible.

As it would now return print settings as well, it would now need to return a Promise that resolves to an object that contains the print settings and the current promise for the PrintPreviewSuccessInfo.
Steps involving printer interaction would need to be run async on background threads.

PrintPreview(nsIPrintSettings settings)->Promise->{nsIPrintSettings, Promise}:
1. settings passed in
2. call content API to create/update preview with settings
3. apply settings to printer and retrieve updated settings (like at [1])
4. compare settings from printer to settings from prefs
5. should normally be no difference so return Promise with settings and Promise
Alternatives
1a. no settings passed (this would be the first call)
   1a1. Get settings from prefs
   1a2. return to 2.
1b. no settings passed in or saved in prefs
   1b1. get default settings from printer
   1b2. call content API to create preview with settings
   1b3. return Promise with settings and Promise
5a. settings from printer differ to settings from prefs or passed in
   5a1. call content API to update preview with settings
   5a2. return Promise with settings and Promise

[1] https://searchfox.org/mozilla-central/rev/7ef5cefd0468b8f509efe38e0212de2398f4c8b3/widget/windows/nsDeviceContextSpecWin.cpp#439-453

Flags: needinfo?(jwatt)
See Also: → 1661294
See Also: 1661294
See Also: → 1669904

(In reply to Bob Owen (:bobowen) from comment #0)

I don't know how the "Apply settings to printer" step works for CUPS printers or even if it is possible.

I don't believe it is possible. I expect we need to collect the capabilities of the printer and validate each setting against those manually. But whether the DEVMODE is used to validate/fix settings on Windows or settings are fixed up by manual comparison, that seems like an implementation detail we should abstract over.

One situation we need to cater for that wouldn't be provided for with this API is when the user has the "Save to PDF" printer selected, but then clicks on "Print using system dialog...". In that case we want to copy as many settings as possible (validating them) onto a new settings object that has its printer name set to the name of a system recognized printer (the system dialog doesn't know what to do with the "Save to PDF" printer). (We do not want to copy the printer name, obiously.) For that, it seem like we probably want to add something like the following to the nsIPrintSettings interface:

// Copies all settings that are valid for this settings object's printer.
// Does not copy the printer name.
Promise copyFromWithValidation(in nsIPrintSettings);

Since we need that API (I think), it seems like it could also be used in the more general case that comment 0 aims to address.

So in the case of the user having never printed to the printer before (no settings saved to prefs) the frontend code would get an nsIPrinter and just pass the settings returned by createDefaultSettings to FrameLoader.print/.printPreview().

In the case the user has used the printer before, the frontend code would get a new settings object, initialize it with initPrintSettingsFromPrefs, immediately dispatch it to FrameLoader.print/.printPreview(), but for now keeping the UI disabled. It would also create a second print settings object and call copyFromWithValidation() on it, passing the the initialized-from-prefs settings object. Once the returend Promise resolved, it would compare the two settings objects for differences (we should add API for that too). If there are no differences, it would simply remove the "creating preview" spinner and enable the UI. In the unlikely event there were differences, it would dispatch a second FrameLoader.print/.printPreview() call with the validated preferences and wait for that Promise to resolve before enabling the UI.

In the rare case where we have to dispatch fixed up settings, essentially we'd behave in the same way we do now, and have the same performance characteristics. In the common case where there are no differences and we don't need to regenerate the print doc with new settings then the content process would have been laying out the doc in parallel to the parent process validating settings. That would make things much faster for users for whom getting printer capabilities is very slow.

This approach would also have the advantage on not complicating the printPreview() API.

Thoughts?

Flags: needinfo?(jwatt)

As Bob just pointed out to me, the API wouldn't be on nsIPrintSettings. It would be on nsIPrinter, and be more like:

Promise copySettingsWithValidaton(fromSettings);
See Also: → 1663005
Blocks: 1663005
Whiteboard: [print2020_v83][old-ui-] → [print2020_v84][old-ui-]
Assignee: nobody → bobowencode
Status: NEW → ASSIGNED

This is to allow settings saved in prefs to be validated against a printer and
for print preview to be updated if any changes affecting layout occur.

Whiteboard: [print2020_v84][old-ui-] → [print2020_v85][old-ui-]
See Also: → 1680838
Attachment #9190796 - Attachment description: WIP - Bug 1669149 part 1: Introduce nsIPrintSettings::LayoutEquivalentTo and nsIPrinter::CopyFromWithValidation. → Bug 1669149 p1: Introduce nsIPrintSettings::LayoutEquivalentTo and nsIPrinter::CopyFromWithValidation.

This means that more precise values can be stored, so that they match what we
actually retrieve from the printer and use in layout.

Depends on D99806

This allows us to detect if any prefs were read in JavaScript.

Depends on D99807

This more precisely matches what we get from the printer and use in layout.

Depends on D99808

This is always available and makes it more consistent for comparing print
settings.
Also change to round when converting back to DEVMODE for better accuracy.

Depends on D99810

The settings are then validated against the printer and if changes affecting layout occur a new preview is generated.

Depends on D99811

Whiteboard: [print2020_v85][old-ui-] → [print2020_v87][old-ui-]
Attachment #9190796 - Attachment description: Bug 1669149 p1: Introduce nsIPrintSettings::LayoutEquivalentTo and nsIPrinter::CopyFromWithValidation. → Bug 1669149 p1: Introduce nsIPrintSettings::EquivalentTo and nsIPrinter::CopyFromWithValidation.
Whiteboard: [print2020_v87][old-ui-] → [print2020_v90][old-ui-]
Attachment #9190796 - Attachment description: Bug 1669149 p1: Introduce nsIPrintSettings::EquivalentTo and nsIPrinter::CopyFromWithValidation. → Bug 1669149 p1: Introduce nsIPrintSettings::EquivalentTo and nsIPrinter::CopyFromWithValidation. r=jwatt
Attachment #9204293 - Attachment description: Bug 1669149 p1.5: Update the printer's DefaultSettings with the global settings. r=jwatt! → Bug 1669149 p2: Update the printer's DefaultSettings with the global settings. r=jwatt!
Attachment #9193294 - Attachment description: Bug 1669149 p2: Never go back to the parent for print settings with tab modal print UI. r=jwatt! → Bug 1669149 p3: Never go back to the parent for print settings with tab modal print UI. r=jwatt!
Attachment #9193297 - Attachment description: Bug 1669149 p3: Change unwriteable margin pref to be stored in twips. r=jwatt! → Bug 1669149 p4: Change unwriteable margin pref to be stored in twips. r=jwatt!
Attachment #9193299 - Attachment description: Bug 1669149 p4: If no print settings are read from prefs return NS_ERROR_NOT_AVAILABLE not NS_OK. r=jwatt! → Bug 1669149 p5: Make nsPrintSettingsService::ReadPrefs return NS_ERROR_NOT_AVAILABLE, not NS_OK, if no prefs are read. r=jwatt!
Attachment #9193301 - Attachment description: Bug 1669149 p5: Change print settings stored as floats to be stored as doubles. r=jwatt! → Bug 1669149 p6: Change print settings stored as floats to be stored as doubles. r=jwatt!
Attachment #9193302 - Attachment description: Bug 1669149 p6: Always use size from device context for print paper size on Windows. r=jwatt! → Bug 1669149 p7: Always use size from device context for print paper size on Windows. r=jwatt!
Pushed by jwatt@mozilla.com:
https://hg.mozilla.org/integration/autoland/rev/2f7c6dff65fc
p1: Introduce nsIPrintSettings::EquivalentTo and nsIPrinter::CopyFromWithValidation. r=jwatt
https://hg.mozilla.org/integration/autoland/rev/6e70617cbb79
p2: Update the printer's DefaultSettings with the global settings. r=jwatt
https://hg.mozilla.org/integration/autoland/rev/1fb0f7dc84a9
p3: Never go back to the parent for print settings with tab modal print UI. r=jwatt
https://hg.mozilla.org/integration/autoland/rev/a969b3be9e10
p4: Change unwriteable margin pref to be stored in twips. r=jwatt
https://hg.mozilla.org/integration/autoland/rev/7cc7109100a6
p5: Make nsPrintSettingsService::ReadPrefs return NS_ERROR_NOT_AVAILABLE, not NS_OK, if no prefs are read. r=jwatt
https://hg.mozilla.org/integration/autoland/rev/9cd220f0da60
p6: Change print settings stored as floats to be stored as doubles. r=jwatt
https://hg.mozilla.org/integration/autoland/rev/2f40a908044e
p7: Always use size from device context for print paper size on Windows. r=jwatt

I've landed all the platform work as parts 1-7 (previously 1-6, but I renumbered part 1.5 before landing) and will split out the final frontend patch into a separate bug, and wait at least a Nightly release before landing it. That should prevent the platform patches from bitrotting again in the event that there are issues getting the frontend patch reviewed, and help with any potential regression tracking.

Summary: Possible changes to PrintPreview API/process flow to validate prefs against printer and improve performance → Platform code changes to prepare to validate prefs against printer to improve performance
Regressions: 1741698
Blocks: 1742621
Attachment #9193303 - Attachment is obsolete: true
Attachment #9193294 - Attachment is obsolete: true
You need to log in before you can comment on or make changes to this bug.

Attachment

General

Created:
Updated:
Size: