Headless printing: refactor print template to allow header/footer customization.

This change enables remote users to define and style printing headers and footers.
Proposed API exposes following element classes:
  'date', 'title', 'url', 'pageNumber', 'totalPages'
...that can be used to tag template elements. Printing subsystem will substitute text
content of these elements with the actual values.

Header and footer templates will be provided over the remote debugging protocol and
injected into the preview later.

Change-Id: Ia3d1737d532b7f951007a0260c4936fcac0276fc
Reviewed-on: https://chromium-review.googlesource.com/813177
Commit-Queue: Pavel Feldman <pfeldman@chromium.org>
Reviewed-by: Demetrios Papadopoulos <dpapad@chromium.org>
Cr-Commit-Position: refs/heads/master@{#523674}
diff --git a/components/printing/renderer/print_render_frame_helper.cc b/components/printing/renderer/print_render_frame_helper.cc
index 663cd77..76bf7cf 100644
--- a/components/printing/renderer/print_render_frame_helper.cc
+++ b/components/printing/renderer/print_render_frame_helper.cc
@@ -618,9 +618,8 @@
   options->SetDouble("height", page_size.height);
   options->SetDouble("topMargin", page_layout.margin_top);
   options->SetDouble("bottomMargin", page_layout.margin_bottom);
-  options->SetString("pageNumber",
-                     base::StringPrintf("%d/%d", page_number, total_pages));
-
+  options->SetInteger("pageNumber", page_number);
+  options->SetInteger("totalPages", total_pages);
   options->SetString("url", params.url);
   base::string16 title = source_frame.GetDocument().Title().Utf16();
   options->SetString("title", title.empty() ? params.title : title);
diff --git a/components/printing/resources/print_preview_page.html b/components/printing/resources/print_preview_page.html
index 4ea37f5..a7fe785 100644
--- a/components/printing/resources/print_preview_page.html
+++ b/components/printing/resources/print_preview_page.html
@@ -3,115 +3,91 @@
 <link rel="stylesheet" href="chrome://resources/css/text_defaults.css">
 <style>
   body {
-    margin: 0px;
-    width: 0px;
+    margin: 0;
+    display: flex;
+    flex-direction: column;
   }
-  .row {
-    display: table-row;
-    vertical-align: inherit;
-  }
+
   #header, #footer {
-    display: table;
-    table-layout:fixed;
-    width: inherit;
+    display: flex;
+    flex: none;
   }
+
   #header {
-    vertical-align: top;
+    align-items: flex-start;
+    padding-top: 0.4cm;
   }
+
   #footer {
-    vertical-align: bottom;
+    align-items: flex-end;
+    padding-bottom: 0.4cm;
   }
-  .text {
-    display: table-cell;
-    font-size: 8px;
-    vertical-align: inherit;
-    white-space: nowrap;
+
+  #content {
+    flex: auto;
   }
-  #page_number {
-    text-align: right;
-  }
-  #title {
-    text-align: center;
-  }
-  #date, #url {
+
+  .left {
+    flex: none;
     padding-left: 0.7cm;
     padding-right: 0.1cm;
   }
-  #title, #page_number {
+
+  .center {
+    flex: auto;
+    padding-left: 0.7cm;
+    padding-right: 0.7cm;
+    text-align: center;
+  }
+
+  .right {
+    flex: none;
+    /* historically does not account for RTL */
     padding-left: 0.1cm;
     padding-right: 0.7cm;
   }
-  #title, #url {
+
+  .text {
+    font-size: 8px;
     overflow: hidden;
     text-overflow: ellipsis;
-  }
-  #title, #date {
-    padding-bottom: 0cm;
-    padding-top: 0.4cm;
-  }
-  #page_number, #url {
-    padding-bottom: 0.4cm;
-    padding-top: 0cm;
+    white-space: nowrap;
   }
 </style>
 <script>
 
-function pixels(value) {
-  return value + 'px';
-}
-  
 function setup(options) {
-  var body = document.querySelector('body');
-  var header = document.querySelector('#header');
-  var content = document.querySelector('#content');
-  var footer = document.querySelector('#footer');
+  const body = document.querySelector('body');
+  const header = document.querySelector('#header');
+  const footer = document.querySelector('#footer');
 
-  body.style.width = pixels(options['width']);
-  body.style.height = pixels(options['height']);
-  header.style.height = pixels(options['topMargin']);
-  content.style.height = pixels(options['height'] - options['topMargin'] -
-                                options['bottomMargin']);
-  footer.style.height = pixels(options['bottomMargin']);
+  body.style.width = `${options.width}px`;
+  body.style.height = `${options.height}px`;
+  header.style.height = `${options.topMargin}px`;
+  footer.style.height = `${options.bottomMargin}px`;
 
-  document.querySelector('#date span').innerText =
-      new Date(options['date']).toLocaleDateString();
-  document.querySelector('#title span').innerText = options['title'];
+  header.innerHTML = options['headerTemplate'] || `
+    <div class='date text left'></div>
+    <div class='title text center'></div>`;
+  footer.innerHTML = options['footerTemplate'] || `
+    <div class='url text left'></div>
+    <div class='center'></div>
+    <div class='text right'>
+      <span class='pageNumber'></span>/<span class='totalPages'></span>
+    </div>`;
 
-  document.querySelector('#url span').innerText = options['url'];
-  document.querySelector('#page_number span').innerText = options['pageNumber'];
-
-  // Reduce date and page number space to give more space to title and url.
-  document.querySelector('#date').style.width =
-      pixels(document.querySelector('#date span').offsetWidth);
-  document.querySelector('#page_number').style.width =
-      pixels(document.querySelector('#page_number span').offsetWidth);
-
-  // Hide text if it doesn't fit into expected margins.
-  if (header.offsetHeight > options['topMargin'] + 1) {
-    header.style.display = 'none';
-    content.style.height = pixels(options['height'] - options['bottomMargin']);
-  }
-  if (footer.offsetHeight > options['bottomMargin'] + 1) {
-    footer.style.display = 'none';
+  options.date = new Date(options.date).toLocaleDateString();
+  for (const cssClass of ['date', 'title', 'url', 'pageNumber', 'totalPages']) {
+    for (const element of document.querySelectorAll(`.${cssClass}`))
+      element.textContent = options[cssClass];
   }
 }
 
 </script>
 </head>
 <body>
-  <div id="header">
-    <div class="row">
-      <div id="date" class="text"><span/></div>
-      <div id="title" class="text"><span/></div>
-    </div>
-  </div>
-  <div id="content">
-  </div>
-  <div id="footer">
-    <div class="row">
-      <div id="url" class="text"><span/></div>
-      <div id="page_number" class="text"><span/></div>
-    </div>
-  </div>
+  <div id="header"></div>
+  <div id="content"></div>
+  <div id="footer"></div>
 </body>
 </html>