Use document from preview for System Dialog printing on Windows.
System dialog shows only properties of selected printers, no system dialog with printers. Removed global Ctrl+Shift+P shortcut on windows. BUG=374321 Review URL: https://codereview.chromium.org/480303002 Cr-Commit-Position: refs/heads/master@{#292032}
This commit is contained in:
chrome
browser
printing
resources
print_preview
ui
webui
print_preview
common
renderer
printing
backend
print_job_constants.ccprint_job_constants.hprinting_context.ccprinting_context.hprinting_context_android.ccprinting_context_android.hprinting_context_linux.ccprinting_context_linux.hprinting_context_mac.hprinting_context_mac.mmprinting_context_no_system_dialog.ccprinting_context_no_system_dialog.hprinting_context_win.ccprinting_context_win.hprinting_context_win_unittest.cc@ -48,6 +48,9 @@ PrintViewManager::~PrintViewManager() {
|
||||
}
|
||||
|
||||
bool PrintViewManager::PrintForSystemDialogNow() {
|
||||
#if defined(OS_WIN)
|
||||
NOTREACHED();
|
||||
#endif
|
||||
return PrintNowInternal(new PrintMsg_PrintForSystemDialog(routing_id()));
|
||||
}
|
||||
|
||||
|
@ -424,7 +424,11 @@ void PrintingMessageFilter::OnUpdatePrintSettingsReply(
|
||||
params.params.document_cookie = printer_query->cookie();
|
||||
params.pages = PageRange::GetPages(printer_query->settings().ranges());
|
||||
}
|
||||
PrintHostMsg_UpdatePrintSettings::WriteReplyParams(reply_msg, params);
|
||||
PrintHostMsg_UpdatePrintSettings::WriteReplyParams(
|
||||
reply_msg,
|
||||
params,
|
||||
printer_query &&
|
||||
(printer_query->last_status() == printing::PrintingContext::CANCEL));
|
||||
Send(reply_msg);
|
||||
// If user hasn't cancelled.
|
||||
if (printer_query.get()) {
|
||||
|
@ -273,12 +273,18 @@ cr.define('print_preview', function() {
|
||||
* @param {!print_preview.DocumentInfo} documentInfo Document data model.
|
||||
* @param {boolean=} opt_isOpenPdfInPreview Whether to open the PDF in the
|
||||
* system's preview application.
|
||||
* @param {boolean=} opt_showSystemDialog Whether to open system dialog for
|
||||
* advanced settings.
|
||||
*/
|
||||
startPrint: function(destination, printTicketStore, cloudPrintInterface,
|
||||
documentInfo, opt_isOpenPdfInPreview) {
|
||||
documentInfo, opt_isOpenPdfInPreview,
|
||||
opt_showSystemDialog) {
|
||||
assert(printTicketStore.isTicketValid(),
|
||||
'Trying to print when ticket is not valid');
|
||||
|
||||
assert(!opt_showSystemDialog || (cr.isWindows && destination.isLocal),
|
||||
'Implemented for Windows only');
|
||||
|
||||
var ticket = {
|
||||
'pageRange': printTicketStore.pageRange.getDocumentPageRanges(),
|
||||
'mediaSize': printTicketStore.mediaSize.getValue(),
|
||||
@ -304,7 +310,8 @@ cr.define('print_preview', function() {
|
||||
'requestID': -1,
|
||||
'fitToPageEnabled': printTicketStore.fitToPage.getValue(),
|
||||
'pageWidth': documentInfo.pageSize.width,
|
||||
'pageHeight': documentInfo.pageSize.height
|
||||
'pageHeight': documentInfo.pageSize.height,
|
||||
'showSystemDialog': opt_showSystemDialog
|
||||
};
|
||||
|
||||
if (!destination.isLocal) {
|
||||
@ -347,6 +354,7 @@ cr.define('print_preview', function() {
|
||||
|
||||
/** Shows the system's native printing dialog. */
|
||||
startShowSystemDialog: function() {
|
||||
assert(!cr.isWindows);
|
||||
chrome.send('showSystemDialog');
|
||||
},
|
||||
|
||||
|
@ -230,6 +230,13 @@ cr.define('print_preview', function() {
|
||||
*/
|
||||
this.isInAppKioskMode_ = false;
|
||||
|
||||
/**
|
||||
* Whether Print with System Dialog option is available.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.isSystemDialogAvailable_ = false;
|
||||
|
||||
/**
|
||||
* State of the print preview UI.
|
||||
* @type {print_preview.PrintPreview.UiState_}
|
||||
@ -243,6 +250,13 @@ cr.define('print_preview', function() {
|
||||
* @private
|
||||
*/
|
||||
this.isPreviewGenerationInProgress_ = true;
|
||||
|
||||
/**
|
||||
* Whether to show system dialog before next printing.
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.showSystemDialogBeforeNextPrint_ = false;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -538,7 +552,9 @@ cr.define('print_preview', function() {
|
||||
this.printTicketStore_,
|
||||
this.cloudPrintInterface_,
|
||||
this.documentInfo_,
|
||||
this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW);
|
||||
this.uiState_ == PrintPreview.UiState_.OPENING_PDF_PREVIEW,
|
||||
this.showSystemDialogBeforeNextPrint_);
|
||||
this.showSystemDialogBeforeNextPrint_ = false;
|
||||
}
|
||||
return PrintPreview.PrintAttemptResult_.PRINTED;
|
||||
},
|
||||
@ -558,6 +574,13 @@ cr.define('print_preview', function() {
|
||||
* @private
|
||||
*/
|
||||
openSystemPrintDialog_: function() {
|
||||
if (!this.shouldShowSystemDialogLink_())
|
||||
return;
|
||||
if (cr.isWindows) {
|
||||
this.showSystemDialogBeforeNextPrint_ = true;
|
||||
this.printDocumentOrOpenPdfPreview_(false /*isPdfPreview*/);
|
||||
return;
|
||||
}
|
||||
setIsVisible($('system-dialog-throbber'), true);
|
||||
this.setIsEnabled_(false);
|
||||
this.uiState_ = PrintPreview.UiState_.OPENING_NATIVE_PRINT_DIALOG;
|
||||
@ -599,9 +622,9 @@ cr.define('print_preview', function() {
|
||||
this.appState_.setInitialized();
|
||||
|
||||
$('document-title').innerText = settings.documentTitle;
|
||||
setIsVisible($('system-dialog-link'),
|
||||
!settings.hidePrintWithSystemDialogLink &&
|
||||
!settings.isInAppKioskMode);
|
||||
this.isSystemDialogAvailable_ = !settings.hidePrintWithSystemDialogLink &&
|
||||
!settings.isInAppKioskMode;
|
||||
setIsVisible($('system-dialog-link'), this.shouldShowSystemDialogLink_());
|
||||
},
|
||||
|
||||
/**
|
||||
@ -1080,6 +1103,23 @@ cr.define('print_preview', function() {
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Returns true if "Print using system dialog" link should be shown for
|
||||
* current destination.
|
||||
* @return {boolean} Returns true if link should be shown.
|
||||
*/
|
||||
shouldShowSystemDialogLink_: function() {
|
||||
if (!this.isSystemDialogAvailable_)
|
||||
return false;
|
||||
if (!cr.isWindows)
|
||||
return true;
|
||||
var selectedDest = this.destinationStore_.selectedDestination;
|
||||
return selectedDest &&
|
||||
selectedDest.origin == print_preview.Destination.Origin.LOCAL &&
|
||||
selectedDest.id !=
|
||||
print_preview.Destination.GooglePromotedId.SAVE_AS_PDF;
|
||||
},
|
||||
|
||||
/**
|
||||
* Called when the open-cloud-print-dialog link is clicked. Opens the Google
|
||||
* Cloud Print web dialog.
|
||||
@ -1105,6 +1145,9 @@ cr.define('print_preview', function() {
|
||||
setIsVisible(
|
||||
$('cloud-print-dialog-link'),
|
||||
selectedDest && !cr.isChromeOS && !selectedDest.isLocal);
|
||||
setIsVisible(
|
||||
$('system-dialog-link'),
|
||||
this.shouldShowSystemDialogLink_());
|
||||
if (selectedDest && this.isInKioskAutoPrintMode_) {
|
||||
this.onPrintButtonClick_();
|
||||
}
|
||||
|
@ -832,8 +832,15 @@ void PrintPreviewHandler::HandlePrint(const base::ListValue* args) {
|
||||
ReportUserActionHistogram(PRINT_WITH_CLOUD_PRINT);
|
||||
SendCloudPrintJob(data.get());
|
||||
} else {
|
||||
UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToPrinter", page_count);
|
||||
ReportUserActionHistogram(PRINT_TO_PRINTER);
|
||||
bool system_dialog = false;
|
||||
settings->GetBoolean(printing::kSettingShowSystemDialog, &system_dialog);
|
||||
if (system_dialog) {
|
||||
UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.SystemDialog", page_count);
|
||||
ReportUserActionHistogram(FALLBACK_TO_ADVANCED_SETTINGS_DIALOG);
|
||||
} else {
|
||||
UMA_HISTOGRAM_COUNTS("PrintPreview.PageCount.PrintToPrinter", page_count);
|
||||
ReportUserActionHistogram(PRINT_TO_PRINTER);
|
||||
}
|
||||
ReportPrintSettingsStats(*settings);
|
||||
|
||||
// This tries to activate the initiator as well, so do not clear the
|
||||
|
@ -383,10 +383,11 @@ IPC_SYNC_MESSAGE_ROUTED0_1(PrintHostMsg_GetDefaultPrintSettings,
|
||||
|
||||
// The renderer wants to update the current print settings with new
|
||||
// |job_settings|.
|
||||
IPC_SYNC_MESSAGE_ROUTED2_1(PrintHostMsg_UpdatePrintSettings,
|
||||
IPC_SYNC_MESSAGE_ROUTED2_2(PrintHostMsg_UpdatePrintSettings,
|
||||
int /* document_cookie */,
|
||||
base::DictionaryValue /* job_settings */,
|
||||
PrintMsg_PrintPages_Params /* current_settings */)
|
||||
PrintMsg_PrintPages_Params /* current_settings */,
|
||||
bool /* canceled */)
|
||||
|
||||
// It's the renderer that controls the printing process when it is generated
|
||||
// by javascript. This step is about showing UI to the user to select the
|
||||
|
@ -162,7 +162,10 @@ void ChromeMockRenderThread::OnCheckForCancel(int32 preview_ui_id,
|
||||
void ChromeMockRenderThread::OnUpdatePrintSettings(
|
||||
int document_cookie,
|
||||
const base::DictionaryValue& job_settings,
|
||||
PrintMsg_PrintPages_Params* params) {
|
||||
PrintMsg_PrintPages_Params* params,
|
||||
bool* canceled) {
|
||||
if (canceled)
|
||||
*canceled = false;
|
||||
// Check and make sure the required settings are all there.
|
||||
// We don't actually care about the values.
|
||||
std::string dummy_string;
|
||||
|
@ -96,7 +96,8 @@ class ChromeMockRenderThread : public content::MockRenderThread {
|
||||
// For print preview, PrintWebViewHelper will update settings.
|
||||
void OnUpdatePrintSettings(int document_cookie,
|
||||
const base::DictionaryValue& job_settings,
|
||||
PrintMsg_PrintPages_Params* params);
|
||||
PrintMsg_PrintPages_Params* params,
|
||||
bool* canceled);
|
||||
|
||||
// A mock printer device used for printing tests.
|
||||
scoped_ptr<MockPrinter> printer_;
|
||||
|
@ -1464,8 +1464,13 @@ bool PrintWebViewHelper::UpdatePrintSettings(
|
||||
int cookie = print_pages_params_ ?
|
||||
print_pages_params_->params.document_cookie : 0;
|
||||
PrintMsg_PrintPages_Params settings;
|
||||
bool canceled = false;
|
||||
Send(new PrintHostMsg_UpdatePrintSettings(
|
||||
routing_id(), cookie, *job_settings, &settings));
|
||||
routing_id(), cookie, *job_settings, &settings, &canceled));
|
||||
if (canceled) {
|
||||
notify_browser_of_print_failure_ = false;
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!job_settings->GetInteger(kPreviewUIID, &settings.params.preview_ui_id)) {
|
||||
NOTREACHED();
|
||||
|
@ -488,4 +488,36 @@ scoped_ptr<DEVMODE, base::FreeDeleter> CreateDevMode(HANDLE printer,
|
||||
return out.Pass();
|
||||
}
|
||||
|
||||
scoped_ptr<DEVMODE, base::FreeDeleter> PromptDevMode(
|
||||
HANDLE printer,
|
||||
const base::string16& printer_name,
|
||||
DEVMODE* in,
|
||||
HWND window,
|
||||
bool* canceled) {
|
||||
LONG buffer_size =
|
||||
DocumentProperties(window,
|
||||
printer,
|
||||
const_cast<wchar_t*>(printer_name.c_str()),
|
||||
NULL,
|
||||
NULL,
|
||||
0);
|
||||
if (buffer_size < static_cast<int>(sizeof(DEVMODE)))
|
||||
return scoped_ptr<DEVMODE, base::FreeDeleter>();
|
||||
scoped_ptr<DEVMODE, base::FreeDeleter> out(
|
||||
reinterpret_cast<DEVMODE*>(malloc(buffer_size)));
|
||||
DWORD flags = (in ? (DM_IN_BUFFER) : 0) | DM_OUT_BUFFER | DM_IN_PROMPT;
|
||||
LONG result = DocumentProperties(window,
|
||||
printer,
|
||||
const_cast<wchar_t*>(printer_name.c_str()),
|
||||
out.get(),
|
||||
in,
|
||||
flags);
|
||||
if (canceled)
|
||||
*canceled = (result == IDCANCEL);
|
||||
if (result != IDOK)
|
||||
return scoped_ptr<DEVMODE, base::FreeDeleter>();
|
||||
CHECK_GE(buffer_size, out.get()->dmSize + out.get()->dmDriverExtra);
|
||||
return out.Pass();
|
||||
}
|
||||
|
||||
} // namespace printing
|
||||
|
@ -186,6 +186,14 @@ PRINTING_EXPORT scoped_ptr<DEVMODE, base::FreeDeleter> CreateDevMode(
|
||||
HANDLE printer,
|
||||
DEVMODE* in);
|
||||
|
||||
// Prompts for new DEVMODE. If |in| is not NULL copy settings from there.
|
||||
PRINTING_EXPORT scoped_ptr<DEVMODE, base::FreeDeleter> PromptDevMode(
|
||||
HANDLE printer,
|
||||
const base::string16& printer_name,
|
||||
DEVMODE* in,
|
||||
HWND window,
|
||||
bool* canceled);
|
||||
|
||||
} // namespace printing
|
||||
|
||||
#endif // PRINTING_BACKEND_WIN_HELPER_H_
|
||||
|
@ -163,6 +163,9 @@ const char kSettingShouldPrintBackgrounds[] = "shouldPrintBackgrounds";
|
||||
// Whether to print selection only.
|
||||
const char kSettingShouldPrintSelectionOnly[] = "shouldPrintSelectionOnly";
|
||||
|
||||
// Whether to print selection only.
|
||||
const char kSettingShowSystemDialog[] = "showSystemDialog";
|
||||
|
||||
// Indices used to represent first preview page and complete preview document.
|
||||
const int FIRST_PAGE_INDEX = 0;
|
||||
const int COMPLETE_PREVIEW_DOCUMENT_INDEX = -1;
|
||||
|
@ -63,6 +63,7 @@ PRINTING_EXPORT extern const char kSettingPrinterOptions[];
|
||||
PRINTING_EXPORT extern const char kSettingTicket[];
|
||||
PRINTING_EXPORT extern const char kSettingShouldPrintBackgrounds[];
|
||||
PRINTING_EXPORT extern const char kSettingShouldPrintSelectionOnly[];
|
||||
PRINTING_EXPORT extern const char kSettingShowSystemDialog[];
|
||||
|
||||
PRINTING_EXPORT extern const int FIRST_PAGE_INDEX;
|
||||
PRINTING_EXPORT extern const int COMPLETE_PREVIEW_DOCUMENT_INDEX;
|
||||
|
@ -114,7 +114,11 @@ PrintingContext::Result PrintingContext::UpdatePrintSettings(
|
||||
return OK;
|
||||
}
|
||||
|
||||
return UpdatePrinterSettings(open_in_external_preview);
|
||||
bool show_system_dialog = false;
|
||||
job_settings.GetBoolean(printing::kSettingShowSystemDialog,
|
||||
&show_system_dialog);
|
||||
|
||||
return UpdatePrinterSettings(open_in_external_preview, show_system_dialog);
|
||||
}
|
||||
|
||||
} // namespace printing
|
||||
|
@ -72,7 +72,8 @@ class PRINTING_EXPORT PrintingContext {
|
||||
// Updates printer settings.
|
||||
// |external_preview| is true if pdf is going to be opened in external
|
||||
// preview. Used by MacOS only now to open Preview.app.
|
||||
virtual Result UpdatePrinterSettings(bool external_preview) = 0;
|
||||
virtual Result UpdatePrinterSettings(bool external_preview,
|
||||
bool show_system_dialog) = 0;
|
||||
|
||||
// Updates Print Settings. |job_settings| contains all print job
|
||||
// settings information. |ranges| has the new page range settings.
|
||||
|
@ -170,7 +170,9 @@ gfx::Size PrintingContextAndroid::GetPdfPaperSizeDeviceUnits() {
|
||||
}
|
||||
|
||||
PrintingContext::Result PrintingContextAndroid::UpdatePrinterSettings(
|
||||
bool external_preview) {
|
||||
bool external_preview,
|
||||
bool show_system_dialog) {
|
||||
DCHECK(!show_system_dialog);
|
||||
DCHECK(!in_print_job_);
|
||||
|
||||
// Intentional No-op.
|
||||
|
@ -37,7 +37,8 @@ class PRINTING_EXPORT PrintingContextAndroid : public PrintingContext {
|
||||
const PrintSettingsCallback& callback) OVERRIDE;
|
||||
virtual Result UseDefaultSettings() OVERRIDE;
|
||||
virtual gfx::Size GetPdfPaperSizeDeviceUnits() OVERRIDE;
|
||||
virtual Result UpdatePrinterSettings(bool external_preview) OVERRIDE;
|
||||
virtual Result UpdatePrinterSettings(bool external_preview,
|
||||
bool show_system_dialog) OVERRIDE;
|
||||
virtual Result InitWithSettings(const PrintSettings& settings) OVERRIDE;
|
||||
virtual Result NewDocument(const base::string16& document_name) OVERRIDE;
|
||||
virtual Result NewPage() OVERRIDE;
|
||||
|
@ -106,7 +106,9 @@ gfx::Size PrintingContextLinux::GetPdfPaperSizeDeviceUnits() {
|
||||
}
|
||||
|
||||
PrintingContext::Result PrintingContextLinux::UpdatePrinterSettings(
|
||||
bool external_preview) {
|
||||
bool external_preview,
|
||||
bool show_system_dialog) {
|
||||
DCHECK(!show_system_dialog);
|
||||
DCHECK(!in_print_job_);
|
||||
DCHECK(!external_preview) << "Not implemented";
|
||||
|
||||
|
@ -43,7 +43,8 @@ class PRINTING_EXPORT PrintingContextLinux : public PrintingContext {
|
||||
const PrintSettingsCallback& callback) OVERRIDE;
|
||||
virtual gfx::Size GetPdfPaperSizeDeviceUnits() OVERRIDE;
|
||||
virtual Result UseDefaultSettings() OVERRIDE;
|
||||
virtual Result UpdatePrinterSettings(bool external_preview) OVERRIDE;
|
||||
virtual Result UpdatePrinterSettings(bool external_preview,
|
||||
bool show_system_dialog) OVERRIDE;
|
||||
virtual Result InitWithSettings(const PrintSettings& settings) OVERRIDE;
|
||||
virtual Result NewDocument(const base::string16& document_name) OVERRIDE;
|
||||
virtual Result NewPage() OVERRIDE;
|
||||
|
@ -31,7 +31,8 @@ class PRINTING_EXPORT PrintingContextMac : public PrintingContext {
|
||||
const PrintSettingsCallback& callback) OVERRIDE;
|
||||
virtual Result UseDefaultSettings() OVERRIDE;
|
||||
virtual gfx::Size GetPdfPaperSizeDeviceUnits() OVERRIDE;
|
||||
virtual Result UpdatePrinterSettings(bool external_preview) OVERRIDE;
|
||||
virtual Result UpdatePrinterSettings(bool external_preview,
|
||||
bool show_system_dialog) OVERRIDE;
|
||||
virtual Result InitWithSettings(const PrintSettings& settings) OVERRIDE;
|
||||
virtual Result NewDocument(const base::string16& document_name) OVERRIDE;
|
||||
virtual Result NewPage() OVERRIDE;
|
||||
|
@ -168,7 +168,9 @@ PrintingContext::Result PrintingContextMac::UseDefaultSettings() {
|
||||
}
|
||||
|
||||
PrintingContext::Result PrintingContextMac::UpdatePrinterSettings(
|
||||
bool external_preview) {
|
||||
bool external_preview,
|
||||
bool show_system_dialog) {
|
||||
DCHECK(!show_system_dialog);
|
||||
DCHECK(!in_print_job_);
|
||||
|
||||
// NOTE: Reset |print_info_| with a copy of |sharedPrintInfo| so as to start
|
||||
|
@ -75,7 +75,9 @@ gfx::Size PrintingContextNoSystemDialog::GetPdfPaperSizeDeviceUnits() {
|
||||
}
|
||||
|
||||
PrintingContext::Result PrintingContextNoSystemDialog::UpdatePrinterSettings(
|
||||
bool external_preview) {
|
||||
bool external_preview,
|
||||
bool show_system_dialog) {
|
||||
DCHECK(!show_system_dialog);
|
||||
|
||||
if (settings_.dpi() == 0)
|
||||
UseDefaultSettings();
|
||||
|
@ -27,7 +27,8 @@ class PRINTING_EXPORT PrintingContextNoSystemDialog : public PrintingContext {
|
||||
const PrintSettingsCallback& callback) OVERRIDE;
|
||||
virtual Result UseDefaultSettings() OVERRIDE;
|
||||
virtual gfx::Size GetPdfPaperSizeDeviceUnits() OVERRIDE;
|
||||
virtual Result UpdatePrinterSettings(bool external_preview) OVERRIDE;
|
||||
virtual Result UpdatePrinterSettings(bool external_preview,
|
||||
bool show_system_dialog) OVERRIDE;
|
||||
virtual Result InitWithSettings(const PrintSettings& settings) OVERRIDE;
|
||||
virtual Result NewDocument(const base::string16& document_name) OVERRIDE;
|
||||
virtual Result NewPage() OVERRIDE;
|
||||
|
@ -50,7 +50,7 @@ scoped_ptr<PrintingContext> PrintingContext::Create(Delegate* delegate) {
|
||||
}
|
||||
|
||||
PrintingContextWin::PrintingContextWin(Delegate* delegate)
|
||||
: PrintingContext(delegate), context_(NULL), dialog_box_(NULL) {
|
||||
: PrintingContext(delegate), context_(NULL) {
|
||||
}
|
||||
|
||||
PrintingContextWin::~PrintingContextWin() {
|
||||
@ -61,63 +61,26 @@ void PrintingContextWin::AskUserForSettings(
|
||||
int max_pages,
|
||||
bool has_selection,
|
||||
const PrintSettingsCallback& callback) {
|
||||
DCHECK(!in_print_job_);
|
||||
dialog_box_dismissed_ = false;
|
||||
|
||||
HWND window = GetRootWindow(delegate_->GetParentView());
|
||||
DCHECK(window);
|
||||
|
||||
// Show the OS-dependent dialog box.
|
||||
// If the user press
|
||||
// - OK, the settings are reset and reinitialized with the new settings. OK is
|
||||
// returned.
|
||||
// - Apply then Cancel, the settings are reset and reinitialized with the new
|
||||
// settings. CANCEL is returned.
|
||||
// - Cancel, the settings are not changed, the previous setting, if it was
|
||||
// initialized before, are kept. CANCEL is returned.
|
||||
// On failure, the settings are reset and FAILED is returned.
|
||||
PRINTDLGEX dialog_options = { sizeof(PRINTDLGEX) };
|
||||
dialog_options.hwndOwner = window;
|
||||
// Disable options we don't support currently.
|
||||
// TODO(maruel): Reuse the previously loaded settings!
|
||||
dialog_options.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE |
|
||||
PD_NOCURRENTPAGE | PD_HIDEPRINTTOFILE;
|
||||
if (!has_selection)
|
||||
dialog_options.Flags |= PD_NOSELECTION;
|
||||
|
||||
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 = arraysize(ranges);
|
||||
dialog_options.nMinPage = 1;
|
||||
dialog_options.nMaxPage = max_pages;
|
||||
dialog_options.lpPageRanges = ranges;
|
||||
} else {
|
||||
// No need to bother, we don't know how many pages are available.
|
||||
dialog_options.Flags |= PD_NOPAGENUMS;
|
||||
}
|
||||
|
||||
if (ShowPrintDialog(&dialog_options) != S_OK) {
|
||||
ResetSettings();
|
||||
callback.Run(FAILED);
|
||||
}
|
||||
|
||||
// TODO(maruel): Support PD_PRINTTOFILE.
|
||||
callback.Run(ParseDialogResultEx(dialog_options));
|
||||
NOTIMPLEMENTED();
|
||||
}
|
||||
|
||||
PrintingContext::Result PrintingContextWin::UseDefaultSettings() {
|
||||
DCHECK(!in_print_job_);
|
||||
|
||||
PRINTDLG dialog_options = { sizeof(PRINTDLG) };
|
||||
dialog_options.Flags = PD_RETURNDC | PD_RETURNDEFAULT;
|
||||
if (PrintDlg(&dialog_options))
|
||||
return ParseDialogResult(dialog_options);
|
||||
scoped_refptr<PrintBackend> backend = PrintBackend::CreateInstance(NULL);
|
||||
base::string16 default_printer =
|
||||
base::UTF8ToWide(backend->GetDefaultPrinterName());
|
||||
if (!default_printer.empty()) {
|
||||
ScopedPrinterHandle printer;
|
||||
if (printer.OpenPrinter(default_printer.c_str())) {
|
||||
scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode =
|
||||
CreateDevMode(printer, NULL);
|
||||
if (InitializeSettings(default_printer, dev_mode.get()) == OK)
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
ReleaseContext();
|
||||
|
||||
// No default printer configured, do we have any printers at all?
|
||||
DWORD bytes_needed = 0;
|
||||
@ -142,23 +105,15 @@ PrintingContext::Result PrintingContextWin::UseDefaultSettings() {
|
||||
continue;
|
||||
scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode =
|
||||
CreateDevMode(printer, NULL);
|
||||
if (!dev_mode || !AllocateContext(info_2->pPrinterName, dev_mode.get(),
|
||||
&context_)) {
|
||||
continue;
|
||||
}
|
||||
if (InitializeSettings(*dev_mode.get(), info_2->pPrinterName, NULL, 0,
|
||||
false)) {
|
||||
if (InitializeSettings(info_2->pPrinterName, dev_mode.get()) == OK)
|
||||
return OK;
|
||||
}
|
||||
ReleaseContext();
|
||||
}
|
||||
if (context_)
|
||||
return OK;
|
||||
}
|
||||
}
|
||||
|
||||
ResetSettings();
|
||||
return FAILED;
|
||||
return OnError();
|
||||
}
|
||||
|
||||
gfx::Size PrintingContextWin::GetPdfPaperSizeDeviceUnits() {
|
||||
@ -192,7 +147,8 @@ gfx::Size PrintingContextWin::GetPdfPaperSizeDeviceUnits() {
|
||||
}
|
||||
|
||||
PrintingContext::Result PrintingContextWin::UpdatePrinterSettings(
|
||||
bool external_preview) {
|
||||
bool external_preview,
|
||||
bool show_system_dialog) {
|
||||
DCHECK(!in_print_job_);
|
||||
DCHECK(!external_preview) << "Not implemented";
|
||||
|
||||
@ -256,19 +212,14 @@ PrintingContext::Result PrintingContextWin::UpdatePrinterSettings(
|
||||
}
|
||||
|
||||
// Update data using DocumentProperties.
|
||||
scoped_dev_mode = CreateDevMode(printer, scoped_dev_mode.get());
|
||||
if (!scoped_dev_mode)
|
||||
return OnError();
|
||||
|
||||
// Set printer then refresh printer settings.
|
||||
if (!AllocateContext(settings_.device_name(), scoped_dev_mode.get(),
|
||||
&context_)) {
|
||||
return OnError();
|
||||
if (show_system_dialog) {
|
||||
scoped_dev_mode = ShowPrintDialog(
|
||||
printer, delegate_->GetParentView(), scoped_dev_mode.get());
|
||||
} else {
|
||||
scoped_dev_mode = CreateDevMode(printer, scoped_dev_mode.get());
|
||||
}
|
||||
PrintSettingsInitializerWin::InitPrintSettings(context_,
|
||||
*scoped_dev_mode.get(),
|
||||
&settings_);
|
||||
return OK;
|
||||
// Set printer then refresh printer settings.
|
||||
return InitializeSettings(settings_.device_name(), scoped_dev_mode.get());
|
||||
}
|
||||
|
||||
PrintingContext::Result PrintingContextWin::InitWithSettings(
|
||||
@ -279,18 +230,13 @@ PrintingContext::Result PrintingContextWin::InitWithSettings(
|
||||
|
||||
// TODO(maruel): settings_.ToDEVMODE()
|
||||
ScopedPrinterHandle printer;
|
||||
if (!printer.OpenPrinter(settings_.device_name().c_str())) {
|
||||
if (!printer.OpenPrinter(settings_.device_name().c_str()))
|
||||
return FAILED;
|
||||
}
|
||||
|
||||
Result status = OK;
|
||||
scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode =
|
||||
CreateDevMode(printer, NULL);
|
||||
|
||||
if (!GetPrinterSettings(printer, settings_.device_name()))
|
||||
status = FAILED;
|
||||
|
||||
if (status != OK)
|
||||
ResetSettings();
|
||||
return status;
|
||||
return InitializeSettings(settings_.device_name(), dev_mode.get());
|
||||
}
|
||||
|
||||
PrintingContext::Result PrintingContextWin::NewDocument(
|
||||
@ -374,10 +320,6 @@ void PrintingContextWin::Cancel() {
|
||||
in_print_job_ = false;
|
||||
if (context_)
|
||||
CancelDC(context_);
|
||||
if (dialog_box_) {
|
||||
DestroyWindow(dialog_box_);
|
||||
dialog_box_dismissed_ = true;
|
||||
}
|
||||
}
|
||||
|
||||
void PrintingContextWin::ReleaseContext() {
|
||||
@ -401,154 +343,31 @@ BOOL PrintingContextWin::AbortProc(HDC hdc, int nCode) {
|
||||
return true;
|
||||
}
|
||||
|
||||
bool PrintingContextWin::InitializeSettings(const DEVMODE& dev_mode,
|
||||
const std::wstring& new_device_name,
|
||||
const PRINTPAGERANGE* ranges,
|
||||
int number_ranges,
|
||||
bool selection_only) {
|
||||
PrintingContext::Result PrintingContextWin::InitializeSettings(
|
||||
const std::wstring& device_name,
|
||||
DEVMODE* dev_mode) {
|
||||
if (!dev_mode)
|
||||
return OnError();
|
||||
|
||||
ReleaseContext();
|
||||
context_ = CreateDC(L"WINSPOOL", device_name.c_str(), NULL, dev_mode);
|
||||
if (!context_)
|
||||
return OnError();
|
||||
|
||||
skia::InitializeDC(context_);
|
||||
DCHECK(GetDeviceCaps(context_, CLIPCAPS));
|
||||
DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_STRETCHDIB);
|
||||
DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_BITMAP64);
|
||||
// Some printers don't advertise these.
|
||||
// DCHECK(GetDeviceCaps(context_, RASTERCAPS) & RC_SCALING);
|
||||
// DCHECK(GetDeviceCaps(context_, SHADEBLENDCAPS) & SB_CONST_ALPHA);
|
||||
// DCHECK(GetDeviceCaps(context_, SHADEBLENDCAPS) & SB_PIXEL_ALPHA);
|
||||
|
||||
// StretchDIBits() support is needed for printing.
|
||||
if (!(GetDeviceCaps(context_, RASTERCAPS) & RC_STRETCHDIB) ||
|
||||
!(GetDeviceCaps(context_, RASTERCAPS) & RC_BITMAP64)) {
|
||||
NOTREACHED();
|
||||
ResetSettings();
|
||||
return false;
|
||||
}
|
||||
|
||||
DCHECK(!in_print_job_);
|
||||
DCHECK(context_);
|
||||
PageRanges ranges_vector;
|
||||
if (!selection_only) {
|
||||
// Convert the PRINTPAGERANGE array to a PrintSettings::PageRanges vector.
|
||||
ranges_vector.reserve(number_ranges);
|
||||
for (int i = 0; i < number_ranges; ++i) {
|
||||
PageRange range;
|
||||
// Transfer from 1-based to 0-based.
|
||||
range.from = ranges[i].nFromPage - 1;
|
||||
range.to = ranges[i].nToPage - 1;
|
||||
ranges_vector.push_back(range);
|
||||
}
|
||||
}
|
||||
settings_.set_device_name(device_name);
|
||||
PrintSettingsInitializerWin::InitPrintSettings(
|
||||
context_, *dev_mode, &settings_);
|
||||
|
||||
settings_.set_ranges(ranges_vector);
|
||||
settings_.set_device_name(new_device_name);
|
||||
settings_.set_selection_only(selection_only);
|
||||
PrintSettingsInitializerWin::InitPrintSettings(context_, dev_mode,
|
||||
&settings_);
|
||||
|
||||
return true;
|
||||
return OK;
|
||||
}
|
||||
|
||||
bool PrintingContextWin::GetPrinterSettings(HANDLE printer,
|
||||
const std::wstring& device_name) {
|
||||
DCHECK(!in_print_job_);
|
||||
|
||||
scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode =
|
||||
CreateDevMode(printer, NULL);
|
||||
|
||||
if (!dev_mode || !AllocateContext(device_name, dev_mode.get(), &context_)) {
|
||||
ResetSettings();
|
||||
return false;
|
||||
}
|
||||
|
||||
return InitializeSettings(*dev_mode.get(), device_name, NULL, 0, false);
|
||||
}
|
||||
|
||||
// static
|
||||
bool PrintingContextWin::AllocateContext(const std::wstring& device_name,
|
||||
const DEVMODE* dev_mode,
|
||||
gfx::NativeDrawingContext* context) {
|
||||
*context = CreateDC(L"WINSPOOL", device_name.c_str(), NULL, dev_mode);
|
||||
DCHECK(*context);
|
||||
return *context != NULL;
|
||||
}
|
||||
|
||||
PrintingContext::Result PrintingContextWin::ParseDialogResultEx(
|
||||
const PRINTDLGEX& dialog_options) {
|
||||
// If the user clicked OK or Apply then Cancel, but not only Cancel.
|
||||
if (dialog_options.dwResultAction != PD_RESULT_CANCEL) {
|
||||
// Start fresh.
|
||||
ResetSettings();
|
||||
|
||||
DEVMODE* dev_mode = NULL;
|
||||
if (dialog_options.hDevMode) {
|
||||
dev_mode =
|
||||
reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode));
|
||||
DCHECK(dev_mode);
|
||||
}
|
||||
|
||||
std::wstring device_name;
|
||||
if (dialog_options.hDevNames) {
|
||||
DEVNAMES* dev_names =
|
||||
reinterpret_cast<DEVNAMES*>(GlobalLock(dialog_options.hDevNames));
|
||||
DCHECK(dev_names);
|
||||
if (dev_names) {
|
||||
device_name = reinterpret_cast<const wchar_t*>(dev_names) +
|
||||
dev_names->wDeviceOffset;
|
||||
GlobalUnlock(dialog_options.hDevNames);
|
||||
}
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
if (dev_mode && !device_name.empty()) {
|
||||
context_ = dialog_options.hDC;
|
||||
PRINTPAGERANGE* page_ranges = NULL;
|
||||
DWORD num_page_ranges = 0;
|
||||
bool print_selection_only = false;
|
||||
if (dialog_options.Flags & PD_PAGENUMS) {
|
||||
page_ranges = dialog_options.lpPageRanges;
|
||||
num_page_ranges = dialog_options.nPageRanges;
|
||||
}
|
||||
if (dialog_options.Flags & PD_SELECTION) {
|
||||
print_selection_only = true;
|
||||
}
|
||||
success = InitializeSettings(*dev_mode,
|
||||
device_name,
|
||||
page_ranges,
|
||||
num_page_ranges,
|
||||
print_selection_only);
|
||||
}
|
||||
|
||||
if (!success && dialog_options.hDC) {
|
||||
DeleteDC(dialog_options.hDC);
|
||||
context_ = NULL;
|
||||
}
|
||||
|
||||
if (dev_mode) {
|
||||
GlobalUnlock(dialog_options.hDevMode);
|
||||
}
|
||||
} else {
|
||||
if (dialog_options.hDC) {
|
||||
DeleteDC(dialog_options.hDC);
|
||||
}
|
||||
}
|
||||
|
||||
if (dialog_options.hDevMode != NULL)
|
||||
GlobalFree(dialog_options.hDevMode);
|
||||
if (dialog_options.hDevNames != NULL)
|
||||
GlobalFree(dialog_options.hDevNames);
|
||||
|
||||
switch (dialog_options.dwResultAction) {
|
||||
case PD_RESULT_PRINT:
|
||||
return context_ ? OK : FAILED;
|
||||
case PD_RESULT_APPLY:
|
||||
return context_ ? CANCEL : FAILED;
|
||||
case PD_RESULT_CANCEL:
|
||||
return CANCEL;
|
||||
default:
|
||||
return FAILED;
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT PrintingContextWin::ShowPrintDialog(PRINTDLGEX* options) {
|
||||
scoped_ptr<DEVMODE, base::FreeDeleter> PrintingContextWin::ShowPrintDialog(
|
||||
HANDLE printer,
|
||||
gfx::NativeView parent_view,
|
||||
DEVMODE* dev_mode) {
|
||||
// Note that this cannot use ui::BaseShellDialog as the print dialog is
|
||||
// system modal: opening it from a background thread can cause Windows to
|
||||
// get the wrong Z-order which will make the print dialog appear behind the
|
||||
@ -558,57 +377,20 @@ HRESULT PrintingContextWin::ShowPrintDialog(PRINTDLGEX* options) {
|
||||
base::MessageLoop::ScopedNestableTaskAllower allow(
|
||||
base::MessageLoop::current());
|
||||
|
||||
return PrintDlgEx(options);
|
||||
}
|
||||
bool canceled = false;
|
||||
scoped_ptr<DEVMODE, base::FreeDeleter> result =
|
||||
PromptDevMode(printer,
|
||||
settings_.device_name(),
|
||||
dev_mode,
|
||||
GetRootWindow(parent_view),
|
||||
&canceled);
|
||||
|
||||
PrintingContext::Result PrintingContextWin::ParseDialogResult(
|
||||
const PRINTDLG& dialog_options) {
|
||||
// If the user clicked OK or Apply then Cancel, but not only Cancel.
|
||||
// Start fresh.
|
||||
ResetSettings();
|
||||
|
||||
DEVMODE* dev_mode = NULL;
|
||||
if (dialog_options.hDevMode) {
|
||||
dev_mode =
|
||||
reinterpret_cast<DEVMODE*>(GlobalLock(dialog_options.hDevMode));
|
||||
DCHECK(dev_mode);
|
||||
if (canceled) {
|
||||
result.reset();
|
||||
abort_printing_ = true;
|
||||
}
|
||||
|
||||
std::wstring device_name;
|
||||
if (dialog_options.hDevNames) {
|
||||
DEVNAMES* dev_names =
|
||||
reinterpret_cast<DEVNAMES*>(GlobalLock(dialog_options.hDevNames));
|
||||
DCHECK(dev_names);
|
||||
if (dev_names) {
|
||||
device_name =
|
||||
reinterpret_cast<const wchar_t*>(
|
||||
reinterpret_cast<const wchar_t*>(dev_names) +
|
||||
dev_names->wDeviceOffset);
|
||||
GlobalUnlock(dialog_options.hDevNames);
|
||||
}
|
||||
}
|
||||
|
||||
bool success = false;
|
||||
if (dev_mode && !device_name.empty()) {
|
||||
context_ = dialog_options.hDC;
|
||||
success = InitializeSettings(*dev_mode, device_name, NULL, 0, false);
|
||||
}
|
||||
|
||||
if (!success && dialog_options.hDC) {
|
||||
DeleteDC(dialog_options.hDC);
|
||||
context_ = NULL;
|
||||
}
|
||||
|
||||
if (dev_mode) {
|
||||
GlobalUnlock(dialog_options.hDevMode);
|
||||
}
|
||||
|
||||
if (dialog_options.hDevMode != NULL)
|
||||
GlobalFree(dialog_options.hDevMode);
|
||||
if (dialog_options.hDevNames != NULL)
|
||||
GlobalFree(dialog_options.hDevNames);
|
||||
|
||||
return context_ ? OK : FAILED;
|
||||
return result.Pass();
|
||||
}
|
||||
|
||||
} // namespace printing
|
||||
|
@ -29,7 +29,8 @@ class PRINTING_EXPORT PrintingContextWin : public PrintingContext {
|
||||
const PrintSettingsCallback& callback) OVERRIDE;
|
||||
virtual Result UseDefaultSettings() OVERRIDE;
|
||||
virtual gfx::Size GetPdfPaperSizeDeviceUnits() OVERRIDE;
|
||||
virtual Result UpdatePrinterSettings(bool external_preview) OVERRIDE;
|
||||
virtual Result UpdatePrinterSettings(bool external_preview,
|
||||
bool show_system_dialog) OVERRIDE;
|
||||
virtual Result InitWithSettings(const PrintSettings& settings) OVERRIDE;
|
||||
virtual Result NewDocument(const base::string16& document_name) OVERRIDE;
|
||||
virtual Result NewPage() OVERRIDE;
|
||||
@ -39,45 +40,24 @@ class PRINTING_EXPORT PrintingContextWin : public PrintingContext {
|
||||
virtual void ReleaseContext() OVERRIDE;
|
||||
virtual gfx::NativeDrawingContext context() const OVERRIDE;
|
||||
|
||||
// Allocates the HDC for a specific DEVMODE.
|
||||
static bool AllocateContext(const std::wstring& printer_name,
|
||||
const DEVMODE* dev_mode,
|
||||
gfx::NativeDrawingContext* context);
|
||||
|
||||
protected:
|
||||
virtual HRESULT ShowPrintDialog(PRINTDLGEX* options);
|
||||
virtual scoped_ptr<DEVMODE, base::FreeDeleter> ShowPrintDialog(
|
||||
HANDLE printer,
|
||||
gfx::NativeView parent_view,
|
||||
DEVMODE* dev_mode);
|
||||
|
||||
private:
|
||||
// Class that manages the PrintDlgEx() callbacks. This is meant to be a
|
||||
// temporary object used during the Print... dialog display.
|
||||
class CallbackHandler;
|
||||
|
||||
// Used in response to the user canceling the printing.
|
||||
static BOOL CALLBACK AbortProc(HDC hdc, int nCode);
|
||||
|
||||
// Reads the settings from the selected device context. Updates settings_ and
|
||||
// its margins.
|
||||
bool InitializeSettings(const DEVMODE& dev_mode,
|
||||
const std::wstring& new_device_name,
|
||||
const PRINTPAGERANGE* ranges,
|
||||
int number_ranges,
|
||||
bool selection_only);
|
||||
|
||||
// Retrieves the printer's default low-level settings. On Windows, context_ is
|
||||
// allocated with this call.
|
||||
bool GetPrinterSettings(HANDLE printer,
|
||||
const std::wstring& device_name);
|
||||
|
||||
// Parses the result of a PRINTDLGEX result.
|
||||
Result ParseDialogResultEx(const PRINTDLGEX& dialog_options);
|
||||
Result ParseDialogResult(const PRINTDLG& dialog_options);
|
||||
virtual Result InitializeSettings(const base::string16& device_name,
|
||||
DEVMODE* dev_mode);
|
||||
|
||||
// The selected printer context.
|
||||
HDC context_;
|
||||
|
||||
// The dialog box for the time it is shown.
|
||||
volatile HWND dialog_box_;
|
||||
|
||||
DISALLOW_COPY_AND_ASSIGN(PrintingContextWin);
|
||||
};
|
||||
|
||||
|
@ -2,20 +2,9 @@
|
||||
// Use of this source code is governed by a BSD-style license that can be
|
||||
// found in the LICENSE file.
|
||||
|
||||
#include <ocidl.h>
|
||||
#include <commdlg.h>
|
||||
|
||||
#include <string>
|
||||
|
||||
#include "base/bind.h"
|
||||
#include "base/bind_helpers.h"
|
||||
#include "base/memory/scoped_ptr.h"
|
||||
#include "base/message_loop/message_loop.h"
|
||||
#include "printing/backend/printing_info_win.h"
|
||||
#include "printing/backend/win_helper.h"
|
||||
#include "printing/printing_test.h"
|
||||
#include "printing/printing_context.h"
|
||||
#include "printing/printing_context_win.h"
|
||||
|
||||
#include "printing/printing_test.h"
|
||||
#include "printing/print_settings.h"
|
||||
#include "testing/gtest/include/gtest/gtest.h"
|
||||
|
||||
@ -40,123 +29,6 @@ class PrintingContextTest : public PrintingTest<testing::Test>,
|
||||
PrintingContext::Result result_;
|
||||
};
|
||||
|
||||
class MockPrintingContextWin : public PrintingContextWin {
|
||||
public:
|
||||
MockPrintingContextWin(Delegate* delegate) : PrintingContextWin(delegate) {}
|
||||
|
||||
protected:
|
||||
// This is a fake PrintDlgEx implementation that sets the right fields in
|
||||
// |lppd| to trigger a bug in older revisions of PrintingContext.
|
||||
HRESULT ShowPrintDialog(PRINTDLGEX* lppd) OVERRIDE {
|
||||
// The interesting bits:
|
||||
// Pretend the user hit print
|
||||
lppd->dwResultAction = PD_RESULT_PRINT;
|
||||
|
||||
// Pretend the page range is 1-5, but since lppd->Flags does not have
|
||||
// PD_SELECTION set, this really shouldn't matter.
|
||||
lppd->nPageRanges = 1;
|
||||
lppd->lpPageRanges[0].nFromPage = 1;
|
||||
lppd->lpPageRanges[0].nToPage = 5;
|
||||
|
||||
base::string16 printer_name = PrintingContextTest::GetDefaultPrinter();
|
||||
ScopedPrinterHandle printer;
|
||||
if (!printer.OpenPrinter(printer_name.c_str()))
|
||||
return E_FAIL;
|
||||
|
||||
scoped_ptr<uint8[]> buffer;
|
||||
const DEVMODE* dev_mode = NULL;
|
||||
HRESULT result = S_OK;
|
||||
lppd->hDC = NULL;
|
||||
lppd->hDevMode = NULL;
|
||||
lppd->hDevNames = NULL;
|
||||
|
||||
PrinterInfo2 info_2;
|
||||
if (info_2.Init(printer)) {
|
||||
dev_mode = info_2.get()->pDevMode;
|
||||
}
|
||||
if (!dev_mode) {
|
||||
result = E_FAIL;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
if (!PrintingContextWin::AllocateContext(
|
||||
printer_name, dev_mode, &lppd->hDC)) {
|
||||
result = E_FAIL;
|
||||
goto Cleanup;
|
||||
}
|
||||
|
||||
size_t dev_mode_size = dev_mode->dmSize + dev_mode->dmDriverExtra;
|
||||
lppd->hDevMode = GlobalAlloc(GMEM_MOVEABLE, dev_mode_size);
|
||||
if (!lppd->hDevMode) {
|
||||
result = E_FAIL;
|
||||
goto Cleanup;
|
||||
}
|
||||
void* dev_mode_ptr = GlobalLock(lppd->hDevMode);
|
||||
if (!dev_mode_ptr) {
|
||||
result = E_FAIL;
|
||||
goto Cleanup;
|
||||
}
|
||||
memcpy(dev_mode_ptr, dev_mode, dev_mode_size);
|
||||
GlobalUnlock(lppd->hDevMode);
|
||||
dev_mode_ptr = NULL;
|
||||
|
||||
size_t driver_size =
|
||||
2 + sizeof(wchar_t) * lstrlen(info_2.get()->pDriverName);
|
||||
size_t printer_size =
|
||||
2 + sizeof(wchar_t) * lstrlen(info_2.get()->pPrinterName);
|
||||
size_t port_size = 2 + sizeof(wchar_t) * lstrlen(info_2.get()->pPortName);
|
||||
size_t dev_names_size =
|
||||
sizeof(DEVNAMES) + driver_size + printer_size + port_size;
|
||||
lppd->hDevNames = GlobalAlloc(GHND, dev_names_size);
|
||||
if (!lppd->hDevNames) {
|
||||
result = E_FAIL;
|
||||
goto Cleanup;
|
||||
}
|
||||
void* dev_names_ptr = GlobalLock(lppd->hDevNames);
|
||||
if (!dev_names_ptr) {
|
||||
result = E_FAIL;
|
||||
goto Cleanup;
|
||||
}
|
||||
DEVNAMES* dev_names = reinterpret_cast<DEVNAMES*>(dev_names_ptr);
|
||||
dev_names->wDefault = 1;
|
||||
dev_names->wDriverOffset = sizeof(DEVNAMES) / sizeof(wchar_t);
|
||||
memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDriverOffset,
|
||||
info_2.get()->pDriverName,
|
||||
driver_size);
|
||||
dev_names->wDeviceOffset =
|
||||
dev_names->wDriverOffset + driver_size / sizeof(wchar_t);
|
||||
memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wDeviceOffset,
|
||||
info_2.get()->pPrinterName,
|
||||
printer_size);
|
||||
dev_names->wOutputOffset =
|
||||
dev_names->wDeviceOffset + printer_size / sizeof(wchar_t);
|
||||
memcpy(reinterpret_cast<uint8*>(dev_names_ptr) + dev_names->wOutputOffset,
|
||||
info_2.get()->pPortName,
|
||||
port_size);
|
||||
GlobalUnlock(lppd->hDevNames);
|
||||
dev_names_ptr = NULL;
|
||||
|
||||
Cleanup:
|
||||
// Note: This section does proper deallocation/free of DC/global handles. We
|
||||
// did not use ScopedHGlobal or ScopedHandle because they did not
|
||||
// perform what we need. Goto's are used based on Windows programming
|
||||
// idiom, to avoid deeply nested if's, and try-catch-finally is not
|
||||
// allowed in Chromium.
|
||||
if (FAILED(result)) {
|
||||
if (lppd->hDC) {
|
||||
DeleteDC(lppd->hDC);
|
||||
}
|
||||
if (lppd->hDevMode) {
|
||||
GlobalFree(lppd->hDevMode);
|
||||
}
|
||||
if (lppd->hDevNames) {
|
||||
GlobalFree(lppd->hDevNames);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
};
|
||||
|
||||
TEST_F(PrintingContextTest, Base) {
|
||||
if (IsTestCaseDisabled())
|
||||
return;
|
||||
@ -174,20 +46,4 @@ TEST_F(PrintingContextTest, Base) {
|
||||
EXPECT_TRUE(ModifyWorldTransform(context->context(), NULL, MWT_IDENTITY));
|
||||
}
|
||||
|
||||
TEST_F(PrintingContextTest, PrintAll) {
|
||||
base::MessageLoop message_loop;
|
||||
if (IsTestCaseDisabled())
|
||||
return;
|
||||
|
||||
MockPrintingContextWin context(this);
|
||||
context.AskUserForSettings(
|
||||
123,
|
||||
false,
|
||||
base::Bind(&PrintingContextTest::PrintSettingsCallback,
|
||||
base::Unretained(this)));
|
||||
EXPECT_EQ(PrintingContext::OK, result());
|
||||
PrintSettings settings = context.settings();
|
||||
EXPECT_EQ(settings.ranges().size(), 0);
|
||||
}
|
||||
|
||||
} // namespace printing
|
||||
|
Reference in New Issue
Block a user