// 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 "pdf/out_of_process_instance.h"

#include <stddef.h>
#include <stdint.h>

#include <algorithm>  // for min/max()
#include <cmath>      // for log() and pow()
#include <list>
#include <memory>

#include "base/logging.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/values.h"
#include "chrome/common/content_restriction.h"
#include "net/base/escape.h"
#include "pdf/pdf.h"
#include "ppapi/c/dev/ppb_cursor_control_dev.h"
#include "ppapi/c/pp_errors.h"
#include "ppapi/c/pp_rect.h"
#include "ppapi/c/private/ppb_instance_private.h"
#include "ppapi/c/private/ppp_pdf.h"
#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
#include "ppapi/cpp/core.h"
#include "ppapi/cpp/dev/memory_dev.h"
#include "ppapi/cpp/dev/text_input_dev.h"
#include "ppapi/cpp/dev/url_util_dev.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/point.h"
#include "ppapi/cpp/private/pdf.h"
#include "ppapi/cpp/private/var_private.h"
#include "ppapi/cpp/rect.h"
#include "ppapi/cpp/resource.h"
#include "ppapi/cpp/url_request_info.h"
#include "ppapi/cpp/var_array.h"
#include "ppapi/cpp/var_dictionary.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/geometry/point_f.h"

namespace chrome_pdf {

namespace {

const char kChromePrint[] = "chrome://print/";
const char kChromeExtension[] =
    "chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai";

// Constants used in handling postMessage() messages.
const char kType[] = "type";
const char kJSId[] = "id";
// Beep messge arguments. (Plugin -> Page).
const char kJSBeepType[] = "beep";
// Viewport message arguments. (Page -> Plugin).
const char kJSViewportType[] = "viewport";
const char kJSUserInitiated[] = "userInitiated";
const char kJSXOffset[] = "xOffset";
const char kJSYOffset[] = "yOffset";
const char kJSZoom[] = "zoom";
const char kJSPinchPhase[] = "pinchPhase";
// kJSPinchX and kJSPinchY represent the center of the pinch gesture.
const char kJSPinchX[] = "pinchX";
const char kJSPinchY[] = "pinchY";
// kJSPinchVector represents the amount of panning caused by the pinch gesture.
const char kJSPinchVectorX[] = "pinchVectorX";
const char kJSPinchVectorY[] = "pinchVectorY";
// Stop scrolling message (Page -> Plugin)
const char kJSStopScrollingType[] = "stopScrolling";
// Document dimension arguments (Plugin -> Page).
const char kJSDocumentDimensionsType[] = "documentDimensions";
const char kJSDocumentWidth[] = "width";
const char kJSDocumentHeight[] = "height";
const char kJSPageDimensions[] = "pageDimensions";
const char kJSPageX[] = "x";
const char kJSPageY[] = "y";
const char kJSPageWidth[] = "width";
const char kJSPageHeight[] = "height";
// Document load progress arguments (Plugin -> Page)
const char kJSLoadProgressType[] = "loadProgress";
const char kJSProgressPercentage[] = "progress";
// Document print preview loaded (Plugin -> Page)
const char kJSPreviewLoadedType[] = "printPreviewLoaded";
// Metadata
const char kJSMetadataType[] = "metadata";
const char kJSBookmarks[] = "bookmarks";
const char kJSTitle[] = "title";
// Get password (Plugin -> Page)
const char kJSGetPasswordType[] = "getPassword";
// Get password complete arguments (Page -> Plugin)
const char kJSGetPasswordCompleteType[] = "getPasswordComplete";
const char kJSPassword[] = "password";
// Print (Page -> Plugin)
const char kJSPrintType[] = "print";
// Save (Page -> Plugin)
const char kJSSaveType[] = "save";
// Go to page (Plugin -> Page)
const char kJSGoToPageType[] = "goToPage";
const char kJSPageNumber[] = "page";
// Reset print preview mode (Page -> Plugin)
const char kJSResetPrintPreviewModeType[] = "resetPrintPreviewMode";
const char kJSPrintPreviewUrl[] = "url";
const char kJSPrintPreviewGrayscale[] = "grayscale";
const char kJSPrintPreviewPageCount[] = "pageCount";
// Load preview page (Page -> Plugin)
const char kJSLoadPreviewPageType[] = "loadPreviewPage";
const char kJSPreviewPageUrl[] = "url";
const char kJSPreviewPageIndex[] = "index";
// Set scroll position (Plugin -> Page)
const char kJSSetScrollPositionType[] = "setScrollPosition";
const char kJSPositionX[] = "x";
const char kJSPositionY[] = "y";
// Scroll by (Plugin -> Page)
const char kJSScrollByType[] = "scrollBy";
// Cancel the stream URL request (Plugin -> Page)
const char kJSCancelStreamUrlType[] = "cancelStreamUrl";
// Navigate to the given URL (Plugin -> Page)
const char kJSNavigateType[] = "navigate";
const char kJSNavigateUrl[] = "url";
const char kJSNavigateWindowOpenDisposition[] = "disposition";
// Open the email editor with the given parameters (Plugin -> Page)
const char kJSEmailType[] = "email";
const char kJSEmailTo[] = "to";
const char kJSEmailCc[] = "cc";
const char kJSEmailBcc[] = "bcc";
const char kJSEmailSubject[] = "subject";
const char kJSEmailBody[] = "body";
// Rotation (Page -> Plugin)
const char kJSRotateClockwiseType[] = "rotateClockwise";
const char kJSRotateCounterclockwiseType[] = "rotateCounterclockwise";
// Select all text in the document (Page -> Plugin)
const char kJSSelectAllType[] = "selectAll";
// Get the selected text in the document (Page -> Plugin)
const char kJSGetSelectedTextType[] = "getSelectedText";
// Reply with selected text (Plugin -> Page)
const char kJSGetSelectedTextReplyType[] = "getSelectedTextReply";
const char kJSSelectedText[] = "selectedText";

// Get the named destination with the given name (Page -> Plugin)
const char kJSGetNamedDestinationType[] = "getNamedDestination";
const char kJSGetNamedDestination[] = "namedDestination";
// Reply with the page number of the named destination (Plugin -> Page)
const char kJSGetNamedDestinationReplyType[] = "getNamedDestinationReply";
const char kJSNamedDestinationPageNumber[] = "pageNumber";

const char kJSTransformPagePointType[] = "transformPagePoint";
const char kJSTransformPagePointReplyType[] = "transformPagePointReply";

// Selecting text in document (Plugin -> Page)
const char kJSSetIsSelectingType[] = "setIsSelecting";
const char kJSIsSelecting[] = "isSelecting";

// Notify when the document was changed and edit mode is toggled.
const char kJSSetIsEditModeType[] = "setIsEditMode";
const char kJSIsEditMode[] = "isEditMode";

// Notify when a form field is focused (Plugin -> Page)
const char kJSFieldFocusType[] = "formFocusChange";
const char kJSFieldFocus[] = "focused";

const int kFindResultCooldownMs = 100;

// Same value as printing::COMPLETE_PREVIEW_DOCUMENT_INDEX.
constexpr int kCompletePDFIndex = -1;
// A different negative value to differentiate itself from |kCompletePDFIndex|.
constexpr int kInvalidPDFIndex = -2;

// A delay to wait between each accessibility page to keep the system
// responsive.
const int kAccessibilityPageDelayMs = 100;

const double kMinZoom = 0.01;

const char kPPPPdfInterface[] = PPP_PDF_INTERFACE_1;

// Used for UMA. Do not delete entries, and keep in sync with histograms.xml.
enum PDFFeatures {
  LOADED_DOCUMENT = 0,
  HAS_TITLE = 1,
  HAS_BOOKMARKS = 2,
  FEATURES_COUNT
};

// Used for UMA. Do not delete entries, and keep in sync with histograms.xml
// and pdfium/public/fpdf_annot.h.
const int kAnnotationTypesCount = 28;

PP_Var GetLinkAtPosition(PP_Instance instance, PP_Point point) {
  pp::Var var;
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (object) {
    var = static_cast<OutOfProcessInstance*>(object)->GetLinkAtPosition(
        pp::Point(point));
  }
  return var.Detach();
}

void Transform(PP_Instance instance, PP_PrivatePageTransformType type) {
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (object) {
    auto* obj_instance = static_cast<OutOfProcessInstance*>(object);
    switch (type) {
      case PP_PRIVATEPAGETRANSFORMTYPE_ROTATE_90_CW:
        obj_instance->RotateClockwise();
        break;
      case PP_PRIVATEPAGETRANSFORMTYPE_ROTATE_90_CCW:
        obj_instance->RotateCounterclockwise();
        break;
    }
  }
}

PP_Bool GetPrintPresetOptionsFromDocument(
    PP_Instance instance,
    PP_PdfPrintPresetOptions_Dev* options) {
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (object) {
    auto* obj_instance = static_cast<OutOfProcessInstance*>(object);
    obj_instance->GetPrintPresetOptionsFromDocument(options);
  }
  return PP_TRUE;
}

void EnableAccessibility(PP_Instance instance) {
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (object) {
    auto* obj_instance = static_cast<OutOfProcessInstance*>(object);
    obj_instance->EnableAccessibility();
  }
}

void SetCaretPosition(PP_Instance instance, const PP_FloatPoint* position) {
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (object) {
    auto* obj_instance = static_cast<OutOfProcessInstance*>(object);
    obj_instance->SetCaretPosition(*position);
  }
}

void MoveRangeSelectionExtent(PP_Instance instance,
                              const PP_FloatPoint* extent) {
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (object) {
    auto* obj_instance = static_cast<OutOfProcessInstance*>(object);
    obj_instance->MoveRangeSelectionExtent(*extent);
  }
}

void SetSelectionBounds(PP_Instance instance,
                        const PP_FloatPoint* base,
                        const PP_FloatPoint* extent) {
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (object) {
    auto* obj_instance = static_cast<OutOfProcessInstance*>(object);
    obj_instance->SetSelectionBounds(*base, *extent);
  }
}

PP_Bool CanEditText(PP_Instance instance) {
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (!object)
    return PP_FALSE;

  auto* obj_instance = static_cast<OutOfProcessInstance*>(object);
  return PP_FromBool(obj_instance->CanEditText());
}

PP_Bool HasEditableText(PP_Instance instance) {
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (!object)
    return PP_FALSE;

  auto* obj_instance = static_cast<OutOfProcessInstance*>(object);
  return PP_FromBool(obj_instance->HasEditableText());
}

void ReplaceSelection(PP_Instance instance, const char* text) {
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (object) {
    auto* obj_instance = static_cast<OutOfProcessInstance*>(object);
    obj_instance->ReplaceSelection(text);
  }
}

PP_Bool CanUndo(PP_Instance instance) {
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (!object)
    return PP_FALSE;

  auto* obj_instance = static_cast<OutOfProcessInstance*>(object);
  return PP_FromBool(obj_instance->CanUndo());
}

PP_Bool CanRedo(PP_Instance instance) {
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (!object)
    return PP_FALSE;

  auto* obj_instance = static_cast<OutOfProcessInstance*>(object);
  return PP_FromBool(obj_instance->CanRedo());
}

void Undo(PP_Instance instance) {
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (object) {
    auto* obj_instance = static_cast<OutOfProcessInstance*>(object);
    obj_instance->Undo();
  }
}

void Redo(PP_Instance instance) {
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (object) {
    auto* obj_instance = static_cast<OutOfProcessInstance*>(object);
    obj_instance->Redo();
  }
}

int32_t PdfPrintBegin(PP_Instance instance,
                      const PP_PrintSettings_Dev* print_settings,
                      const PP_PdfPrintSettings_Dev* pdf_print_settings) {
  void* object = pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (!object)
    return 0;

  auto* obj_instance = static_cast<OutOfProcessInstance*>(object);
  return obj_instance->PdfPrintBegin(print_settings, pdf_print_settings);
}

const PPP_Pdf ppp_private = {
    &GetLinkAtPosition,
    &Transform,
    &GetPrintPresetOptionsFromDocument,
    &EnableAccessibility,
    &SetCaretPosition,
    &MoveRangeSelectionExtent,
    &SetSelectionBounds,
    &CanEditText,
    &HasEditableText,
    &ReplaceSelection,
    &CanUndo,
    &CanRedo,
    &Undo,
    &Redo,
    &PdfPrintBegin,
};

int ExtractPrintPreviewPageIndex(base::StringPiece src_url) {
  // Sample |src_url| format: chrome://print/id/page_index/print.pdf
  // The page_index is zero-based, but can be negative with special meanings.
  std::vector<base::StringPiece> url_substr =
      base::SplitStringPiece(src_url.substr(strlen(kChromePrint)), "/",
                             base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
  if (url_substr.size() != 3)
    return kInvalidPDFIndex;

  if (url_substr[2] != "print.pdf")
    return kInvalidPDFIndex;

  int page_index = 0;
  if (!base::StringToInt(url_substr[1], &page_index))
    return kInvalidPDFIndex;
  return page_index;
}

bool IsPrintPreviewUrl(base::StringPiece url) {
  return url.starts_with(kChromePrint);
}

bool IsPreviewingPDF(int print_preview_page_count) {
  return print_preview_page_count == 0;
}

void ScaleFloatPoint(float scale, pp::FloatPoint* point) {
  point->set_x(point->x() * scale);
  point->set_y(point->y() * scale);
}

void ScalePoint(float scale, pp::Point* point) {
  point->set_x(static_cast<int>(point->x() * scale));
  point->set_y(static_cast<int>(point->y() * scale));
}

void ScaleRect(float scale, pp::Rect* rect) {
  int left = static_cast<int>(floorf(rect->x() * scale));
  int top = static_cast<int>(floorf(rect->y() * scale));
  int right = static_cast<int>(ceilf((rect->x() + rect->width()) * scale));
  int bottom = static_cast<int>(ceilf((rect->y() + rect->height()) * scale));
  rect->SetRect(left, top, right - left, bottom - top);
}

}  // namespace

OutOfProcessInstance::OutOfProcessInstance(PP_Instance instance)
    : pp::Instance(instance),
      pp::Find_Private(this),
      pp::Printing_Dev(this),
      cursor_(PP_CURSORTYPE_POINTER),
      zoom_(1.0),
      needs_reraster_(true),
      last_bitmap_smaller_(false),
      device_scale_(1.0),
      full_(false),
      paint_manager_(this, this, true),
      first_paint_(true),
      document_load_state_(LOAD_STATE_LOADING),
      preview_document_load_state_(LOAD_STATE_COMPLETE),
      uma_(this),
      told_browser_about_unsupported_feature_(false),
      font_substitution_reported_(false),
      print_preview_page_count_(-1),
      print_preview_loaded_page_count_(-1),
      last_progress_sent_(0),
      recently_sent_find_update_(false),
      received_viewport_message_(false),
      did_call_start_loading_(false),
      stop_scrolling_(false),
      background_color_(0),
      top_toolbar_height_in_viewport_coords_(0),
      accessibility_state_(ACCESSIBILITY_STATE_OFF),
      is_print_preview_(false) {
  callback_factory_.Initialize(this);
  pp::Module::Get()->AddPluginInterface(kPPPPdfInterface, &ppp_private);
  AddPerInstanceObject(kPPPPdfInterface, this);

  RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
  RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
  RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_TOUCH);

  for (size_t i = 0; i < PDFACTION_BUCKET_BOUNDARY; i++)
    preview_action_recorded_[i] = false;
}

OutOfProcessInstance::~OutOfProcessInstance() {
  RemovePerInstanceObject(kPPPPdfInterface, this);
  // Explicitly reset the PDFEngine during destruction as it may call back into
  // this object.
  engine_.reset();
}

bool OutOfProcessInstance::Init(uint32_t argc,
                                const char* argn[],
                                const char* argv[]) {
  // Check if the PDF is being loaded in the PDF chrome extension. We only allow
  // the plugin to be loaded in the extension and print preview to avoid
  // exposing sensitive APIs directly to external websites.
  pp::Var document_url_var = pp::URLUtil_Dev::Get()->GetDocumentURL(this);
  if (!document_url_var.is_string())
    return false;

  std::string document_url = document_url_var.AsString();
  base::StringPiece document_url_piece(document_url);
  is_print_preview_ = IsPrintPreviewUrl(document_url_piece);
  if (!document_url_piece.starts_with(kChromeExtension) && !is_print_preview_)
    return false;

  // Check if the plugin is full frame. This is passed in from JS.
  for (uint32_t i = 0; i < argc; ++i) {
    if (strcmp(argn[i], "full-frame") == 0) {
      full_ = true;
      break;
    }
  }

  // Allow the plugin to handle find requests.
  SetPluginToHandleFindRequests();

  text_input_ = std::make_unique<pp::TextInput_Dev>(this);

  bool enable_javascript = false;
  const char* stream_url = nullptr;
  const char* original_url = nullptr;
  const char* top_level_url = nullptr;
  const char* headers = nullptr;
  for (uint32_t i = 0; i < argc; ++i) {
    bool success = true;
    if (strcmp(argn[i], "src") == 0) {
      original_url = argv[i];
    } else if (strcmp(argn[i], "stream-url") == 0) {
      stream_url = argv[i];
    } else if (strcmp(argn[i], "top-level-url") == 0) {
      top_level_url = argv[i];
    } else if (strcmp(argn[i], "headers") == 0) {
      headers = argv[i];
    } else if (strcmp(argn[i], "background-color") == 0) {
      success = base::HexStringToUInt(argv[i], &background_color_);
    } else if (strcmp(argn[i], "top-toolbar-height") == 0) {
      success =
          base::StringToInt(argv[i], &top_toolbar_height_in_viewport_coords_);
    } else if (strcmp(argn[i], "javascript") == 0) {
      enable_javascript = (strcmp(argv[i], "allow") == 0);
    }
    if (!success)
      return false;
  }

  if (!original_url)
    return false;

  if (!stream_url)
    stream_url = original_url;

  if (!engine_) {
    // TODO(tsepez): fix lifetime issue, conditionalize javascript.
    engine_ = PDFEngine::Create(this, true);
  }

  // If we're in print preview mode we don't need to load the document yet.
  // A |kJSResetPrintPreviewModeType| message will be sent to the plugin letting
  // it know the url to load. By not loading here we avoid loading the same
  // document twice.
  if (IsPrintPreview())
    return true;

  LoadUrl(stream_url, /*is_print_preview=*/false);
  url_ = original_url;
  pp::PDF::SetCrashData(GetPluginInstance(), original_url, top_level_url);
  return engine_->New(original_url, headers);
}

void OutOfProcessInstance::HandleMessage(const pp::Var& message) {
  pp::VarDictionary dict(message);
  if (!dict.Get(kType).is_string()) {
    NOTREACHED();
    return;
  }

  std::string type = dict.Get(kType).AsString();

  if (type == kJSViewportType && dict.Get(pp::Var(kJSXOffset)).is_number() &&
      dict.Get(pp::Var(kJSYOffset)).is_number() &&
      dict.Get(pp::Var(kJSZoom)).is_number() &&
      dict.Get(pp::Var(kJSPinchPhase)).is_number()) {
    received_viewport_message_ = true;
    stop_scrolling_ = false;
    PinchPhase pinch_phase =
        static_cast<PinchPhase>(dict.Get(pp::Var(kJSPinchPhase)).AsInt());
    double zoom = dict.Get(pp::Var(kJSZoom)).AsDouble();
    double zoom_ratio = zoom / zoom_;

    pp::FloatPoint scroll_offset(dict.Get(pp::Var(kJSXOffset)).AsDouble(),
                                 dict.Get(pp::Var(kJSYOffset)).AsDouble());

    if (pinch_phase == PINCH_START) {
      scroll_offset_at_last_raster_ = scroll_offset;
      last_bitmap_smaller_ = false;
      needs_reraster_ = false;
      return;
    }

    // When zooming in, we set a layer transform to avoid unneeded rerasters.
    // Also, if we're zooming out and the last time we rerastered was when
    // we were even further zoomed out (i.e. we pinch zoomed in and are now
    // pinch zooming back out in the same gesture), we update the layer
    // transform instead of rerastering.
    if (pinch_phase == PINCH_UPDATE_ZOOM_IN ||
        (pinch_phase == PINCH_UPDATE_ZOOM_OUT && zoom_ratio > 1.0)) {
      if (!(dict.Get(pp::Var(kJSPinchX)).is_number() &&
            dict.Get(pp::Var(kJSPinchY)).is_number() &&
            dict.Get(pp::Var(kJSPinchVectorX)).is_number() &&
            dict.Get(pp::Var(kJSPinchVectorY)).is_number())) {
        NOTREACHED();
        return;
      }

      pp::Point pinch_center(dict.Get(pp::Var(kJSPinchX)).AsDouble(),
                             dict.Get(pp::Var(kJSPinchY)).AsDouble());
      // Pinch vector is the panning caused due to change in pinch
      // center between start and end of the gesture.
      pp::Point pinch_vector =
          pp::Point(dict.Get(kJSPinchVectorX).AsDouble() * zoom_ratio,
                    dict.Get(kJSPinchVectorY).AsDouble() * zoom_ratio);
      pp::Point scroll_delta;
      // If the rendered document doesn't fill the display area we will
      // use |paint_offset| to anchor the paint vertically into the same place.
      // We use the scroll bars instead of the pinch vector to get the actual
      // position on screen of the paint.
      pp::Point paint_offset;

      if (plugin_size_.width() > GetDocumentPixelWidth() * zoom_ratio) {
        // We want to keep the paint in the middle but it must stay in the same
        // position relative to the scroll bars.
        paint_offset = pp::Point(0, (1 - zoom_ratio) * pinch_center.y());
        scroll_delta =
            pp::Point(0, (scroll_offset.y() -
                          scroll_offset_at_last_raster_.y() * zoom_ratio));

        pinch_vector = pp::Point();
        last_bitmap_smaller_ = true;
      } else if (last_bitmap_smaller_) {
        pinch_center = pp::Point((plugin_size_.width() / device_scale_) / 2,
                                 (plugin_size_.height() / device_scale_) / 2);
        const double zoom_when_doc_covers_plugin_width =
            zoom_ * plugin_size_.width() / GetDocumentPixelWidth();
        paint_offset = pp::Point(
            (1 - zoom / zoom_when_doc_covers_plugin_width) * pinch_center.x(),
            (1 - zoom_ratio) * pinch_center.y());
        pinch_vector = pp::Point();
        scroll_delta =
            pp::Point((scroll_offset.x() -
                       scroll_offset_at_last_raster_.x() * zoom_ratio),
                      (scroll_offset.y() -
                       scroll_offset_at_last_raster_.y() * zoom_ratio));
      }

      paint_manager_.SetTransform(zoom_ratio, pinch_center,
                                  pinch_vector + paint_offset + scroll_delta,
                                  true);
      needs_reraster_ = false;
      return;
    }

    if (pinch_phase == PINCH_UPDATE_ZOOM_OUT || pinch_phase == PINCH_END) {
      // We reraster on pinch zoom out in order to solve the invalid regions
      // that appear after zooming out.
      // On pinch end the scale is again 1.f and we request a reraster
      // in the new position.
      paint_manager_.ClearTransform();
      last_bitmap_smaller_ = false;
      needs_reraster_ = true;

      // If we're rerastering due to zooming out, we need to update
      // |scroll_offset_at_last_raster_|, in case the user continues the
      // gesture by zooming in.
      scroll_offset_at_last_raster_ = scroll_offset;
    }

    // Bound the input parameters.
    zoom = std::max(kMinZoom, zoom);
    DCHECK(dict.Get(pp::Var(kJSUserInitiated)).is_bool());
    if (dict.Get(pp::Var(kJSUserInitiated)).AsBool())
      PrintPreviewHistogramEnumeration(UPDATE_ZOOM);

    SetZoom(zoom);
    scroll_offset = BoundScrollOffsetToDocument(scroll_offset);
    engine_->ScrolledToXPosition(scroll_offset.x() * device_scale_);
    engine_->ScrolledToYPosition(scroll_offset.y() * device_scale_);
  } else if (type == kJSGetPasswordCompleteType &&
             dict.Get(pp::Var(kJSPassword)).is_string()) {
    if (password_callback_) {
      pp::CompletionCallbackWithOutput<pp::Var> callback = *password_callback_;
      password_callback_.reset();
      *callback.output() = dict.Get(pp::Var(kJSPassword)).pp_var();
      callback.Run(PP_OK);
    } else {
      NOTREACHED();
    }
  } else if (type == kJSPrintType) {
    Print();
  } else if (type == kJSSaveType) {
    engine_->KillFormFocus();
    pp::PDF::SaveAs(this);
  } else if (type == kJSRotateClockwiseType) {
    RotateClockwise();
  } else if (type == kJSRotateCounterclockwiseType) {
    RotateCounterclockwise();
  } else if (type == kJSSelectAllType) {
    engine_->SelectAll();
  } else if (type == kJSResetPrintPreviewModeType &&
             dict.Get(pp::Var(kJSPrintPreviewUrl)).is_string() &&
             dict.Get(pp::Var(kJSPrintPreviewGrayscale)).is_bool() &&
             dict.Get(pp::Var(kJSPrintPreviewPageCount)).is_int()) {
    // For security reasons, crash if the URL that is trying to be loaded here
    // isn't a print preview one.
    std::string url = dict.Get(pp::Var(kJSPrintPreviewUrl)).AsString();
    CHECK(IsPrintPreview());
    CHECK(IsPrintPreviewUrl(url));

    int print_preview_page_count =
        dict.Get(pp::Var(kJSPrintPreviewPageCount)).AsInt();
    if (print_preview_page_count < 0) {
      NOTREACHED();
      return;
    }

    // The page count is zero if the print preview source is a PDF. In which
    // case, the page index for |url| should be at |kCompletePDFIndex|.
    // When the page count is not zero, then the source is not PDF. In which
    // case, the page index for |url| should be non-negative.
    bool is_previewing_pdf = IsPreviewingPDF(print_preview_page_count);
    int page_index = ExtractPrintPreviewPageIndex(url);
    if (is_previewing_pdf) {
      if (page_index != kCompletePDFIndex) {
        NOTREACHED();
        return;
      }
    } else {
      if (page_index < 0) {
        NOTREACHED();
        return;
      }
    }

    print_preview_page_count_ = print_preview_page_count;
    print_preview_loaded_page_count_ = 0;
    url_ = url;
    preview_pages_info_ = base::queue<PreviewPageInfo>();
    preview_document_load_state_ = LOAD_STATE_COMPLETE;
    document_load_state_ = LOAD_STATE_LOADING;
    LoadUrl(url_, /*is_print_preview=*/false);
    preview_engine_.reset();
    engine_ = PDFEngine::Create(this, false);
    engine_->SetGrayscale(dict.Get(pp::Var(kJSPrintPreviewGrayscale)).AsBool());
    engine_->New(url_.c_str(), nullptr /* empty header */);

    paint_manager_.InvalidateRect(pp::Rect(pp::Point(), plugin_size_));
    PrintPreviewHistogramEnumeration(PRINT_PREVIEW_SHOWN);
  } else if (type == kJSLoadPreviewPageType &&
             dict.Get(pp::Var(kJSPreviewPageUrl)).is_string() &&
             dict.Get(pp::Var(kJSPreviewPageIndex)).is_int()) {
    std::string url = dict.Get(pp::Var(kJSPreviewPageUrl)).AsString();
    // For security reasons we crash if the URL that is trying to be loaded here
    // isn't a print preview one.
    CHECK(IsPrintPreview());
    CHECK(IsPrintPreviewUrl(url));
    ProcessPreviewPageInfo(url, dict.Get(pp::Var(kJSPreviewPageIndex)).AsInt());
  } else if (type == kJSStopScrollingType) {
    stop_scrolling_ = true;
  } else if (type == kJSGetSelectedTextType) {
    std::string selected_text = engine_->GetSelectedText();
    // Always return unix newlines to JS.
    base::ReplaceChars(selected_text, "\r", std::string(), &selected_text);
    pp::VarDictionary reply;
    reply.Set(pp::Var(kType), pp::Var(kJSGetSelectedTextReplyType));
    reply.Set(pp::Var(kJSSelectedText), selected_text);
    PostMessage(reply);
  } else if (type == kJSGetNamedDestinationType &&
             dict.Get(pp::Var(kJSGetNamedDestination)).is_string()) {
    base::Optional<PDFEngine::NamedDestination> named_destination =
        engine_->GetNamedDestination(
            dict.Get(pp::Var(kJSGetNamedDestination)).AsString());
    pp::VarDictionary reply;
    reply.Set(pp::Var(kType), pp::Var(kJSGetNamedDestinationReplyType));
    reply.Set(
        pp::Var(kJSNamedDestinationPageNumber),
        named_destination ? static_cast<int>(named_destination->page) : -1);
    PostMessage(reply);
  } else if (type == kJSTransformPagePointType &&
             dict.Get(pp::Var(kJSPageNumber)).is_int() &&
             dict.Get(pp::Var(kJSPageX)).is_int() &&
             dict.Get(pp::Var(kJSPageY)).is_int() &&
             dict.Get(pp::Var(kJSId)).is_int()) {
    gfx::PointF page_xy(dict.Get(pp::Var(kJSPageX)).AsInt(),
                        dict.Get(pp::Var(kJSPageY)).AsInt());
    gfx::PointF device_xy = engine_->TransformPagePoint(
        dict.Get(pp::Var(kJSPageNumber)).AsInt(), page_xy);

    pp::VarDictionary reply;
    reply.Set(pp::Var(kType), pp::Var(kJSTransformPagePointReplyType));
    reply.Set(pp::Var(kJSPositionX), device_xy.x());
    reply.Set(pp::Var(kJSPositionY), device_xy.y());
    reply.Set(pp::Var(kJSId), dict.Get(pp::Var(kJSId)).AsInt());
    PostMessage(reply);
  } else {
    NOTREACHED();
  }
}

bool OutOfProcessInstance::HandleInputEvent(const pp::InputEvent& event) {
  // To simplify things, convert the event into device coordinates.
  pp::InputEvent event_device_res(event);
  {
    pp::MouseInputEvent mouse_event(event);
    if (!mouse_event.is_null()) {
      pp::Point point = mouse_event.GetPosition();
      pp::Point movement = mouse_event.GetMovement();
      ScalePoint(device_scale_, &point);
      point.set_x(point.x() - available_area_.x());

      ScalePoint(device_scale_, &movement);
      mouse_event =
          pp::MouseInputEvent(this, event.GetType(), event.GetTimeStamp(),
                              event.GetModifiers(), mouse_event.GetButton(),
                              point, mouse_event.GetClickCount(), movement);
      event_device_res = mouse_event;
    }
  }
  {
    pp::TouchInputEvent touch_event(event);
    if (!touch_event.is_null()) {
      pp::TouchInputEvent new_touch_event = pp::TouchInputEvent(
          this, touch_event.GetType(), touch_event.GetTimeStamp(),
          touch_event.GetModifiers());

      for (uint32_t i = 0;
           i < touch_event.GetTouchCount(PP_TOUCHLIST_TYPE_TARGETTOUCHES);
           i++) {
        pp::TouchPoint touch_point =
            touch_event.GetTouchByIndex(PP_TOUCHLIST_TYPE_TARGETTOUCHES, i);

        pp::FloatPoint point = touch_point.position();
        ScaleFloatPoint(device_scale_, &point);
        point.set_x(point.x() - available_area_.x());

        new_touch_event.AddTouchPoint(
            PP_TOUCHLIST_TYPE_TARGETTOUCHES,
            {touch_point.id(), point, touch_point.radii(),
             touch_point.rotation_angle(), touch_point.pressure()});
      }
      event_device_res = new_touch_event;
    }
  }

  if (engine_->HandleEvent(event_device_res))
    return true;

  // Middle click is used for scrolling and is handled by the container page.
  pp::MouseInputEvent mouse_event(event_device_res);
  if (!mouse_event.is_null() &&
      mouse_event.GetButton() == PP_INPUTEVENT_MOUSEBUTTON_MIDDLE) {
    return false;
  }

  // Return true for unhandled clicks so the plugin takes focus.
  return (event.GetType() == PP_INPUTEVENT_TYPE_MOUSEDOWN);
}

void OutOfProcessInstance::DidChangeView(const pp::View& view) {
  pp::Rect view_rect(view.GetRect());
  float old_device_scale = device_scale_;
  float device_scale = view.GetDeviceScale();
  pp::Size view_device_size(view_rect.width() * device_scale,
                            view_rect.height() * device_scale);

  if (view_device_size != plugin_size_ || device_scale != device_scale_) {
    device_scale_ = device_scale;
    plugin_dip_size_ = view_rect.size();
    plugin_size_ = view_device_size;

    paint_manager_.SetSize(view_device_size, device_scale_);

    pp::Size new_image_data_size =
        PaintManager::GetNewContextSize(image_data_.size(), plugin_size_);
    if (new_image_data_size != image_data_.size()) {
      image_data_ = pp::ImageData(this, PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                                  new_image_data_size, false);
      first_paint_ = true;
    }

    if (image_data_.is_null()) {
      DCHECK(plugin_size_.IsEmpty());
      return;
    }

    OnGeometryChanged(zoom_, old_device_scale);
  }

  if (!stop_scrolling_) {
    scroll_offset_ = view.GetScrollOffset();
    // Because view messages come from the DOM, the coordinates of the viewport
    // are 0-based (i.e. they do not correspond to the viewport's coordinates in
    // JS), so we need to subtract the toolbar height to convert them into
    // viewport coordinates.
    pp::FloatPoint scroll_offset_float(
        scroll_offset_.x(),
        scroll_offset_.y() - top_toolbar_height_in_viewport_coords_);
    scroll_offset_float = BoundScrollOffsetToDocument(scroll_offset_float);
    engine_->ScrolledToXPosition(scroll_offset_float.x() * device_scale_);
    engine_->ScrolledToYPosition(scroll_offset_float.y() * device_scale_);
  }
}

void OutOfProcessInstance::DidChangeFocus(bool has_focus) {
  if (!has_focus)
    engine_->KillFormFocus();
}

void OutOfProcessInstance::GetPrintPresetOptionsFromDocument(
    PP_PdfPrintPresetOptions_Dev* options) {
  options->is_scaling_disabled = PP_FromBool(IsPrintScalingDisabled());
  options->duplex =
      static_cast<PP_PrivateDuplexMode_Dev>(engine_->GetDuplexType());
  options->copies = engine_->GetCopiesToPrint();
  pp::Size uniform_page_size;
  options->is_page_size_uniform =
      PP_FromBool(engine_->GetPageSizeAndUniformity(&uniform_page_size));
  options->uniform_page_size = uniform_page_size;
}

void OutOfProcessInstance::EnableAccessibility() {
  if (accessibility_state_ == ACCESSIBILITY_STATE_LOADED)
    return;

  if (accessibility_state_ == ACCESSIBILITY_STATE_OFF)
    accessibility_state_ = ACCESSIBILITY_STATE_PENDING;

  if (document_load_state_ == LOAD_STATE_COMPLETE)
    LoadAccessibility();
}

void OutOfProcessInstance::LoadAccessibility() {
  accessibility_state_ = ACCESSIBILITY_STATE_LOADED;
  PP_PrivateAccessibilityDocInfo doc_info;
  doc_info.page_count = engine_->GetNumberOfPages();
  doc_info.text_accessible = PP_FromBool(
      engine_->HasPermission(PDFEngine::PERMISSION_COPY_ACCESSIBLE));
  doc_info.text_copyable =
      PP_FromBool(engine_->HasPermission(PDFEngine::PERMISSION_COPY));

  pp::PDF::SetAccessibilityDocInfo(GetPluginInstance(), &doc_info);

  // If the document contents isn't accessible, don't send anything more.
  if (!(engine_->HasPermission(PDFEngine::PERMISSION_COPY) ||
        engine_->HasPermission(PDFEngine::PERMISSION_COPY_ACCESSIBLE))) {
    return;
  }

  SendAccessibilityViewportInfo();

  // Schedule loading the first page.
  pp::CompletionCallback callback = callback_factory_.NewCallback(
      &OutOfProcessInstance::SendNextAccessibilityPage);
  pp::Module::Get()->core()->CallOnMainThread(kAccessibilityPageDelayMs,
                                              callback, 0);
}

void OutOfProcessInstance::SendNextAccessibilityPage(int32_t page_index) {
  int page_count = engine_->GetNumberOfPages();
  if (page_index < 0 || page_index >= page_count)
    return;

  int char_count = engine_->GetCharCount(page_index);

  // Treat a char count of -1 (error) as 0 (an empty page), since
  // other pages might have valid content.
  if (char_count < 0)
    char_count = 0;

  PP_PrivateAccessibilityPageInfo page_info;
  page_info.page_index = page_index;
  page_info.bounds = engine_->GetPageBoundsRect(page_index);
  page_info.char_count = char_count;

  std::vector<PP_PrivateAccessibilityCharInfo> chars(page_info.char_count);
  for (uint32_t i = 0; i < page_info.char_count; ++i) {
    chars[i].unicode_character = engine_->GetCharUnicode(page_index, i);
  }

  std::vector<PP_PrivateAccessibilityTextRunInfo> text_runs;
  int char_index = 0;
  while (char_index < char_count) {
    PP_PrivateAccessibilityTextRunInfo text_run_info;
    pp::FloatRect bounds;
    engine_->GetTextRunInfo(page_index, char_index, &text_run_info.len,
                            &text_run_info.font_size, &bounds);
    DCHECK_LE(char_index + text_run_info.len,
              static_cast<uint32_t>(char_count));
    text_run_info.direction = PP_PRIVATEDIRECTION_LTR;
    text_run_info.bounds = bounds;
    text_runs.push_back(text_run_info);

    // We need to provide enough information to draw a bounding box
    // around any arbitrary text range, but the bounding boxes of characters
    // we get from PDFium don't necessarily "line up". Walk through the
    // characters in each text run and let the width of each character be
    // the difference between the x coordinate of one character and the
    // x coordinate of the next. The rest of the bounds of each character
    // can be computed from the bounds of the text run.
    pp::FloatRect char_bounds = engine_->GetCharBounds(page_index, char_index);
    for (uint32_t i = 0; i < text_run_info.len - 1; i++) {
      DCHECK_LT(char_index + i + 1, static_cast<uint32_t>(char_count));
      pp::FloatRect next_char_bounds =
          engine_->GetCharBounds(page_index, char_index + i + 1);
      chars[char_index + i].char_width = next_char_bounds.x() - char_bounds.x();
      char_bounds = next_char_bounds;
    }
    chars[char_index + text_run_info.len - 1].char_width = char_bounds.width();

    char_index += text_run_info.len;
  }

  page_info.text_run_count = text_runs.size();
  pp::PDF::SetAccessibilityPageInfo(GetPluginInstance(), &page_info,
                                    text_runs.data(), chars.data());

  // Schedule loading the next page.
  pp::CompletionCallback callback = callback_factory_.NewCallback(
      &OutOfProcessInstance::SendNextAccessibilityPage);
  pp::Module::Get()->core()->CallOnMainThread(kAccessibilityPageDelayMs,
                                              callback, page_index + 1);
}

void OutOfProcessInstance::SendAccessibilityViewportInfo() {
  PP_PrivateAccessibilityViewportInfo viewport_info;
  viewport_info.scroll.x = 0;
  viewport_info.scroll.y =
      -top_toolbar_height_in_viewport_coords_ * device_scale_;
  viewport_info.offset = available_area_.point();
  viewport_info.zoom = zoom_ * device_scale_;

  engine_->GetSelection(&viewport_info.selection_start_page_index,
                        &viewport_info.selection_start_char_index,
                        &viewport_info.selection_end_page_index,
                        &viewport_info.selection_end_char_index);

  pp::PDF::SetAccessibilityViewportInfo(GetPluginInstance(), &viewport_info);
}

void OutOfProcessInstance::SelectionChanged(const pp::Rect& left,
                                            const pp::Rect& right) {
  pp::Point l(left.point().x() + available_area_.x(), left.point().y());
  pp::Point r(right.x() + available_area_.x(), right.point().y());

  float inverse_scale = 1.0f / device_scale_;
  ScalePoint(inverse_scale, &l);
  ScalePoint(inverse_scale, &r);

  pp::PDF::SelectionChanged(GetPluginInstance(),
                            PP_MakeFloatPoint(l.x(), l.y()), left.height(),
                            PP_MakeFloatPoint(r.x(), r.y()), right.height());
  if (accessibility_state_ == ACCESSIBILITY_STATE_LOADED)
    SendAccessibilityViewportInfo();
}

void OutOfProcessInstance::SetCaretPosition(const pp::FloatPoint& position) {
  pp::Point new_position(position.x(), position.y());
  ScalePoint(device_scale_, &new_position);
  new_position.set_x(new_position.x() - available_area_.x());
  engine_->SetCaretPosition(new_position);
}

void OutOfProcessInstance::MoveRangeSelectionExtent(
    const pp::FloatPoint& extent) {
  pp::Point new_extent(extent.x(), extent.y());
  ScalePoint(device_scale_, &new_extent);
  new_extent.set_x(new_extent.x() - available_area_.x());
  engine_->MoveRangeSelectionExtent(new_extent);
}

void OutOfProcessInstance::SetSelectionBounds(const pp::FloatPoint& base,
                                              const pp::FloatPoint& extent) {
  pp::Point new_base_point(base.x(), base.y());
  ScalePoint(device_scale_, &new_base_point);
  new_base_point.set_x(new_base_point.x() - available_area_.x());

  pp::Point new_extent_point(extent.x(), extent.y());
  ScalePoint(device_scale_, &new_extent_point);
  new_extent_point.set_x(new_extent_point.x() - available_area_.x());

  engine_->SetSelectionBounds(new_base_point, new_extent_point);
}

pp::Var OutOfProcessInstance::GetLinkAtPosition(const pp::Point& point) {
  pp::Point offset_point(point);
  ScalePoint(device_scale_, &offset_point);
  offset_point.set_x(offset_point.x() - available_area_.x());
  return engine_->GetLinkAtPosition(offset_point);
}

bool OutOfProcessInstance::CanEditText() {
  return engine_->CanEditText();
}

bool OutOfProcessInstance::HasEditableText() {
  return engine_->HasEditableText();
}

void OutOfProcessInstance::ReplaceSelection(const std::string& text) {
  engine_->ReplaceSelection(text);
}

bool OutOfProcessInstance::CanUndo() {
  return engine_->CanUndo();
}

bool OutOfProcessInstance::CanRedo() {
  return engine_->CanRedo();
}

void OutOfProcessInstance::Undo() {
  engine_->Undo();
}

void OutOfProcessInstance::Redo() {
  engine_->Redo();
}

int32_t OutOfProcessInstance::PdfPrintBegin(
    const PP_PrintSettings_Dev* print_settings,
    const PP_PdfPrintSettings_Dev* pdf_print_settings) {
  // For us num_pages is always equal to the number of pages in the PDF
  // document irrespective of the printable area.
  int32_t ret = engine_->GetNumberOfPages();
  if (!ret)
    return 0;

  uint32_t supported_formats = engine_->QuerySupportedPrintOutputFormats();
  if ((print_settings->format & supported_formats) == 0)
    return 0;

  print_settings_.is_printing = true;
  print_settings_.pepper_print_settings = *print_settings;
  print_settings_.pdf_print_settings = *pdf_print_settings;
  engine_->PrintBegin();
  return ret;
}

uint32_t OutOfProcessInstance::QuerySupportedPrintOutputFormats() {
  return engine_->QuerySupportedPrintOutputFormats();
}

int32_t OutOfProcessInstance::PrintBegin(
    const PP_PrintSettings_Dev& print_settings) {
  // Replaced with PdfPrintBegin();
  NOTREACHED();
  return 0;
}

pp::Resource OutOfProcessInstance::PrintPages(
    const PP_PrintPageNumberRange_Dev* page_ranges,
    uint32_t page_range_count) {
  if (!print_settings_.is_printing)
    return pp::Resource();

  print_settings_.print_pages_called = true;
  return engine_->PrintPages(page_ranges, page_range_count,
                             print_settings_.pepper_print_settings,
                             print_settings_.pdf_print_settings);
}

void OutOfProcessInstance::PrintEnd() {
  if (print_settings_.print_pages_called)
    UserMetricsRecordAction("PDF.PrintPage");
  print_settings_.Clear();
  engine_->PrintEnd();
}

bool OutOfProcessInstance::IsPrintScalingDisabled() {
  return !engine_->GetPrintScaling();
}

bool OutOfProcessInstance::StartFind(const std::string& text,
                                     bool case_sensitive) {
  engine_->StartFind(text, case_sensitive);
  return true;
}

void OutOfProcessInstance::SelectFindResult(bool forward) {
  engine_->SelectFindResult(forward);
}

void OutOfProcessInstance::StopFind() {
  engine_->StopFind();
  tickmarks_.clear();
  SetTickmarks(tickmarks_);
}

void OutOfProcessInstance::OnPaint(const std::vector<pp::Rect>& paint_rects,
                                   std::vector<PaintManager::ReadyRect>* ready,
                                   std::vector<pp::Rect>* pending) {
  if (image_data_.is_null()) {
    DCHECK(plugin_size_.IsEmpty());
    return;
  }
  if (first_paint_) {
    first_paint_ = false;
    pp::Rect rect = pp::Rect(pp::Point(), image_data_.size());
    FillRect(rect, background_color_);
    ready->push_back(PaintManager::ReadyRect(rect, image_data_, true));
  }

  if (!received_viewport_message_ || !needs_reraster_)
    return;

  engine_->PrePaint();

  for (const auto& paint_rect : paint_rects) {
    // Intersect with plugin area since there could be pending invalidates from
    // when the plugin area was larger.
    pp::Rect rect = paint_rect.Intersect(pp::Rect(pp::Point(), plugin_size_));
    if (rect.IsEmpty())
      continue;

    pp::Rect pdf_rect = available_area_.Intersect(rect);
    if (!pdf_rect.IsEmpty()) {
      pdf_rect.Offset(available_area_.x() * -1, 0);

      std::vector<pp::Rect> pdf_ready;
      std::vector<pp::Rect> pdf_pending;
      engine_->Paint(pdf_rect, &image_data_, &pdf_ready, &pdf_pending);
      for (auto& ready_rect : pdf_ready) {
        ready_rect.Offset(available_area_.point());
        ready->push_back(
            PaintManager::ReadyRect(ready_rect, image_data_, false));
      }
      for (auto& pending_rect : pdf_pending) {
        pending_rect.Offset(available_area_.point());
        pending->push_back(pending_rect);
      }
    }

    // Ensure the region above the first page (if any) is filled;
    int32_t first_page_ypos = engine_->GetNumberOfPages() == 0
                                  ? 0
                                  : engine_->GetPageScreenRect(0).y();
    if (rect.y() < first_page_ypos) {
      pp::Rect region = rect.Intersect(pp::Rect(
          pp::Point(), pp::Size(plugin_size_.width(), first_page_ypos)));
      ready->push_back(PaintManager::ReadyRect(region, image_data_, false));
      FillRect(region, background_color_);
    }

    for (const auto& background_part : background_parts_) {
      pp::Rect intersection = background_part.location.Intersect(rect);
      if (!intersection.IsEmpty()) {
        FillRect(intersection, background_part.color);
        ready->push_back(
            PaintManager::ReadyRect(intersection, image_data_, false));
      }
    }
  }

  engine_->PostPaint();
}

void OutOfProcessInstance::DidOpen(int32_t result) {
  if (result == PP_OK) {
    if (!engine_->HandleDocumentLoad(embed_loader_)) {
      document_load_state_ = LOAD_STATE_LOADING;
      DocumentLoadFailed();
    }
  } else if (result != PP_ERROR_ABORTED) {  // Can happen in tests.
    DocumentLoadFailed();
  }
}

void OutOfProcessInstance::DidOpenPreview(int32_t result) {
  if (result == PP_OK) {
    preview_client_ = std::make_unique<PreviewModeClient>(this);
    preview_engine_ = PDFEngine::Create(preview_client_.get(), false);
    preview_engine_->HandleDocumentLoad(embed_preview_loader_);
  } else {
    NOTREACHED();
  }
}

void OutOfProcessInstance::CalculateBackgroundParts() {
  background_parts_.clear();
  int left_width = available_area_.x();
  int right_start = available_area_.right();
  int right_width = abs(plugin_size_.width() - available_area_.right());
  int bottom = std::min(available_area_.bottom(), plugin_size_.height());

  // Add the left, right, and bottom rectangles.  Note: we assume only
  // horizontal centering.
  BackgroundPart part = {pp::Rect(0, 0, left_width, bottom), background_color_};
  if (!part.location.IsEmpty())
    background_parts_.push_back(part);
  part.location = pp::Rect(right_start, 0, right_width, bottom);
  if (!part.location.IsEmpty())
    background_parts_.push_back(part);
  part.location =
      pp::Rect(0, bottom, plugin_size_.width(), plugin_size_.height() - bottom);
  if (!part.location.IsEmpty())
    background_parts_.push_back(part);
}

int OutOfProcessInstance::GetDocumentPixelWidth() const {
  return static_cast<int>(ceil(document_size_.width() * zoom_ * device_scale_));
}

int OutOfProcessInstance::GetDocumentPixelHeight() const {
  return static_cast<int>(
      ceil(document_size_.height() * zoom_ * device_scale_));
}

void OutOfProcessInstance::FillRect(const pp::Rect& rect, uint32_t color) {
  DCHECK(!image_data_.is_null() || rect.IsEmpty());
  uint32_t* buffer_start = static_cast<uint32_t*>(image_data_.data());
  int stride = image_data_.stride();
  uint32_t* ptr = buffer_start + rect.y() * stride / 4 + rect.x();
  int height = rect.height();
  int width = rect.width();
  for (int y = 0; y < height; ++y) {
    for (int x = 0; x < width; ++x)
      *(ptr + x) = color;
    ptr += stride / 4;
  }
}

void OutOfProcessInstance::DocumentSizeUpdated(const pp::Size& size) {
  document_size_ = size;

  pp::VarDictionary dimensions;
  dimensions.Set(kType, kJSDocumentDimensionsType);
  dimensions.Set(kJSDocumentWidth, pp::Var(document_size_.width()));
  dimensions.Set(kJSDocumentHeight, pp::Var(document_size_.height()));
  pp::VarArray page_dimensions_array;
  size_t num_pages = engine_->GetNumberOfPages();
  if (page_is_processed_.size() < num_pages)
    page_is_processed_.resize(num_pages);

  for (size_t i = 0; i < num_pages; ++i) {
    pp::Rect page_rect = engine_->GetPageRect(i);
    pp::VarDictionary page_dimensions;
    page_dimensions.Set(kJSPageX, pp::Var(page_rect.x()));
    page_dimensions.Set(kJSPageY, pp::Var(page_rect.y()));
    page_dimensions.Set(kJSPageWidth, pp::Var(page_rect.width()));
    page_dimensions.Set(kJSPageHeight, pp::Var(page_rect.height()));
    page_dimensions_array.Set(i, page_dimensions);
  }
  dimensions.Set(kJSPageDimensions, page_dimensions_array);
  PostMessage(dimensions);

  OnGeometryChanged(zoom_, device_scale_);
}

void OutOfProcessInstance::Invalidate(const pp::Rect& rect) {
  pp::Rect offset_rect(rect);
  offset_rect.Offset(available_area_.point());
  paint_manager_.InvalidateRect(offset_rect);
}

void OutOfProcessInstance::DidScroll(const pp::Point& point) {
  if (!image_data_.is_null())
    paint_manager_.ScrollRect(available_area_, point);
}

void OutOfProcessInstance::ScrollToX(int x_in_screen_coords) {
  pp::VarDictionary position;
  position.Set(kType, kJSSetScrollPositionType);
  position.Set(kJSPositionX, pp::Var(x_in_screen_coords / device_scale_));
  PostMessage(position);
}

void OutOfProcessInstance::ScrollToY(int y_in_screen_coords,
                                     bool compensate_for_toolbar) {
  pp::VarDictionary position;
  position.Set(kType, kJSSetScrollPositionType);
  float new_y_viewport_coords = y_in_screen_coords / device_scale_;
  if (compensate_for_toolbar) {
    new_y_viewport_coords -= top_toolbar_height_in_viewport_coords_;
  }
  position.Set(kJSPositionY, pp::Var(new_y_viewport_coords));
  PostMessage(position);
}

void OutOfProcessInstance::ScrollBy(const pp::Point& point) {
  pp::VarDictionary position;
  position.Set(kType, kJSScrollByType);
  position.Set(kJSPositionX, pp::Var(point.x() / device_scale_));
  position.Set(kJSPositionY, pp::Var(point.y() / device_scale_));
  PostMessage(position);
}

void OutOfProcessInstance::ScrollToPage(int page) {
  if (engine_->GetNumberOfPages() == 0)
    return;

  pp::VarDictionary message;
  message.Set(kType, kJSGoToPageType);
  message.Set(kJSPageNumber, pp::Var(page));
  PostMessage(message);
}

void OutOfProcessInstance::NavigateTo(const std::string& url,
                                      WindowOpenDisposition disposition) {
  pp::VarDictionary message;
  message.Set(kType, kJSNavigateType);
  message.Set(kJSNavigateUrl, url);
  message.Set(kJSNavigateWindowOpenDisposition,
              pp::Var(static_cast<int32_t>(disposition)));
  PostMessage(message);
}

void OutOfProcessInstance::UpdateCursor(PP_CursorType_Dev cursor) {
  if (cursor == cursor_)
    return;
  cursor_ = cursor;

  const PPB_CursorControl_Dev* cursor_interface =
      reinterpret_cast<const PPB_CursorControl_Dev*>(
          pp::Module::Get()->GetBrowserInterface(
              PPB_CURSOR_CONTROL_DEV_INTERFACE));
  if (!cursor_interface) {
    NOTREACHED();
    return;
  }

  cursor_interface->SetCursor(pp_instance(), cursor_,
                              pp::ImageData().pp_resource(), nullptr);
}

void OutOfProcessInstance::UpdateTickMarks(
    const std::vector<pp::Rect>& tickmarks) {
  float inverse_scale = 1.0f / device_scale_;
  std::vector<pp::Rect> scaled_tickmarks = tickmarks;
  for (auto& tickmark : scaled_tickmarks)
    ScaleRect(inverse_scale, &tickmark);
  tickmarks_ = scaled_tickmarks;
}

void OutOfProcessInstance::NotifyNumberOfFindResultsChanged(int total,
                                                            bool final_result) {
  // We don't want to spam the renderer with too many updates to the number of
  // find results. Don't send an update if we sent one too recently. If it's the
  // final update, we always send it though.
  if (final_result) {
    NumberOfFindResultsChanged(total, final_result);
    SetTickmarks(tickmarks_);
    return;
  }

  if (recently_sent_find_update_)
    return;

  NumberOfFindResultsChanged(total, final_result);
  SetTickmarks(tickmarks_);
  recently_sent_find_update_ = true;
  pp::CompletionCallback callback = callback_factory_.NewCallback(
      &OutOfProcessInstance::ResetRecentlySentFindUpdate);
  pp::Module::Get()->core()->CallOnMainThread(kFindResultCooldownMs, callback,
                                              0);
}

void OutOfProcessInstance::NotifySelectedFindResultChanged(
    int current_find_index) {
  DCHECK_GE(current_find_index, -1);
  SelectedFindResultChanged(current_find_index);
}

void OutOfProcessInstance::NotifyPageBecameVisible(
    const PDFEngine::PageFeatures* page_features) {
  if (!page_features || !page_features->IsInitialized() ||
      page_features->index >= static_cast<int>(page_is_processed_.size()) ||
      page_is_processed_[page_features->index]) {
    return;
  }

  for (const int annotation_type : page_features->annotation_types) {
    DCHECK_GE(annotation_type, 0);
    DCHECK_LT(annotation_type, kAnnotationTypesCount);
    if (annotation_type < 0 || annotation_type >= kAnnotationTypesCount)
      continue;

    if (annotation_types_counted_.find(annotation_type) ==
        annotation_types_counted_.end()) {
      HistogramEnumeration("PDF.AnnotationType", annotation_type,
                           kAnnotationTypesCount);
      annotation_types_counted_.insert(annotation_type);
    }
  }
  page_is_processed_[page_features->index] = true;
}

void OutOfProcessInstance::GetDocumentPassword(
    pp::CompletionCallbackWithOutput<pp::Var> callback) {
  if (password_callback_) {
    NOTREACHED();
    return;
  }

  password_callback_ =
      std::make_unique<pp::CompletionCallbackWithOutput<pp::Var>>(callback);
  pp::VarDictionary message;
  message.Set(pp::Var(kType), pp::Var(kJSGetPasswordType));
  PostMessage(message);
}

void OutOfProcessInstance::Beep() {
  pp::VarDictionary message;
  message.Set(pp::Var(kType), pp::Var(kJSBeepType));
  PostMessage(message);
}

void OutOfProcessInstance::Alert(const std::string& message) {
  pp::PDF::ShowAlertDialog(this, message.c_str());
}

bool OutOfProcessInstance::Confirm(const std::string& message) {
  return pp::PDF::ShowConfirmDialog(this, message.c_str());
}

std::string OutOfProcessInstance::Prompt(const std::string& question,
                                         const std::string& default_answer) {
  pp::Var result =
      pp::PDF::ShowPromptDialog(this, question.c_str(), default_answer.c_str());
  return result.is_string() ? result.AsString() : std::string();
}

std::string OutOfProcessInstance::GetURL() {
  return url_;
}

void OutOfProcessInstance::Email(const std::string& to,
                                 const std::string& cc,
                                 const std::string& bcc,
                                 const std::string& subject,
                                 const std::string& body) {
  pp::VarDictionary message;
  message.Set(pp::Var(kType), pp::Var(kJSEmailType));
  message.Set(pp::Var(kJSEmailTo),
              pp::Var(net::EscapeUrlEncodedData(to, false)));
  message.Set(pp::Var(kJSEmailCc),
              pp::Var(net::EscapeUrlEncodedData(cc, false)));
  message.Set(pp::Var(kJSEmailBcc),
              pp::Var(net::EscapeUrlEncodedData(bcc, false)));
  message.Set(pp::Var(kJSEmailSubject),
              pp::Var(net::EscapeUrlEncodedData(subject, false)));
  message.Set(pp::Var(kJSEmailBody),
              pp::Var(net::EscapeUrlEncodedData(body, false)));
  PostMessage(message);
}

void OutOfProcessInstance::Print() {
  if (!engine_->HasPermission(PDFEngine::PERMISSION_PRINT_LOW_QUALITY) &&
      !engine_->HasPermission(PDFEngine::PERMISSION_PRINT_HIGH_QUALITY)) {
    return;
  }

  pp::CompletionCallback callback =
      callback_factory_.NewCallback(&OutOfProcessInstance::OnPrint);
  pp::Module::Get()->core()->CallOnMainThread(0, callback);
}

void OutOfProcessInstance::OnPrint(int32_t) {
  pp::PDF::Print(this);
}

void OutOfProcessInstance::SubmitForm(const std::string& url,
                                      const void* data,
                                      int length) {
  pp::URLRequestInfo request(this);
  request.SetURL(url);
  request.SetMethod("POST");
  request.AppendDataToBody(reinterpret_cast<const char*>(data), length);

  pp::CompletionCallback callback =
      callback_factory_.NewCallback(&OutOfProcessInstance::FormDidOpen);
  form_loader_ = CreateURLLoaderInternal();
  int rv = form_loader_.Open(request, callback);
  if (rv != PP_OK_COMPLETIONPENDING)
    callback.Run(rv);
}

void OutOfProcessInstance::FormDidOpen(int32_t result) {
  // TODO: inform the user of success/failure.
  if (result != PP_OK) {
    LOG(ERROR) << "FormDidOpen failed: " << result;
  }
}

pp::URLLoader OutOfProcessInstance::CreateURLLoader() {
  if (full_) {
    if (!did_call_start_loading_) {
      did_call_start_loading_ = true;
      pp::PDF::DidStartLoading(this);
    }

    // Disable save and print until the document is fully loaded, since they
    // would generate an incomplete document.  Need to do this each time we
    // call DidStartLoading since that resets the content restrictions.
    pp::PDF::SetContentRestriction(
        this, CONTENT_RESTRICTION_SAVE | CONTENT_RESTRICTION_PRINT);
  }

  return CreateURLLoaderInternal();
}

std::vector<PDFEngine::Client::SearchStringResult>
OutOfProcessInstance::SearchString(const base::char16* string,
                                   const base::char16* term,
                                   bool case_sensitive) {
  PP_PrivateFindResult* pp_results;
  uint32_t count = 0;
  pp::PDF::SearchString(this, reinterpret_cast<const unsigned short*>(string),
                        reinterpret_cast<const unsigned short*>(term),
                        case_sensitive, &pp_results, &count);

  std::vector<SearchStringResult> results(count);
  for (uint32_t i = 0; i < count; ++i) {
    results[i].start_index = pp_results[i].start_index;
    results[i].length = pp_results[i].length;
  }

  pp::Memory_Dev memory;
  memory.MemFree(pp_results);

  return results;
}

void OutOfProcessInstance::DocumentPaintOccurred() {}

void OutOfProcessInstance::DocumentLoadComplete(
    const PDFEngine::DocumentFeatures& document_features,
    uint32_t file_size) {
  // Clear focus state for OSK.
  FormTextFieldFocusChange(false);

  DCHECK_EQ(LOAD_STATE_LOADING, document_load_state_);
  document_load_state_ = LOAD_STATE_COMPLETE;
  UserMetricsRecordAction("PDF.LoadSuccess");
  HistogramEnumeration("PDF.DocumentFeature", LOADED_DOCUMENT, FEATURES_COUNT);
  if (!font_substitution_reported_)
    HistogramEnumeration("PDF.IsFontSubstituted", 0, 2);

  // Note: If we are in print preview mode the scroll location is retained
  // across document loads so we don't want to scroll again and override it.
  if (IsPrintPreview()) {
    if (IsPreviewingPDF(print_preview_page_count_)) {
      SendPrintPreviewLoadedNotification();
    } else {
      DCHECK_EQ(0, print_preview_loaded_page_count_);
      print_preview_loaded_page_count_ = 1;
      AppendBlankPrintPreviewPages();
    }
    OnGeometryChanged(0, 0);
  }

  pp::VarDictionary metadata_message;
  metadata_message.Set(pp::Var(kType), pp::Var(kJSMetadataType));
  std::string title = engine_->GetMetadata("Title");
  if (!base::TrimWhitespace(base::UTF8ToUTF16(title), base::TRIM_ALL).empty()) {
    metadata_message.Set(pp::Var(kJSTitle), pp::Var(title));
    HistogramEnumeration("PDF.DocumentFeature", HAS_TITLE, FEATURES_COUNT);
  }

  pp::VarArray bookmarks = engine_->GetBookmarks();
  metadata_message.Set(pp::Var(kJSBookmarks), bookmarks);
  if (bookmarks.GetLength() > 0)
    HistogramEnumeration("PDF.DocumentFeature", HAS_BOOKMARKS, FEATURES_COUNT);
  PostMessage(metadata_message);

  pp::VarDictionary progress_message;
  progress_message.Set(pp::Var(kType), pp::Var(kJSLoadProgressType));
  progress_message.Set(pp::Var(kJSProgressPercentage), pp::Var(100));
  PostMessage(progress_message);

  if (accessibility_state_ == ACCESSIBILITY_STATE_PENDING)
    LoadAccessibility();

  if (!full_)
    return;

  if (did_call_start_loading_) {
    pp::PDF::DidStopLoading(this);
    did_call_start_loading_ = false;
  }

  int content_restrictions =
      CONTENT_RESTRICTION_CUT | CONTENT_RESTRICTION_PASTE;
  if (!engine_->HasPermission(PDFEngine::PERMISSION_COPY))
    content_restrictions |= CONTENT_RESTRICTION_COPY;

  if (!engine_->HasPermission(PDFEngine::PERMISSION_PRINT_LOW_QUALITY) &&
      !engine_->HasPermission(PDFEngine::PERMISSION_PRINT_HIGH_QUALITY)) {
    content_restrictions |= CONTENT_RESTRICTION_PRINT;
  }

  pp::PDF::SetContentRestriction(this, content_restrictions);
  static const int32_t kMaxFileSizeInKB = 12 * 1024 * 1024;
  HistogramCustomCounts("PDF.FileSizeInKB", file_size / 1024, 0,
                        kMaxFileSizeInKB, 50);
  HistogramCustomCounts("PDF.PageCount", document_features.page_count, 1,
                        1000000, 50);
  HistogramEnumeration("PDF.HasAttachment",
                       document_features.has_attachments ? 1 : 0, 2);
  HistogramEnumeration("PDF.IsLinearized",
                       document_features.is_linearized ? 1 : 0, 2);
  HistogramEnumeration("PDF.IsTagged", document_features.is_tagged ? 1 : 0, 2);
  HistogramEnumeration("PDF.FormType",
                       static_cast<int32_t>(document_features.form_type),
                       static_cast<int32_t>(PDFEngine::FormType::kCount));
}

void OutOfProcessInstance::RotateClockwise() {
  PrintPreviewHistogramEnumeration(ROTATE);
  engine_->RotateClockwise();
}

void OutOfProcessInstance::RotateCounterclockwise() {
  PrintPreviewHistogramEnumeration(ROTATE);
  engine_->RotateCounterclockwise();
}

void OutOfProcessInstance::PreviewDocumentLoadComplete() {
  if (preview_document_load_state_ != LOAD_STATE_LOADING ||
      preview_pages_info_.empty()) {
    return;
  }

  preview_document_load_state_ = LOAD_STATE_COMPLETE;

  int dest_page_index = preview_pages_info_.front().second;
  DCHECK_GT(dest_page_index, 0);
  preview_pages_info_.pop();
  DCHECK(preview_engine_);
  engine_->AppendPage(preview_engine_.get(), dest_page_index);

  ++print_preview_loaded_page_count_;
  LoadNextPreviewPage();
}

void OutOfProcessInstance::DocumentLoadFailed() {
  DCHECK_EQ(LOAD_STATE_LOADING, document_load_state_);
  UserMetricsRecordAction("PDF.LoadFailure");

  if (did_call_start_loading_) {
    pp::PDF::DidStopLoading(this);
    did_call_start_loading_ = false;
  }

  document_load_state_ = LOAD_STATE_FAILED;
  paint_manager_.InvalidateRect(pp::Rect(pp::Point(), plugin_size_));

  // Send a progress value of -1 to indicate a failure.
  pp::VarDictionary message;
  message.Set(pp::Var(kType), pp::Var(kJSLoadProgressType));
  message.Set(pp::Var(kJSProgressPercentage), pp::Var(-1));
  PostMessage(message);
}

void OutOfProcessInstance::FontSubstituted() {
  if (font_substitution_reported_)
    return;
  font_substitution_reported_ = true;
  uma_.HistogramEnumeration("PDF.IsFontSubstituted", 1, 2);
}

void OutOfProcessInstance::PreviewDocumentLoadFailed() {
  UserMetricsRecordAction("PDF.PreviewDocumentLoadFailure");
  if (preview_document_load_state_ != LOAD_STATE_LOADING ||
      preview_pages_info_.empty()) {
    return;
  }

  // Even if a print preview page failed to load, keep going.
  preview_document_load_state_ = LOAD_STATE_FAILED;
  preview_pages_info_.pop();
  ++print_preview_loaded_page_count_;
  LoadNextPreviewPage();
}

pp::Instance* OutOfProcessInstance::GetPluginInstance() {
  return this;
}

void OutOfProcessInstance::DocumentHasUnsupportedFeature(
    const std::string& feature) {
  DCHECK(!feature.empty());
  std::string metric("PDF_Unsupported_");
  metric += feature;
  if (!unsupported_features_reported_.count(metric)) {
    unsupported_features_reported_.insert(metric);
    UserMetricsRecordAction(metric);
  }

  // Since we use an info bar, only do this for full frame plugins..
  if (!full_)
    return;

  if (told_browser_about_unsupported_feature_)
    return;
  told_browser_about_unsupported_feature_ = true;

  pp::PDF::HasUnsupportedFeature(this);
}

void OutOfProcessInstance::DocumentLoadProgress(uint32_t available,
                                                uint32_t doc_size) {
  double progress = 0.0;
  if (doc_size) {
    progress = 100.0 * static_cast<double>(available) / doc_size;
  } else {
    // Document size is unknown. Use heuristics.
    // We'll make progress logarithmic from 0 to 100M.
    static const double kFactor = log(100000000.0) / 100.0;
    if (available > 0)
      progress = std::min(log(static_cast<double>(available)) / kFactor, 100.0);
  }

  // We send 100% load progress in DocumentLoadComplete.
  if (progress >= 100)
    return;

  // Avoid sending too many progress messages over PostMessage.
  if (progress > last_progress_sent_ + 1) {
    last_progress_sent_ = progress;
    pp::VarDictionary message;
    message.Set(pp::Var(kType), pp::Var(kJSLoadProgressType));
    message.Set(pp::Var(kJSProgressPercentage), pp::Var(progress));
    PostMessage(message);
  }
}

void OutOfProcessInstance::FormTextFieldFocusChange(bool in_focus) {
  if (!text_input_)
    return;

  pp::VarDictionary message;
  message.Set(pp::Var(kType), pp::Var(kJSFieldFocusType));
  message.Set(pp::Var(kJSFieldFocus), pp::Var(in_focus));
  PostMessage(message);

  text_input_->SetTextInputType(in_focus ? PP_TEXTINPUT_TYPE_DEV_TEXT
                                         : PP_TEXTINPUT_TYPE_DEV_NONE);
}

void OutOfProcessInstance::ResetRecentlySentFindUpdate(int32_t /* unused */) {
  recently_sent_find_update_ = false;
}

void OutOfProcessInstance::OnGeometryChanged(double old_zoom,
                                             float old_device_scale) {
  if (zoom_ != old_zoom || device_scale_ != old_device_scale)
    engine_->ZoomUpdated(zoom_ * device_scale_);

  available_area_ = pp::Rect(plugin_size_);
  int doc_width = GetDocumentPixelWidth();
  if (doc_width < available_area_.width()) {
    available_area_.Offset((available_area_.width() - doc_width) / 2, 0);
    available_area_.set_width(doc_width);
  }
  int bottom_of_document =
      GetDocumentPixelHeight() +
      (top_toolbar_height_in_viewport_coords_ * device_scale_);
  if (bottom_of_document < available_area_.height())
    available_area_.set_height(bottom_of_document);

  CalculateBackgroundParts();
  engine_->PageOffsetUpdated(available_area_.point());
  engine_->PluginSizeUpdated(available_area_.size());

  if (document_size_.IsEmpty())
    return;
  paint_manager_.InvalidateRect(pp::Rect(pp::Point(), plugin_size_));

  if (accessibility_state_ == ACCESSIBILITY_STATE_LOADED)
    SendAccessibilityViewportInfo();
}

void OutOfProcessInstance::LoadUrl(const std::string& url,
                                   bool is_print_preview) {
  pp::URLRequestInfo request(this);
  request.SetURL(url);
  request.SetMethod("GET");
  request.SetFollowRedirects(false);

  pp::URLLoader* loader =
      is_print_preview ? &embed_preview_loader_ : &embed_loader_;
  *loader = CreateURLLoaderInternal();
  pp::CompletionCallback callback = callback_factory_.NewCallback(
      is_print_preview ? &OutOfProcessInstance::DidOpenPreview
                       : &OutOfProcessInstance::DidOpen);
  int rv = loader->Open(request, callback);
  if (rv != PP_OK_COMPLETIONPENDING)
    callback.Run(rv);
}

pp::URLLoader OutOfProcessInstance::CreateURLLoaderInternal() {
  pp::URLLoader loader(this);

  const PPB_URLLoaderTrusted* trusted_interface =
      reinterpret_cast<const PPB_URLLoaderTrusted*>(
          pp::Module::Get()->GetBrowserInterface(
              PPB_URLLOADERTRUSTED_INTERFACE));
  if (trusted_interface)
    trusted_interface->GrantUniversalAccess(loader.pp_resource());
  return loader;
}

void OutOfProcessInstance::SetZoom(double scale) {
  double old_zoom = zoom_;
  zoom_ = scale;
  OnGeometryChanged(old_zoom, device_scale_);
}

void OutOfProcessInstance::AppendBlankPrintPreviewPages() {
  engine_->AppendBlankPages(print_preview_page_count_);
  LoadNextPreviewPage();
}

bool OutOfProcessInstance::IsPrintPreview() {
  return is_print_preview_;
}

uint32_t OutOfProcessInstance::GetBackgroundColor() {
  return background_color_;
}

void OutOfProcessInstance::CancelBrowserDownload() {
  pp::VarDictionary message;
  message.Set(kType, kJSCancelStreamUrlType);
  PostMessage(message);
}

void OutOfProcessInstance::IsSelectingChanged(bool is_selecting) {
  pp::VarDictionary message;
  message.Set(kType, kJSSetIsSelectingType);
  message.Set(kJSIsSelecting, pp::Var(is_selecting));
  PostMessage(message);
  if (is_selecting)
    PrintPreviewHistogramEnumeration(SELECT_TEXT);
}

void OutOfProcessInstance::IsEditModeChanged(bool is_edit_mode) {
  pp::VarDictionary message;
  message.Set(kType, kJSSetIsEditModeType);
  message.Set(kJSIsEditMode, pp::Var(is_edit_mode));
  PostMessage(message);
}

float OutOfProcessInstance::GetToolbarHeightInScreenCoords() {
  return top_toolbar_height_in_viewport_coords_ * device_scale_;
}

void OutOfProcessInstance::ProcessPreviewPageInfo(const std::string& url,
                                                  int dest_page_index) {
  DCHECK(IsPrintPreview());

  if (dest_page_index < 0 || dest_page_index >= print_preview_page_count_) {
    NOTREACHED();
    return;
  }

  // Print Preview JS will send the loadPreviewPage message for every page,
  // including the first page in the print preview, which has already been
  // loaded when handing the resetPrintPreviewMode message. Just ignore it.
  if (dest_page_index == 0)
    return;

  int src_page_index = ExtractPrintPreviewPageIndex(url);
  if (src_page_index < 0) {
    NOTREACHED();
    return;
  }

  preview_pages_info_.push(std::make_pair(url, dest_page_index));
  LoadAvailablePreviewPage();
}

void OutOfProcessInstance::LoadAvailablePreviewPage() {
  if (preview_pages_info_.empty() ||
      document_load_state_ != LOAD_STATE_COMPLETE ||
      preview_document_load_state_ == LOAD_STATE_LOADING) {
    return;
  }

  preview_document_load_state_ = LOAD_STATE_LOADING;
  const std::string& url = preview_pages_info_.front().first;
  LoadUrl(url, /*is_print_preview=*/true);
}

void OutOfProcessInstance::LoadNextPreviewPage() {
  if (!preview_pages_info_.empty()) {
    DCHECK_LT(print_preview_loaded_page_count_, print_preview_page_count_);
    LoadAvailablePreviewPage();
    return;
  }

  if (print_preview_loaded_page_count_ == print_preview_page_count_) {
    SendPrintPreviewLoadedNotification();
  }
}

void OutOfProcessInstance::SendPrintPreviewLoadedNotification() {
  pp::VarDictionary loaded_message;
  loaded_message.Set(pp::Var(kType), pp::Var(kJSPreviewLoadedType));
  PostMessage(loaded_message);
}

void OutOfProcessInstance::UserMetricsRecordAction(const std::string& action) {
  // TODO(raymes): Move this function to PPB_UMA_Private.
  pp::PDF::UserMetricsRecordAction(this, pp::Var(action));
}

pp::FloatPoint OutOfProcessInstance::BoundScrollOffsetToDocument(
    const pp::FloatPoint& scroll_offset) {
  float max_x = document_size_.width() * zoom_ - plugin_dip_size_.width();
  float x = std::max(std::min(scroll_offset.x(), max_x), 0.0f);
  float min_y = -top_toolbar_height_in_viewport_coords_;
  float max_y = document_size_.height() * zoom_ - plugin_dip_size_.height();
  float y = std::max(std::min(scroll_offset.y(), max_y), min_y);
  return pp::FloatPoint(x, y);
}

void OutOfProcessInstance::HistogramCustomCounts(const std::string& name,
                                                 int32_t sample,
                                                 int32_t min,
                                                 int32_t max,
                                                 uint32_t bucket_count) {
  if (IsPrintPreview())
    return;

  uma_.HistogramCustomCounts(name, sample, min, max, bucket_count);
}

void OutOfProcessInstance::HistogramEnumeration(const std::string& name,
                                                int32_t sample,
                                                int32_t boundary_value) {
  if (IsPrintPreview())
    return;
  uma_.HistogramEnumeration(name, sample, boundary_value);
}

void OutOfProcessInstance::PrintPreviewHistogramEnumeration(int32_t sample) {
  if (!IsPrintPreview())
    return;
  if (preview_action_recorded_[sample])
    return;
  uma_.HistogramEnumeration("PrintPreview.PdfAction", sample,
                            PDFACTION_BUCKET_BOUNDARY);
  preview_action_recorded_[sample] = true;
}

void OutOfProcessInstance::PrintSettings::Clear() {
  is_printing = false;
  print_pages_called = false;
  memset(&pepper_print_settings, 0, sizeof(pepper_print_settings));
  memset(&pdf_print_settings, 0, sizeof(pdf_print_settings));
}

}  // namespace chrome_pdf
