merge in klp-factoryrom-release history after reset to klp-release
diff --git a/chromium/java/com/android/webview/chromium/WebViewChromium.java b/chromium/java/com/android/webview/chromium/WebViewChromium.java
index d6aced6..996c376 100644
--- a/chromium/java/com/android/webview/chromium/WebViewChromium.java
+++ b/chromium/java/com/android/webview/chromium/WebViewChromium.java
@@ -26,8 +26,10 @@
 import android.net.http.SslCertificate;
 import android.os.Build;
 import android.os.Bundle;
+import android.os.CancellationSignal;
 import android.os.Message;
-import android.print.PrintDocumentAdapter;
+import android.os.ParcelFileDescriptor;
+import android.print.PrintAttributes;
 import android.text.TextUtils;
 import android.util.Base64;
 import android.util.Log;
@@ -57,7 +59,6 @@
 import org.chromium.android_webview.AwContents;
 import org.chromium.android_webview.AwLayoutSizer;
 import org.chromium.android_webview.AwPdfExportAttributes;
-import org.chromium.android_webview.AwPrintDocumentAdapter;
 import org.chromium.base.ThreadUtils;
 import org.chromium.content.browser.LoadUrlParams;
 import org.chromium.net.NetworkChangeNotifier;
@@ -719,9 +720,48 @@
     }
 
     @Override
-    public PrintDocumentAdapter createPrintDocumentAdapter() {
+    public void exportToPdf(ParcelFileDescriptor fd, PrintAttributes attributes,
+            ValueCallback<Boolean> resultCallback, CancellationSignal cancellationSignal)
+            throws java.io.IOException {
         checkThread();
-        return new AwPrintDocumentAdapter(mAwContents.getPdfExporter());
+        // We convert frameworks attributes to an android_webview specific print attributes
+        // so we do not tie upstreaming android_webview changes to installation of correct
+        // SDK to try bots.
+        if (attributes == null) {
+            throw new IllegalArgumentException("attributes cannot be null");
+        }
+        if (attributes.getMediaSize() == null) {
+            throw new  IllegalArgumentException("attributes must specify a media size");
+        }
+        if (attributes.getResolution() == null) {
+            throw new IllegalArgumentException("attributes must specify print resolution");
+        }
+        if (attributes.getMargins() == null) {
+            throw new IllegalArgumentException("attributes must specify margins");
+        }
+        AwPdfExportAttributes pdfAttributes = new AwPdfExportAttributes();
+        pdfAttributes.pageWidth = attributes.getMediaSize().getWidthMils();
+        pdfAttributes.pageHeight = attributes.getMediaSize().getHeightMils();
+        pdfAttributes.dpi = getPrintDpi(attributes);
+        pdfAttributes.leftMargin = attributes.getMargins().getLeftMils();
+        pdfAttributes.rightMargin = attributes.getMargins().getRightMils();
+        pdfAttributes.topMargin = attributes.getMargins().getTopMils();
+        pdfAttributes.bottomMargin = attributes.getMargins().getBottomMils();
+
+        mAwContents.getPdfExporter().exportToPdf(fd, pdfAttributes, resultCallback,
+                cancellationSignal);
+    }
+
+    private static int getPrintDpi(PrintAttributes attributes) {
+        // TODO(sgurun) android print attributes support horizontal and
+        // vertical DPI. Chrome has only one DPI. Revisit this.
+        int horizontalDpi = attributes.getResolution().getHorizontalDpi();
+        int verticalDpi = attributes.getResolution().getVerticalDpi();
+        if (horizontalDpi != verticalDpi) {
+            Log.w(TAG, "Horizontal and vertical DPIs differ. Using horizontal DPI " +
+                    " hDpi=" + horizontalDpi + " vDPI=" + verticalDpi);
+        }
+        return horizontalDpi;
     }
 
     @Override
diff --git a/chromium/plat_support/graphics_utils.cpp b/chromium/plat_support/graphics_utils.cpp
index 73f7632..4db61a1 100644
--- a/chromium/plat_support/graphics_utils.cpp
+++ b/chromium/plat_support/graphics_utils.cpp
@@ -26,9 +26,9 @@
 #include <jni.h>
 #include <utils/Log.h>
 #include <utils/UniquePtr.h>
+#include <utils/Vector.h>
 #include "graphic_buffer_impl.h"
 #include "GraphicsJNI.h"
-#include "SkCanvasStateUtils.h"
 #include "SkGraphics.h"
 #include "SkPicture.h"
 
@@ -39,20 +39,112 @@
 
 class PixelInfo : public AwPixelInfo {
  public:
-  PixelInfo(SkCanvas* canvas);
+  PixelInfo(SkCanvas* canvas, const SkBitmap* bitmap);
   ~PixelInfo();
+
+  void AddRectToClip(const SkIRect& rect);
+
+ private:
+  const SkBitmap* bitmap_;
+  SkAutoLockPixels bitmap_locker_;
+  Vector<int> clip_rect_storage_;
 };
 
+class ClipValidator : public SkCanvas::ClipVisitor {
+ public:
+  ClipValidator() : failed_(false) {}
+  bool failed() { return failed_; }
 
-PixelInfo::PixelInfo(SkCanvas* canvas) {
+  // ClipVisitor
+  virtual void clipRect(const SkRect& rect, SkRegion::Op op, bool antialias) {
+    failed_ |= antialias;
+  }
+
+  virtual void clipPath(const SkPath&, SkRegion::Op, bool antialias) {
+    failed_ |= antialias;
+  }
+
+ private:
+  bool failed_;
+};
+
+PixelInfo::PixelInfo(SkCanvas* canvas, const SkBitmap* bitmap)
+    : bitmap_(bitmap),
+      bitmap_locker_(*bitmap) {
   memset(this, 0, sizeof(AwPixelInfo));
   version = kAwPixelInfoVersion;
-  state = SkCanvasStateUtils::CaptureCanvasState(canvas);
 }
 
-PixelInfo::~PixelInfo() {
-  if (state)
-    SkCanvasStateUtils::ReleaseCanvasState(state);
+PixelInfo::~PixelInfo() {}
+
+void PixelInfo::AddRectToClip(const SkIRect& rect) {
+  ALOG_ASSERT(rect.width() >= 0 && rect.height() >= 0);
+  clip_rect_storage_.push_back(rect.x());
+  clip_rect_storage_.push_back(rect.y());
+  clip_rect_storage_.push_back(rect.width());
+  clip_rect_storage_.push_back(rect.height());
+  clip_rects = const_cast<int*>(clip_rect_storage_.array());
+  clip_rect_count = clip_rect_storage_.size() / 4;
+}
+
+PixelInfo* TryToCreatePixelInfo(SkCanvas* canvas) {
+  // Check the clip can decompose into simple rectangles. This validator is
+  // not a perfect guarantee, but it's the closest I can do with the current
+  // API. TODO: compile this out in release builds as currently Java canvases
+  // do not allow for antialiased clip.
+  ClipValidator validator;
+  canvas->replayClips(&validator);
+  if (validator.failed())
+    return NULL;
+
+  SkCanvas::LayerIter layer(SkCanvas::LayerIter(canvas, false));
+  if (layer.done())
+    return NULL;
+  SkDevice* device = layer.device();
+  if (!device)
+    return NULL;
+  const SkBitmap* bitmap = &device->accessBitmap(true);
+  if (!bitmap->lockPixelsAreWritable())
+    return NULL;
+  const SkRegion& region = layer.clip();
+  layer.next();
+  // Currently don't handle multiple layers well, so early out
+  // TODO: Return all layers in PixelInfo
+  if (!layer.done())
+    return NULL;
+
+  UniquePtr<PixelInfo> pixels(new PixelInfo(canvas, bitmap));
+  pixels->config =
+      bitmap->config() == SkBitmap::kARGB_8888_Config ? AwConfig_ARGB_8888 :
+      bitmap->config() == SkBitmap::kARGB_4444_Config ? AwConfig_ARGB_4444 :
+      bitmap->config() == SkBitmap::kRGB_565_Config ? AwConfig_RGB_565 : -1;
+  if (pixels->config < 0)
+    return NULL;
+
+  pixels->width = bitmap->width();
+  pixels->height = bitmap->height();
+  pixels->row_bytes = bitmap->rowBytes();
+  pixels->pixels = bitmap->getPixels();
+  const SkMatrix& matrix = layer.matrix();
+  for (int i = 0; i < 9; i++) {
+    pixels->matrix[i] = matrix.get(i);
+  }
+
+  if (region.isEmpty()) {
+    pixels->AddRectToClip(region.getBounds());
+  } else {
+    SkRegion::Iterator clip_iterator(region);
+    for (; !clip_iterator.done(); clip_iterator.next()) {
+      pixels->AddRectToClip(clip_iterator.rect());
+    }
+  }
+
+  // WebViewClassic used the DrawFilter for its own purposes (e.g. disabling
+  // dithering when zooming/scrolling) so for now at least, just ignore any
+  // client supplied DrawFilter.
+  ALOGW_IF(canvas->getDrawFilter(),
+           "DrawFilter not supported in webviewchromium, will be ignored");
+  return pixels.release();
 }
 
 AwPixelInfo* GetPixels(JNIEnv* env, jobject java_canvas) {
@@ -60,18 +152,7 @@
   if (!canvas)
     return NULL;
 
-  // Workarounds for http://crbug.com/271096: SW draw only supports
-  // translate & scale transforms, and a simple rectangular clip.
-  // (This also avoids significant wasted time in calling
-  // SkCanvasStateUtils::CaptureCanvasState when the clip is complex).
-  if (!canvas->getTotalClip().isRect() ||
-      (canvas->getTotalMatrix().getType() &
-                ~(SkMatrix::kTranslate_Mask | SkMatrix::kScale_Mask))) {
-    return NULL;
-  }
-
-  UniquePtr<PixelInfo> pixels(new PixelInfo(canvas));
-  return pixels->state ? pixels.release() : NULL;
+  return TryToCreatePixelInfo(canvas);
 }
 
 void ReleasePixels(AwPixelInfo* pixels) {