Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1048)

Unified Diff: chrome/browser/ui/webui/print_preview_handler.cc

Issue 8245012: Revert 105087 - PrintPreview: Fix printer color settings issues based on printer ppd/schema infor... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: Created 9 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
Index: chrome/browser/ui/webui/print_preview_handler.cc
===================================================================
--- chrome/browser/ui/webui/print_preview_handler.cc (revision 105094)
+++ chrome/browser/ui/webui/print_preview_handler.cc (working copy)
@@ -17,6 +17,8 @@
#include "base/memory/ref_counted.h"
#include "base/metrics/histogram.h"
#include "base/path_service.h"
+#include "base/string_split.h"
+#include "base/string_util.h"
#include "base/threading/thread.h"
#include "base/threading/thread_restrictions.h"
#include "base/utf_string_conversions.h"
@@ -28,7 +30,6 @@
#include "chrome/browser/printing/print_dialog_cloud.h"
#include "chrome/browser/printing/print_job_manager.h"
#include "chrome/browser/printing/print_preview_tab_controller.h"
-#include "chrome/browser/printing/print_system_task_proxy.h"
#include "chrome/browser/printing/print_view_manager.h"
#include "chrome/browser/printing/printer_manager_dialog.h"
#include "chrome/browser/sessions/restore_tab_helper.h"
@@ -46,15 +47,125 @@
#include "printing/metafile.h"
#include "printing/metafile_impl.h"
#include "printing/page_range.h"
-#include "printing/print_settings.h"
+#include "printing/print_job_constants.h"
+#if defined(USE_CUPS)
+#include <cups/cups.h>
+#include <cups/ppd.h>
+
+#include "base/file_util.h"
+#endif
+
#if !defined(OS_CHROMEOS)
#include "base/command_line.h"
#include "chrome/common/chrome_switches.h"
#endif
+#if defined(USE_CUPS) && !defined(OS_MACOSX)
+namespace printing_internal {
+
+void parse_lpoptions(const FilePath& filepath, const std::string& printer_name,
+ int* num_options, cups_option_t** options) {
+ std::string content;
+ if (!file_util::ReadFileToString(filepath, &content))
+ return;
+
+ const char kDest[] = "dest";
+ const char kDefault[] = "default";
+ size_t kDestLen = sizeof(kDest) - 1;
+ size_t kDefaultLen = sizeof(kDefault) - 1;
+ std::vector <std::string> lines;
+ base::SplitString(content, '\n', &lines);
+
+ for (size_t i = 0; i < lines.size(); ++i) {
+ std::string line = lines[i];
+ if (line.empty())
+ continue;
+
+ if (base::strncasecmp (line.c_str(), kDefault, kDefaultLen) == 0 &&
+ isspace(line[kDefaultLen])) {
+ line = line.substr(kDefaultLen);
+ } else if (base::strncasecmp (line.c_str(), kDest, kDestLen) == 0 &&
+ isspace(line[kDestLen])) {
+ line = line.substr(kDestLen);
+ } else {
+ continue;
+ }
+
+ TrimWhitespaceASCII(line, TRIM_ALL, &line);
+ if (line.empty())
+ continue;
+
+ size_t space_found = line.find(' ');
+ if (space_found == std::string::npos)
+ continue;
+
+ std::string name = line.substr(0, space_found);
+ if (name.empty())
+ continue;
+
+ if (base::strncasecmp(printer_name.c_str(), name.c_str(),
+ name.length()) != 0) {
+ continue; // This is not the required printer.
+ }
+
+ line = line.substr(space_found + 1);
+ TrimWhitespaceASCII(line, TRIM_ALL, &line); // Remove extra spaces.
+ if (line.empty())
+ continue;
+ // Parse the selected printer custom options.
+ *num_options = cupsParseOptions(line.c_str(), 0, options);
+ }
+}
+
+void mark_lpoptions(const std::string& printer_name, ppd_file_t** ppd) {
+ cups_option_t* options = NULL;
+ int num_options = 0;
+ ppdMarkDefaults(*ppd);
+
+ const char kSystemLpOptionPath[] = "/etc/cups/lpoptions";
+ const char kUserLpOptionPath[] = ".cups/lpoptions";
+
+ std::vector<FilePath> file_locations;
+ file_locations.push_back(FilePath(kSystemLpOptionPath));
+ file_locations.push_back(file_util::GetHomeDir().Append(kUserLpOptionPath));
+
+ for (std::vector<FilePath>::const_iterator it = file_locations.begin();
+ it != file_locations.end(); ++it) {
+ num_options = 0;
+ options = NULL;
+ parse_lpoptions(*it, printer_name, &num_options, &options);
+ if (num_options > 0 && options) {
+ cupsMarkOptions(*ppd, num_options, options);
+ cupsFreeOptions(num_options, options);
+ }
+ }
+}
+
+} // printing_internal namespace
+#endif
+
namespace {
+const char kDisableColorOption[] = "disableColorOption";
+const char kSetColorAsDefault[] = "setColorAsDefault";
+const char kSetDuplexAsDefault[] = "setDuplexAsDefault";
+const char kPrinterColorModelForColor[] = "printerColorModelForColor";
+const char kPrinterDefaultDuplexValue[] = "printerDefaultDuplexValue";
+
+#if defined(USE_CUPS)
+const char kColorDevice[] = "ColorDevice";
+const char kColorModel[] = "ColorModel";
+const char kColorModelForColor[] = "Color";
+const char kCMYK[] = "CMYK";
+const char kDuplex[] = "Duplex";
+const char kDuplexNone[] = "None";
+#elif defined(OS_WIN)
+const char kPskColor[] = "psk:Color";
+const char kPskDuplexFeature[] = "psk:JobDuplexAllDocumentsContiguously";
+const char kPskTwoSided[] = "psk:TwoSided";
+#endif
+
enum UserActionBuckets {
PRINT_TO_PRINTER,
PRINT_TO_PDF,
@@ -152,8 +263,8 @@
int color_mode;
if (settings.GetInteger(printing::kSettingColor, &color_mode)) {
- ReportPrintSettingHistogram(
- printing::isColorModelSelected(color_mode) ? COLOR : BLACK_AND_WHITE);
+ ReportPrintSettingHistogram(color_mode == printing::GRAY ? BLACK_AND_WHITE :
+ COLOR);
}
}
@@ -163,6 +274,229 @@
} // namespace
+class PrintSystemTaskProxy
+ : public base::RefCountedThreadSafe<PrintSystemTaskProxy,
+ BrowserThread::DeleteOnUIThread> {
+ public:
+ PrintSystemTaskProxy(const base::WeakPtr<PrintPreviewHandler>& handler,
+ printing::PrintBackend* print_backend,
+ bool has_logged_printers_count)
+ : handler_(handler),
+ print_backend_(print_backend),
+ has_logged_printers_count_(has_logged_printers_count) {
+ }
+
+ void GetDefaultPrinter() {
+ VLOG(1) << "Get default printer start";
+ StringValue* default_printer = NULL;
+ if (PrintPreviewHandler::last_used_printer_name_ == NULL) {
+ default_printer = new StringValue(
+ print_backend_->GetDefaultPrinterName());
+ } else {
+ default_printer = new StringValue(
+ *PrintPreviewHandler::last_used_printer_name_);
+ }
+ std::string default_printer_string;
+ default_printer->GetAsString(&default_printer_string);
+ VLOG(1) << "Get default printer finished, found: "
+ << default_printer_string;
+
+ StringValue* cloud_print_data = NULL;
+ if (PrintPreviewHandler::last_used_printer_cloud_print_data_ != NULL) {
+ cloud_print_data = new StringValue(
+ *PrintPreviewHandler::last_used_printer_cloud_print_data_);
+ } else {
+ cloud_print_data = new StringValue("");
+ }
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&PrintSystemTaskProxy::SendDefaultPrinter, this,
+ default_printer, cloud_print_data));
+ }
+
+ void SendDefaultPrinter(const StringValue* default_printer,
+ const StringValue* cloud_print_data) {
+ if (handler_)
+ handler_->SendDefaultPrinter(*default_printer, *cloud_print_data);
+ delete default_printer;
+ }
+
+ void EnumeratePrinters() {
+ VLOG(1) << "Enumerate printers start";
+ ListValue* printers = new ListValue;
+
+ printing::PrinterList printer_list;
+ print_backend_->EnumeratePrinters(&printer_list);
+
+ if (!has_logged_printers_count_) {
+ // Record the total number of printers.
+ UMA_HISTOGRAM_COUNTS("PrintPreview.NumberOfPrinters",
+ printer_list.size());
+ }
+
+ int i = 0;
+ for (printing::PrinterList::iterator iter = printer_list.begin();
+ iter != printer_list.end(); ++iter, ++i) {
+ DictionaryValue* printer_info = new DictionaryValue;
+ std::string printerName;
+ #if defined(OS_MACOSX)
+ // On Mac, |iter->printer_description| specifies the printer name and
+ // |iter->printer_name| specifies the device name / printer queue name.
+ printerName = iter->printer_description;
+ #else
+ printerName = iter->printer_name;
+ #endif
+ printer_info->SetString(printing::kSettingPrinterName, printerName);
+ printer_info->SetString(printing::kSettingDeviceName, iter->printer_name);
+ printers->Append(printer_info);
+ }
+ VLOG(1) << "Enumerate printers finished, found " << i << " printers";
+
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&PrintSystemTaskProxy::SetupPrinterList, this, printers));
+ }
+
+ void SetupPrinterList(ListValue* printers) {
+ if (handler_) {
+ handler_->SetupPrinterList(*printers);
+ }
+ delete printers;
+ }
+
+ void GetPrinterCapabilities(const std::string& printer_name) {
+ VLOG(1) << "Get printer capabilities start for " << printer_name;
+ printing::PrinterCapsAndDefaults printer_info;
+ bool supports_color = true;
+ bool set_duplex_as_default = false;
+ int printer_color_space = printing::GRAY;
+ int default_duplex_setting_value = printing::UNKNOWN_DUPLEX_MODE;
+ if (!print_backend_->GetPrinterCapsAndDefaults(printer_name,
+ &printer_info)) {
+ return;
+ }
+
+#if defined(USE_CUPS)
+ FilePath ppd_file_path;
+ if (!file_util::CreateTemporaryFile(&ppd_file_path))
+ return;
+
+ int data_size = printer_info.printer_capabilities.length();
+ if (data_size != file_util::WriteFile(
+ ppd_file_path,
+ printer_info.printer_capabilities.data(),
+ data_size)) {
+ file_util::Delete(ppd_file_path, false);
+ return;
+ }
+
+ ppd_file_t* ppd = ppdOpenFile(ppd_file_path.value().c_str());
+ if (ppd) {
+#if !defined(OS_MACOSX)
+ printing_internal::mark_lpoptions(printer_name, &ppd);
+#endif
+ ppd_attr_t* attr = ppdFindAttr(ppd, kColorDevice, NULL);
+ if (attr && attr->value)
+ supports_color = ppd->color_device;
+
+ ppd_choice_t* duplex_choice = ppdFindMarkedChoice(ppd, kDuplex);
+ if (duplex_choice) {
+ ppd_option_t* option = ppdFindOption(ppd, kDuplex);
+ if (option)
+ duplex_choice = ppdFindChoice(option, option->defchoice);
+ }
+
+ if (duplex_choice) {
+ if (base::strcasecmp(duplex_choice->choice, kDuplexNone) != 0) {
+ set_duplex_as_default = true;
+ default_duplex_setting_value = printing::LONG_EDGE;
+ } else {
+ default_duplex_setting_value = printing::SIMPLEX;
+ }
+ }
+
+ if (supports_color) {
+ // Identify the color space (COLOR/CMYK) for this printer.
+ ppd_option_t* color_model = ppdFindOption(ppd, kColorModel);
+ if (color_model) {
+ if (ppdFindChoice(color_model, kColorModelForColor))
+ printer_color_space = printing::COLOR;
+ else if (ppdFindChoice(color_model, kCMYK))
+ printer_color_space = printing::CMYK;
+ }
+ }
+ ppdClose(ppd);
+ }
+ file_util::Delete(ppd_file_path, false);
+#elif defined(OS_WIN)
+ // According to XPS 1.0 spec, only color printers have psk:Color.
+ // Therefore we don't need to parse the whole XML file, we just need to
+ // search the string. The spec can be found at:
+ // http://msdn.microsoft.com/en-us/windows/hardware/gg463431.
+ supports_color = (printer_info.printer_capabilities.find(kPskColor) !=
+ std::string::npos);
+ if (supports_color)
+ printer_color_space = printing::COLOR;
+
+ set_duplex_as_default =
+ (printer_info.printer_defaults.find(kPskDuplexFeature) !=
+ std::string::npos) &&
+ (printer_info.printer_defaults.find(kPskTwoSided) !=
+ std::string::npos);
+
+ if (printer_info.printer_defaults.find(kPskDuplexFeature) !=
+ std::string::npos) {
+ if (printer_info.printer_defaults.find(kPskTwoSided) !=
+ std::string::npos) {
+ default_duplex_setting_value = printing::LONG_EDGE;
+ } else {
+ default_duplex_setting_value = printing::SIMPLEX;
+ }
+ }
+#else
+ NOTIMPLEMENTED();
+#endif
+
+ DictionaryValue settings_info;
+ settings_info.SetBoolean(kDisableColorOption, !supports_color);
+ if (!supports_color) {
+ settings_info.SetBoolean(kSetColorAsDefault, false);
+ } else {
+ settings_info.SetBoolean(kSetColorAsDefault,
+ PrintPreviewHandler::last_used_color_setting_);
+ }
+ settings_info.SetBoolean(kSetDuplexAsDefault, set_duplex_as_default);
+ settings_info.SetInteger(kPrinterColorModelForColor, printer_color_space);
+ settings_info.SetInteger(kPrinterDefaultDuplexValue,
+ default_duplex_setting_value);
+ BrowserThread::PostTask(
+ BrowserThread::UI, FROM_HERE,
+ base::Bind(&PrintSystemTaskProxy::SendPrinterCapabilities, this,
+ settings_info.DeepCopy()));
+ }
+
+ void SendPrinterCapabilities(DictionaryValue* settings_info) {
+ if (handler_)
+ handler_->SendPrinterCapabilities(*settings_info);
+ delete settings_info;
+ }
+
+ private:
+ friend struct BrowserThread::DeleteOnThread<BrowserThread::UI>;
+ friend class DeleteTask<PrintSystemTaskProxy>;
+
+ ~PrintSystemTaskProxy() {}
+
+ base::WeakPtr<PrintPreviewHandler> handler_;
+
+ scoped_refptr<printing::PrintBackend> print_backend_;
+
+ bool has_logged_printers_count_;
+
+ DISALLOW_COPY_AND_ASSIGN(PrintSystemTaskProxy);
+};
+
// A Task implementation that stores a PDF file on disk.
class PrintToPdfTask : public Task {
public:
@@ -195,8 +529,7 @@
FilePath* PrintPreviewHandler::last_saved_path_ = NULL;
std::string* PrintPreviewHandler::last_used_printer_cloud_print_data_ = NULL;
std::string* PrintPreviewHandler::last_used_printer_name_ = NULL;
-printing::ColorModels PrintPreviewHandler::last_used_color_model_ =
- printing::UNKNOWN_COLOR_MODEL;
+bool PrintPreviewHandler::last_used_color_setting_ = false;
PrintPreviewHandler::PrintPreviewHandler()
: print_backend_(printing::PrintBackend::CreateInstance(NULL)),
@@ -377,11 +710,11 @@
if (!settings.get())
return;
- // Storing last used color model.
- int color_model;
- if (!settings->GetInteger(printing::kSettingColor, &color_model))
- color_model = printing::GRAY;
- last_used_color_model_ = static_cast<printing::ColorModels>(color_model);
+ // Storing last used color setting.
+ int color_mode;
+ if (!settings->GetInteger(printing::kSettingColor, &color_mode))
+ color_mode = printing::GRAY;
+ last_used_color_setting_ = (color_mode != printing::GRAY);
bool print_to_pdf = false;
settings->GetBoolean(printing::kSettingPrintToPDF, &print_to_pdf);
« no previous file with comments | « chrome/browser/ui/webui/print_preview_handler.h ('k') | chrome/browser/ui/webui/print_preview_handler_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698