diff options
author | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-08 14:30:41 +0200 |
---|---|---|
committer | Jocelyn Turcotte <jocelyn.turcotte@digia.com> | 2014-08-12 13:49:54 +0200 |
commit | ab0a50979b9eb4dfa3320eff7e187e41efedf7a9 (patch) | |
tree | 498dfb8a97ff3361a9f7486863a52bb4e26bb898 /chromium/printing | |
parent | 4ce69f7403811819800e7c5ae1318b2647e778d1 (diff) | |
download | qtwebengine-chromium-ab0a50979b9eb4dfa3320eff7e187e41efedf7a9.tar.gz |
Update Chromium to beta version 37.0.2062.68
Change-Id: I188e3b5aff1bec75566014291b654eb19f5bc8ca
Reviewed-by: Andras Becsi <andras.becsi@digia.com>
Diffstat (limited to 'chromium/printing')
52 files changed, 1829 insertions, 1202 deletions
diff --git a/chromium/printing/BUILD.gn b/chromium/printing/BUILD.gn new file mode 100644 index 00000000000..6d767aafa9b --- /dev/null +++ b/chromium/printing/BUILD.gn @@ -0,0 +1,256 @@ +# Copyright 2014 The Chromium Authors. All rights reserved. +# Use of this source code is governed by a BSD-style license that can be +# found in the LICENSE file. + +import("//build/config/ui.gni") +if (is_mac) { + import("//build/config/mac/mac_sdk.gni") +} +if (is_android) { + import("//build/config/android/rules.gni") +} + +use_cups = ((is_linux && !is_chromeos) || is_mac) + +component("printing") { + sources = [ + "backend/print_backend.cc", + "backend/print_backend.h", + "backend/print_backend_consts.cc", + "backend/print_backend_consts.h", + "backend/print_backend_dummy.cc", + "backend/printing_info_win.cc", + "backend/printing_info_win.h", + "emf_win.cc", + "emf_win.h", + "image.cc", + "image.h", + "image_android.cc", + "image_linux.cc", + "image_mac.cc", + "image_win.cc", + "metafile.h", + "metafile_impl.h", + "metafile_skia_wrapper.cc", + "metafile_skia_wrapper.h", + "page_number.cc", + "page_number.h", + "page_range.cc", + "page_range.h", + "page_setup.cc", + "page_setup.h", + "page_size_margins.h", + "pdf_metafile_cg_mac.cc", + "pdf_metafile_cg_mac.h", + "pdf_metafile_skia.cc", + "pdf_metafile_skia.h", + "print_destination_interface.h", + "print_destination_none.cc", + "print_dialog_gtk_interface.h", + "print_job_constants.cc", + "print_job_constants.h", + "print_settings.cc", + "print_settings.h", + "print_settings_conversion.cc", + "print_settings_conversion.h", + "print_settings_initializer_mac.cc", + "print_settings_initializer_mac.h", + "print_settings_initializer_win.cc", + "print_settings_initializer_win.h", + "printed_document.cc", + "printed_document.h", + "printed_document_linux.cc", + "printed_document_mac.cc", + "printed_document_win.cc", + "printed_page.cc", + "printed_page.h", + "printed_pages_source.h", + "printing_context.cc", + "printing_context.h", + "printing_utils.cc", + "printing_utils.h", + "units.cc", + "units.h", + ] + + cflags = [] + defines = [ "PRINTING_IMPLEMENTATION" ] + + deps = [ + "//base", + "//base:i18n", + "//base/third_party/dynamic_annotations", + "//skia", + "//third_party/icu", + "//ui/gfx", + "//ui/gfx/geometry", + "//url", + ] + + if (use_aura) { + # deps += [ "//ui/aura" ] TODO(GYP) + } + + if (is_mac) { + # Mac-Aura does not support printing. + if (use_aura) { + sources -= [ + "printed_document_mac.cc", + ] + } else { + sources += [ + "printing_context_mac.mm", + "printing_context_mac.h", + ] + } + } + + if (is_win) { + # PRINT_BACKEND_AVAILABLE disables the default dummy implementation of the + # print backend and enables a custom implementation instead. + defines += [ "PRINT_BACKEND_AVAILABLE" ] + sources += [ + "backend/win_helper.cc", + "backend/win_helper.h", + "backend/print_backend_win.cc", + "printing_context_win.cc", + "printing_context_win.h", + ] + } + + if (is_chromeos) { + sources += [ + "printing_context_no_system_dialog.cc", + "printing_context_no_system_dialog.h", + ] + } + + if (use_cups) { + cups_version = exec_script("cups_config_helper.py", [ "--api-version" ], + "trim string") + + configs += [ ":cups" ] + + if (is_linux) { + if (cups_version == "1.6" || cups_version == "1.7") { + cflags += [ + # CUPS 1.6 deprecated the PPD APIs, but we will stay with this + # API for now as supported Linux and Mac OS'es are still using + # older versions of CUPS. More info: crbug.com/226176 + "-Wno-deprecated-declarations", + # CUPS 1.7 deprecates httpConnectEncrypt(), see the mac section + # below. + ] + } + } + + if (is_mac && mac_sdk_version == "10.9") { + # The 10.9 SDK includes cups 1.7, which deprecates + # httpConnectEncrypt() in favor of httpConnect2(). hhttpConnect2() + # is new in 1.7, so it doesn't exist on OS X 10.6-10.8 and we + # can't use it until 10.9 is our minimum system version. + # (cups_version isn't reliable on OS X, so key the check off of + # mac_sdk). + cflags += [ "-Wno-deprecated-declarations" ] + } + + # PRINT_BACKEND_AVAILABLE disables the default dummy implementation + # of the print backend and enables a custom implementation instead. + defines += [ "PRINT_BACKEND_AVAILABLE" ] + + sources += [ + "backend/cups_helper.cc", + "backend/cups_helper.h", + "backend/print_backend_cups.cc", + ] + } + + if (is_chromeos) { + # PRINT_BACKEND_AVAILABLE disables the default dummy implementation + # of the print backend and enables a custom implementation instead. + defines += [ "PRINT_BACKEND_AVAILABLE" ] + + sources += [ + "backend/print_backend_chromeos.cc", + ] + } else if (is_linux) { # Non-ChromeOS Linux. + sources += [ + "printing_context_linux.cc", + "printing_context_linux.h", + ] + } + + if (is_android) { + sources += [ + "printing_context_android.cc", + "printing_context_android.h", + ] + + deps += [ ":printing_jni_headers" ] + } +} + +test("printing_unittests") { + sources = [ + "emf_win_unittest.cc", + "page_number_unittest.cc", + "page_range_unittest.cc", + "page_setup_unittest.cc", + "pdf_metafile_cg_mac_unittest.cc", + "printed_page_unittest.cc", + "printing_context_win_unittest.cc", + "printing_test.h", + "printing_utils_unittest.cc", + "units_unittest.cc", + ] + + if (use_cups) { + configs += [ ":cups" ] + sources += [ "backend/cups_helper_unittest.cc" ] + } + + deps = [ + ":printing", + "//base/allocator", + "//base/test:run_all_unittests", + "//base/test:test_support", + "//testing/gtest", + "//ui/base", + "//ui/gfx", + "//ui/gfx/geometry", + ] +} + +if (use_cups) { + config("cups") { + defines = [ "USE_CUPS" ] + + if (is_mac) { + libs = [ "libcups.dylib" ] + } else { + libs = exec_script("cups_config_helper.py", [ "--libs-for-gn" ], "value") + } + } +} + +if (is_android) { + generate_jni("printing_jni_headers") { + sources = [ + "android/java/src/org/chromium/printing/PrintingContext.java", + ] + jni_package = "printing" + } + + # TODO(GYP) + #{ + # 'target_name': 'printing_java', + # 'type': 'none', + # 'variables': { + # 'java_in_dir': '../printing/android/java', + # }, + # 'dependencies': [ + # '../base/base.gyp:base_java', + # ], + # 'includes': [ '../build/java.gypi' ], + #} +} diff --git a/chromium/printing/DEPS b/chromium/printing/DEPS index bc43b418c77..97c498be708 100644 --- a/chromium/printing/DEPS +++ b/chromium/printing/DEPS @@ -8,6 +8,5 @@ include_rules = [ "+ui/base/resource", "+ui/base/text", "+ui/gfx", - "+ui/shell_dialogs", "+win8/util", ] diff --git a/chromium/printing/backend/cups_helper.cc b/chromium/printing/backend/cups_helper.cc index 5636f089476..959e93737cd 100644 --- a/chromium/printing/backend/cups_helper.cc +++ b/chromium/printing/backend/cups_helper.cc @@ -6,14 +6,17 @@ #include <cups/ppd.h> +#include "base/base_paths.h" #include "base/file_util.h" #include "base/logging.h" +#include "base/path_service.h" #include "base/strings/string_number_conversions.h" #include "base/strings/string_split.h" #include "base/strings/string_util.h" #include "base/values.h" #include "printing/backend/print_backend.h" #include "printing/backend/print_backend_consts.h" +#include "printing/units.h" #include "url/gurl.h" namespace printing { @@ -31,6 +34,9 @@ const char kHighGray[] = "High.Gray"; const char kDuplex[] = "Duplex"; const char kDuplexNone[] = "None"; +const char kPageSize[] = "PageSize"; + +const double kMicronsPerPoint = 10.0f * kHundrethsMMPerInch / kPointsPerInch; #if !defined(OS_MACOSX) void ParseLpOptions(const base::FilePath& filepath, @@ -62,7 +68,7 @@ void ParseLpOptions(const base::FilePath& filepath, continue; } - TrimWhitespaceASCII(line, TRIM_ALL, &line); + base::TrimWhitespaceASCII(line, base::TRIM_ALL, &line); if (line.empty()) continue; @@ -80,7 +86,8 @@ void ParseLpOptions(const base::FilePath& filepath, } line = line.substr(space_found + 1); - TrimWhitespaceASCII(line, TRIM_ALL, &line); // Remove extra spaces. + // Remove extra spaces. + base::TrimWhitespaceASCII(line, base::TRIM_ALL, &line); if (line.empty()) continue; // Parse the selected printer custom options. @@ -98,8 +105,9 @@ void MarkLpOptions(const std::string& printer_name, ppd_file_t** ppd) { std::vector<base::FilePath> file_locations; file_locations.push_back(base::FilePath(kSystemLpOptionPath)); - file_locations.push_back(base::FilePath( - base::GetHomeDir().Append(kUserLpOptionPath))); + base::FilePath homedir; + PathService::Get(base::DIR_HOME, &homedir); + file_locations.push_back(base::FilePath(homedir.Append(kUserLpOptionPath))); for (std::vector<base::FilePath>::const_iterator it = file_locations.begin(); it != file_locations.end(); ++it) { @@ -313,7 +321,7 @@ HttpConnectionCUPS::HttpConnectionCUPS(const GURL& print_server_url, return; int port = print_server_url.IntPort(); - if (port == url_parse::PORT_UNSPECIFIED) + if (port == url::PORT_UNSPECIFIED) port = kDefaultIPPServerPort; http_ = httpConnectEncrypt(print_server_url.host().c_str(), port, encryption); @@ -345,7 +353,7 @@ bool ParsePpdCapabilities( return false; int data_size = printer_capabilities.length(); - if (data_size != file_util::WriteFile( + if (data_size != base::WriteFile( ppd_file_path, printer_capabilities.data(), data_size)) { @@ -354,13 +362,22 @@ bool ParsePpdCapabilities( } ppd_file_t* ppd = ppdOpenFile(ppd_file_path.value().c_str()); - if (!ppd) + if (!ppd) { + int line = 0; + ppd_status_t ppd_status = ppdLastError(&line); + LOG(ERROR) << "Failed to open PDD file: error " << ppd_status << " at line " + << line << ", " << ppdErrorString(ppd_status); return false; + } printing::PrinterSemanticCapsAndDefaults caps; #if !defined(OS_MACOSX) MarkLpOptions(printer_name, &ppd); #endif + caps.collate_capable = true; + caps.collate_default = true; + caps.copies_capable = true; + ppd_choice_t* duplex_choice = ppdFindMarkedChoice(ppd, kDuplex); if (!duplex_choice) { ppd_option_t* option = ppdFindOption(ppd, kDuplex); @@ -389,6 +406,34 @@ bool ParsePpdCapabilities( caps.color_model = cm_color; caps.bw_model = cm_black; + if (ppd->num_sizes > 0 && ppd->sizes) { + VLOG(1) << "Paper list size - " << ppd->num_sizes; + ppd_option_t* paper_option = ppdFindOption(ppd, kPageSize); + for (int i = 0; i < ppd->num_sizes; ++i) { + gfx::Size paper_size_microns( + static_cast<int>(ppd->sizes[i].width * kMicronsPerPoint + 0.5), + static_cast<int>(ppd->sizes[i].length * kMicronsPerPoint + 0.5)); + if (paper_size_microns.width() > 0 && paper_size_microns.height() > 0) { + PrinterSemanticCapsAndDefaults::Paper paper; + paper.size_um = paper_size_microns; + paper.vendor_id = ppd->sizes[i].name; + if (paper_option) { + ppd_choice_t* paper_choice = + ppdFindChoice(paper_option, ppd->sizes[i].name); + // Human readable paper name should be UTF-8 encoded, but some PPDs + // do not follow this standard. + if (paper_choice && base::IsStringUTF8(paper_choice->text)) { + paper.display_name = paper_choice->text; + } + } + caps.papers.push_back(paper); + if (i == 0 || ppd->sizes[i].marked) { + caps.default_paper = paper; + } + } + } + } + ppdClose(ppd); base::DeleteFile(ppd_file_path, false); diff --git a/chromium/printing/backend/cups_helper_unittest.cc b/chromium/printing/backend/cups_helper_unittest.cc index 7f2b77cbe4e..01c5c65d364 100644 --- a/chromium/printing/backend/cups_helper_unittest.cc +++ b/chromium/printing/backend/cups_helper_unittest.cc @@ -33,10 +33,13 @@ TEST(PrintBackendCupsHelperTest, TestPpdParsingNoColorDuplexLongEdge) { printing::PrinterSemanticCapsAndDefaults caps; EXPECT_TRUE(printing::ParsePpdCapabilities("test", test_ppd_data, &caps)); - EXPECT_FALSE(caps.color_changeable); - EXPECT_FALSE(caps.color_default); + EXPECT_TRUE(caps.collate_capable); + EXPECT_TRUE(caps.collate_default); + EXPECT_TRUE(caps.copies_capable); EXPECT_TRUE(caps.duplex_capable); EXPECT_EQ(caps.duplex_default, printing::LONG_EDGE); + EXPECT_FALSE(caps.color_changeable); + EXPECT_FALSE(caps.color_default); } // Test duplex detection code, which regressed in http://crbug.com/103999. @@ -58,10 +61,13 @@ TEST(PrintBackendCupsHelperTest, TestPpdParsingNoColorDuplexSimples) { printing::PrinterSemanticCapsAndDefaults caps; EXPECT_TRUE(printing::ParsePpdCapabilities("test", test_ppd_data, &caps)); - EXPECT_FALSE(caps.color_changeable); - EXPECT_FALSE(caps.color_default); + EXPECT_TRUE(caps.collate_capable); + EXPECT_TRUE(caps.collate_default); + EXPECT_TRUE(caps.copies_capable); EXPECT_TRUE(caps.duplex_capable); EXPECT_EQ(caps.duplex_default, printing::SIMPLEX); + EXPECT_FALSE(caps.color_changeable); + EXPECT_FALSE(caps.color_default); } TEST(PrintBackendCupsHelperTest, TestPpdParsingNoColorNoDuplex) { @@ -82,10 +88,13 @@ TEST(PrintBackendCupsHelperTest, TestPpdParsingNoColorNoDuplex) { printing::PrinterSemanticCapsAndDefaults caps; EXPECT_TRUE(printing::ParsePpdCapabilities("test", test_ppd_data, &caps)); - EXPECT_FALSE(caps.color_changeable); - EXPECT_FALSE(caps.color_default); + EXPECT_TRUE(caps.collate_capable); + EXPECT_TRUE(caps.collate_default); + EXPECT_TRUE(caps.copies_capable); EXPECT_FALSE(caps.duplex_capable); EXPECT_EQ(caps.duplex_default, printing::UNKNOWN_DUPLEX_MODE); + EXPECT_FALSE(caps.color_changeable); + EXPECT_FALSE(caps.color_default); } TEST(PrintBackendCupsHelperTest, TestPpdParsingColorTrueDuplexLongEdge) { @@ -115,10 +124,13 @@ TEST(PrintBackendCupsHelperTest, TestPpdParsingColorTrueDuplexLongEdge) { printing::PrinterSemanticCapsAndDefaults caps; EXPECT_TRUE(printing::ParsePpdCapabilities("test", test_ppd_data, &caps)); - EXPECT_TRUE(caps.color_changeable); - EXPECT_TRUE(caps.color_default); + EXPECT_TRUE(caps.collate_capable); + EXPECT_TRUE(caps.collate_default); + EXPECT_TRUE(caps.copies_capable); EXPECT_TRUE(caps.duplex_capable); EXPECT_EQ(caps.duplex_default, printing::LONG_EDGE); + EXPECT_TRUE(caps.color_changeable); + EXPECT_TRUE(caps.color_default); } TEST(PrintBackendCupsHelperTest, TestPpdParsingColorFalseDuplexLongEdge) { @@ -152,8 +164,44 @@ TEST(PrintBackendCupsHelperTest, TestPpdParsingColorFalseDuplexLongEdge) { printing::PrinterSemanticCapsAndDefaults caps; EXPECT_TRUE(printing::ParsePpdCapabilities("test", test_ppd_data, &caps)); - EXPECT_TRUE(caps.color_changeable); - EXPECT_FALSE(caps.color_default); + EXPECT_TRUE(caps.collate_capable); + EXPECT_TRUE(caps.collate_default); + EXPECT_TRUE(caps.copies_capable); EXPECT_TRUE(caps.duplex_capable); EXPECT_EQ(caps.duplex_default, printing::LONG_EDGE); + EXPECT_TRUE(caps.color_changeable); + EXPECT_FALSE(caps.color_default); +} + +TEST(PrintBackendCupsHelperTest, TestPpdParsingPageSize) { + std::string test_ppd_data; + test_ppd_data.append( + "*PPD-Adobe: \"4.3\"\n\n" + "*OpenUI *PageSize: PickOne\n" + "*OrderDependency: 30 AnySetup *PageSize\n" + "*DefaultPageSize: Letter\n" + "*PageSize Letter/US Letter: \"" + " <</DeferredMediaSelection true /PageSize [612 792] " + " /ImagingBBox null /MediaClass null >> setpagedevice\"\n" + "*End\n" + "*PageSize Legal/US Legal: \"" + " <</DeferredMediaSelection true /PageSize [612 1008] " + " /ImagingBBox null /MediaClass null >> setpagedevice\"\n" + "*End\n" + "*DefaultPaperDimension: Letter\n" + "*PaperDimension Letter/US Letter: \"612 792\"\n" + "*PaperDimension Legal/US Legal: \"612 1008\"\n\n" + "*CloseUI: *PageSize\n\n"); + + printing::PrinterSemanticCapsAndDefaults caps; + EXPECT_TRUE(printing::ParsePpdCapabilities("test", test_ppd_data, &caps)); + ASSERT_EQ(2UL, caps.papers.size()); + EXPECT_EQ("Letter", caps.papers[0].vendor_id); + EXPECT_EQ("US Letter", caps.papers[0].display_name); + EXPECT_EQ(215900, caps.papers[0].size_um.width()); + EXPECT_EQ(279400, caps.papers[0].size_um.height()); + EXPECT_EQ("Legal", caps.papers[1].vendor_id); + EXPECT_EQ("US Legal", caps.papers[1].display_name); + EXPECT_EQ(215900, caps.papers[1].size_um.width()); + EXPECT_EQ(355600, caps.papers[1].size_um.height()); } diff --git a/chromium/printing/backend/print_backend.cc b/chromium/printing/backend/print_backend.cc index 29d38fba645..fefa7899eb3 100644 --- a/chromium/printing/backend/print_backend.cc +++ b/chromium/printing/backend/print_backend.cc @@ -13,10 +13,16 @@ PrinterBasicInfo::PrinterBasicInfo() PrinterBasicInfo::~PrinterBasicInfo() {} PrinterSemanticCapsAndDefaults::PrinterSemanticCapsAndDefaults() - : color_changeable(false), + : collate_capable(false), + collate_default(false), + copies_capable(false), duplex_capable(false), + duplex_default(UNKNOWN_DUPLEX_MODE), + color_changeable(false), color_default(false), - duplex_default(UNKNOWN_DUPLEX_MODE) {} + color_model(UNKNOWN_COLOR_MODEL), + bw_model(UNKNOWN_COLOR_MODEL) +{} PrinterSemanticCapsAndDefaults::~PrinterSemanticCapsAndDefaults() {} diff --git a/chromium/printing/backend/print_backend.h b/chromium/printing/backend/print_backend.h index d698d1149d8..e03ef42e37c 100644 --- a/chromium/printing/backend/print_backend.h +++ b/chromium/printing/backend/print_backend.h @@ -12,6 +12,7 @@ #include "base/memory/ref_counted.h" #include "printing/print_job_constants.h" #include "printing/printing_export.h" +#include "ui/gfx/geometry/size.h" namespace base { class DictionaryValue; @@ -37,18 +38,29 @@ struct PRINTING_EXPORT PrinterSemanticCapsAndDefaults { PrinterSemanticCapsAndDefaults(); ~PrinterSemanticCapsAndDefaults(); - // Capabilities. - bool color_changeable; + bool collate_capable; + bool collate_default; + + bool copies_capable; + bool duplex_capable; + DuplexMode duplex_default; -#if defined(USE_CUPS) + bool color_changeable; + bool color_default; ColorModel color_model; ColorModel bw_model; -#endif - // Current defaults. - bool color_default; - DuplexMode duplex_default; + struct Paper { + std::string display_name; + std::string vendor_id; + gfx::Size size_um; + }; + std::vector<Paper> papers; + Paper default_paper; + + std::vector<gfx::Size> dpis; + gfx::Size default_dpi; }; struct PRINTING_EXPORT PrinterCapsAndDefaults { diff --git a/chromium/printing/backend/print_backend_consts.cc b/chromium/printing/backend/print_backend_consts.cc index 8b2f6db07ae..1717a464738 100644 --- a/chromium/printing/backend/print_backend_consts.cc +++ b/chromium/printing/backend/print_backend_consts.cc @@ -6,11 +6,11 @@ #include "printing/backend/print_backend_consts.h" -const char kLocationTagName[] = "location"; -const char kDriverNameTagName[] = "drivername"; -const char kDriverInfoTagName[] = "system_driverinfo"; -const char kCUPSPrintServerURL[] = "print_server_url"; const char kCUPSBlocking[] = "cups_blocking"; const char kCUPSEncryption[] = "cups_encryption"; -const char kValueTrue[] = "true"; +const char kCUPSPrintServerURL[] = "print_server_url"; +const char kDriverInfoTagName[] = "system_driverinfo"; +const char kDriverNameTagName[] = "printer-make-and-model"; // Match CUPS. +const char kLocationTagName[] = "printer-location"; // Match CUPS. const char kValueFalse[] = "false"; +const char kValueTrue[] = "true"; diff --git a/chromium/printing/backend/print_backend_consts.h b/chromium/printing/backend/print_backend_consts.h index 0cab35e5b20..083ec2edcf7 100644 --- a/chromium/printing/backend/print_backend_consts.h +++ b/chromium/printing/backend/print_backend_consts.h @@ -7,13 +7,13 @@ #include "printing/printing_export.h" -PRINTING_EXPORT extern const char kLocationTagName[]; -PRINTING_EXPORT extern const char kDriverNameTagName[]; -PRINTING_EXPORT extern const char kDriverInfoTagName[]; -PRINTING_EXPORT extern const char kCUPSPrintServerURL[]; PRINTING_EXPORT extern const char kCUPSBlocking[]; PRINTING_EXPORT extern const char kCUPSEncryption[]; -PRINTING_EXPORT extern const char kValueTrue[]; +PRINTING_EXPORT extern const char kCUPSPrintServerURL[]; +PRINTING_EXPORT extern const char kDriverInfoTagName[]; +PRINTING_EXPORT extern const char kDriverNameTagName[]; +PRINTING_EXPORT extern const char kLocationTagName[]; PRINTING_EXPORT extern const char kValueFalse[]; +PRINTING_EXPORT extern const char kValueTrue[]; #endif // PRINTING_BACKEND_PRINT_BACKEND_CONSTS_H_ diff --git a/chromium/printing/backend/print_backend_cups.cc b/chromium/printing/backend/print_backend_cups.cc index bf7141e05de..0f2f0e79133 100644 --- a/chromium/printing/backend/print_backend_cups.cc +++ b/chromium/printing/backend/print_backend_cups.cc @@ -10,10 +10,6 @@ #include <errno.h> #include <pthread.h> -#if !defined(OS_MACOSX) -#include <gcrypt.h> -#endif - #include "base/debug/leak_annotations.h" #include "base/file_util.h" #include "base/lazy_instance.h" @@ -25,76 +21,6 @@ #include "printing/backend/print_backend_consts.h" #include "url/gurl.h" -#if !defined(OS_MACOSX) -GCRY_THREAD_OPTION_PTHREAD_IMPL; - -namespace { - -// Init GCrypt library (needed for CUPS) using pthreads. -// There exists a bug in CUPS library, where it crashed with: "ath.c:184: -// _gcry_ath_mutex_lock: Assertion `*lock == ((ath_mutex_t) 0)' failed." -// It happened when multiple threads tried printing simultaneously. -// Google search for 'gnutls thread safety' provided a solution that -// initialized gcrypt and gnutls. - -// TODO(phajdan.jr): Remove this after https://bugs.g10code.com/gnupg/issue1197 -// gets fixed on all Linux distros we support (i.e. when they ship libgcrypt -// with the fix). - -// Initially, we linked with -lgnutls and simply called gnutls_global_init(), -// but this did not work well since we build one binary on Ubuntu Hardy and -// expect it to run on many Linux distros. (See http://crbug.com/46954) -// So instead we use dlopen() and dlsym() to dynamically load and call -// gnutls_global_init(). - -class GcryptInitializer { - public: - GcryptInitializer() { - Init(); - } - - private: - void Init() { - const char* kGnuTlsFiles[] = { - "libgnutls.so.28", - "libgnutls.so.26", - "libgnutls.so", - }; - gcry_control(GCRYCTL_SET_THREAD_CBS, &gcry_threads_pthread); - for (size_t i = 0; i < arraysize(kGnuTlsFiles); ++i) { - void* gnutls_lib = dlopen(kGnuTlsFiles[i], RTLD_NOW); - if (!gnutls_lib) { - VLOG(1) << "Cannot load " << kGnuTlsFiles[i]; - continue; - } - const char* kGnuTlsInitFuncName = "gnutls_global_init"; - int (*pgnutls_global_init)(void) = reinterpret_cast<int(*)()>( - dlsym(gnutls_lib, kGnuTlsInitFuncName)); - if (!pgnutls_global_init) { - VLOG(1) << "Could not find " << kGnuTlsInitFuncName - << " in " << kGnuTlsFiles[i]; - continue; - } - { - // GnuTLS has a genuine small memory leak that is easier to annotate - // than suppress. See http://crbug.com/176888#c7 - // TODO(earthdok): remove this once the leak is fixed. - ANNOTATE_SCOPED_MEMORY_LEAK; - if ((*pgnutls_global_init)() != 0) - LOG(ERROR) << "gnutls_global_init() failed"; - } - return; - } - LOG(ERROR) << "Cannot find libgnutls"; - } -}; - -base::LazyInstance<GcryptInitializer> g_gcrypt_initializer = - LAZY_INSTANCE_INITIALIZER; - -} // namespace -#endif // !defined(OS_MACOSX) - namespace printing { static const char kCUPSPrinterInfoOpt[] = "printer-info"; @@ -239,8 +165,7 @@ bool PrintBackendCUPS::GetPrinterCapsAndDefaults( base::FilePath ppd_path(GetPPD(printer_name.c_str())); // In some cases CUPS failed to get ppd file. if (ppd_path.empty()) { - LOG(ERROR) << "CUPS: Failed to get PPD" - << ", printer name: " << printer_name; + LOG(ERROR) << "CUPS: Failed to get PPD, printer name: " << printer_name; return false; } @@ -296,11 +221,6 @@ bool PrintBackendCUPS::IsValidPrinter(const std::string& printer_name) { scoped_refptr<PrintBackend> PrintBackend::CreateInstance( const base::DictionaryValue* print_backend_settings) { -#if !defined(OS_MACOSX) - // Initialize gcrypt library. - g_gcrypt_initializer.Get(); -#endif - std::string print_server_url_str, cups_blocking; int encryption = HTTP_ENCRYPT_NEVER; if (print_backend_settings) { @@ -320,6 +240,12 @@ scoped_refptr<PrintBackend> PrintBackend::CreateInstance( int PrintBackendCUPS::GetDests(cups_dest_t** dests) { if (print_server_url_.is_empty()) { // Use default (local) print server. + // GnuTLS has a genuine small memory leak that is easier to annotate + // than suppress. See http://crbug.com/176888#c7 + // In theory any CUPS function can trigger this leak, but in + // PrintBackendCUPS, this is the most likely spot. + // TODO(earthdok): remove this once the leak is fixed. + ANNOTATE_SCOPED_MEMORY_LEAK; return cupsGetDests(dests); } else { HttpConnectionCUPS http(print_server_url_, cups_encryption_); diff --git a/chromium/printing/backend/print_backend_dummy.cc b/chromium/printing/backend/print_backend_dummy.cc index fdc3b7ff363..c73e5370720 100644 --- a/chromium/printing/backend/print_backend_dummy.cc +++ b/chromium/printing/backend/print_backend_dummy.cc @@ -14,7 +14,7 @@ namespace printing { scoped_refptr<PrintBackend> PrintBackend::CreateInstance( - const DictionaryValue* print_backend_settings) { + const base::DictionaryValue* print_backend_settings) { NOTREACHED(); return NULL; } diff --git a/chromium/printing/backend/print_backend_win.cc b/chromium/printing/backend/print_backend_win.cc index 0d1958fd39c..a8139f397e0 100644 --- a/chromium/printing/backend/print_backend_win.cc +++ b/chromium/printing/backend/print_backend_win.cc @@ -8,6 +8,8 @@ #include <winspool.h> #include "base/memory/scoped_ptr.h" +#include "base/numerics/safe_conversions.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/string_piece.h" #include "base/strings/utf_string_conversions.h" #include "base/win/scoped_bstr.h" @@ -17,6 +19,7 @@ #include "printing/backend/printing_info_win.h" #include "printing/backend/win_helper.h" +namespace printing { namespace { @@ -33,9 +36,121 @@ HRESULT StreamOnHGlobalToString(IStream* stream, std::string* out) { return hr; } -} // namespace +template <class T> +void GetDeviceCapabilityArray(const wchar_t* printer, + const wchar_t* port, + WORD id, + std::vector<T>* result) { + int count = DeviceCapabilities(printer, port, id, NULL, NULL); + if (count <= 0) + return; + std::vector<T> tmp; + tmp.resize(count * 2); + count = DeviceCapabilities(printer, port, id, + reinterpret_cast<LPTSTR>(tmp.data()), NULL); + if (count <= 0) + return; + CHECK_LE(count, base::checked_cast<int>(tmp.size())); + tmp.resize(count); + result->swap(tmp); +} -namespace printing { +void LoadPaper(const wchar_t* printer, + const wchar_t* port, + const DEVMODE* devmode, + PrinterSemanticCapsAndDefaults* caps) { + static const size_t kToUm = 100; // Windows uses 0.1mm. + static const size_t kMaxPaperName = 64; + + struct PaperName { + wchar_t chars[kMaxPaperName]; + }; + + DCHECK_EQ(sizeof(PaperName), sizeof(wchar_t) * kMaxPaperName); + + // Paper + std::vector<PaperName> names; + GetDeviceCapabilityArray(printer, port, DC_PAPERNAMES, &names); + + std::vector<POINT> sizes; + GetDeviceCapabilityArray(printer, port, DC_PAPERSIZE, &sizes); + + std::vector<WORD> ids; + GetDeviceCapabilityArray(printer, port, DC_PAPERS, &ids); + + DCHECK_EQ(ids.size(), sizes.size()); + DCHECK_EQ(names.size(), sizes.size()); + + if (ids.size() != sizes.size()) + ids.clear(); + if (names.size() != sizes.size()) + names.clear(); + + for (size_t i = 0; i < sizes.size(); ++i) { + PrinterSemanticCapsAndDefaults::Paper paper; + paper.size_um.SetSize(sizes[i].x * kToUm, sizes[i].y * kToUm); + if (!names.empty()) { + const wchar_t* name_start = names[i].chars; + base::string16 tmp_name(name_start, kMaxPaperName); + // Trim trailing zeros. + tmp_name = tmp_name.c_str(); + paper.display_name = base::WideToUTF8(tmp_name); + } + if (!ids.empty()) + paper.vendor_id = base::UintToString(ids[i]); + caps->papers.push_back(paper); + } + + if (devmode) { + // Copy paper with the same ID as default paper. + if (devmode->dmFields & DM_PAPERSIZE) { + for (size_t i = 0; i < ids.size(); ++i) { + if (ids[i] == devmode->dmPaperSize) { + DCHECK_EQ(ids.size(), caps->papers.size()); + caps->default_paper = caps->papers[i]; + break; + } + } + } + + gfx::Size default_size; + if (devmode->dmFields & DM_PAPERWIDTH) + default_size.set_width(devmode->dmPaperWidth * kToUm); + if (devmode->dmFields & DM_PAPERLENGTH) + default_size.set_height(devmode->dmPaperLength * kToUm); + + if (!default_size.IsEmpty()) { + // Reset default paper if |dmPaperWidth| or |dmPaperLength| does not + // match default paper set by. + if (default_size != caps->default_paper.size_um) + caps->default_paper = PrinterSemanticCapsAndDefaults::Paper(); + caps->default_paper.size_um = default_size; + } + } +} + +void LoadDpi(const wchar_t* printer, + const wchar_t* port, + const DEVMODE* devmode, + PrinterSemanticCapsAndDefaults* caps) { + std::vector<POINT> dpis; + GetDeviceCapabilityArray(printer, port, DC_ENUMRESOLUTIONS, &dpis); + + for (size_t i = 0; i < dpis.size() ; ++i) + caps->dpis.push_back(gfx::Size(dpis[i].x, dpis[i].y)); + + if (devmode) { + if ((devmode->dmFields & DM_PRINTQUALITY) && devmode->dmPrintQuality > 0) { + caps->default_dpi.SetSize(devmode->dmPrintQuality, + devmode->dmPrintQuality); + if (devmode->dmFields & DM_YRESOLUTION) { + caps->default_dpi.set_height(devmode->dmYResolution); + } + } + } +} + +} // namespace class PrintBackendWin : public PrintBackend { public: @@ -95,48 +210,35 @@ std::string PrintBackendWin::GetDefaultPrinterName() { TCHAR default_printer_name[MAX_PATH]; if (!::GetDefaultPrinter(default_printer_name, &size)) return std::string(); - return WideToUTF8(default_printer_name); + return base::WideToUTF8(default_printer_name); } bool PrintBackendWin::GetPrinterSemanticCapsAndDefaults( const std::string& printer_name, PrinterSemanticCapsAndDefaults* printer_info) { ScopedPrinterHandle printer_handle; - if (!printer_handle.OpenPrinter(UTF8ToWide(printer_name).c_str())) { + if (!printer_handle.OpenPrinter(base::UTF8ToWide(printer_name).c_str())) { LOG(WARNING) << "Failed to open printer, error = " << GetLastError(); return false; } PrinterInfo5 info_5; - if (!info_5.Init(printer_handle)) { + if (!info_5.Init(printer_handle)) return false; - } - DCHECK_EQ(info_5.get()->pPrinterName, UTF8ToUTF16(printer_name)); + const wchar_t* name = info_5.get()->pPrinterName; + const wchar_t* port = info_5.get()->pPortName; + DCHECK_EQ(name, base::UTF8ToUTF16(printer_name)); PrinterSemanticCapsAndDefaults caps; - // Get printer capabilities. For more info see here: - // http://msdn.microsoft.com/en-us/library/windows/desktop/dd183552(v=vs.85).aspx - caps.color_changeable = (::DeviceCapabilities(info_5.get()->pPrinterName, - info_5.get()->pPortName, - DC_COLORDEVICE, - NULL, - NULL) == 1); - - caps.duplex_capable = (::DeviceCapabilities(info_5.get()->pPrinterName, - info_5.get()->pPortName, - DC_DUPLEX, - NULL, - NULL) == 1); - - UserDefaultDevMode user_settings; - - if (user_settings.Init(printer_handle)) { - if ((user_settings.get()->dmFields & DM_COLOR) == DM_COLOR) - caps.color_default = (user_settings.get()->dmColor == DMCOLOR_COLOR); - - if ((user_settings.get()->dmFields & DM_DUPLEX) == DM_DUPLEX) { - switch (user_settings.get()->dmDuplex) { + scoped_ptr<DEVMODE, base::FreeDeleter> user_settings = + CreateDevMode(printer_handle, NULL); + if (user_settings) { + if (user_settings->dmFields & DM_COLOR) + caps.color_default = (user_settings->dmColor == DMCOLOR_COLOR); + + if (user_settings->dmFields & DM_DUPLEX) { + switch (user_settings->dmDuplex) { case DMDUP_SIMPLEX: caps.duplex_default = SIMPLEX; break; @@ -150,12 +252,34 @@ bool PrintBackendWin::GetPrinterSemanticCapsAndDefaults( NOTREACHED(); } } + + if (user_settings->dmFields & DM_COLLATE) + caps.collate_default = (user_settings->dmCollate == DMCOLLATE_TRUE); } else { LOG(WARNING) << "Fallback to color/simplex mode."; caps.color_default = caps.color_changeable; caps.duplex_default = SIMPLEX; } + // Get printer capabilities. For more info see here: + // http://msdn.microsoft.com/en-us/library/windows/desktop/dd183552(v=vs.85).aspx + caps.color_changeable = + (DeviceCapabilities(name, port, DC_COLORDEVICE, NULL, NULL) == 1); + caps.color_model = printing::COLOR; + caps.bw_model = printing::GRAY; + + caps.duplex_capable = + (DeviceCapabilities(name, port, DC_DUPLEX, NULL, NULL) == 1); + + caps.collate_capable = + (DeviceCapabilities(name, port, DC_COLLATE, NULL, NULL) == 1); + + caps.copies_capable = + (DeviceCapabilities(name, port, DC_COPIES, NULL, NULL) > 1); + + LoadPaper(name, port, user_settings.get(), &caps); + LoadDpi(name, port, user_settings.get(), &caps); + *printer_info = caps; return true; } @@ -173,7 +297,7 @@ bool PrintBackendWin::GetPrinterCapsAndDefaults( } DCHECK(printer_info); HPTPROVIDER provider = NULL; - std::wstring printer_name_wide = UTF8ToWide(printer_name); + std::wstring printer_name_wide = base::UTF8ToWide(printer_name); HRESULT hr = XPSModule::OpenProvider(printer_name_wide, 1, &provider); if (provider) { base::win::ScopedComPtr<IStream> print_capabilities_stream; @@ -197,27 +321,18 @@ bool PrintBackendWin::GetPrinterCapsAndDefaults( } ScopedPrinterHandle printer_handle; if (printer_handle.OpenPrinter(printer_name_wide.c_str())) { - LONG devmode_size = DocumentProperties( - NULL, printer_handle, const_cast<LPTSTR>(printer_name_wide.c_str()), - NULL, NULL, 0); - if (devmode_size <= 0) + scoped_ptr<DEVMODE, base::FreeDeleter> devmode_out( + CreateDevMode(printer_handle, NULL)); + if (!devmode_out) return false; - scoped_ptr<BYTE[]> devmode_out_buffer(new BYTE[devmode_size]); - DEVMODE* devmode_out = - reinterpret_cast<DEVMODE*>(devmode_out_buffer.get()); - DocumentProperties( - NULL, printer_handle, const_cast<LPTSTR>(printer_name_wide.c_str()), - devmode_out, NULL, DM_OUT_BUFFER); base::win::ScopedComPtr<IStream> printer_defaults_stream; hr = CreateStreamOnHGlobal(NULL, TRUE, printer_defaults_stream.Receive()); DCHECK(SUCCEEDED(hr)); if (printer_defaults_stream) { - hr = XPSModule::ConvertDevModeToPrintTicket(provider, - devmode_size, - devmode_out, - kPTJobScope, - printer_defaults_stream); + DWORD dm_size = devmode_out->dmSize + devmode_out->dmDriverExtra; + hr = XPSModule::ConvertDevModeToPrintTicket(provider, dm_size, + devmode_out.get(), kPTJobScope, printer_defaults_stream); DCHECK(SUCCEEDED(hr)); if (SUCCEEDED(hr)) { hr = StreamOnHGlobalToString(printer_defaults_stream.get(), @@ -236,7 +351,7 @@ bool PrintBackendWin::GetPrinterCapsAndDefaults( std::string PrintBackendWin::GetPrinterDriverInfo( const std::string& printer_name) { ScopedPrinterHandle printer; - if (!printer.OpenPrinter(UTF8ToWide(printer_name).c_str())) { + if (!printer.OpenPrinter(base::UTF8ToWide(printer_name).c_str())) { return std::string(); } return GetDriverInfo(printer); @@ -244,7 +359,7 @@ std::string PrintBackendWin::GetPrinterDriverInfo( bool PrintBackendWin::IsValidPrinter(const std::string& printer_name) { ScopedPrinterHandle printer_handle; - return printer_handle.OpenPrinter(UTF8ToWide(printer_name).c_str()); + return printer_handle.OpenPrinter(base::UTF8ToWide(printer_name).c_str()); } scoped_refptr<PrintBackend> PrintBackend::CreateInstance( diff --git a/chromium/printing/backend/printing_info_win.cc b/chromium/printing/backend/printing_info_win.cc index 0e4509430d2..e759639857f 100644 --- a/chromium/printing/backend/printing_info_win.cc +++ b/chromium/printing/backend/printing_info_win.cc @@ -44,23 +44,4 @@ uint8* GetPrinterInfo(HANDLE printer, int level) { } // namespace internal -UserDefaultDevMode::UserDefaultDevMode() : dev_mode_(NULL) { -} - -bool UserDefaultDevMode::Init(HANDLE printer) { - if (info_9_.Init(printer)) - dev_mode_ = info_9_.get()->pDevMode; - - if (!dev_mode_ && info_8_.Init(printer)) - dev_mode_ = info_8_.get()->pDevMode; - - if (!dev_mode_ && info_2_.Init(printer)) - dev_mode_ = info_2_.get()->pDevMode; - - return dev_mode_ != NULL; -} - -UserDefaultDevMode::~UserDefaultDevMode() { -} - } // namespace printing diff --git a/chromium/printing/backend/printing_info_win.h b/chromium/printing/backend/printing_info_win.h index 931ae6df0c4..11341943ce2 100644 --- a/chromium/printing/backend/printing_info_win.h +++ b/chromium/printing/backend/printing_info_win.h @@ -58,34 +58,9 @@ class DriverInfo { typedef internal::PrinterInfo<PRINTER_INFO_2, 2> PrinterInfo2; typedef internal::PrinterInfo<PRINTER_INFO_5, 5> PrinterInfo5; -typedef internal::PrinterInfo<PRINTER_INFO_8, 8> PrinterInfo8; -typedef internal::PrinterInfo<PRINTER_INFO_9, 9> PrinterInfo9; typedef internal::DriverInfo<DRIVER_INFO_6, 6> DriverInfo6; -// Retrieves DEVMODE from PRINTER_INFO_* structures. -// Requests in following order: -// 9 (user-default), -// 8 (admin-default), -// 2 (printer-default). -class PRINTING_EXPORT UserDefaultDevMode { - public: - UserDefaultDevMode(); - ~UserDefaultDevMode(); - - bool Init(HANDLE printer); - - const DEVMODE* get() const { - return dev_mode_; - } - - private: - PrinterInfo2 info_2_; - PrinterInfo8 info_8_; - PrinterInfo9 info_9_; - const DEVMODE* dev_mode_; -}; - } // namespace printing #endif // PRINTING_BACKEND_PRINTING_INFO_WIN_H_ diff --git a/chromium/printing/backend/win_helper.cc b/chromium/printing/backend/win_helper.cc index 3d114d9110d..075913eed3e 100644 --- a/chromium/printing/backend/win_helper.cc +++ b/chromium/printing/backend/win_helper.cc @@ -10,7 +10,11 @@ #include "base/files/file_path.h" #include "base/logging.h" #include "base/memory/scoped_ptr.h" +#include "base/numerics/safe_conversions.h" +#include "base/strings/string_util.h" +#include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/win/scoped_comptr.h" #include "printing/backend/print_backend.h" #include "printing/backend/print_backend_consts.h" #include "printing/backend/printing_info_win.h" @@ -75,6 +79,42 @@ PTReleaseMemoryProc g_release_memory_proc = NULL; PTCloseProviderProc g_close_provider_proc = NULL; StartXpsPrintJobProc g_start_xps_print_job_proc = NULL; +HRESULT StreamFromPrintTicket(const std::string& print_ticket, + IStream** stream) { + DCHECK(stream); + HRESULT hr = CreateStreamOnHGlobal(NULL, TRUE, stream); + if (FAILED(hr)) { + return hr; + } + ULONG bytes_written = 0; + (*stream)->Write(print_ticket.c_str(), + base::checked_cast<ULONG>(print_ticket.length()), + &bytes_written); + DCHECK(bytes_written == print_ticket.length()); + LARGE_INTEGER pos = {0}; + ULARGE_INTEGER new_pos = {0}; + (*stream)->Seek(pos, STREAM_SEEK_SET, &new_pos); + return S_OK; +} + +const char kXpsTicketTemplate[] = + "<?xml version='1.0' encoding='UTF-8'?>" + "<psf:PrintTicket " + "xmlns:psf='" + "http://schemas.microsoft.com/windows/2003/08/printing/printschemaframework' " + "xmlns:psk=" + "'http://schemas.microsoft.com/windows/2003/08/printing/printschemakeywords' " + "version='1'>" + "<psf:Feature name='psk:PageOutputColor'>" + "<psf:Option name='psk:%s'>" + "</psf:Option>" + "</psf:Feature>" + "</psf:PrintTicket>"; + +const char kXpsTicketColor[] = "Color"; +const char kXpsTicketMonochrome[] = "Monochrome"; + + } // namespace @@ -289,15 +329,19 @@ bool InitBasicPrinterInfo(HANDLE printer, PrinterBasicInfo* printer_info) { if (!info_2.Init(printer)) return false; - printer_info->printer_name = WideToUTF8(info_2.get()->pPrinterName); - if (info_2.get()->pComment) - printer_info->printer_description = WideToUTF8(info_2.get()->pComment); - if (info_2.get()->pLocation) + printer_info->printer_name = base::WideToUTF8(info_2.get()->pPrinterName); + if (info_2.get()->pComment) { + printer_info->printer_description = + base::WideToUTF8(info_2.get()->pComment); + } + if (info_2.get()->pLocation) { printer_info->options[kLocationTagName] = - WideToUTF8(info_2.get()->pLocation); - if (info_2.get()->pDriverName) + base::WideToUTF8(info_2.get()->pLocation); + } + if (info_2.get()->pDriverName) { printer_info->options[kDriverNameTagName] = - WideToUTF8(info_2.get()->pDriverName); + base::WideToUTF8(info_2.get()->pDriverName); + } printer_info->printer_status = info_2.get()->Status; std::string driver_info = GetDriverInfo(printer); @@ -319,16 +363,16 @@ std::string GetDriverInfo(HANDLE printer) { std::string info[4]; if (info_6.get()->pName) - info[0] = WideToUTF8(info_6.get()->pName); + info[0] = base::WideToUTF8(info_6.get()->pName); if (info_6.get()->pDriverPath) { scoped_ptr<FileVersionInfo> version_info( FileVersionInfo::CreateFileVersionInfo( base::FilePath(info_6.get()->pDriverPath))); if (version_info.get()) { - info[1] = WideToUTF8(version_info->file_version()); - info[2] = WideToUTF8(version_info->product_name()); - info[3] = WideToUTF8(version_info->product_version()); + info[1] = base::WideToUTF8(version_info->file_version()); + info[2] = base::WideToUTF8(version_info->product_name()); + info[3] = base::WideToUTF8(version_info->product_version()); } } @@ -341,4 +385,102 @@ std::string GetDriverInfo(HANDLE printer) { return driver_info; } +scoped_ptr<DEVMODE, base::FreeDeleter> XpsTicketToDevMode( + const base::string16& printer_name, + const std::string& print_ticket) { + scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode; + printing::ScopedXPSInitializer xps_initializer; + if (!xps_initializer.initialized()) { + // TODO(sanjeevr): Handle legacy proxy case (with no prntvpt.dll) + return dev_mode.Pass(); + } + + printing::ScopedPrinterHandle printer; + if (!printer.OpenPrinter(printer_name.c_str())) + return dev_mode.Pass(); + + base::win::ScopedComPtr<IStream> pt_stream; + HRESULT hr = StreamFromPrintTicket(print_ticket, pt_stream.Receive()); + if (FAILED(hr)) + return dev_mode.Pass(); + + HPTPROVIDER provider = NULL; + hr = printing::XPSModule::OpenProvider(printer_name, 1, &provider); + if (SUCCEEDED(hr)) { + ULONG size = 0; + DEVMODE* dm = NULL; + // Use kPTJobScope, because kPTDocumentScope breaks duplex. + hr = printing::XPSModule::ConvertPrintTicketToDevMode(provider, + pt_stream, + kUserDefaultDevmode, + kPTJobScope, + &size, + &dm, + NULL); + if (SUCCEEDED(hr)) { + // Correct DEVMODE using DocumentProperties. See documentation for + // PTConvertPrintTicketToDevMode. + dev_mode = CreateDevMode(printer, dm); + printing::XPSModule::ReleaseMemory(dm); + } + printing::XPSModule::CloseProvider(provider); + } + return dev_mode.Pass(); +} + +scoped_ptr<DEVMODE, base::FreeDeleter> CreateDevModeWithColor( + HANDLE printer, + const base::string16& printer_name, + bool color) { + scoped_ptr<DEVMODE, base::FreeDeleter> default = CreateDevMode(printer, NULL); + if (!default) + return default.Pass(); + + if ((default->dmFields & DM_COLOR) && + ((default->dmColor == DMCOLOR_COLOR) == color)) { + return default.Pass(); + } + + default->dmFields |= DM_COLOR; + default->dmColor = color ? DMCOLOR_COLOR : DMCOLOR_MONOCHROME; + + DriverInfo6 info_6; + if (!info_6.Init(printer)) + return default.Pass(); + + const DRIVER_INFO_6* p = info_6.get(); + + // Only HP known to have issues. + if (!p->pszMfgName || wcscmp(p->pszMfgName, L"HP") != 0) + return default.Pass(); + + // Need XPS for this workaround. + printing::ScopedXPSInitializer xps_initializer; + if (!xps_initializer.initialized()) + return default.Pass(); + + const char* xps_color = color ? kXpsTicketColor : kXpsTicketMonochrome; + std::string xps_ticket = base::StringPrintf(kXpsTicketTemplate, xps_color); + scoped_ptr<DEVMODE, base::FreeDeleter> ticket = + printing::XpsTicketToDevMode(printer_name, xps_ticket); + if (!ticket) + return default.Pass(); + + return ticket.Pass(); +} + +scoped_ptr<DEVMODE, base::FreeDeleter> CreateDevMode(HANDLE printer, + DEVMODE* in) { + LONG buffer_size = DocumentProperties(NULL, printer, L"", 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; + if (DocumentProperties(NULL, printer, L"", out.get(), in, flags) != IDOK) + return scoped_ptr<DEVMODE, base::FreeDeleter>(); + CHECK_GE(buffer_size, out.get()->dmSize + out.get()->dmDriverExtra); + return out.Pass(); +} + } // namespace printing diff --git a/chromium/printing/backend/win_helper.h b/chromium/printing/backend/win_helper.h index db66bf89c48..18d035557e8 100644 --- a/chromium/printing/backend/win_helper.h +++ b/chromium/printing/backend/win_helper.h @@ -6,12 +6,13 @@ #define PRINTING_BACKEND_WIN_HELPER_H_ #include <objidl.h> -#include <winspool.h> #include <prntvpt.h> +#include <winspool.h> #include <xpsprint.h> #include <string> +#include "base/memory/scoped_ptr.h" #include "base/strings/string16.h" #include "base/win/scoped_handle.h" #include "printing/printing_export.h" @@ -169,6 +170,22 @@ PRINTING_EXPORT bool InitBasicPrinterInfo(HANDLE printer, PRINTING_EXPORT std::string GetDriverInfo(HANDLE printer); +PRINTING_EXPORT scoped_ptr<DEVMODE, base::FreeDeleter> XpsTicketToDevMode( + const base::string16& printer_name, + const std::string& print_ticket); + +// Creates default DEVMODE and sets color option. Some devices need special +// workaround for color. +PRINTING_EXPORT scoped_ptr<DEVMODE, base::FreeDeleter> CreateDevModeWithColor( + HANDLE printer, + const base::string16& printer_name, + bool color); + +// Creates new DEVMODE. If |in| is not NULL copy settings from there. +PRINTING_EXPORT scoped_ptr<DEVMODE, base::FreeDeleter> CreateDevMode( + HANDLE printer, + DEVMODE* in); + } // namespace printing #endif // PRINTING_BACKEND_WIN_HELPER_H_ diff --git a/chromium/printing/cups_config_helper.py b/chromium/printing/cups_config_helper.py index 3fe5fe04e1a..f3c22fae964 100755 --- a/chromium/printing/cups_config_helper.py +++ b/chromium/printing/cups_config_helper.py @@ -11,7 +11,8 @@ to keep these separate: cflags are only needed when compiling files that use cups directly, while libs are only needed on the final link line. -TODO(evan): remove me once +This can be dramatically simplified or maybe removed (depending on GN +requirements) when this is fixed: https://bugs.launchpad.net/ubuntu/+source/cupsys/+bug/163704 is fixed. """ @@ -20,7 +21,8 @@ import subprocess import sys def usage(): - print 'usage: %s {--cflags|--ldflags|--libs}' % sys.argv[0] + print 'usage: %s {--api-version|--cflags|--ldflags|--libs|--libs-for-gn}' % \ + sys.argv[0] def run_cups_config(mode): @@ -46,6 +48,11 @@ def run_cups_config(mode): if flag_mode is None or flag_mode == mode: flags_subset.append(flag) + # Note: cross build is confused by the option, and may trigger linker + # warning causing build error. + if '-lgnutls' in flags_subset: + flags_subset.remove('-lgnutls') + return flags_subset @@ -55,11 +62,33 @@ def main(): return 1 mode = sys.argv[1] - if mode not in ('--cflags', '--libs', '--ldflags'): + if mode == '--api-version': + subprocess.call(['cups-config', '--api-version']) + return 0 + + # All other modes get the flags. + if mode not in ('--cflags', '--libs', '--libs-for-gn', '--ldflags'): usage() return 1 + + if mode == '--libs-for-gn': + gn_libs_output = True + mode = '--libs' + else: + gn_libs_output = False + flags = run_cups_config(mode) - print ' '.join(flags) + + if gn_libs_output: + # Strip "-l" from beginning of libs, quote, and surround in [ ]. + print '[' + for lib in flags: + if lib[:2] == "-l": + print '"%s", ' % lib[2:] + print ']' + else: + print ' '.join(flags) + return 0 diff --git a/chromium/printing/image.cc b/chromium/printing/image.cc index b9c0010e615..bae89f8a0fa 100644 --- a/chromium/printing/image.cc +++ b/chromium/printing/image.cc @@ -8,7 +8,7 @@ #include "base/file_util.h" #include "base/md5.h" -#include "base/safe_numerics.h" +#include "base/numerics/safe_conversions.h" #include "base/strings/string_number_conversions.h" #include "printing/metafile.h" #include "printing/metafile_impl.h" @@ -70,10 +70,10 @@ bool Image::SaveToPng(const base::FilePath& filepath) const { &compressed); DCHECK(success && compressed.size()); if (success) { - int write_bytes = file_util::WriteFile( + int write_bytes = base::WriteFile( filepath, reinterpret_cast<char*>(&*compressed.begin()), - base::checked_numeric_cast<int>(compressed.size())); + base::checked_cast<int>(compressed.size())); success = (write_bytes == static_cast<int>(compressed.size())); DCHECK(success); } @@ -152,7 +152,7 @@ bool Image::LoadMetafile(const std::string& data) { DCHECK(!data.empty()); NativeMetafile metafile; if (!metafile.InitFromData(data.data(), - base::checked_numeric_cast<uint32>(data.size()))) + base::checked_cast<uint32>(data.size()))) return false; return LoadMetafile(metafile); } diff --git a/chromium/printing/metafile_impl.h b/chromium/printing/metafile_impl.h index 840a1cede68..9fb2307131d 100644 --- a/chromium/printing/metafile_impl.h +++ b/chromium/printing/metafile_impl.h @@ -13,10 +13,10 @@ namespace printing { -#if defined(OS_WIN) +#if defined(OS_WIN) && !defined(WIN_PDF_METAFILE_FOR_PRINTING) typedef Emf NativeMetafile; typedef PdfMetafileSkia PreviewMetafile; -#elif defined(OS_POSIX) +#else typedef PdfMetafileSkia NativeMetafile; typedef PdfMetafileSkia PreviewMetafile; #endif diff --git a/chromium/printing/page_size_margins.cc b/chromium/printing/page_size_margins.cc deleted file mode 100644 index a28c6ada3c8..00000000000 --- a/chromium/printing/page_size_margins.cc +++ /dev/null @@ -1,29 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "printing/page_size_margins.h" - -#include "base/logging.h" -#include "base/values.h" -#include "printing/print_job_constants.h" - -namespace printing { - -void GetCustomMarginsFromJobSettings(const base::DictionaryValue& settings, - PageSizeMargins* page_size_margins) { - const base::DictionaryValue* custom_margins; - if (!settings.GetDictionary(kSettingMarginsCustom, &custom_margins) || - !custom_margins->GetDouble(kSettingMarginTop, - &page_size_margins->margin_top) || - !custom_margins->GetDouble(kSettingMarginBottom, - &page_size_margins->margin_bottom) || - !custom_margins->GetDouble(kSettingMarginLeft, - &page_size_margins->margin_left) || - !custom_margins->GetDouble(kSettingMarginRight, - &page_size_margins->margin_right)) { - NOTREACHED(); - } -} - -} // namespace printing diff --git a/chromium/printing/page_size_margins.h b/chromium/printing/page_size_margins.h index b6913724a90..478730850a3 100644 --- a/chromium/printing/page_size_margins.h +++ b/chromium/printing/page_size_margins.h @@ -7,10 +7,6 @@ #include "printing/printing_export.h" -namespace base { -class DictionaryValue; -} - namespace printing { // Struct that holds margin and content area sizes of a page. Units are @@ -24,9 +20,6 @@ struct PageSizeMargins { double margin_left; }; -PRINTING_EXPORT void GetCustomMarginsFromJobSettings( - const base::DictionaryValue& settings, PageSizeMargins* page_size_margins); - } // namespace printing #endif // PRINTING_PAGE_SIZE_MARGINS_H_ diff --git a/chromium/printing/pdf_metafile_skia.cc b/chromium/printing/pdf_metafile_skia.cc index b386cf91989..515b3fe4d1c 100644 --- a/chromium/printing/pdf_metafile_skia.cc +++ b/chromium/printing/pdf_metafile_skia.cc @@ -5,11 +5,10 @@ #include "printing/pdf_metafile_skia.h" #include "base/containers/hash_tables.h" -#include "base/file_descriptor_posix.h" #include "base/file_util.h" #include "base/metrics/histogram.h" +#include "base/numerics/safe_conversions.h" #include "base/posix/eintr_wrapper.h" -#include "base/safe_numerics.h" #include "skia/ext/refptr.h" #include "skia/ext/vector_platform_device_skia.h" #include "third_party/skia/include/core/SkData.h" @@ -27,6 +26,10 @@ #include "printing/pdf_metafile_cg_mac.h" #endif +#if defined(OS_POSIX) +#include "base/file_descriptor_posix.h" +#endif + namespace printing { struct PdfMetafileSkiaData { @@ -112,7 +115,7 @@ bool PdfMetafileSkia::FinishDocument() { } uint32 PdfMetafileSkia::GetDataSize() const { - return base::checked_numeric_cast<uint32>(data_->pdf_stream_.getOffset()); + return base::checked_cast<uint32>(data_->pdf_stream_.getOffset()); } bool PdfMetafileSkia::GetData(void* dst_buffer, @@ -128,9 +131,9 @@ bool PdfMetafileSkia::GetData(void* dst_buffer, bool PdfMetafileSkia::SaveTo(const base::FilePath& file_path) const { DCHECK_GT(data_->pdf_stream_.getOffset(), 0U); SkAutoDataUnref data(data_->pdf_stream_.copyToData()); - if (file_util::WriteFile(file_path, - reinterpret_cast<const char*>(data->data()), - GetDataSize()) != static_cast<int>(GetDataSize())) { + if (base::WriteFile(file_path, + reinterpret_cast<const char*>(data->data()), + GetDataSize()) != static_cast<int>(GetDataSize())) { DLOG(ERROR) << "Failed to save file " << file_path.value().c_str(); return false; } @@ -203,9 +206,9 @@ bool PdfMetafileSkia::SaveToFD(const base::FileDescriptor& fd) const { bool result = true; SkAutoDataUnref data(data_->pdf_stream_.copyToData()); - if (file_util::WriteFileDescriptor(fd.fd, - reinterpret_cast<const char*>(data->data()), - GetDataSize()) != + if (base::WriteFileDescriptor(fd.fd, + reinterpret_cast<const char*>(data->data()), + GetDataSize()) != static_cast<int>(GetDataSize())) { DLOG(ERROR) << "Failed to save file with fd " << fd.fd; result = false; @@ -241,7 +244,7 @@ PdfMetafileSkia* PdfMetafileSkia::GetMetafileForCurrentPage() { PdfMetafileSkia* metafile = new PdfMetafileSkia; metafile->InitFromData(data->bytes(), - base::checked_numeric_cast<uint32>(data->size())); + base::checked_cast<uint32>(data->size())); return metafile; } diff --git a/chromium/printing/print_destination_win.cc b/chromium/printing/print_destination_win.cc deleted file mode 100644 index 6b98f4c5319..00000000000 --- a/chromium/printing/print_destination_win.cc +++ /dev/null @@ -1,55 +0,0 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "printing/print_destination_interface.h" - -#include "base/safe_numerics.h" -#include "base/win/metro.h" -#include "win8/util/win8_util.h" - -namespace printing { - -class PrintDestinationWin : public PrintDestinationInterface { - public: - PrintDestinationWin() - : metro_set_print_page_count_(NULL), - metro_set_print_page_content_(NULL) { - HMODULE metro_module = base::win::GetMetroModule(); - if (metro_module != NULL) { - metro_set_print_page_count_ = - reinterpret_cast<MetroSetPrintPageCount>( - ::GetProcAddress(metro_module, "MetroSetPrintPageCount")); - metro_set_print_page_content_ = - reinterpret_cast<MetroSetPrintPageContent>( - ::GetProcAddress(metro_module, "MetroSetPrintPageContent")); - } - } - virtual void SetPageCount(int page_count) { - if (metro_set_print_page_count_) - metro_set_print_page_count_(page_count); - } - - virtual void SetPageContent(int page_number, - void* content, - size_t content_size) { - if (metro_set_print_page_content_) - metro_set_print_page_content_(page_number - 1, content, - base::checked_numeric_cast<UINT32>(content_size)); - } - private: - typedef void (*MetroSetPrintPageCount)(INT); - typedef void (*MetroSetPrintPageContent)(INT, VOID*, UINT32); - MetroSetPrintPageCount metro_set_print_page_count_; - MetroSetPrintPageContent metro_set_print_page_content_; -}; - -PrintDestinationInterface* CreatePrintDestination() { - // We currently only support the Metro print destination. - if (win8::IsSingleWindowMetroMode()) - return new PrintDestinationWin; - else - return NULL; -} - -} // namespace printing diff --git a/chromium/printing/print_dialog_gtk_interface.h b/chromium/printing/print_dialog_gtk_interface.h index e3506dd9359..e06e43eb9e8 100644 --- a/chromium/printing/print_dialog_gtk_interface.h +++ b/chromium/printing/print_dialog_gtk_interface.h @@ -6,7 +6,7 @@ #define PRINTING_PRINT_DIALOG_GTK_INTERFACE_H_ #include "base/strings/string16.h" -#include "printing/printing_context_gtk.h" +#include "printing/printing_context_linux.h" #include "ui/gfx/native_widget_types.h" namespace printing { @@ -31,7 +31,7 @@ class PrintDialogGtkInterface { virtual void ShowDialog( gfx::NativeView parent_view, bool has_selection, - const PrintingContextGtk::PrintSettingsCallback& callback) = 0; + const PrintingContextLinux::PrintSettingsCallback& callback) = 0; // Prints the document named |document_name| contained in |metafile|. // Called from the print worker thread. Once called, the diff --git a/chromium/printing/print_job_constants.cc b/chromium/printing/print_job_constants.cc index 9a28ddb1325..8ac5db4f721 100644 --- a/chromium/printing/print_job_constants.cc +++ b/chromium/printing/print_job_constants.cc @@ -15,6 +15,9 @@ const char kPreviewRequestID[] = "requestID"; // Unique ID to identify a print preview UI. const char kPreviewUIID[] = "previewUIID"; +// Capabilities option. Contains the capabilities in CDD format. +const char kSettingCapabilities[] = "capabilities"; + // Print using cloud print: true if selected, false if not. const char kSettingCloudPrintId[] = "cloudPrintID"; @@ -74,6 +77,18 @@ const char kSettingHeaderFooterURL[] = "url"; // Page orientation: true for landscape, false for portrait. const char kSettingLandscape[] = "landscape"; +// Key that specifies the requested media size. +const char kSettingMediaSize[] = "mediaSize"; + +// Key that specifies the requested media height in microns. +const char kSettingMediaSizeHeightMicrons[] = "height_microns"; + +// Key that specifies the requested media width in microns. +const char kSettingMediaSizeWidthMicrons[] = "width_microns"; + +// Key that specifies the requested media platform specific vendor id. +const char kSettingMediaSizeVendorId[] = "vendor_id"; + // Key that specifies the bottom margin of the page. const char kSettingMarginBottom[] = "marginBottom"; @@ -120,6 +135,12 @@ const char kSettingPrintableAreaHeight[] = "printableAreaHeight"; // Printer name. const char kSettingPrinterName[] = "printerName"; +// Printer description. +const char kSettingPrinterDescription[] = "printerDescription"; + +// Additional printer options. +const char kSettingPrinterOptions[] = "printerOptions"; + // Print to PDF option: true if selected, false if not. const char kSettingPrintToPDF[] = "printToPDF"; diff --git a/chromium/printing/print_job_constants.h b/chromium/printing/print_job_constants.h index 35cb9c72416..257cba6d75d 100644 --- a/chromium/printing/print_job_constants.h +++ b/chromium/printing/print_job_constants.h @@ -13,6 +13,7 @@ namespace printing { PRINTING_EXPORT extern const char kIsFirstRequest[]; PRINTING_EXPORT extern const char kPreviewRequestID[]; PRINTING_EXPORT extern const char kPreviewUIID[]; +PRINTING_EXPORT extern const char kSettingCapabilities[]; PRINTING_EXPORT extern const char kSettingCloudPrintId[]; PRINTING_EXPORT extern const char kSettingCloudPrintDialog[]; PRINTING_EXPORT extern const char kSettingCollate[]; @@ -31,6 +32,10 @@ PRINTING_EXPORT extern const char kSettingHeaderFooterDate[]; PRINTING_EXPORT extern const char kSettingHeaderFooterTitle[]; PRINTING_EXPORT extern const char kSettingHeaderFooterURL[]; PRINTING_EXPORT extern const char kSettingLandscape[]; +PRINTING_EXPORT extern const char kSettingMediaSize[]; +PRINTING_EXPORT extern const char kSettingMediaSizeHeightMicrons[]; +PRINTING_EXPORT extern const char kSettingMediaSizeWidthMicrons[]; +PRINTING_EXPORT extern const char kSettingMediaSizeVendorId[]; PRINTING_EXPORT extern const char kSettingMarginBottom[]; PRINTING_EXPORT extern const char kSettingMarginLeft[]; PRINTING_EXPORT extern const char kSettingMarginRight[]; @@ -44,13 +49,15 @@ PRINTING_EXPORT extern const char kSettingPageRangeTo[]; PRINTING_EXPORT extern const char kSettingPageWidth[]; PRINTING_EXPORT extern const char kSettingPageHeight[]; PRINTING_EXPORT extern const char kSettingPreviewModifiable[]; +PRINTING_EXPORT extern const char kSettingPrintToPDF[]; +PRINTING_EXPORT extern const char kSettingPrintWithPrivet[]; +PRINTING_EXPORT extern const char kSettingPrintableAreaHeight[]; +PRINTING_EXPORT extern const char kSettingPrintableAreaWidth[]; PRINTING_EXPORT extern const char kSettingPrintableAreaX[]; PRINTING_EXPORT extern const char kSettingPrintableAreaY[]; -PRINTING_EXPORT extern const char kSettingPrintableAreaWidth[]; -PRINTING_EXPORT extern const char kSettingPrintableAreaHeight[]; +PRINTING_EXPORT extern const char kSettingPrinterDescription[]; PRINTING_EXPORT extern const char kSettingPrinterName[]; -PRINTING_EXPORT extern const char kSettingPrintToPDF[]; -PRINTING_EXPORT extern const char kSettingPrintWithPrivet[]; +PRINTING_EXPORT extern const char kSettingPrinterOptions[]; PRINTING_EXPORT extern const char kSettingTicket[]; PRINTING_EXPORT extern const char kSettingShouldPrintBackgrounds[]; PRINTING_EXPORT extern const char kSettingShouldPrintSelectionOnly[]; @@ -130,6 +137,7 @@ enum MarginType { NO_MARGINS, PRINTABLE_AREA_MARGINS, CUSTOM_MARGINS, + MARGIN_TYPE_LAST = CUSTOM_MARGINS }; } // namespace printing diff --git a/chromium/printing/print_settings.cc b/chromium/printing/print_settings.cc index f2dc42585da..b1c50c9e372 100644 --- a/chromium/printing/print_settings.cc +++ b/chromium/printing/print_settings.cc @@ -128,6 +128,7 @@ void PrintSettings::Clear() { url_ = base::string16(); display_header_footer_ = false; device_name_.clear(); + requested_media_ = RequestedMedia(); page_setup_device_units_.Clear(); dpi_ = 0; landscape_ = false; diff --git a/chromium/printing/print_settings.h b/chromium/printing/print_settings.h index b18d86022a5..01b3135fbee 100644 --- a/chromium/printing/print_settings.h +++ b/chromium/printing/print_settings.h @@ -29,6 +29,19 @@ PRINTING_EXPORT void GetColorModelForMode(int color_mode, // OS-independent print settings. class PRINTING_EXPORT PrintSettings { public: + // Media properties requested by the user. Default instance represents + // default media selection. + struct RequestedMedia { + // Size of the media, in microns. + gfx::Size size_microns; + // Platform specific id to map it back to the particular media. + std::string vendor_id; + + bool IsDefault() const { + return size_microns.IsEmpty() && vendor_id.empty(); + } + }; + PrintSettings(); ~PrintSettings(); @@ -36,6 +49,9 @@ class PRINTING_EXPORT PrintSettings { void Clear(); void SetCustomMargins(const PageMargins& requested_margins_in_points); + const PageMargins& requested_custom_margins_in_points() const { + return requested_custom_margins_in_points_; + } void set_margin_type(MarginType margin_type) { margin_type_ = margin_type; } MarginType margin_type() const { return margin_type_; } @@ -43,6 +59,16 @@ class PRINTING_EXPORT PrintSettings { void SetOrientation(bool landscape); bool landscape() const { return landscape_; } + // Updates user requested media. + void set_requested_media(const RequestedMedia& media) { + requested_media_ = media; + } + // Media properties requested by the user. Translated into device media by the + // platform specific layers. + const RequestedMedia& requested_media() const { + return requested_media_; + } + // Set printer printable area in in device units. // Some platforms already provide flipped area. Set |landscape_needs_flip| // to false on those platforms to avoid double flipping. @@ -174,6 +200,9 @@ class PRINTING_EXPORT PrintSettings { // Printer device name as opened by the OS. base::string16 device_name_; + // Media requested by the user. + RequestedMedia requested_media_; + // Page setup in device units. PageSetup page_setup_device_units_; diff --git a/chromium/printing/print_settings_conversion.cc b/chromium/printing/print_settings_conversion.cc new file mode 100644 index 00000000000..a0c5eacf33b --- /dev/null +++ b/chromium/printing/print_settings_conversion.cc @@ -0,0 +1,249 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#include "printing/print_settings_conversion.h" + +#include <algorithm> +#include <cmath> +#include <string> + +#include "base/strings/string_number_conversions.h" +#include "base/strings/utf_string_conversions.h" +#include "base/time/time.h" +#include "base/values.h" +#include "printing/page_size_margins.h" +#include "printing/print_job_constants.h" +#include "printing/print_settings.h" +#include "printing/units.h" + +namespace printing { + +namespace { + +void GetCustomMarginsFromJobSettings(const base::DictionaryValue& settings, + PageSizeMargins* page_size_margins) { + const base::DictionaryValue* custom_margins; + if (!settings.GetDictionary(kSettingMarginsCustom, &custom_margins) || + !custom_margins->GetDouble(kSettingMarginTop, + &page_size_margins->margin_top) || + !custom_margins->GetDouble(kSettingMarginBottom, + &page_size_margins->margin_bottom) || + !custom_margins->GetDouble(kSettingMarginLeft, + &page_size_margins->margin_left) || + !custom_margins->GetDouble(kSettingMarginRight, + &page_size_margins->margin_right)) { + NOTREACHED(); + } +} + +void SetMarginsToJobSettings(const std::string& json_path, + const PageMargins& margins, + base::DictionaryValue* job_settings) { + base::DictionaryValue* dict = new base::DictionaryValue; + job_settings->Set(json_path, dict); + dict->SetInteger(kSettingMarginTop, margins.top); + dict->SetInteger(kSettingMarginBottom, margins.bottom); + dict->SetInteger(kSettingMarginLeft, margins.left); + dict->SetInteger(kSettingMarginRight, margins.right); +} + +void SetSizeToJobSettings(const std::string& json_path, + const gfx::Size& size, + base::DictionaryValue* job_settings) { + base::DictionaryValue* dict = new base::DictionaryValue; + job_settings->Set(json_path, dict); + dict->SetInteger("width", size.width()); + dict->SetInteger("height", size.height()); +} + +void SetRectToJobSettings(const std::string& json_path, + const gfx::Rect& rect, + base::DictionaryValue* job_settings) { + base::DictionaryValue* dict = new base::DictionaryValue; + job_settings->Set(json_path, dict); + dict->SetInteger("x", rect.x()); + dict->SetInteger("y", rect.y()); + dict->SetInteger("width", rect.width()); + dict->SetInteger("height", rect.height()); +} + +} // namespace + +bool PrintSettingsFromJobSettings(const base::DictionaryValue& job_settings, + PrintSettings* settings) { + bool display_header_footer = false; + if (!job_settings.GetBoolean(kSettingHeaderFooterEnabled, + &display_header_footer)) { + return false; + } + settings->set_display_header_footer(display_header_footer); + + if (settings->display_header_footer()) { + base::string16 title; + base::string16 url; + if (!job_settings.GetString(kSettingHeaderFooterTitle, &title) || + !job_settings.GetString(kSettingHeaderFooterURL, &url)) { + return false; + } + settings->set_title(title); + settings->set_url(url); + } + + bool backgrounds = false; + bool selection_only = false; + if (!job_settings.GetBoolean(kSettingShouldPrintBackgrounds, &backgrounds) || + !job_settings.GetBoolean(kSettingShouldPrintSelectionOnly, + &selection_only)) { + return false; + } + settings->set_should_print_backgrounds(backgrounds); + settings->set_selection_only(selection_only); + + PrintSettings::RequestedMedia requested_media; + const base::DictionaryValue* media_size_value = NULL; + if (job_settings.GetDictionary(kSettingMediaSize, &media_size_value)) { + int width_microns = 0; + int height_microns = 0; + if (media_size_value->GetInteger(kSettingMediaSizeWidthMicrons, + &width_microns) && + media_size_value->GetInteger(kSettingMediaSizeHeightMicrons, + &height_microns)) { + requested_media.size_microns = gfx::Size(width_microns, height_microns); + } + std::string vendor_id; + if (media_size_value->GetString(kSettingMediaSizeVendorId, &vendor_id) && + !vendor_id.empty()) { + requested_media.vendor_id = vendor_id; + } + } + settings->set_requested_media(requested_media); + + int margin_type = DEFAULT_MARGINS; + if (!job_settings.GetInteger(kSettingMarginsType, &margin_type) || + (margin_type != DEFAULT_MARGINS && + margin_type != NO_MARGINS && + margin_type != CUSTOM_MARGINS && + margin_type != PRINTABLE_AREA_MARGINS)) { + margin_type = DEFAULT_MARGINS; + } + settings->set_margin_type(static_cast<MarginType>(margin_type)); + + if (margin_type == CUSTOM_MARGINS) { + PageSizeMargins page_size_margins; + GetCustomMarginsFromJobSettings(job_settings, &page_size_margins); + + PageMargins margins_in_points; + margins_in_points.Clear(); + margins_in_points.top = page_size_margins.margin_top; + margins_in_points.bottom = page_size_margins.margin_bottom; + margins_in_points.left = page_size_margins.margin_left; + margins_in_points.right = page_size_margins.margin_right; + + settings->SetCustomMargins(margins_in_points); + } + + PageRanges new_ranges; + const base::ListValue* page_range_array = NULL; + if (job_settings.GetList(kSettingPageRange, &page_range_array)) { + for (size_t index = 0; index < page_range_array->GetSize(); ++index) { + const base::DictionaryValue* dict; + if (!page_range_array->GetDictionary(index, &dict)) + continue; + + PageRange range; + if (!dict->GetInteger(kSettingPageRangeFrom, &range.from) || + !dict->GetInteger(kSettingPageRangeTo, &range.to)) { + continue; + } + + // Page numbers are 1-based in the dictionary. + // Page numbers are 0-based for the printing context. + range.from--; + range.to--; + new_ranges.push_back(range); + } + } + settings->set_ranges(new_ranges); + + int color = 0; + bool landscape = false; + int duplex_mode = 0; + base::string16 device_name; + bool collate = false; + int copies = 1; + + if (!job_settings.GetBoolean(kSettingCollate, &collate) || + !job_settings.GetInteger(kSettingCopies, &copies) || + !job_settings.GetInteger(kSettingColor, &color) || + !job_settings.GetInteger(kSettingDuplexMode, &duplex_mode) || + !job_settings.GetBoolean(kSettingLandscape, &landscape) || + !job_settings.GetString(kSettingDeviceName, &device_name)) { + return false; + } + + settings->set_collate(collate); + settings->set_copies(copies); + settings->SetOrientation(landscape); + settings->set_device_name(device_name); + settings->set_duplex_mode(static_cast<DuplexMode>(duplex_mode)); + settings->set_color(static_cast<ColorModel>(color)); + + return true; +} + +void PrintSettingsToJobSettingsDebug(const PrintSettings& settings, + base::DictionaryValue* job_settings) { + job_settings->SetBoolean(kSettingHeaderFooterEnabled, + settings.display_header_footer()); + job_settings->SetString(kSettingHeaderFooterTitle, settings.title()); + job_settings->SetString(kSettingHeaderFooterURL, settings.url()); + job_settings->SetBoolean(kSettingShouldPrintBackgrounds, + settings.should_print_backgrounds()); + job_settings->SetBoolean(kSettingShouldPrintSelectionOnly, + settings.selection_only()); + job_settings->SetInteger(kSettingMarginsType, settings.margin_type()); + if (!settings.ranges().empty()) { + base::ListValue* page_range_array = new base::ListValue; + job_settings->Set(kSettingPageRange, page_range_array); + for (size_t i = 0; i < settings.ranges().size(); ++i) { + base::DictionaryValue* dict = new base::DictionaryValue; + page_range_array->Append(dict); + dict->SetInteger(kSettingPageRangeFrom, settings.ranges()[i].from + 1); + dict->SetInteger(kSettingPageRangeTo, settings.ranges()[i].to + 1); + } + } + + job_settings->SetBoolean(kSettingCollate, settings.collate()); + job_settings->SetInteger(kSettingCopies, settings.copies()); + job_settings->SetInteger(kSettingColor, settings.color()); + job_settings->SetInteger(kSettingDuplexMode, settings.duplex_mode()); + job_settings->SetBoolean(kSettingLandscape, settings.landscape()); + job_settings->SetString(kSettingDeviceName, settings.device_name()); + + // Following values are not read form JSON by InitSettings, so do not have + // common public constants. So just serialize in "debug" section. + base::DictionaryValue* debug = new base::DictionaryValue; + job_settings->Set("debug", debug); + debug->SetDouble("minShrink", settings.min_shrink()); + debug->SetDouble("maxShrink", settings.max_shrink()); + debug->SetInteger("desiredDpi", settings.desired_dpi()); + debug->SetInteger("dpi", settings.dpi()); + debug->SetInteger("deviceUnitsPerInch", settings.device_units_per_inch()); + debug->SetBoolean("support_alpha_blend", settings.should_print_backgrounds()); + debug->SetString("media_vendor_od", settings.requested_media().vendor_id); + SetSizeToJobSettings( + "media_size", settings.requested_media().size_microns, debug); + SetMarginsToJobSettings("requested_custom_margins_in_points", + settings.requested_custom_margins_in_points(), + debug); + const PageSetup& page_setup = settings.page_setup_device_units(); + SetMarginsToJobSettings( + "effective_margins", page_setup.effective_margins(), debug); + SetSizeToJobSettings("physical_size", page_setup.physical_size(), debug); + SetRectToJobSettings("overlay_area", page_setup.overlay_area(), debug); + SetRectToJobSettings("content_area", page_setup.content_area(), debug); + SetRectToJobSettings("printable_area", page_setup.printable_area(), debug); +} + +} // namespace printing diff --git a/chromium/printing/print_settings_conversion.h b/chromium/printing/print_settings_conversion.h new file mode 100644 index 00000000000..92e8670c06e --- /dev/null +++ b/chromium/printing/print_settings_conversion.h @@ -0,0 +1,31 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PRINTING_PRINT_SETTINGS_CONVERSION_H_ +#define PRINTING_PRINT_SETTINGS_CONVERSION_H_ + +#include "base/basictypes.h" +#include "base/logging.h" +#include "printing/page_range.h" +#include "printing/printing_export.h" + +namespace base { +class DictionaryValue; +} + +namespace printing { + +class PrintSettings; + +bool PrintSettingsFromJobSettings(const base::DictionaryValue& job_settings, + PrintSettings* print_settings); + +// Use for debug only, because output is not completely consistent with format +// of |PrintSettingsFromJobSettings| input. +void PrintSettingsToJobSettingsDebug(const PrintSettings& settings, + base::DictionaryValue* job_settings); + +} // namespace printing + +#endif // PRINTING_PRINT_SETTINGS_CONVERSION_H_ diff --git a/chromium/printing/print_settings_initializer.cc b/chromium/printing/print_settings_initializer.cc deleted file mode 100644 index 565fc785a12..00000000000 --- a/chromium/printing/print_settings_initializer.cc +++ /dev/null @@ -1,106 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "printing/print_settings_initializer.h" - -#include <algorithm> -#include <cmath> -#include <string> - -#include "base/strings/string_number_conversions.h" -#include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" -#include "base/values.h" -#include "printing/page_size_margins.h" -#include "printing/print_job_constants.h" -#include "printing/print_settings.h" -#include "printing/units.h" - -namespace printing { - -bool PrintSettingsInitializer::InitSettings( - const base::DictionaryValue& job_settings, - const PageRanges& ranges, - PrintSettings* settings) { - bool display_header_footer = false; - if (!job_settings.GetBoolean(kSettingHeaderFooterEnabled, - &display_header_footer)) { - return false; - } - settings->set_display_header_footer(display_header_footer); - - if (settings->display_header_footer()) { - base::string16 title; - base::string16 url; - if (!job_settings.GetString(kSettingHeaderFooterTitle, &title) || - !job_settings.GetString(kSettingHeaderFooterURL, &url)) { - return false; - } - settings->set_title(title); - settings->set_url(url); - } - - bool backgrounds = false; - bool selection_only = false; - if (!job_settings.GetBoolean(kSettingShouldPrintBackgrounds, &backgrounds) || - !job_settings.GetBoolean(kSettingShouldPrintSelectionOnly, - &selection_only)) { - return false; - } - settings->set_should_print_backgrounds(backgrounds); - settings->set_selection_only(selection_only); - - int margin_type = DEFAULT_MARGINS; - if (!job_settings.GetInteger(kSettingMarginsType, &margin_type) || - (margin_type != DEFAULT_MARGINS && - margin_type != NO_MARGINS && - margin_type != CUSTOM_MARGINS && - margin_type != PRINTABLE_AREA_MARGINS)) { - margin_type = DEFAULT_MARGINS; - } - settings->set_margin_type(static_cast<MarginType>(margin_type)); - - if (margin_type == CUSTOM_MARGINS) { - PageSizeMargins page_size_margins; - GetCustomMarginsFromJobSettings(job_settings, &page_size_margins); - - PageMargins margins_in_points; - margins_in_points.Clear(); - margins_in_points.top = page_size_margins.margin_top; - margins_in_points.bottom = page_size_margins.margin_bottom; - margins_in_points.left = page_size_margins.margin_left; - margins_in_points.right = page_size_margins.margin_right; - - settings->SetCustomMargins(margins_in_points); - } - - settings->set_ranges(ranges); - - int color = 0; - bool landscape = false; - int duplex_mode = 0; - base::string16 device_name; - bool collate = false; - int copies = 1; - - if (!job_settings.GetBoolean(kSettingCollate, &collate) || - !job_settings.GetInteger(kSettingCopies, &copies) || - !job_settings.GetInteger(kSettingColor, &color) || - !job_settings.GetInteger(kSettingDuplexMode, &duplex_mode) || - !job_settings.GetBoolean(kSettingLandscape, &landscape) || - !job_settings.GetString(kSettingDeviceName, &device_name)) { - return false; - } - - settings->set_collate(collate); - settings->set_copies(copies); - settings->SetOrientation(landscape); - settings->set_device_name(device_name); - settings->set_duplex_mode(static_cast<DuplexMode>(duplex_mode)); - settings->set_color(static_cast<ColorModel>(color)); - - return true; -} - -} // namespace printing diff --git a/chromium/printing/print_settings_initializer.h b/chromium/printing/print_settings_initializer.h deleted file mode 100644 index a1093c5a3b8..00000000000 --- a/chromium/printing/print_settings_initializer.h +++ /dev/null @@ -1,37 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PRINTING_PRINT_SETTINGS_INITIALIZER_H_ -#define PRINTING_PRINT_SETTINGS_INITIALIZER_H_ - -#include "base/basictypes.h" -#include "base/logging.h" -#include "printing/page_range.h" -#include "printing/printing_export.h" - -namespace base { -class DictionaryValue; -} - -namespace printing { - -class PrintSettings; - -// Initializes the header footer strings in the PrintSettings object from the -// provided |job_settings|. -class PRINTING_EXPORT PrintSettingsInitializer { - public: - static bool InitSettings( - const base::DictionaryValue& job_settings, - const PageRanges& ranges, - PrintSettings* print_settings); - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(PrintSettingsInitializer); -}; - -} // namespace printing - -#endif // PRINTING_PRINT_SETTINGS_INITIALIZER_H_ - diff --git a/chromium/printing/print_settings_initializer_gtk.cc b/chromium/printing/print_settings_initializer_gtk.cc deleted file mode 100644 index 53cb9bbee38..00000000000 --- a/chromium/printing/print_settings_initializer_gtk.cc +++ /dev/null @@ -1,81 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#include "printing/print_settings_initializer_gtk.h" - -#include <gtk/gtk.h> -#include <gtk/gtkunixprint.h> - -#include "base/strings/string16.h" -#include "base/strings/utf_string_conversions.h" -#include "printing/print_settings.h" -#include "printing/units.h" - -namespace printing { - -// static -void PrintSettingsInitializerGtk::InitPrintSettings( - GtkPrintSettings* settings, - GtkPageSetup* page_setup, - PrintSettings* print_settings) { - DCHECK(settings); - DCHECK(page_setup); - DCHECK(print_settings); - - base::string16 name(base::UTF8ToUTF16(static_cast<const char*>( - gtk_print_settings_get_printer(settings)))); - print_settings->set_device_name(name); - - gfx::Size physical_size_device_units; - gfx::Rect printable_area_device_units; - int dpi = gtk_print_settings_get_resolution(settings); - if (dpi) { - // Initialize page_setup_device_units_. - physical_size_device_units.SetSize( - gtk_page_setup_get_paper_width(page_setup, GTK_UNIT_INCH) * dpi, - gtk_page_setup_get_paper_height(page_setup, GTK_UNIT_INCH) * dpi); - printable_area_device_units.SetRect( - gtk_page_setup_get_left_margin(page_setup, GTK_UNIT_INCH) * dpi, - gtk_page_setup_get_top_margin(page_setup, GTK_UNIT_INCH) * dpi, - gtk_page_setup_get_page_width(page_setup, GTK_UNIT_INCH) * dpi, - gtk_page_setup_get_page_height(page_setup, GTK_UNIT_INCH) * dpi); - } else { - // Use default values if we cannot get valid values from the print dialog. - dpi = kPixelsPerInch; - double page_width_in_pixel = kLetterWidthInch * dpi; - double page_height_in_pixel = kLetterHeightInch * dpi; - physical_size_device_units.SetSize( - static_cast<int>(page_width_in_pixel), - static_cast<int>(page_height_in_pixel)); - printable_area_device_units.SetRect( - static_cast<int>(kLeftMarginInInch * dpi), - static_cast<int>(kTopMarginInInch * dpi), - page_width_in_pixel - (kLeftMarginInInch + kRightMarginInInch) * dpi, - page_height_in_pixel - (kTopMarginInInch + kBottomMarginInInch) * dpi); - } - - print_settings->set_dpi(dpi); - - // Note: With the normal GTK print dialog, when the user selects the landscape - // orientation, all that does is change the paper size. Which seems to be - // enough to render the right output and send it to the printer. - // The orientation value stays as portrait and does not actually affect - // printing. - // Thus this is only useful in print preview mode, where we manually set the - // orientation and change the paper size ourselves. - GtkPageOrientation orientation = gtk_print_settings_get_orientation(settings); - // Set before SetPrinterPrintableArea to make it flip area if necessary. - print_settings->SetOrientation(orientation == GTK_PAGE_ORIENTATION_LANDSCAPE); - DCHECK_EQ(print_settings->device_units_per_inch(), dpi); - print_settings->SetPrinterPrintableArea(physical_size_device_units, - printable_area_device_units, - true); -} - -const double PrintSettingsInitializerGtk::kTopMarginInInch = 0.25; -const double PrintSettingsInitializerGtk::kBottomMarginInInch = 0.56; -const double PrintSettingsInitializerGtk::kLeftMarginInInch = 0.25; -const double PrintSettingsInitializerGtk::kRightMarginInInch = 0.25; - -} // namespace printing diff --git a/chromium/printing/print_settings_initializer_gtk.h b/chromium/printing/print_settings_initializer_gtk.h deleted file mode 100644 index 828c34d1290..00000000000 --- a/chromium/printing/print_settings_initializer_gtk.h +++ /dev/null @@ -1,38 +0,0 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. -// Use of this source code is governed by a BSD-style license that can be -// found in the LICENSE file. - -#ifndef PRINTING_PRINT_SETTINGS_INITIALIZER_GTK_H_ -#define PRINTING_PRINT_SETTINGS_INITIALIZER_GTK_H_ - -#include "base/logging.h" -#include "printing/page_range.h" - -typedef struct _GtkPrintSettings GtkPrintSettings; -typedef struct _GtkPageSetup GtkPageSetup; - -namespace printing { - -class PrintSettings; - -// Initializes a PrintSettings object from the provided Gtk printer objects. -class PRINTING_EXPORT PrintSettingsInitializerGtk { - public: - static void InitPrintSettings(GtkPrintSettings* settings, - GtkPageSetup* page_setup, - PrintSettings* print_settings); - - // The default margins, in points. These values are based on 72 dpi, - // with 0.25 margins on top, left, and right, and 0.56 on bottom. - static const double kTopMarginInInch; - static const double kRightMarginInInch; - static const double kBottomMarginInInch; - static const double kLeftMarginInInch; - - private: - DISALLOW_IMPLICIT_CONSTRUCTORS(PrintSettingsInitializerGtk); -}; - -} // namespace printing - -#endif // PRINTING_PRINT_SETTINGS_INITIALIZER_GTK_H_ diff --git a/chromium/printing/printed_document.cc b/chromium/printing/printed_document.cc index 1f08ac1c73c..6d2a9a037dd 100644 --- a/chromium/printing/printed_document.cc +++ b/chromium/printing/printed_document.cc @@ -9,16 +9,23 @@ #include <string> #include <vector> +#include "base/bind.h" #include "base/file_util.h" #include "base/files/file_path.h" #include "base/i18n/file_util_icu.h" #include "base/i18n/time_formatting.h" +#include "base/json/json_writer.h" #include "base/lazy_instance.h" +#include "base/memory/ref_counted_memory.h" #include "base/message_loop/message_loop.h" +#include "base/numerics/safe_conversions.h" #include "base/strings/string_util.h" #include "base/strings/stringprintf.h" #include "base/strings/utf_string_conversions.h" +#include "base/time/time.h" +#include "base/values.h" #include "printing/page_number.h" +#include "printing/print_settings_conversion.h" #include "printing/printed_page.h" #include "printing/printed_pages_source.h" #include "printing/units.h" @@ -26,30 +33,65 @@ #include "ui/gfx/font.h" #include "ui/gfx/text_elider.h" +namespace printing { + namespace { -struct PrintDebugDumpPath { - PrintDebugDumpPath() - : enabled(false) { - } +base::LazyInstance<base::FilePath> g_debug_dump_info = + LAZY_INSTANCE_INITIALIZER; - bool enabled; - base::FilePath debug_dump_path; -}; +void DebugDumpPageTask(const base::string16& doc_name, + const PrintedPage* page) { + if (g_debug_dump_info.Get().empty()) + return; -base::LazyInstance<PrintDebugDumpPath> g_debug_dump_info = - LAZY_INSTANCE_INITIALIZER; + base::string16 filename = doc_name; + filename += + base::ASCIIToUTF16(base::StringPrintf("_%04d", page->page_number())); +#if defined(OS_WIN) + page->metafile()->SaveTo(PrintedDocument::CreateDebugDumpPath( + filename, FILE_PATH_LITERAL(".emf"))); +#else // OS_WIN + page->metafile()->SaveTo(PrintedDocument::CreateDebugDumpPath( + filename, FILE_PATH_LITERAL(".pdf"))); +#endif // OS_WIN +} -} // namespace +void DebugDumpDataTask(const base::string16& doc_name, + const base::FilePath::StringType& extension, + const base::RefCountedMemory* data) { + base::FilePath path = + PrintedDocument::CreateDebugDumpPath(doc_name, extension); + if (path.empty()) + return; + base::WriteFile(path, + reinterpret_cast<const char*>(data->front()), + base::checked_cast<int>(data->size())); +} -namespace printing { +void DebugDumpSettings(const base::string16& doc_name, + const PrintSettings& settings, + base::TaskRunner* blocking_runner) { + base::DictionaryValue job_settings; + PrintSettingsToJobSettingsDebug(settings, &job_settings); + std::string settings_str; + base::JSONWriter::WriteWithOptions( + &job_settings, base::JSONWriter::OPTIONS_PRETTY_PRINT, &settings_str); + scoped_refptr<base::RefCountedMemory> data = + base::RefCountedString::TakeString(&settings_str); + blocking_runner->PostTask( + FROM_HERE, + base::Bind( + &DebugDumpDataTask, doc_name, FILE_PATH_LITERAL(".json"), data)); +} + +} // namespace PrintedDocument::PrintedDocument(const PrintSettings& settings, PrintedPagesSource* source, - int cookie) - : mutable_(source), - immutable_(settings, source, cookie) { - + int cookie, + base::TaskRunner* blocking_runner) + : mutable_(source), immutable_(settings, source, cookie, blocking_runner) { // Records the expected page count if a range is setup. if (!settings.ranges().empty()) { // If there is a range, set the number of page @@ -58,6 +100,9 @@ PrintedDocument::PrintedDocument(const PrintSettings& settings, mutable_.expected_page_count_ += range.to - range.from + 1; } } + + if (!g_debug_dump_info.Get().empty()) + DebugDumpSettings(name(), settings, blocking_runner); } PrintedDocument::~PrintedDocument() { @@ -65,17 +110,18 @@ PrintedDocument::~PrintedDocument() { void PrintedDocument::SetPage(int page_number, Metafile* metafile, +#if defined(OS_WIN) double shrink, +#endif // OS_WIN const gfx::Size& paper_size, const gfx::Rect& page_rect) { // Notice the page_number + 1, the reason is that this is the value that will // be shown. Users dislike 0-based counting. scoped_refptr<PrintedPage> page( - new PrintedPage(page_number + 1, - metafile, - paper_size, - page_rect, - shrink)); + new PrintedPage(page_number + 1, metafile, paper_size, page_rect)); +#if defined(OS_WIN) + page->set_shrink_factor(shrink); +#endif // OS_WIN { base::AutoLock lock(lock_); mutable_.pages_[page_number] = page; @@ -85,20 +131,22 @@ void PrintedDocument::SetPage(int page_number, mutable_.first_page = page_number; #endif } - DebugDump(*page.get()); + + if (!g_debug_dump_info.Get().empty()) { + immutable_.blocking_runner_->PostTask( + FROM_HERE, base::Bind(&DebugDumpPageTask, name(), page)); + } } -bool PrintedDocument::GetPage(int page_number, - scoped_refptr<PrintedPage>* page) { - base::AutoLock lock(lock_); - PrintedPages::const_iterator itr = mutable_.pages_.find(page_number); - if (itr != mutable_.pages_.end()) { - if (itr->second.get()) { - *page = itr->second; - return true; - } +scoped_refptr<PrintedPage> PrintedDocument::GetPage(int page_number) { + scoped_refptr<PrintedPage> page; + { + base::AutoLock lock(lock_); + PrintedPages::const_iterator itr = mutable_.pages_.find(page_number); + if (itr != mutable_.pages_.end()) + page = itr->second; } - return false; + return page; } bool PrintedDocument::IsComplete() const { @@ -172,35 +220,40 @@ int PrintedDocument::expected_page_count() const { return mutable_.expected_page_count_; } -void PrintedDocument::DebugDump(const PrintedPage& page) { - if (!g_debug_dump_info.Get().enabled) - return; +void PrintedDocument::set_debug_dump_path( + const base::FilePath& debug_dump_path) { + g_debug_dump_info.Get() = debug_dump_path; +} +base::FilePath PrintedDocument::CreateDebugDumpPath( + const base::string16& document_name, + const base::FilePath::StringType& extension) { + if (g_debug_dump_info.Get().empty()) + return base::FilePath(); + // Create a filename. base::string16 filename; - filename += name(); + base::Time now(base::Time::Now()); + filename = base::TimeFormatShortDateAndTime(now); filename += base::ASCIIToUTF16("_"); - filename += base::ASCIIToUTF16( - base::StringPrintf("%02d", page.page_number())); + filename += document_name; + base::FilePath::StringType system_filename; #if defined(OS_WIN) - filename += base::ASCIIToUTF16("_.emf"); - page.metafile()->SaveTo( - g_debug_dump_info.Get().debug_dump_path.Append(filename)); -#else // OS_WIN - filename += base::ASCIIToUTF16("_.pdf"); - page.metafile()->SaveTo( - g_debug_dump_info.Get().debug_dump_path.Append( - base::UTF16ToUTF8(filename))); + system_filename = filename; +#else // OS_WIN + system_filename = base::UTF16ToUTF8(filename); #endif // OS_WIN + file_util::ReplaceIllegalCharactersInPath(&system_filename, '_'); + return g_debug_dump_info.Get().Append(system_filename).AddExtension( + extension); } -void PrintedDocument::set_debug_dump_path( - const base::FilePath& debug_dump_path) { - g_debug_dump_info.Get().enabled = !debug_dump_path.empty(); - g_debug_dump_info.Get().debug_dump_path = debug_dump_path; -} - -const base::FilePath& PrintedDocument::debug_dump_path() { - return g_debug_dump_info.Get().debug_dump_path; +void PrintedDocument::DebugDumpData( + const base::RefCountedMemory* data, + const base::FilePath::StringType& extension) { + if (g_debug_dump_info.Get().empty()) + return; + immutable_.blocking_runner_->PostTask( + FROM_HERE, base::Bind(&DebugDumpDataTask, name(), extension, data)); } PrintedDocument::Mutable::Mutable(PrintedPagesSource* source) @@ -217,17 +270,18 @@ PrintedDocument::Mutable::~Mutable() { PrintedDocument::Immutable::Immutable(const PrintSettings& settings, PrintedPagesSource* source, - int cookie) + int cookie, + base::TaskRunner* blocking_runner) : settings_(settings), - source_message_loop_(base::MessageLoop::current()), name_(source->RenderSourceName()), - cookie_(cookie) { + cookie_(cookie), + blocking_runner_(blocking_runner) { } PrintedDocument::Immutable::~Immutable() { } -#if (defined(OS_POSIX) && defined(USE_AURA)) || defined(OS_ANDROID) +#if defined(OS_CHROMEOS) || defined(OS_ANDROID) // This function is not used on aura linux/chromeos or android. void PrintedDocument::RenderPrintedPage(const PrintedPage& page, PrintingContext* context) const { diff --git a/chromium/printing/printed_document.h b/chromium/printing/printed_document.h index b8af4bb5f39..4d0e41ec5d0 100644 --- a/chromium/printing/printed_document.h +++ b/chromium/printing/printed_document.h @@ -7,6 +7,7 @@ #include <map> +#include "base/files/file_path.h" #include "base/memory/ref_counted.h" #include "base/strings/string16.h" #include "base/synchronization/lock.h" @@ -14,8 +15,8 @@ #include "ui/gfx/native_widget_types.h" namespace base { -class FilePath; -class MessageLoop; +class RefCountedMemory; +class TaskRunner; } namespace printing { @@ -38,17 +39,23 @@ class PRINTING_EXPORT PrintedDocument // originating source and settings. PrintedDocument(const PrintSettings& settings, PrintedPagesSource* source, - int cookie); + int cookie, + base::TaskRunner* blocking_runner); // Sets a page's data. 0-based. Takes metafile ownership. // Note: locks for a short amount of time. - void SetPage(int page_number, Metafile* metafile, double shrink, - const gfx::Size& paper_size, const gfx::Rect& page_rect); + void SetPage(int page_number, + Metafile* metafile, +#if defined(OS_WIN) + double shrink, +#endif // OS_WIN + const gfx::Size& paper_size, + const gfx::Rect& page_rect); // Retrieves a page. If the page is not available right now, it - // requests to have this page be rendered and returns false. + // requests to have this page be rendered and returns NULL. // Note: locks for a short amount of time. - bool GetPage(int page_number, scoped_refptr<PrintedPage>* page); + scoped_refptr<PrintedPage> GetPage(int page_number); // Draws the page in the context. // Note: locks for a short amount of time in debug only. @@ -97,7 +104,16 @@ class PRINTING_EXPORT PrintedDocument // no files are generated. static void set_debug_dump_path(const base::FilePath& debug_dump_path); - static const base::FilePath& debug_dump_path(); + // Creates debug file name from given |document_name| and |extension|. + // |extension| should include '.', example ".pdf" + // Returns empty |base::FilePath| if debug dumps is not enabled. + static base::FilePath CreateDebugDumpPath( + const base::string16& document_name, + const base::FilePath::StringType& extension); + + // Dump data on blocking task runner if debug dumps enabled. + void DebugDumpData(const base::RefCountedMemory* data, + const base::FilePath::StringType& extension); private: friend class base::RefCountedThreadSafe<PrintedDocument>; @@ -138,16 +154,15 @@ class PRINTING_EXPORT PrintedDocument // any lock held. This is because it can't be changed after the object's // construction. struct Immutable { - Immutable(const PrintSettings& settings, PrintedPagesSource* source, - int cookie); + Immutable(const PrintSettings& settings, + PrintedPagesSource* source, + int cookie, + base::TaskRunner* blocking_runner); ~Immutable(); // Print settings used to generate this document. Immutable. PrintSettings settings_; - // Native thread for the render source. - base::MessageLoop* source_message_loop_; - // Document name. Immutable. base::string16 name_; @@ -158,9 +173,10 @@ class PRINTING_EXPORT PrintedDocument // simpler hash of PrintSettings since a new document is made each time the // print settings change. int cookie_; - }; - void DebugDump(const PrintedPage& page); + // Native thread for blocking operations, like file access. + scoped_refptr<base::TaskRunner> blocking_runner_; + }; // All writable data member access must be guarded by this lock. Needs to be // mutable since it can be acquired from const member functions. diff --git a/chromium/printing/printed_document_gtk.cc b/chromium/printing/printed_document_linux.cc index 0970b251e2d..a800307a170 100644 --- a/chromium/printing/printed_document_gtk.cc +++ b/chromium/printing/printed_document_linux.cc @@ -1,4 +1,4 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. @@ -7,10 +7,11 @@ #include "base/logging.h" #include "printing/page_number.h" #include "printing/printed_page.h" -#include "printing/printing_context_gtk.h" +#include "printing/printing_context_linux.h" namespace printing { +#if !defined(OS_CHROMEOS) && !defined(OS_ANDROID) void PrintedDocument::RenderPrintedPage( const PrintedPage& page, PrintingContext* context) const { #ifndef NDEBUG @@ -26,10 +27,11 @@ void PrintedDocument::RenderPrintedPage( { base::AutoLock lock(lock_); if (page.page_number() - 1 == mutable_.first_page) { - reinterpret_cast<PrintingContextGtk*>(context)->PrintDocument( + static_cast<PrintingContextLinux*>(context)->PrintDocument( page.metafile()); } } } +#endif // !OS_CHROMEOS && !OS_ANDROID } // namespace printing diff --git a/chromium/printing/printed_page.cc b/chromium/printing/printed_page.cc index af7b7388f86..19b9fd38f30 100644 --- a/chromium/printing/printed_page.cc +++ b/chromium/printing/printed_page.cc @@ -9,13 +9,14 @@ namespace printing { PrintedPage::PrintedPage(int page_number, Metafile* metafile, const gfx::Size& page_size, - const gfx::Rect& page_content_rect, - double shrink_factor) + const gfx::Rect& page_content_rect) : page_number_(page_number), metafile_(metafile), +#if defined(OS_WIN) + shrink_factor_(0.0f), +#endif // OS_WIN page_size_(page_size), - page_content_rect_(page_content_rect), - shrink_factor_(shrink_factor) { + page_content_rect_(page_content_rect) { } PrintedPage::~PrintedPage() { diff --git a/chromium/printing/printed_page.h b/chromium/printing/printed_page.h index 40e96e041d3..a1adfa4b416 100644 --- a/chromium/printing/printed_page.h +++ b/chromium/printing/printed_page.h @@ -25,15 +25,19 @@ class PRINTING_EXPORT PrintedPage PrintedPage(int page_number, Metafile* metafile, const gfx::Size& page_size, - const gfx::Rect& page_content_rect, - double shrink_factor); + const gfx::Rect& page_content_rect); // Getters int page_number() const { return page_number_; } const Metafile* metafile() const; const gfx::Size& page_size() const { return page_size_; } const gfx::Rect& page_content_rect() const { return page_content_rect_; } +#if defined(OS_WIN) + void set_shrink_factor(double shrink_factor) { + shrink_factor_ = shrink_factor; + } double shrink_factor() const { return shrink_factor_; } +#endif // OS_WIN // Get page content rect adjusted based on // http://dev.w3.org/csswg/css3-page/#positioning-page-box @@ -51,6 +55,11 @@ class PRINTING_EXPORT PrintedPage // Actual paint data. const scoped_ptr<Metafile> metafile_; +#if defined(OS_WIN) + // Shrink done in comparison to desired_dpi. + double shrink_factor_; +#endif // OS_WIN + // The physical page size. To support multiple page formats inside on print // job. const gfx::Size page_size_; @@ -58,9 +67,6 @@ class PRINTING_EXPORT PrintedPage // The printable area of the page. const gfx::Rect page_content_rect_; - // Shrink done in comparison to desired_dpi. - double shrink_factor_; - DISALLOW_COPY_AND_ASSIGN(PrintedPage); }; diff --git a/chromium/printing/printed_page_unittest.cc b/chromium/printing/printed_page_unittest.cc index 9cce52a1cb8..d37d93a60cf 100644 --- a/chromium/printing/printed_page_unittest.cc +++ b/chromium/printing/printed_page_unittest.cc @@ -12,56 +12,52 @@ TEST(PrintedPageTest, GetCenteredPageContentRect) { gfx::Rect page_content; // No centering. - page = new PrintedPage(1, - NULL, - gfx::Size(1200, 1200), - gfx::Rect(0, 0, 400, 1100), - 0.2f); + page = new PrintedPage( + 1, NULL, gfx::Size(1200, 1200), gfx::Rect(0, 0, 400, 1100)); page->GetCenteredPageContentRect(gfx::Size(1000, 1000), &page_content); EXPECT_EQ(0, page_content.x()); EXPECT_EQ(0, page_content.y()); EXPECT_EQ(400, page_content.width()); EXPECT_EQ(1100, page_content.height()); - EXPECT_EQ(0.2f, page->shrink_factor()); // X centered. - page = new PrintedPage(1, - NULL, - gfx::Size(500, 1200), - gfx::Rect(0, 0, 400, 1100), - 0.8f); + page = new PrintedPage( + 1, NULL, gfx::Size(500, 1200), gfx::Rect(0, 0, 400, 1100)); page->GetCenteredPageContentRect(gfx::Size(1000, 1000), &page_content); EXPECT_EQ(250, page_content.x()); EXPECT_EQ(0, page_content.y()); EXPECT_EQ(400, page_content.width()); EXPECT_EQ(1100, page_content.height()); - EXPECT_EQ(0.8f, page->shrink_factor()); // Y centered. - page = new PrintedPage(1, - NULL, - gfx::Size(1200, 500), - gfx::Rect(0, 0, 400, 1100), - 1.0f); + page = new PrintedPage( + 1, NULL, gfx::Size(1200, 500), gfx::Rect(0, 0, 400, 1100)); page->GetCenteredPageContentRect(gfx::Size(1000, 1000), &page_content); EXPECT_EQ(0, page_content.x()); EXPECT_EQ(250, page_content.y()); EXPECT_EQ(400, page_content.width()); EXPECT_EQ(1100, page_content.height()); - EXPECT_EQ(1.0f, page->shrink_factor()); // Both X and Y centered. - page = new PrintedPage(1, - NULL, - gfx::Size(500, 500), - gfx::Rect(0, 0, 400, 1100), - 0.3f); + page = + new PrintedPage(1, NULL, gfx::Size(500, 500), gfx::Rect(0, 0, 400, 1100)); page->GetCenteredPageContentRect(gfx::Size(1000, 1000), &page_content); EXPECT_EQ(250, page_content.x()); EXPECT_EQ(250, page_content.y()); EXPECT_EQ(400, page_content.width()); EXPECT_EQ(1100, page_content.height()); - EXPECT_EQ(0.3f, page->shrink_factor()); } +#if defined(OS_WIN) +TEST(PrintedPageTest, Shrink) { + scoped_refptr<PrintedPage> page = new PrintedPage( + 1, NULL, gfx::Size(1200, 1200), gfx::Rect(0, 0, 400, 1100)); + EXPECT_EQ(0.0f, page->shrink_factor()); + page->set_shrink_factor(0.2f); + EXPECT_EQ(0.2f, page->shrink_factor()); + page->set_shrink_factor(0.7f); + EXPECT_EQ(0.7f, page->shrink_factor()); +} +#endif // OS_WIN + } // namespace printing diff --git a/chromium/printing/printing.gyp b/chromium/printing/printing.gyp index 3371745545e..bfec0fc450a 100644 --- a/chromium/printing/printing.gyp +++ b/chromium/printing/printing.gyp @@ -18,7 +18,7 @@ '../third_party/icu/icu.gyp:icui18n', '../third_party/icu/icu.gyp:icuuc', '../ui/gfx/gfx.gyp:gfx', - '../ui/shell_dialogs/shell_dialogs.gyp:shell_dialogs', + '../ui/gfx/gfx.gyp:gfx_geometry', '../url/url.gyp:url_lib', ], 'defines': [ @@ -53,7 +53,6 @@ 'page_range.h', 'page_setup.cc', 'page_setup.h', - 'page_size_margins.cc', 'page_size_margins.h', 'pdf_metafile_cg_mac.cc', 'pdf_metafile_cg_mac.h', @@ -61,23 +60,20 @@ 'pdf_metafile_skia.h', 'print_destination_interface.h', 'print_destination_none.cc', - 'print_destination_win.cc', 'print_dialog_gtk_interface.h', 'print_job_constants.cc', 'print_job_constants.h', 'print_settings.cc', 'print_settings.h', - 'print_settings_initializer.cc', - 'print_settings_initializer.h', - 'print_settings_initializer_gtk.cc', - 'print_settings_initializer_gtk.h', + 'print_settings_conversion.cc', + 'print_settings_conversion.h', 'print_settings_initializer_mac.cc', 'print_settings_initializer_mac.h', 'print_settings_initializer_win.cc', 'print_settings_initializer_win.h', 'printed_document.cc', 'printed_document.h', - 'printed_document_gtk.cc', + 'printed_document_linux.cc', 'printed_document_mac.cc', 'printed_document_win.cc', 'printed_page.cc', @@ -100,22 +96,6 @@ 'dependencies': [ '<(DEPTH)/ui/aura/aura.gyp:aura', ], - }], - ['toolkit_uses_gtk == 0',{ - 'sources/': [['exclude', '_cairo\\.cc$']] - }], - ['OS!="mac"', {'sources/': [['exclude', '_mac\\.(cc|mm?)$']]}], - ['OS!="win"', {'sources/': [['exclude', '_win\\.cc$']] - }, { # else: OS=="win" - 'sources/': [['exclude', '_posix\\.cc$']] - }], - ['toolkit_uses_gtk == 1', { - 'dependencies': [ - # For FT_Init_FreeType and friends. - '../build/linux/system.gyp:freetype2', - '../build/linux/system.gyp:gtk', - '../build/linux/system.gyp:gtkprint', - ], }], # Mac-Aura does not support printing. ['OS=="mac" and use_aura==1',{ @@ -133,14 +113,8 @@ }], ['OS=="win"', { 'dependencies': [ - '../win8/win8.gyp:win8_util', + '<(DEPTH)/ui/aura/aura.gyp:aura', ], - 'conditions': [ - ['use_aura==1', { - 'dependencies': [ - '<(DEPTH)/ui/aura/aura.gyp:aura', - ], - }]], 'defines': [ # PRINT_BACKEND_AVAILABLE disables the default dummy implementation # of the print backend and enables a custom implementation instead. @@ -153,11 +127,8 @@ 'printing_context_win.cc', 'printing_context_win.h', ], - 'sources!': [ - 'print_destination_none.cc', - ], }], - ['chromeos==1 or (use_aura==1 and OS!="win")',{ + ['chromeos==1',{ 'sources': [ 'printing_context_no_system_dialog.cc', 'printing_context_no_system_dialog.h', @@ -171,11 +142,6 @@ 'cups_version': '<!(cups-config --api-version)', }, 'conditions': [ - ['OS!="mac"', { - 'dependencies': [ - '../build/linux/system.gyp:libgcrypt', - ], - }], ['cups_version in ["1.6", "1.7"]', { 'cflags': [ # CUPS 1.6 deprecated the PPD APIs, but we will stay with this @@ -221,10 +187,10 @@ 'backend/print_backend_chromeos.cc', ], }], - ['toolkit_uses_gtk==1 and chromeos==0', { + ['OS=="linux" and chromeos==0', { 'sources': [ - 'printing_context_gtk.cc', - 'printing_context_gtk.h', + 'printing_context_linux.cc', + 'printing_context_linux.h', ], }], ['OS=="android"', { @@ -232,11 +198,8 @@ 'printing_context_android.cc', 'printing_context_android.h', ], - 'dependencies': [ - 'printing_jni_headers', - ], - 'include_dirs': [ - '<(SHARED_INTERMEDIATE_DIR)/printing', + 'dependencies': [ + 'printing_jni_headers', ], }], ], @@ -245,12 +208,13 @@ 'target_name': 'printing_unittests', 'type': 'executable', 'dependencies': [ - 'printing', - '../testing/gtest.gyp:gtest', '../base/base.gyp:run_all_unittests', '../base/base.gyp:test_support_base', + '../testing/gtest.gyp:gtest', + '../ui/base/ui_base.gyp:ui_base', '../ui/gfx/gfx.gyp:gfx', - '../ui/ui.gyp:ui', + '../ui/gfx/gfx.gyp:gfx_geometry', + 'printing', ], 'sources': [ 'emf_win_unittest.cc', @@ -265,7 +229,6 @@ 'units_unittest.cc', ], 'conditions': [ - ['toolkit_uses_gtk == 0', {'sources/': [['exclude', '_gtk_unittest\\.cc$']]}], ['OS!="mac"', {'sources/': [['exclude', '_mac_unittest\\.(cc|mm?)$']]}], ['OS!="win"', {'sources/': [['exclude', '_win_unittest\\.cc$']]}], ['use_cups==1', { @@ -276,14 +239,9 @@ 'backend/cups_helper_unittest.cc', ], }], - ['toolkit_uses_gtk == 1', { - 'dependencies': [ - '../build/linux/system.gyp:gtk', - ], - }], [ 'os_posix == 1 and OS != "mac" and OS != "android" and OS != "ios"', { 'conditions': [ - ['linux_use_tcmalloc == 1', { + ['use_allocator!="none"', { 'dependencies': [ '../base/allocator/allocator.gyp:allocator', ], @@ -317,7 +275,7 @@ ], }, }], - [ 'os_bsd==1', { + ['os_bsd==1', { 'cflags': [ '<!@(python cups_config_helper.py --cflags)', ], @@ -339,7 +297,6 @@ ], 'variables': { 'jni_gen_package': 'printing', - 'jni_generator_ptr_type': 'long', }, 'includes': [ '../build/jni_generator.gypi' ], }, diff --git a/chromium/printing/printing_context.cc b/chromium/printing/printing_context.cc index c8e8e8711aa..bcafb40ad82 100644 --- a/chromium/printing/printing_context.cc +++ b/chromium/printing/printing_context.cc @@ -8,7 +8,8 @@ #include "base/values.h" #include "printing/page_setup.h" #include "printing/page_size_margins.h" -#include "printing/print_settings_initializer.h" +#include "printing/print_job_constants.h" +#include "printing/print_settings_conversion.h" #include "printing/units.h" namespace printing { @@ -47,13 +48,29 @@ PrintingContext::Result PrintingContext::OnError() { return abort_printing_ ? CANCEL : FAILED; } +PrintingContext::Result PrintingContext::UsePdfSettings() { + scoped_ptr<base::DictionaryValue> pdf_settings(new base::DictionaryValue); + pdf_settings->SetBoolean(kSettingHeaderFooterEnabled, false); + pdf_settings->SetBoolean(kSettingShouldPrintBackgrounds, false); + pdf_settings->SetBoolean(kSettingShouldPrintSelectionOnly, false); + pdf_settings->SetInteger(kSettingMarginsType, printing::NO_MARGINS); + pdf_settings->SetBoolean(kSettingCollate, true); + pdf_settings->SetInteger(kSettingCopies, 1); + pdf_settings->SetInteger(kSettingColor, printing::COLOR); + pdf_settings->SetInteger(kSettingDuplexMode, printing::SIMPLEX); + pdf_settings->SetBoolean(kSettingLandscape, false); + pdf_settings->SetString(kSettingDeviceName, ""); + pdf_settings->SetBoolean(kSettingPrintToPDF, true); + pdf_settings->SetBoolean(kSettingCloudPrintDialog, false); + pdf_settings->SetBoolean(kSettingPrintWithPrivet, false); + return UpdatePrintSettings(*pdf_settings); +} + PrintingContext::Result PrintingContext::UpdatePrintSettings( - const base::DictionaryValue& job_settings, - const PageRanges& ranges) { + const base::DictionaryValue& job_settings) { ResetSettings(); - if (!PrintSettingsInitializer::InitSettings(job_settings, ranges, - &settings_)) { + if (!PrintSettingsFromJobSettings(job_settings, &settings_)) { NOTREACHED(); return OnError(); } @@ -76,16 +93,21 @@ PrintingContext::Result PrintingContext::UpdatePrintSettings( if (!open_in_external_preview && (print_to_pdf || print_to_cloud || is_cloud_dialog || print_with_privet)) { settings_.set_dpi(kDefaultPdfDpi); - // Cloud print should get size and rect from capabilities received from - // server. gfx::Size paper_size(GetPdfPaperSizeDeviceUnits()); + if (!settings_.requested_media().size_microns.IsEmpty()) { + float deviceMicronsPerDeviceUnit = + (kHundrethsMMPerInch * 10.0f) / settings_.device_units_per_inch(); + paper_size = gfx::Size(settings_.requested_media().size_microns.width() / + deviceMicronsPerDeviceUnit, + settings_.requested_media().size_microns.height() / + deviceMicronsPerDeviceUnit); + } gfx::Rect paper_rect(0, 0, paper_size.width(), paper_size.height()); if (print_to_cloud || print_with_privet) { paper_rect.Inset( kCloudPrintMarginInch * settings_.device_units_per_inch(), kCloudPrintMarginInch * settings_.device_units_per_inch()); } - DCHECK_EQ(settings_.device_units_per_inch(), kDefaultPdfDpi); settings_.SetPrinterPrintableArea(paper_size, paper_rect, true); return OK; } diff --git a/chromium/printing/printing_context.h b/chromium/printing/printing_context.h index 7a0a8c8b99a..823a5af4466 100644 --- a/chromium/printing/printing_context.h +++ b/chromium/printing/printing_context.h @@ -51,6 +51,9 @@ class PRINTING_EXPORT PrintingContext { // default device settings. virtual Result UseDefaultSettings() = 0; + // Updates the context with PDF printer settings. + Result UsePdfSettings(); + // Returns paper size to be used for PDF or Cloud Print in device units. virtual gfx::Size GetPdfPaperSizeDeviceUnits() = 0; @@ -61,8 +64,7 @@ class PRINTING_EXPORT PrintingContext { // Updates Print Settings. |job_settings| contains all print job // settings information. |ranges| has the new page range settings. - Result UpdatePrintSettings(const base::DictionaryValue& job_settings, - const PageRanges& ranges); + Result UpdatePrintSettings(const base::DictionaryValue& job_settings); // Initializes with predefined settings. virtual Result InitWithSettings(const PrintSettings& settings) = 0; diff --git a/chromium/printing/printing_context_android.cc b/chromium/printing/printing_context_android.cc index 76c65382aea..5729267f320 100644 --- a/chromium/printing/printing_context_android.cc +++ b/chromium/printing/printing_context_android.cc @@ -188,7 +188,7 @@ PrintingContext::Result PrintingContextAndroid::InitWithSettings( } PrintingContext::Result PrintingContextAndroid::NewDocument( - const string16& document_name) { + const base::string16& document_name) { DCHECK(!in_print_job_); in_print_job_ = true; diff --git a/chromium/printing/printing_context_gtk.cc b/chromium/printing/printing_context_linux.cc index d757df726fd..3b6d2ee9f1f 100644 --- a/chromium/printing/printing_context_gtk.cc +++ b/chromium/printing/printing_context_linux.cc @@ -1,11 +1,8 @@ -// Copyright (c) 2012 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#include "printing/printing_context_gtk.h" - -#include <gtk/gtk.h> -#include <gtk/gtkunixprint.h> +#include "printing/printing_context_linux.h" #include "base/logging.h" #include "base/values.h" @@ -19,7 +16,11 @@ namespace { // Function pointer for creating print dialogs. |callback| is only used when // |show_dialog| is true. printing::PrintDialogGtkInterface* (*create_dialog_func_)( - printing::PrintingContextGtk* context) = NULL; + printing::PrintingContextLinux* context) = NULL; + +// Function pointer for determining paper size. +gfx::Size (*get_pdf_paper_size_)( + printing::PrintingContextLinux* context) = NULL; } // namespace @@ -27,15 +28,15 @@ namespace printing { // static PrintingContext* PrintingContext::Create(const std::string& app_locale) { - return static_cast<PrintingContext*>(new PrintingContextGtk(app_locale)); + return static_cast<PrintingContext*>(new PrintingContextLinux(app_locale)); } -PrintingContextGtk::PrintingContextGtk(const std::string& app_locale) +PrintingContextLinux::PrintingContextLinux(const std::string& app_locale) : PrintingContext(app_locale), print_dialog_(NULL) { } -PrintingContextGtk::~PrintingContextGtk() { +PrintingContextLinux::~PrintingContextLinux() { ReleaseContext(); if (print_dialog_) @@ -43,32 +44,52 @@ PrintingContextGtk::~PrintingContextGtk() { } // static -void PrintingContextGtk::SetCreatePrintDialogFunction( +void PrintingContextLinux::SetCreatePrintDialogFunction( PrintDialogGtkInterface* (*create_dialog_func)( - PrintingContextGtk* context)) { + PrintingContextLinux* context)) { DCHECK(create_dialog_func); DCHECK(!create_dialog_func_); create_dialog_func_ = create_dialog_func; } -void PrintingContextGtk::PrintDocument(const Metafile* metafile) { +// static +void PrintingContextLinux::SetPdfPaperSizeFunction( + gfx::Size (*get_pdf_paper_size)(PrintingContextLinux* context)) { + DCHECK(get_pdf_paper_size); + DCHECK(!get_pdf_paper_size_); + get_pdf_paper_size_ = get_pdf_paper_size; +} + +void PrintingContextLinux::PrintDocument(const Metafile* metafile) { DCHECK(print_dialog_); DCHECK(metafile); print_dialog_->PrintDocument(metafile, document_name_); } -void PrintingContextGtk::AskUserForSettings( +void PrintingContextLinux::AskUserForSettings( gfx::NativeView parent_view, int max_pages, bool has_selection, const PrintSettingsCallback& callback) { + if (!print_dialog_) { + // Can only get here if the renderer is sending bad messages. + // http://crbug.com/341777 + NOTREACHED(); + callback.Run(FAILED); + return; + } + print_dialog_->ShowDialog(parent_view, has_selection, callback); } -PrintingContext::Result PrintingContextGtk::UseDefaultSettings() { +PrintingContext::Result PrintingContextLinux::UseDefaultSettings() { DCHECK(!in_print_job_); ResetSettings(); + + if (!create_dialog_func_) + return OK; + if (!print_dialog_) { print_dialog_ = create_dialog_func_(this); print_dialog_->AddRefToDialog(); @@ -78,25 +99,21 @@ PrintingContext::Result PrintingContextGtk::UseDefaultSettings() { return OK; } -gfx::Size PrintingContextGtk::GetPdfPaperSizeDeviceUnits() { - GtkPageSetup* page_setup = gtk_page_setup_new(); - - gfx::SizeF paper_size( - gtk_page_setup_get_paper_width(page_setup, GTK_UNIT_INCH), - gtk_page_setup_get_paper_height(page_setup, GTK_UNIT_INCH)); +gfx::Size PrintingContextLinux::GetPdfPaperSizeDeviceUnits() { + if (get_pdf_paper_size_) + return get_pdf_paper_size_(this); - g_object_unref(page_setup); - - return gfx::Size( - paper_size.width() * settings_.device_units_per_inch(), - paper_size.height() * settings_.device_units_per_inch()); + return gfx::Size(); } -PrintingContext::Result PrintingContextGtk::UpdatePrinterSettings( +PrintingContext::Result PrintingContextLinux::UpdatePrinterSettings( bool external_preview) { DCHECK(!in_print_job_); DCHECK(!external_preview) << "Not implemented"; + if (!create_dialog_func_) + return OK; + if (!print_dialog_) { print_dialog_ = create_dialog_func_(this); print_dialog_->AddRefToDialog(); @@ -108,7 +125,7 @@ PrintingContext::Result PrintingContextGtk::UpdatePrinterSettings( return OK; } -PrintingContext::Result PrintingContextGtk::InitWithSettings( +PrintingContext::Result PrintingContextLinux::InitWithSettings( const PrintSettings& settings) { DCHECK(!in_print_job_); @@ -117,7 +134,7 @@ PrintingContext::Result PrintingContextGtk::InitWithSettings( return OK; } -PrintingContext::Result PrintingContextGtk::NewDocument( +PrintingContext::Result PrintingContextLinux::NewDocument( const base::string16& document_name) { DCHECK(!in_print_job_); in_print_job_ = true; @@ -127,7 +144,7 @@ PrintingContext::Result PrintingContextGtk::NewDocument( return OK; } -PrintingContext::Result PrintingContextGtk::NewPage() { +PrintingContext::Result PrintingContextLinux::NewPage() { if (abort_printing_) return CANCEL; DCHECK(in_print_job_); @@ -137,7 +154,7 @@ PrintingContext::Result PrintingContextGtk::NewPage() { return OK; } -PrintingContext::Result PrintingContextGtk::PageDone() { +PrintingContext::Result PrintingContextLinux::PageDone() { if (abort_printing_) return CANCEL; DCHECK(in_print_job_); @@ -147,7 +164,7 @@ PrintingContext::Result PrintingContextGtk::PageDone() { return OK; } -PrintingContext::Result PrintingContextGtk::DocumentDone() { +PrintingContext::Result PrintingContextLinux::DocumentDone() { if (abort_printing_) return CANCEL; DCHECK(in_print_job_); @@ -156,19 +173,18 @@ PrintingContext::Result PrintingContextGtk::DocumentDone() { return OK; } -void PrintingContextGtk::Cancel() { +void PrintingContextLinux::Cancel() { abort_printing_ = true; in_print_job_ = false; } -void PrintingContextGtk::ReleaseContext() { +void PrintingContextLinux::ReleaseContext() { // Intentional No-op. } -gfx::NativeDrawingContext PrintingContextGtk::context() const { +gfx::NativeDrawingContext PrintingContextLinux::context() const { // Intentional No-op. return NULL; } } // namespace printing - diff --git a/chromium/printing/printing_context_gtk.h b/chromium/printing/printing_context_linux.h index 8476bfb30a5..307601488db 100644 --- a/chromium/printing/printing_context_gtk.h +++ b/chromium/printing/printing_context_linux.h @@ -1,9 +1,9 @@ -// Copyright (c) 2011 The Chromium Authors. All rights reserved. +// Copyright 2014 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -#ifndef PRINTING_PRINTING_CONTEXT_GTK_H_ -#define PRINTING_PRINTING_CONTEXT_GTK_H_ +#ifndef PRINTING_PRINTING_CONTEXT_LINUX_H_ +#define PRINTING_PRINTING_CONTEXT_LINUX_H_ #include <string> @@ -18,15 +18,20 @@ namespace printing { class Metafile; class PrintDialogGtkInterface; -class PRINTING_EXPORT PrintingContextGtk : public PrintingContext { +// PrintingContext with optional native UI for print dialog and pdf_paper_size. +class PRINTING_EXPORT PrintingContextLinux : public PrintingContext { public: - explicit PrintingContextGtk(const std::string& app_locale); - virtual ~PrintingContextGtk(); + explicit PrintingContextLinux(const std::string& app_locale); + virtual ~PrintingContextLinux(); // Sets the function that creates the print dialog. static void SetCreatePrintDialogFunction( PrintDialogGtkInterface* (*create_dialog_func)( - PrintingContextGtk* context)); + PrintingContextLinux* context)); + + // Sets the function that returns pdf paper size through the native API. + static void SetPdfPaperSizeFunction( + gfx::Size (*get_pdf_paper_size)(PrintingContextLinux* context)); // Prints the document contained in |metafile|. void PrintDocument(const Metafile* metafile); @@ -53,10 +58,9 @@ class PRINTING_EXPORT PrintingContextGtk : public PrintingContext { base::string16 document_name_; PrintDialogGtkInterface* print_dialog_; - DISALLOW_COPY_AND_ASSIGN(PrintingContextGtk); + DISALLOW_COPY_AND_ASSIGN(PrintingContextLinux); }; } // namespace printing -#endif // PRINTING_PRINTING_CONTEXT_GTK_H_ - +#endif // PRINTING_PRINTING_CONTEXT_LINUX_H_ diff --git a/chromium/printing/printing_context_mac.h b/chromium/printing/printing_context_mac.h index 9257510807e..f16ef545e7c 100644 --- a/chromium/printing/printing_context_mac.h +++ b/chromium/printing/printing_context_mac.h @@ -54,13 +54,18 @@ class PRINTING_EXPORT PrintingContextMac : public PrintingContext { PageRanges GetPageRangesFromPrintInfo(); // Updates |print_info_| to use the given printer. - // Returns true if the printer was set else returns false. + // Returns true if the printer was set. bool SetPrinter(const std::string& device_name); - // Updates |print_info_| page format with user default paper information. - // Returns true if the paper was set else returns false. + // Updates |print_info_| page format with paper selected by user. If paper was + // not selected, default system paper is used. + // Returns true if the paper was set. bool UpdatePageFormatWithPaperInfo(); + // Updates |print_info_| page format with |paper|. + // Returns true if the paper was set. + bool UpdatePageFormatWithPaper(PMPaper paper, PMPageFormat page_format); + // Sets the print job destination type as preview job. // Returns true if the print job destination type is set. bool SetPrintPreviewJob(); diff --git a/chromium/printing/printing_context_mac.mm b/chromium/printing/printing_context_mac.mm index 088d3ea286c..9bbe5ac1de9 100644 --- a/chromium/printing/printing_context_mac.mm +++ b/chromium/printing/printing_context_mac.mm @@ -24,14 +24,45 @@ namespace printing { namespace { +const int kMaxPaperSizeDiffereceInPoints = 2; + // Return true if PPD name of paper is equal. -bool IsPaperNameEqual(const PMPaper& paper1, const PMPaper& paper2) { - CFStringRef name1 = NULL; +bool IsPaperNameEqual(CFStringRef name1, const PMPaper& paper2) { CFStringRef name2 = NULL; - return (PMPaperGetPPDPaperName(paper1, &name1) == noErr) && - (PMPaperGetPPDPaperName(paper2, &name2) == noErr) && - (CFStringCompare(name1, name2, - kCFCompareCaseInsensitive) == kCFCompareEqualTo); + return (name1 && PMPaperGetPPDPaperName(paper2, &name2) == noErr) && + (CFStringCompare(name1, name2, kCFCompareCaseInsensitive) == + kCFCompareEqualTo); +} + +PMPaper MatchPaper(CFArrayRef paper_list, + CFStringRef name, + double width, + double height) { + double best_match = std::numeric_limits<double>::max(); + PMPaper best_matching_paper = NULL; + int num_papers = CFArrayGetCount(paper_list); + for (int i = 0; i < num_papers; ++i) { + PMPaper paper = (PMPaper)[(NSArray*)paper_list objectAtIndex : i]; + double paper_width = 0.0; + double paper_height = 0.0; + PMPaperGetWidth(paper, &paper_width); + PMPaperGetHeight(paper, &paper_height); + double difference = + std::max(fabs(width - paper_width), fabs(height - paper_height)); + + // Ignore papers with size too different from expected. + if (difference > kMaxPaperSizeDiffereceInPoints) + continue; + + if (name && IsPaperNameEqual(name, paper)) + return paper; + + if (difference < best_match) { + best_matching_paper = paper; + best_match = difference; + } + } + return best_matching_paper; } } // namespace @@ -149,7 +180,7 @@ PrintingContext::Result PrintingContextMac::UpdatePrinterSettings( return OnError(); } else { // Don't need this for preview. - if (!SetPrinter(UTF16ToUTF8(settings_.device_name())) || + if (!SetPrinter(base::UTF16ToUTF8(settings_.device_name())) || !SetCopiesInPrintSettings(settings_.copies()) || !SetCollateInPrintSettings(settings_.collate()) || !SetDuplexModeInPrintSettings(settings_.duplex_mode()) || @@ -214,7 +245,7 @@ bool PrintingContextMac::SetPrinter(const std::string& device_name) { } PMPrinter new_printer = PMPrinterCreateFromPrinterID(new_printer_id.get()); - if (new_printer == NULL) + if (!new_printer) return false; OSStatus status = PMSessionSetCurrentPMPrinter(print_session, new_printer); @@ -229,89 +260,75 @@ bool PrintingContextMac::UpdatePageFormatWithPaperInfo() { PMPageFormat default_page_format = static_cast<PMPageFormat>([print_info_.get() PMPageFormat]); - PMPaper default_paper; - if (PMGetPageFormatPaper(default_page_format, &default_paper) != noErr) - return false; - - double default_page_width = 0.0; - double default_page_height = 0.0; - if (PMPaperGetWidth(default_paper, &default_page_width) != noErr) - return false; - - if (PMPaperGetHeight(default_paper, &default_page_height) != noErr) - return false; - PMPrinter current_printer = NULL; if (PMSessionGetCurrentPrinter(print_session, ¤t_printer) != noErr) return false; - if (current_printer == nil) - return false; + double page_width = 0.0; + double page_height = 0.0; + base::ScopedCFTypeRef<CFStringRef> paper_name; + PMPaperMargins margins = {0}; + + const PrintSettings::RequestedMedia& media = settings_.requested_media(); + if (media.IsDefault()) { + PMPaper default_paper; + if (PMGetPageFormatPaper(default_page_format, &default_paper) != noErr || + PMPaperGetWidth(default_paper, &page_width) != noErr || + PMPaperGetHeight(default_paper, &page_height) != noErr) { + return false; + } + + // Ignore result, because we can continue without following. + CFStringRef tmp_paper_name = NULL; + PMPaperGetPPDPaperName(default_paper, &tmp_paper_name); + PMPaperGetMargins(default_paper, &margins); + paper_name.reset(tmp_paper_name, base::scoped_policy::RETAIN); + } else { + const double kMutiplier = kPointsPerInch / (10.0f * kHundrethsMMPerInch); + page_width = media.size_microns.width() * kMutiplier; + page_height = media.size_microns.height() * kMutiplier; + paper_name.reset(base::SysUTF8ToCFStringRef(media.vendor_id)); + } CFArrayRef paper_list = NULL; if (PMPrinterGetPaperList(current_printer, &paper_list) != noErr) return false; - double best_match = std::numeric_limits<double>::max(); - PMPaper best_matching_paper = kPMNoData; - int num_papers = CFArrayGetCount(paper_list); - for (int i = 0; i < num_papers; ++i) { - PMPaper paper = (PMPaper)[(NSArray*)paper_list objectAtIndex: i]; - double paper_width = 0.0; - double paper_height = 0.0; - PMPaperGetWidth(paper, &paper_width); - PMPaperGetHeight(paper, &paper_height); - double current_match = std::max(fabs(default_page_width - paper_width), - fabs(default_page_height - paper_height)); - // Ignore paper sizes that are very different. - if (current_match > 2) - continue; - current_match += IsPaperNameEqual(paper, default_paper) ? 0 : 1; - if (current_match < best_match) { - best_matching_paper = paper; - best_match = current_match; - } - } + PMPaper best_matching_paper = + MatchPaper(paper_list, paper_name, page_width, page_height); - if (best_matching_paper == kPMNoData) { - PMPaper paper = kPMNoData; - // Create a custom paper for the specified default page size. - PMPaperMargins default_margins; - if (PMPaperGetMargins(default_paper, &default_margins) != noErr) - return false; + if (best_matching_paper) + return UpdatePageFormatWithPaper(best_matching_paper, default_page_format); - const PMPaperMargins margins = - {default_margins.top, default_margins.left, default_margins.bottom, - default_margins.right}; - CFStringRef paper_id = CFSTR("Custom paper ID"); - CFStringRef paper_name = CFSTR("Custom paper"); - if (PMPaperCreateCustom(current_printer, paper_id, paper_name, - default_page_width, default_page_height, &margins, &paper) != - noErr) { - return false; - } - [print_info_.get() updateFromPMPageFormat]; - PMRelease(paper); - } else { - PMPageFormat chosen_page_format = NULL; - if (PMCreatePageFormat((PMPageFormat*) &chosen_page_format) != noErr) - return false; + // Do nothing if unmatched paper was default system paper. + if (media.IsDefault()) + return true; - // Create page format from that paper. - if (PMCreatePageFormatWithPMPaper(&chosen_page_format, - best_matching_paper) != noErr) { - PMRelease(chosen_page_format); - return false; - } - // Copy over the original format with the new page format. - if (PMCopyPageFormat(chosen_page_format, default_page_format) != noErr) { - PMRelease(chosen_page_format); - return false; - } - [print_info_.get() updateFromPMPageFormat]; - PMRelease(chosen_page_format); + PMPaper paper = NULL; + if (PMPaperCreateCustom(current_printer, + CFSTR("Custom paper ID"), + CFSTR("Custom paper"), + page_width, + page_height, + &margins, + &paper) != noErr) { + return false; } - return true; + bool result = UpdatePageFormatWithPaper(paper, default_page_format); + PMRelease(paper); + return result; +} + +bool PrintingContextMac::UpdatePageFormatWithPaper(PMPaper paper, + PMPageFormat page_format) { + PMPageFormat new_format = NULL; + if (PMCreatePageFormatWithPMPaper(&new_format, paper) != noErr) + return false; + // Copy over the original format with the new page format. + bool result = (PMCopyPageFormat(new_format, page_format) == noErr); + [print_info_.get() updateFromPMPageFormat]; + PMRelease(new_format); + return result; } bool PrintingContextMac::SetCopiesInPrintSettings(int copies) { diff --git a/chromium/printing/printing_context_win.cc b/chromium/printing/printing_context_win.cc index 9e97dd24d2b..b32b3d2faa0 100644 --- a/chromium/printing/printing_context_win.cc +++ b/chromium/printing/printing_context_win.cc @@ -8,14 +8,11 @@ #include <algorithm> -#include "base/i18n/file_util_icu.h" -#include "base/i18n/time_formatting.h" #include "base/message_loop/message_loop.h" #include "base/metrics/histogram.h" +#include "base/strings/string_number_conversions.h" #include "base/strings/utf_string_conversions.h" -#include "base/time/time.h" #include "base/values.h" -#include "base/win/metro.h" #include "printing/backend/print_backend.h" #include "printing/backend/printing_info_win.h" #include "printing/backend/win_helper.h" @@ -25,23 +22,20 @@ #include "printing/printing_utils.h" #include "printing/units.h" #include "skia/ext/platform_device.h" -#include "win8/util/win8_util.h" #if defined(USE_AURA) -#include "ui/aura/remote_root_window_host_win.h" -#include "ui/aura/root_window.h" +#include "ui/aura/remote_window_tree_host_win.h" #include "ui/aura/window.h" +#include "ui/aura/window_event_dispatcher.h" #endif -using base::Time; - namespace { HWND GetRootWindow(gfx::NativeView view) { HWND window = NULL; #if defined(USE_AURA) if (view) - window = view->GetDispatcher()->host()->GetAcceleratedWidget(); + window = view->GetHost()->GetAcceleratedWidget(); #else if (view && IsWindow(view)) { window = GetAncestor(view, GA_ROOTOWNER); @@ -165,11 +159,7 @@ PrintingContext* PrintingContext::Create(const std::string& app_locale) { } PrintingContextWin::PrintingContextWin(const std::string& app_locale) - : PrintingContext(app_locale), - context_(NULL), - dialog_box_(NULL), - print_dialog_func_(&PrintDlgEx) { -} + : PrintingContext(app_locale), context_(NULL), dialog_box_(NULL) {} PrintingContextWin::~PrintingContextWin() { ReleaseContext(); @@ -179,25 +169,6 @@ void PrintingContextWin::AskUserForSettings( gfx::NativeView view, int max_pages, bool has_selection, const PrintSettingsCallback& callback) { DCHECK(!in_print_job_); - // TODO(scottmg): Possibly this has to move into the threaded runner too? - if (win8::IsSingleWindowMetroMode()) { - // The system dialog can not be opened while running in Metro. - // But we can programatically launch the Metro print device charm though. - HMODULE metro_module = base::win::GetMetroModule(); - if (metro_module != NULL) { - typedef void (*MetroShowPrintUI)(); - MetroShowPrintUI metro_show_print_ui = - reinterpret_cast<MetroShowPrintUI>( - ::GetProcAddress(metro_module, "MetroShowPrintUI")); - if (metro_show_print_ui) { - // TODO(mad): Remove this once we can send user metrics from the metro - // driver. crbug.com/142330 - UMA_HISTOGRAM_ENUMERATION("Metro.Print", 1, 2); - metro_show_print_ui(); - } - } - return callback.Run(CANCEL); - } dialog_box_dismissed_ = false; HWND window = GetRootWindow(view); @@ -212,40 +183,39 @@ void PrintingContextWin::AskUserForSettings( // - 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 = - reinterpret_cast<PRINTDLGEX*>(malloc(sizeof(PRINTDLGEX))); - ZeroMemory(dialog_options, sizeof(PRINTDLGEX)); - dialog_options->lStructSize = sizeof(PRINTDLGEX); - dialog_options->hwndOwner = window; + 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; + dialog_options.Flags = PD_RETURNDC | PD_USEDEVMODECOPIESANDCOLLATE | + PD_NOCURRENTPAGE | PD_HIDEPRINTTOFILE; if (!has_selection) - dialog_options->Flags |= PD_NOSELECTION; + dialog_options.Flags |= PD_NOSELECTION; - const size_t max_page_ranges = 32; - PRINTPAGERANGE* ranges = new PRINTPAGERANGE[max_page_ranges]; - dialog_options->lpPageRanges = ranges; - dialog_options->nStartPage = START_PAGE_GENERAL; + 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 = max_page_ranges; - dialog_options->nMinPage = 1; - dialog_options->nMaxPage = 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; + dialog_options.Flags |= PD_NOPAGENUMS; } - callback_ = callback; - print_settings_dialog_ = new ui::PrintSettingsDialogWin(this); - print_settings_dialog_->GetPrintSettings( - print_dialog_func_, window, dialog_options); + if (ShowPrintDialog(&dialog_options) != S_OK) { + ResetSettings(); + callback.Run(FAILED); + } + + // TODO(maruel): Support PD_PRINTTOFILE. + callback.Run(ParseDialogResultEx(dialog_options)); } PrintingContext::Result PrintingContextWin::UseDefaultSettings() { @@ -262,7 +232,7 @@ PrintingContext::Result PrintingContextWin::UseDefaultSettings() { (void)::EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, NULL, 0, &bytes_needed, &count_returned); if (bytes_needed) { - DCHECK(bytes_needed >= count_returned * sizeof(PRINTER_INFO_2)); + DCHECK_GE(bytes_needed, count_returned * sizeof(PRINTER_INFO_2)); scoped_ptr<BYTE[]> printer_info_buffer(new BYTE[bytes_needed]); BOOL ret = ::EnumPrinters(PRINTER_ENUM_LOCAL|PRINTER_ENUM_CONNECTIONS, NULL, 2, printer_info_buffer.get(), @@ -270,17 +240,22 @@ PrintingContext::Result PrintingContextWin::UseDefaultSettings() { &count_returned); if (ret && count_returned) { // have printers // Open the first successfully found printer. - for (DWORD count = 0; count < count_returned; ++count) { - PRINTER_INFO_2* info_2 = reinterpret_cast<PRINTER_INFO_2*>( - printer_info_buffer.get() + count * sizeof(PRINTER_INFO_2)); - std::wstring printer_name = info_2->pPrinterName; - if (info_2->pDevMode == NULL || printer_name.length() == 0) + const PRINTER_INFO_2* info_2 = + reinterpret_cast<PRINTER_INFO_2*>(printer_info_buffer.get()); + const PRINTER_INFO_2* info_2_end = info_2 + count_returned; + for (; info_2 < info_2_end; ++info_2) { + ScopedPrinterHandle printer; + if (!printer.OpenPrinter(info_2->pPrinterName)) continue; - if (!AllocateContext(printer_name, info_2->pDevMode, &context_)) - break; - if (InitializeSettings(*info_2->pDevMode, printer_name, - NULL, 0, false)) { - break; + 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)) { + return OK; } ReleaseContext(); } @@ -329,68 +304,76 @@ PrintingContext::Result PrintingContextWin::UpdatePrinterSettings( DCHECK(!external_preview) << "Not implemented"; ScopedPrinterHandle printer; - LPWSTR device_name_wide = - const_cast<wchar_t*>(settings_.device_name().c_str()); - if (!printer.OpenPrinter(device_name_wide)) + if (!printer.OpenPrinter(settings_.device_name().c_str())) return OnError(); // Make printer changes local to Chrome. // See MSDN documentation regarding DocumentProperties. - scoped_ptr<uint8[]> buffer; - DEVMODE* dev_mode = NULL; - LONG buffer_size = DocumentProperties(NULL, printer, device_name_wide, - NULL, NULL, 0); - if (buffer_size > 0) { - buffer.reset(new uint8[buffer_size]); - memset(buffer.get(), 0, buffer_size); - if (DocumentProperties(NULL, printer, device_name_wide, - reinterpret_cast<PDEVMODE>(buffer.get()), NULL, - DM_OUT_BUFFER) == IDOK) { - dev_mode = reinterpret_cast<PDEVMODE>(buffer.get()); - } - } - if (dev_mode == NULL) { - buffer.reset(); + scoped_ptr<DEVMODE, base::FreeDeleter> scoped_dev_mode = + CreateDevModeWithColor(printer, settings_.device_name(), + settings_.color() != GRAY); + if (!scoped_dev_mode) return OnError(); - } - if (settings_.color() == GRAY) - dev_mode->dmColor = DMCOLOR_MONOCHROME; - else - dev_mode->dmColor = DMCOLOR_COLOR; - - dev_mode->dmCopies = std::max(settings_.copies(), 1); - if (dev_mode->dmCopies > 1) { // do not change collate unless multiple copies - dev_mode->dmCollate = settings_.collate() ? DMCOLLATE_TRUE : - DMCOLLATE_FALSE; - } - switch (settings_.duplex_mode()) { - case LONG_EDGE: - dev_mode->dmDuplex = DMDUP_VERTICAL; - break; - case SHORT_EDGE: - dev_mode->dmDuplex = DMDUP_HORIZONTAL; - break; - case SIMPLEX: - dev_mode->dmDuplex = DMDUP_SIMPLEX; - break; - default: // UNKNOWN_DUPLEX_MODE - break; - } - dev_mode->dmOrientation = settings_.landscape() ? DMORIENT_LANDSCAPE : - DMORIENT_PORTRAIT; + { + DEVMODE* dev_mode = scoped_dev_mode.get(); + dev_mode->dmCopies = std::max(settings_.copies(), 1); + if (dev_mode->dmCopies > 1) { // do not change unless multiple copies + dev_mode->dmFields |= DM_COPIES; + dev_mode->dmCollate = settings_.collate() ? DMCOLLATE_TRUE : + DMCOLLATE_FALSE; + } + + switch (settings_.duplex_mode()) { + case LONG_EDGE: + dev_mode->dmFields |= DM_DUPLEX; + dev_mode->dmDuplex = DMDUP_VERTICAL; + break; + case SHORT_EDGE: + dev_mode->dmFields |= DM_DUPLEX; + dev_mode->dmDuplex = DMDUP_HORIZONTAL; + break; + case SIMPLEX: + dev_mode->dmFields |= DM_DUPLEX; + dev_mode->dmDuplex = DMDUP_SIMPLEX; + break; + default: // UNKNOWN_DUPLEX_MODE + break; + } + + dev_mode->dmFields |= DM_ORIENTATION; + dev_mode->dmOrientation = settings_.landscape() ? DMORIENT_LANDSCAPE : + DMORIENT_PORTRAIT; + + const PrintSettings::RequestedMedia& requested_media = + settings_.requested_media(); + static const int kFromUm = 100; // Windows uses 0.1mm. + int width = requested_media.size_microns.width() / kFromUm; + int height = requested_media.size_microns.height() / kFromUm; + unsigned id = 0; + if (base::StringToUint(requested_media.vendor_id, &id) && id) { + dev_mode->dmFields |= DM_PAPERSIZE; + dev_mode->dmPaperSize = static_cast<short>(id); + } else if (width > 0 && height > 0) { + dev_mode->dmFields |= DM_PAPERWIDTH; + dev_mode->dmPaperWidth = width; + dev_mode->dmFields |= DM_PAPERLENGTH; + dev_mode->dmPaperLength = height; + } + } // Update data using DocumentProperties. - if (DocumentProperties(NULL, printer, device_name_wide, dev_mode, dev_mode, - DM_IN_BUFFER | DM_OUT_BUFFER) != IDOK) { + 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(), dev_mode, &context_)) { + if (!AllocateContext(settings_.device_name(), scoped_dev_mode.get(), + &context_)) { return OnError(); } - PrintSettingsInitializerWin::InitPrintSettings(context_, *dev_mode, + PrintSettingsInitializerWin::InitPrintSettings(context_, + *scoped_dev_mode.get(), &settings_); return OK; } @@ -434,26 +417,14 @@ PrintingContext::Result PrintingContextWin::NewDocument( DCHECK(SimplifyDocumentTitle(document_name) == document_name); DOCINFO di = { sizeof(DOCINFO) }; - const std::wstring& document_name_wide = UTF16ToWide(document_name); - di.lpszDocName = document_name_wide.c_str(); + di.lpszDocName = document_name.c_str(); // Is there a debug dump directory specified? If so, force to print to a file. - base::FilePath debug_dump_path = PrintedDocument::debug_dump_path(); - if (!debug_dump_path.empty()) { - // Create a filename. - std::wstring filename; - Time now(Time::Now()); - filename = base::TimeFormatShortDateNumeric(now); - filename += L"_"; - filename += base::TimeFormatTimeOfDay(now); - filename += L"_"; - filename += UTF16ToWide(document_name); - filename += L"_"; - filename += L"buffer.prn"; - file_util::ReplaceIllegalCharactersInPath(&filename, '_'); - debug_dump_path.Append(filename); - di.lpszOutput = debug_dump_path.value().c_str(); - } + base::string16 debug_dump_path = + PrintedDocument::CreateDebugDumpPath(document_name, + FILE_PATH_LITERAL(".prn")).value(); + if (!debug_dump_path.empty()) + di.lpszOutput = debug_dump_path.c_str(); // No message loop running in unit tests. DCHECK(!base::MessageLoop::current() || @@ -527,20 +498,6 @@ gfx::NativeDrawingContext PrintingContextWin::context() const { return context_; } -void PrintingContextWin::PrintSettingsConfirmed(PRINTDLGEX* dialog_options) { - // TODO(maruel): Support PD_PRINTTOFILE. - callback_.Run(ParseDialogResultEx(*dialog_options)); - delete [] dialog_options->lpPageRanges; - free(dialog_options); -} - -void PrintingContextWin::PrintSettingsCancelled(PRINTDLGEX* dialog_options) { - ResetSettings(); - callback_.Run(FAILED); - delete [] dialog_options->lpPageRanges; - free(dialog_options); -} - // static BOOL PrintingContextWin::AbortProc(HDC hdc, int nCode) { if (nCode) { @@ -601,15 +558,15 @@ bool PrintingContextWin::GetPrinterSettings(HANDLE printer, const std::wstring& device_name) { DCHECK(!in_print_job_); - UserDefaultDevMode user_settings; + scoped_ptr<DEVMODE, base::FreeDeleter> dev_mode = + CreateDevMode(printer, NULL); - if (!user_settings.Init(printer) || - !AllocateContext(device_name, user_settings.get(), &context_)) { + if (!dev_mode || !AllocateContext(device_name, dev_mode.get(), &context_)) { ResetSettings(); return false; } - return InitializeSettings(*user_settings.get(), device_name, NULL, 0, false); + return InitializeSettings(*dev_mode.get(), device_name, NULL, 0, false); } // static @@ -698,6 +655,19 @@ PrintingContext::Result PrintingContextWin::ParseDialogResultEx( } } +HRESULT PrintingContextWin::ShowPrintDialog(PRINTDLGEX* options) { + // 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 + // browser frame (but still being modal) so neither the browser frame nor + // the print dialog will get any input. See http://crbug.com/342697 + // http://crbug.com/180997 for details. + base::MessageLoop::ScopedNestableTaskAllower allow( + base::MessageLoop::current()); + + return PrintDlgEx(options); +} + PrintingContext::Result PrintingContextWin::ParseDialogResult( const PRINTDLG& dialog_options) { // If the user clicked OK or Apply then Cancel, but not only Cancel. diff --git a/chromium/printing/printing_context_win.h b/chromium/printing/printing_context_win.h index 3be4917109f..6c1e42041b6 100644 --- a/chromium/printing/printing_context_win.h +++ b/chromium/printing/printing_context_win.h @@ -14,13 +14,10 @@ #include "build/build_config.h" #include "printing/printing_context.h" #include "ui/gfx/native_widget_types.h" -#include "ui/shell_dialogs/print_settings_dialog_win.h" namespace printing { -class PRINTING_EXPORT PrintingContextWin - : public PrintingContext, - public ui::PrintSettingsDialogWin::Observer { +class PRINTING_EXPORT PrintingContextWin : public PrintingContext { public: explicit PrintingContextWin(const std::string& app_locale); ~PrintingContextWin(); @@ -43,22 +40,14 @@ class PRINTING_EXPORT PrintingContextWin virtual void ReleaseContext() OVERRIDE; virtual gfx::NativeDrawingContext context() const OVERRIDE; - // PrintSettingsDialogWin::Observer implementation: - virtual void PrintSettingsConfirmed(PRINTDLGEX* dialog_options) OVERRIDE; - virtual void PrintSettingsCancelled(PRINTDLGEX* dialog_options) OVERRIDE; - -#if defined(UNIT_TEST) || defined(PRINTING_IMPLEMENTATION) - // Sets a fake PrintDlgEx function pointer in tests. - void SetPrintDialog(HRESULT (__stdcall *print_dialog_func)(LPPRINTDLGEX)) { - print_dialog_func_ = print_dialog_func; - } -#endif // defined(UNIT_TEST) - // 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); + private: // Class that manages the PrintDlgEx() callbacks. This is meant to be a // temporary object used during the Print... dialog display. @@ -90,16 +79,6 @@ class PRINTING_EXPORT PrintingContextWin // The dialog box for the time it is shown. volatile HWND dialog_box_; - // Function pointer that defaults to PrintDlgEx. It can be changed using - // SetPrintDialog() in tests. - HRESULT (__stdcall *print_dialog_func_)(LPPRINTDLGEX); - - // Where to notify when the dialog is closed. - PrintSettingsCallback callback_; - - // Wrapper around native print dialog that runs it on a background thread. - scoped_refptr<ui::PrintSettingsDialogWin> print_settings_dialog_; - DISALLOW_COPY_AND_ASSIGN(PrintingContextWin); }; diff --git a/chromium/printing/printing_context_win_unittest.cc b/chromium/printing/printing_context_win_unittest.cc index 94f8e838552..c9facc9c0b8 100644 --- a/chromium/printing/printing_context_win_unittest.cc +++ b/chromium/printing/printing_context_win_unittest.cc @@ -10,148 +10,157 @@ #include "base/bind.h" #include "base/bind_helpers.h" #include "base/memory/scoped_ptr.h" -#include "base/run_loop.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/print_settings.h" #include "testing/gtest/include/gtest/gtest.h" +namespace printing { + // This test is automatically disabled if no printer is available. class PrintingContextTest : public PrintingTest<testing::Test> { public: - void PrintSettingsCallback(printing::PrintingContext::Result result) { + void PrintSettingsCallback(PrintingContext::Result result) { result_ = result; - base::MessageLoop::current()->QuitWhenIdle(); } protected: - printing::PrintingContext::Result result() const { return result_; } + PrintingContext::Result result() const { return result_; } private: - printing::PrintingContext::Result result_; + PrintingContext::Result result_; }; -// This is a fake PrintDlgEx implementation that sets the right fields in -// |lppd| to trigger a bug in older revisions of PrintingContext. -HRESULT WINAPI PrintDlgExMock(LPPRINTDLGEX lppd) { - // 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; - - // Painful paperwork. - std::wstring printer_name = PrintingContextTest::GetDefaultPrinter(); - HANDLE printer; - if (!OpenPrinter(const_cast<wchar_t*>(printer_name.c_str()), &printer, NULL)) - 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; - - printing::PrinterInfo2 info_2; - if (info_2.Init(printer)) { - dev_mode = info_2.get()->pDevMode; - } - if (!dev_mode) { - result = E_FAIL; - goto Cleanup; - } +class MockPrintingContextWin : public PrintingContextWin { + public: + MockPrintingContextWin() : PrintingContextWin("") {} - if (!printing::PrintingContextWin::AllocateContext(printer_name, dev_mode, - &lppd->hDC)) { - result = E_FAIL; - goto Cleanup; - } + 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; + } - 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 (!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; } - if (lppd->hDevMode) { - GlobalFree(lppd->hDevMode); + 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; } - if (lppd->hDevNames) { - GlobalFree(lppd->hDevNames); + 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; } - ClosePrinter(printer); - return result; -} +}; TEST_F(PrintingContextTest, Base) { if (IsTestCaseDisabled()) return; - printing::PrintSettings settings; + PrintSettings settings; settings.set_device_name(GetDefaultPrinter()); // Initialize it. - scoped_ptr<printing::PrintingContext> context( - printing::PrintingContext::Create(std::string())); - EXPECT_EQ(printing::PrintingContext::OK, context->InitWithSettings(settings)); + scoped_ptr<PrintingContext> context(PrintingContext::Create(std::string())); + EXPECT_EQ(PrintingContext::OK, context->InitWithSettings(settings)); // The print may lie to use and may not support world transformation. // Verify right now. @@ -161,19 +170,17 @@ TEST_F(PrintingContextTest, Base) { } TEST_F(PrintingContextTest, PrintAll) { - base::MessageLoopForUI loop; + base::MessageLoop message_loop; if (IsTestCaseDisabled()) return; - std::string dummy_locale; - printing::PrintingContextWin context(dummy_locale); - context.SetPrintDialog(&PrintDlgExMock); + MockPrintingContextWin context; context.AskUserForSettings( NULL, 123, false, base::Bind(&PrintingContextTest::PrintSettingsCallback, base::Unretained(this))); - base::RunLoop().Run(); - EXPECT_EQ(printing::PrintingContext::OK, result()); - - printing::PrintSettings settings = context.settings(); + EXPECT_EQ(PrintingContext::OK, result()); + PrintSettings settings = context.settings(); EXPECT_EQ(settings.ranges().size(), 0); } + +} // namespace printing diff --git a/chromium/printing/printing_utils_unittest.cc b/chromium/printing/printing_utils_unittest.cc index 24a380d4436..be66fab83c8 100644 --- a/chromium/printing/printing_utils_unittest.cc +++ b/chromium/printing/printing_utils_unittest.cc @@ -9,7 +9,7 @@ namespace printing { std::string Simplify(const char* title) { - return UTF16ToUTF8(SimplifyDocumentTitle(ASCIIToUTF16(title))); + return base::UTF16ToUTF8(SimplifyDocumentTitle(base::ASCIIToUTF16(title))); } TEST(PrintingUtilsTest, SimplifyDocumentTitle) { diff --git a/chromium/printing/pwg_raster_settings.h b/chromium/printing/pwg_raster_settings.h new file mode 100644 index 00000000000..dc87b93738a --- /dev/null +++ b/chromium/printing/pwg_raster_settings.h @@ -0,0 +1,33 @@ +// Copyright 2014 The Chromium Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +#ifndef PRINTING_BITMAP_TRANSFORM_SETTINGS_H_ +#define PRINTING_BITMAP_TRANSFORM_SETTINGS_H_ + +#include "base/tuple.h" +#include "ipc/ipc_param_traits.h" +#include "printing/printing_export.h" +#include "ui/gfx/rect.h" + +namespace printing { + +enum PwgRasterTransformType { + TRANSFORM_NORMAL, + TRANSFORM_ROTATE_180, + TRANSFORM_FLIP_HORIZONTAL, + TRANSFORM_FLIP_VERTICAL +}; + +struct PwgRasterSettings { + // How to transform odd-numbered pages. + PwgRasterTransformType odd_page_transform; + // Rotate all pages (on top of odd-numbered page transform). + bool rotate_all_pages; + // Rasterize pages in reverse order. + bool reverse_page_order; +}; + +} // namespace printing + +#endif // PRINTING_BITMAP_TRANSFORM_SETTINGS_H_ |