Reland 100233 PrintPreview: Added code to identify the printer default duplex value.

Added code to identify the printer default duplex value. If we are
unable to get the default value, hide the two sided option in the preview tab.

BUG=89204
TEST=Please refer to bug description.

Original Commit: http://src.chromium.org/viewvc/chrome?view=rev&revision=100233
Try bot results are in http://codereview.chromium.org/7817013/ patch set 13.
Original Review URL: http://codereview.chromium.org/7817013/

Review URL: http://codereview.chromium.org/7859007

git-svn-id: svn://svn.chromium.org/chrome/trunk/src@100256 0039d316-1c4b-4281-b951-d872f2087c98
diff --git a/chrome/browser/printing/print_dialog_gtk.cc b/chrome/browser/printing/print_dialog_gtk.cc
index 4c3bb82..ccdd07b7 100644
--- a/chrome/browser/printing/print_dialog_gtk.cc
+++ b/chrome/browser/printing/print_dialog_gtk.cc
@@ -200,19 +200,24 @@
     }
     gtk_print_settings_set(gtk_settings_, kCUPSColorModel, color_mode);
 
-    const char* cups_duplex_mode;
-    switch (duplex_mode) {
-      case printing::LONG_EDGE:
-        cups_duplex_mode = kDuplexNoTumble;
-        break;
-      case printing::SHORT_EDGE:
-        cups_duplex_mode = kDuplexTumble;
-        break;
-      default:
-        cups_duplex_mode = kDuplexNone;
-        break;
+    if (duplex_mode != printing::UNKNOWN_DUPLEX_MODE) {
+      const char* cups_duplex_mode = NULL;
+      switch (duplex_mode) {
+        case printing::LONG_EDGE:
+          cups_duplex_mode = kDuplexNoTumble;
+          break;
+        case printing::SHORT_EDGE:
+          cups_duplex_mode = kDuplexTumble;
+          break;
+        case printing::SIMPLEX:
+          cups_duplex_mode = kDuplexNone;
+          break;
+        default:  // UNKNOWN_DUPLEX_MODE
+          NOTREACHED();
+          break;
+      }
+      gtk_print_settings_set(gtk_settings_, kCUPSDuplex, cups_duplex_mode);
     }
-    gtk_print_settings_set(gtk_settings_, kCUPSDuplex, cups_duplex_mode);
   }
 
   gtk_print_settings_set_orientation(
diff --git a/chrome/browser/resources/print_preview/copies_settings.js b/chrome/browser/resources/print_preview/copies_settings.js
index 3c48e45..0abba44 100644
--- a/chrome/browser/resources/print_preview/copies_settings.js
+++ b/chrome/browser/resources/print_preview/copies_settings.js
@@ -22,6 +22,13 @@
     this.collateCheckbox_ = $('collate');
     this.hint_ = $('copies-hint');
     this.twoSidedCheckbox_ = $('two-sided');
+    this.twoSidedOption_ = $('two-sided-div');
+
+    // Constant values matches printing::DuplexMode enum. Not using const
+    // keyword because it is not allowed by JS strict mode.
+    this.SIMPLEX = 0;
+    this.LONG_EDGE = 1;
+    this.UNKNOWN_DUPLEX_MODE = -1;
   }
 
   cr.addSingletonGetter(CopiesSettings);
@@ -56,15 +63,16 @@
     },
 
     /**
-     * Gets the duplex mode for printing.
+     * Gets the duplex mode information for printing.
      * @return {number} duplex mode.
      */
-     get duplexMode() {
-      // Constant values matches printing::DuplexMode enum. Not using const
-      // keyword because it is not allowed by JS strict mode.
-      var SIMPLEX = 0;
-      var LONG_EDGE = 1;
-      return !this.twoSidedCheckbox_.checked ? SIMPLEX : LONG_EDGE;
+    get duplexMode() {
+      if (this.twoSidedOption_.hidden)
+        return this.UNKNOWN_DUPLEX_MODE;
+      else if (this.twoSidedCheckbox_.checked)
+        return this.LONG_EDGE;
+      else
+        return this.SIMPLEX;
     },
 
     /**
@@ -158,7 +166,8 @@
         fadeInElement(this.copiesOption_);
         $('hr-before-copies').classList.add('invisible');
       }
-      this.twoSidedCheckbox_.checked = e.printerCapabilities.setDuplexAsDefault;
+      this.updateTwoSidedOption_(
+          e.printerCapabilities.printerDefaultDuplexValue);
     },
 
     /**
@@ -190,6 +199,25 @@
                                        this.collateOption_.hidden);
     },
 
+    /*
+     * Takes care of showing/hiding the two sided option and also updates the
+     * default state of the checkbox.
+     * @param {number} defaultDuplexValue Specifies the default duplex value.
+     * @private
+     */
+     updateTwoSidedOption_: function(defaultDuplexValue) {
+      // On Windows, some printers don't specify their duplex values in the
+      // printer schema. If the printer duplex value is UNKNOWN_DUPLEX_MODE,
+      // hide the two sided option in preview tab UI.
+      // Ref bug: http://crbug.com/89204
+      this.twoSidedOption_.hidden =
+          (defaultDuplexValue == this.UNKNOWN_DUPLEX_MODE);
+      this.twoSidedOption_.setAttribute('aria-hidden',
+                                        this.twoSidedOption_.hidden);
+      if (!this.twoSidedOption_.hidden)
+        this.twoSidedCheckbox_.checked = !!defaultDuplexValue;
+     },
+
     /**
      * Updates the state of the increment/decrement buttons based on the current
      * |textfield_| value.
diff --git a/chrome/browser/resources/print_preview/print_preview.js b/chrome/browser/resources/print_preview/print_preview.js
index b73f6b9..9e750388 100644
--- a/chrome/browser/resources/print_preview/print_preview.js
+++ b/chrome/browser/resources/print_preview/print_preview.js
@@ -239,6 +239,7 @@
         'setColorAsDefault': true,
         'setDuplexAsDefault': false,
         'printerColorModelForColor': colorSettings.COLOR,
+        'printerDefaultDuplexValue': copiesSettings.UNKNOWN_DUPLEX_MODE,
         'disableCopiesOption': true});
   } else {
     // This message will call back to 'updateWithPrinterCapabilities'
diff --git a/chrome/browser/ui/webui/print_preview_handler.cc b/chrome/browser/ui/webui/print_preview_handler.cc
index 9d233c4..3df0e3f 100644
--- a/chrome/browser/ui/webui/print_preview_handler.cc
+++ b/chrome/browser/ui/webui/print_preview_handler.cc
@@ -59,6 +59,7 @@
 const char kSetColorAsDefault[] = "setColorAsDefault";
 const char kSetDuplexAsDefault[] = "setDuplexAsDefault";
 const char kPrinterColorModelForColor[] = "printerColorModelForColor";
+const char kPrinterDefaultDuplexValue[] = "printerDefaultDuplexValue";
 
 #if defined(USE_CUPS)
 const char kColorDevice[] = "ColorDevice";
@@ -281,6 +282,7 @@
     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;
@@ -306,16 +308,24 @@
       if (attr && attr->value)
         supports_color = ppd->color_device;
 
-      ppd_choice_t* ch = ppdFindMarkedChoice(ppd, kDuplex);
-      if (ch == NULL) {
+      ppd_choice_t* duplex_choice = ppdFindMarkedChoice(ppd, kDuplex);
+      if (duplex_choice == NULL) {
         ppd_option_t* option = ppdFindOption(ppd, kDuplex);
         if (option != NULL)
-          ch = ppdFindChoice(option, option->defchoice);
+          duplex_choice = ppdFindChoice(option, option->defchoice);
       }
 
-      if (ch != NULL && strcmp(ch->choice, kDuplexNone) != 0)
+      if (duplex_choice != NULL &&
+          strcmp(duplex_choice->choice, kDuplexNone) != 0)
         set_duplex_as_default = true;
 
+      if (duplex_choice != NULL) {
+        if (strcmp(duplex_choice->choice, kDuplexNone) != 0)
+          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);
@@ -326,7 +336,6 @@
             printer_color_space = printing::CMYK;
         }
       }
-
       ppdClose(ppd);
     }
     file_util::Delete(ppd_file_path, false);
@@ -345,6 +354,16 @@
             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
@@ -359,6 +378,8 @@
     }
     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,
         NewRunnableMethod(this,
diff --git a/chrome/test/data/webui/print_preview.js b/chrome/test/data/webui/print_preview.js
index dacefd0..09bec48e 100644
--- a/chrome/test/data/webui/print_preview.js
+++ b/chrome/test/data/webui/print_preview.js
@@ -68,6 +68,7 @@
             disableColorOption: true,
             setColorAsDefault: true,
             disableCopiesOption: true,
+            printerDefaultDuplexValue: copiesSettings.SIMPLEX,
           });
         }));
     var savedArgs = new SaveMockArguments();
@@ -298,6 +299,7 @@
           setColorAsDefault: true,
           disableCopiesOption: true,
           disableLandscapeOption: true,
+          printerDefaultDuplexValue: copiesSettings.SIMPLEX,
         });
       }));
 
@@ -317,6 +319,7 @@
           setColorAsDefault: true,
           disableCopiesOption: false,
           disableLandscapeOption: false,
+          printerDefaultDuplexValue: copiesSettings.SIMPLEX,
         });
       }));
 
@@ -331,6 +334,7 @@
           setColorAsDefault: false,
           disableCopiesOption: false,
           disableLandscapeOption: false,
+          printerDefaultDuplexValue: copiesSettings.SIMPLEX,
         });
       }));
 
@@ -339,6 +343,56 @@
   expectTrue(colorSettings.bwRadioButton.checked);
 });
 
+// Test to verify that duplex settings are set according to the printer
+// capabilities.
+TEST_F('PrintPreviewWebUITest', 'TestDuplexSettings', function() {
+  this.mockHandler.expects(once()).getPrinterCapabilities('FooDevice').
+      will(callFunction(function() {
+        updateWithPrinterCapabilities({
+          disableColorOption: false,
+          setColorAsDefault: false,
+          disableCopiesOption: false,
+          disableLandscapeOption: false,
+          printerDefaultDuplexValue: copiesSettings.SIMPLEX,
+        });
+      }));
+  updateControlsWithSelectedPrinterCapabilities();
+  expectEquals(copiesSettings.duplexMode, copiesSettings.SIMPLEX);
+  expectEquals(copiesSettings.twoSidedOption_.hidden, false);
+
+  // If the printer default duplex value is UNKNOWN_DUPLEX_MODE, hide the
+  // two sided option.
+  this.mockHandler.expects(once()).getPrinterCapabilities('FooDevice').
+      will(callFunction(function() {
+        updateWithPrinterCapabilities({
+          disableColorOption: false,
+          setColorAsDefault: false,
+          disableCopiesOption: false,
+          disableLandscapeOption: false,
+          printerDefaultDuplexValue: copiesSettings.UNKNOWN_DUPLEX_MODE,
+        });
+      }));
+  updateControlsWithSelectedPrinterCapabilities();
+  expectEquals(copiesSettings.duplexMode, copiesSettings.UNKNOWN_DUPLEX_MODE);
+  expectEquals(copiesSettings.twoSidedOption_.hidden, true);
+
+  this.mockHandler.expects(once()).getPrinterCapabilities('FooDevice').
+      will(callFunction(function() {
+        updateWithPrinterCapabilities({
+          disableColorOption: false,
+          setColorAsDefault: false,
+          disableCopiesOption: false,
+          disableLandscapeOption: false,
+          printerDefaultDuplexValue: copiesSettings.SIMPLEX,
+        });
+      }));
+  updateControlsWithSelectedPrinterCapabilities();
+  expectEquals(copiesSettings.twoSidedOption_.hidden, false);
+  expectEquals(copiesSettings.duplexMode, copiesSettings.SIMPLEX);
+  copiesSettings.twoSidedCheckbox.checked = true;
+  expectEquals(copiesSettings.duplexMode, copiesSettings.LONG_EDGE);
+});
+
 // Test that changing the selected printer updates the preview.
 TEST_F('PrintPreviewWebUITest', 'TestPrinterChangeUpdatesPreview', function() {
   var savedArgs = new SaveMockArguments();
diff --git a/printing/print_job_constants.h b/printing/print_job_constants.h
index 99b2892..ebd63c2 100644
--- a/printing/print_job_constants.h
+++ b/printing/print_job_constants.h
@@ -49,6 +49,7 @@
 
 // Print job duplex mode values.
 enum DuplexMode {
+  UNKNOWN_DUPLEX_MODE = -1,
   SIMPLEX,
   LONG_EDGE,
   SHORT_EDGE,
diff --git a/printing/printing_context_mac.mm b/printing/printing_context_mac.mm
index 8ba4db81..3534496 100644
--- a/printing/printing_context_mac.mm
+++ b/printing/printing_context_mac.mm
@@ -236,9 +236,11 @@
     case SHORT_EDGE:
       duplexSetting = kPMDuplexTumble;
       break;
-    default:
+    case SIMPLEX:
       duplexSetting = kPMDuplexNone;
       break;
+    default:  // UNKNOWN_DUPLEX_MODE
+      return true;
   }
 
   PMPrintSettings pmPrintSettings =
diff --git a/printing/printing_context_win.cc b/printing/printing_context_win.cc
index a098a66..c467457 100644
--- a/printing/printing_context_win.cc
+++ b/printing/printing_context_win.cc
@@ -383,9 +383,11 @@
     case SHORT_EDGE:
       dev_mode->dmDuplex = DMDUP_HORIZONTAL;
       break;
-    default:  // simplex
+    case SIMPLEX:
       dev_mode->dmDuplex = DMDUP_SIMPLEX;
       break;
+    default:  // UNKNOWN_DUPLEX_MODE
+      break;
   }
   dev_mode->dmOrientation = landscape ? DMORIENT_LANDSCAPE : DMORIENT_PORTRAIT;