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

#include <algorithm>  // for min()
#define _USE_MATH_DEFINES  // for M_PI
#include <cmath>      // for log() and pow()
#include <math.h>
#include <list>

#include "base/json/json_reader.h"
#include "base/json/json_writer.h"
#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/values.h"
#include "chrome/browser/chrome_page_zoom_constants.h"
#include "chrome/common/content_restriction.h"
#include "content/public/common/page_zoom.h"
#include "net/base/escape.h"
#include "pdf/draw_utils.h"
#include "pdf/number_image_generator.h"
#include "pdf/pdf.h"
#include "pdf/resource_consts.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/ppp_pdf.h"
#include "ppapi/c/trusted/ppb_url_loader_trusted.h"
#include "ppapi/cpp/core.h"
#include "ppapi/cpp/dev/font_dev.h"
#include "ppapi/cpp/dev/memory_dev.h"
#include "ppapi/cpp/dev/text_input_dev.h"
#include "ppapi/cpp/module.h"
#include "ppapi/cpp/point.h"
#include "ppapi/cpp/private/pdf.h"
#include "ppapi/cpp/rect.h"
#include "ppapi/cpp/resource.h"
#include "ppapi/cpp/url_request_info.h"
#include "ui/events/keycodes/keyboard_codes.h"

#if defined(OS_MACOSX)
#include "base/mac/mac_util.h"
#endif

namespace chrome_pdf {

struct ToolbarButtonInfo {
  uint32 id;
  Button::ButtonStyle style;
  PP_ResourceImage normal;
  PP_ResourceImage highlighted;
  PP_ResourceImage pressed;
};

namespace {

// Uncomment following #define to enable thumbnails.
// #define ENABLE_THUMBNAILS

const uint32 kToolbarSplashTimeoutMs = 6000;
const uint32 kMessageTextColor = 0xFF575757;
const uint32 kMessageTextSize = 22;
const uint32 kProgressFadeTimeoutMs = 250;
const uint32 kProgressDelayTimeoutMs = 1000;
const uint32 kAutoScrollTimeoutMs = 50;
const double kAutoScrollFactor = 0.2;

// Javascript methods.
const char* kJSAccessibility = "accessibility";
const char* kJSDocumentLoadComplete = "documentLoadComplete";
const char* kJSGetHeight = "getHeight";
const char* kJSGetHorizontalScrollbarThickness =
    "getHorizontalScrollbarThickness";
const char* kJSGetPageLocationNormalized = "getPageLocationNormalized";
const char* kJSGetVerticalScrollbarThickness = "getVerticalScrollbarThickness";
const char* kJSGetWidth = "getWidth";
const char* kJSGetZoomLevel = "getZoomLevel";
const char* kJSGoToPage = "goToPage";
const char* kJSGrayscale = "grayscale";
const char* kJSLoadPreviewPage = "loadPreviewPage";
const char* kJSOnLoad = "onload";
const char* kJSOnPluginSizeChanged = "onPluginSizeChanged";
const char* kJSOnScroll = "onScroll";
const char* kJSPageXOffset = "pageXOffset";
const char* kJSPageYOffset = "pageYOffset";
const char* kJSPrintPreviewPageCount = "printPreviewPageCount";
const char* kJSReload = "reload";
const char* kJSRemovePrintButton = "removePrintButton";
const char* kJSResetPrintPreviewUrl = "resetPrintPreviewUrl";
const char* kJSSendKeyEvent = "sendKeyEvent";
const char* kJSSetPageNumbers = "setPageNumbers";
const char* kJSSetPageXOffset = "setPageXOffset";
const char* kJSSetPageYOffset = "setPageYOffset";
const char* kJSSetZoomLevel = "setZoomLevel";
const char* kJSZoomFitToHeight = "fitToHeight";
const char* kJSZoomFitToWidth = "fitToWidth";
const char* kJSZoomIn = "zoomIn";
const char* kJSZoomOut = "zoomOut";

// URL reference parameters.
// For more possible parameters, see RFC 3778 and the "PDF Open Parameters"
// document from Adobe.
const char kDelimiters[] = "#&";
const char kNamedDest[] = "nameddest";
const char kPage[] = "page";

const char kChromePrint[] = "chrome://print/";

// Dictionary Value key names for the document accessibility info
const char kAccessibleNumberOfPages[] = "numberOfPages";
const char kAccessibleLoaded[] = "loaded";
const char kAccessibleCopyable[] = "copyable";

const ToolbarButtonInfo kPDFToolbarButtons[] = {
  { kFitToPageButtonId, Button::BUTTON_STATE,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTP,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTP_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTP_PRESSED },
  { kFitToWidthButtonId, Button::BUTTON_STATE,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTW,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTW_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTW_PRESSED },
  { kZoomOutButtonId, Button::BUTTON_CLICKABLE,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT_PRESSED },
  { kZoomInButtonId, Button::BUTTON_CLICKABLE,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_PRESSED },
  { kSaveButtonId, Button::BUTTON_CLICKABLE,
      PP_RESOURCEIMAGE_PDF_BUTTON_SAVE,
      PP_RESOURCEIMAGE_PDF_BUTTON_SAVE_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_SAVE_PRESSED },
  { kPrintButtonId, Button::BUTTON_CLICKABLE,
      PP_RESOURCEIMAGE_PDF_BUTTON_PRINT,
      PP_RESOURCEIMAGE_PDF_BUTTON_PRINT_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_PRINT_PRESSED },
};

const ToolbarButtonInfo kPDFNoPrintToolbarButtons[] = {
  { kFitToPageButtonId, Button::BUTTON_STATE,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTP,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTP_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTP_PRESSED },
  { kFitToWidthButtonId, Button::BUTTON_STATE,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTW,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTW_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTW_PRESSED },
  { kZoomOutButtonId, Button::BUTTON_CLICKABLE,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT_PRESSED },
  { kZoomInButtonId, Button::BUTTON_CLICKABLE,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_PRESSED },
  { kSaveButtonId, Button::BUTTON_CLICKABLE,
      PP_RESOURCEIMAGE_PDF_BUTTON_SAVE,
      PP_RESOURCEIMAGE_PDF_BUTTON_SAVE_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_SAVE_PRESSED },
  { kPrintButtonId, Button::BUTTON_CLICKABLE,
      PP_RESOURCEIMAGE_PDF_BUTTON_PRINT_DISABLED,
      PP_RESOURCEIMAGE_PDF_BUTTON_PRINT_DISABLED,
      PP_RESOURCEIMAGE_PDF_BUTTON_PRINT_DISABLED }
};

const ToolbarButtonInfo kPrintPreviewToolbarButtons[] = {
  { kFitToPageButtonId, Button::BUTTON_STATE,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTP,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTP_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTP_PRESSED },
  { kFitToWidthButtonId, Button::BUTTON_STATE,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTW,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTW_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_FTW_PRESSED },
  { kZoomOutButtonId, Button::BUTTON_CLICKABLE,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMOUT_PRESSED },
  { kZoomInButtonId, Button::BUTTON_CLICKABLE,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_END,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_END_HOVER,
      PP_RESOURCEIMAGE_PDF_BUTTON_ZOOMIN_END_PRESSED },
};

static const char kPPPPdfInterface[] = PPP_PDF_INTERFACE_1;

PP_Var GetLinkAtPosition(PP_Instance instance, PP_Point point) {
  pp::Var var;
  void* object =
      pp::Instance::GetPerInstanceObject(instance, kPPPPdfInterface);
  if (object)
    var = static_cast<Instance*>(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) {
    Instance* obj_instance = static_cast<Instance*>(object);
    switch (type) {
      case PP_PRIVATEPAGETRANSFORMTYPE_ROTATE_90_CW:
        obj_instance->RotateClockwise();
        break;
      case PP_PRIVATEPAGETRANSFORMTYPE_ROTATE_90_CCW:
        obj_instance->RotateCounterclockwise();
        break;
    }
  }
}

const PPP_Pdf ppp_private = {
  &GetLinkAtPosition,
  &Transform
};

int ExtractPrintPreviewPageIndex(const std::string& src_url) {
  // Sample |src_url| format: chrome://print/id/page_index/print.pdf
  std::vector<std::string> url_substr;
  base::SplitString(src_url.substr(strlen(kChromePrint)), '/', &url_substr);
  if (url_substr.size() != 3)
    return -1;

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

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

bool IsPrintPreviewUrl(const std::string& url) {
  return url.substr(0, strlen(kChromePrint)) == kChromePrint;
}

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);
}

template<class T>
T ClipToRange(T value, T lower_boundary, T upper_boundary) {
  DCHECK(lower_boundary <= upper_boundary);
  return std::max<T>(lower_boundary, std::min<T>(value, upper_boundary));
}

}  // namespace

Instance::Instance(PP_Instance instance)
    : pp::InstancePrivate(instance),
      pp::Find_Private(this),
      pp::Printing_Dev(this),
      pp::Selection_Dev(this),
      pp::WidgetClient_Dev(this),
      pp::Zoom_Dev(this),
      cursor_(PP_CURSORTYPE_POINTER),
      timer_pending_(false),
      current_timer_id_(0),
      zoom_(1.0),
      device_scale_(1.0),
      printing_enabled_(true),
      hidpi_enabled_(false),
      full_(IsFullFrame()),
      zoom_mode_(full_ ? ZOOM_AUTO : ZOOM_SCALE),
      did_call_start_loading_(false),
      is_autoscroll_(false),
      scrollbar_thickness_(-1),
      scrollbar_reserved_thickness_(-1),
      current_tb_info_(NULL),
      current_tb_info_size_(0),
      paint_manager_(this, this, true),
      delayed_progress_timer_id_(0),
      first_paint_(true),
      painted_first_page_(false),
      show_page_indicator_(false),
      document_load_state_(LOAD_STATE_LOADING),
      preview_document_load_state_(LOAD_STATE_COMPLETE),
      told_browser_about_unsupported_feature_(false),
      print_preview_page_count_(0) {
  loader_factory_.Initialize(this);
  timer_factory_.Initialize(this);
  form_factory_.Initialize(this);
  print_callback_factory_.Initialize(this);
  engine_.reset(PDFEngine::Create(this));
  pp::Module::Get()->AddPluginInterface(kPPPPdfInterface, &ppp_private);
  AddPerInstanceObject(kPPPPdfInterface, this);

  RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_MOUSE);
  RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_WHEEL);
  RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_KEYBOARD);
  RequestFilteringInputEvents(PP_INPUTEVENT_CLASS_TOUCH);
}

Instance::~Instance() {
  RemovePerInstanceObject(kPPPPdfInterface, this);
}

bool Instance::Init(uint32_t argc, const char* argn[], const char* argv[]) {
  // For now, we hide HiDPI support behind a flag.
  if (pp::PDF::IsFeatureEnabled(this, PP_PDFFEATURE_HIDPI))
    hidpi_enabled_ = true;

  printing_enabled_ = pp::PDF::IsFeatureEnabled(this, PP_PDFFEATURE_PRINTING);
  if (printing_enabled_) {
    CreateToolbar(kPDFToolbarButtons, arraysize(kPDFToolbarButtons));
  } else {
    CreateToolbar(kPDFNoPrintToolbarButtons,
                  arraysize(kPDFNoPrintToolbarButtons));
  }

  CreateProgressBar();

  // Load autoscroll anchor image.
  autoscroll_anchor_ =
      CreateResourceImage(PP_RESOURCEIMAGE_PDF_PAN_SCROLL_ICON);

#ifdef ENABLE_THUMBNAILS
  CreateThumbnails();
#endif
  const char* url = NULL;
  for (uint32_t i = 0; i < argc; ++i) {
    if (strcmp(argn[i], "src") == 0) {
      url = argv[i];
      break;
    }
  }

  if (!url)
    return false;

  CreatePageIndicator(IsPrintPreviewUrl(url));

  if (!full_) {
    // For PDFs embedded in a frame, we don't get the data automatically like we
    // do for full-frame loads.  Start loading the data manually.
    LoadUrl(url);
  }

  ZoomLimitsChanged(kMinZoom, kMaxZoom);

  text_input_.reset(new pp::TextInput_Dev(this));

  url_ = url;
  return engine_->New(url);
}

bool Instance::HandleDocumentLoad(const pp::URLLoader& loader) {
  delayed_progress_timer_id_ = ScheduleTimer(kProgressBarId,
                                             kProgressDelayTimeoutMs);
  return engine_->HandleDocumentLoad(loader);
}

bool Instance::HandleInputEvent(const pp::InputEvent& event) {
  // To simplify things, convert the event into device coordinates if it is
  // a mouse event.
  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);
      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;
    }
  }

  // Check if we need to go to autoscroll mode.
  if (event.GetType() == PP_INPUTEVENT_TYPE_MOUSEMOVE &&
     (event.GetModifiers() & PP_INPUTEVENT_MODIFIER_MIDDLEBUTTONDOWN)) {
    pp::MouseInputEvent mouse_event(event_device_res);
    pp::Point pos = mouse_event.GetPosition();
    EnableAutoscroll(pos);
    UpdateCursor(CalculateAutoscroll(pos));
    return true;
  } else {
    // Quit autoscrolling on any other event.
    DisableAutoscroll();
  }

#ifdef ENABLE_THUMBNAILS
  if (event.GetType() == PP_INPUTEVENT_TYPE_MOUSELEAVE)
    thumbnails_.SlideOut();

  if (thumbnails_.HandleEvent(event_device_res))
    return true;
#endif

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

#ifdef ENABLE_THUMBNAILS
  if (v_scrollbar_.get() && event.GetType() == PP_INPUTEVENT_TYPE_MOUSEMOVE) {
    pp::MouseInputEvent mouse_event(event);
    pp::Point pt = mouse_event.GetPosition();
    pp::Rect v_scrollbar_rc;
    v_scrollbar_->GetLocation(&v_scrollbar_rc);
    // There is a bug (https://bugs.webkit.org/show_bug.cgi?id=45208)
    // in the webkit that makes event.u.mouse.button
    // equal to PP_INPUTEVENT_MOUSEBUTTON_LEFT, even when no button is pressed.
    // To work around this issue we use modifier for now, and will switch
    // to button once the bug is fixed and webkit got merged back to our tree.
    if (v_scrollbar_rc.Contains(pt) &&
        (event.GetModifiers() & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN)) {
      thumbnails_.SlideIn();
    }

    // When scrollbar is in the scrolling mode we should display thumbnails
    // even the mouse is outside the thumbnail and scrollbar areas.
    // If mouse is outside plugin area, we are still getting mouse move events
    // while scrolling. See bug description for details:
    // http://code.google.com/p/chromium/issues/detail?id=56444
    if (!v_scrollbar_rc.Contains(pt) && thumbnails_.visible() &&
        !(event.GetModifiers() & PP_INPUTEVENT_MODIFIER_LEFTBUTTONDOWN) &&
        !thumbnails_.rect().Contains(pt)) {
      thumbnails_.SlideOut();
    }
  }
#endif

  // Need to pass the event to the engine first, since if we're over an edit
  // control we want it to get keyboard events (like space) instead of the
  // scrollbar.
  // TODO: will have to offset the mouse coordinates once we support bidi and
  // there could be scrollbars on the left.
  pp::InputEvent offset_event(event_device_res);
  bool try_engine_first = true;
  switch (offset_event.GetType()) {
    case PP_INPUTEVENT_TYPE_MOUSEDOWN:
    case PP_INPUTEVENT_TYPE_MOUSEUP:
    case PP_INPUTEVENT_TYPE_MOUSEMOVE:
    case PP_INPUTEVENT_TYPE_MOUSEENTER:
    case PP_INPUTEVENT_TYPE_MOUSELEAVE: {
      pp::MouseInputEvent mouse_event(event_device_res);
      pp::MouseInputEvent mouse_event_dip(event);
      pp::Point point = mouse_event.GetPosition();
      point.set_x(point.x() - available_area_.x());
      offset_event = pp::MouseInputEvent(
          this,
          event.GetType(),
          event.GetTimeStamp(),
          event.GetModifiers(),
          mouse_event.GetButton(),
          point,
          mouse_event.GetClickCount(),
          mouse_event.GetMovement());
      if (!engine_->IsSelecting()) {
        if (!IsOverlayScrollbar() &&
            !available_area_.Contains(mouse_event.GetPosition())) {
          try_engine_first = false;
        } else if (IsOverlayScrollbar()) {
          pp::Rect temp;
          if ((v_scrollbar_.get() && v_scrollbar_->GetLocation(&temp) &&
              temp.Contains(mouse_event_dip.GetPosition())) ||
              (h_scrollbar_.get() && h_scrollbar_->GetLocation(&temp) &&
              temp.Contains(mouse_event_dip.GetPosition()))) {
            try_engine_first = false;
          }
        }
      }
      break;
    }
    default:
      break;
  }
  if (try_engine_first && engine_->HandleEvent(offset_event))
    return true;

  // Left/Right arrows should scroll to the beginning of the Prev/Next page if
  // there is no horizontal scroll bar.
  // If fit-to-height, PgDown/PgUp should scroll to the beginning of the
  // Prev/Next page.
  if (v_scrollbar_.get() && event.GetType() == PP_INPUTEVENT_TYPE_KEYDOWN) {
    pp::KeyboardInputEvent keyboard_event(event);
    bool page_down =
        (!h_scrollbar_.get() &&
            keyboard_event.GetKeyCode() == ui::VKEY_RIGHT) ||
        (zoom_mode_ == ZOOM_FIT_TO_PAGE &&
            keyboard_event.GetKeyCode() == ui::VKEY_NEXT);
    bool page_up =
        (!h_scrollbar_.get() &&
            keyboard_event.GetKeyCode() == ui::VKEY_LEFT) ||
        (zoom_mode_ == ZOOM_FIT_TO_PAGE &&
            keyboard_event.GetKeyCode() == ui::VKEY_PRIOR);

    if (page_down) {
      int page = engine_->GetFirstVisiblePage();
      // Engine calculates visible page including delimiter to the page size.
      // We need to check here if the page itself is completely out of view and
      // scroll to the next one in that case.
      if (engine_->GetPageRect(page).bottom() * zoom_ <=
          v_scrollbar_->GetValue())
        page++;
      ScrollToPage(page + 1);
      UpdateCursor(PP_CURSORTYPE_POINTER);
      return true;
    } else if (page_up) {
      int page = engine_->GetFirstVisiblePage();
      if (engine_->GetPageRect(page).y() * zoom_ >= v_scrollbar_->GetValue())
        page--;
      ScrollToPage(page);
      UpdateCursor(PP_CURSORTYPE_POINTER);
      return true;
    }
  }

  if (v_scrollbar_.get() && v_scrollbar_->HandleEvent(event)) {
    UpdateCursor(PP_CURSORTYPE_POINTER);
    return true;
  }

  if (h_scrollbar_.get() && h_scrollbar_->HandleEvent(event)) {
    UpdateCursor(PP_CURSORTYPE_POINTER);
    return true;
  }

  if (timer_pending_ &&
      (event.GetType() == PP_INPUTEVENT_TYPE_MOUSEUP ||
       event.GetType() == PP_INPUTEVENT_TYPE_MOUSEMOVE)) {
    timer_factory_.CancelAll();
    timer_pending_ = false;
  } else if (event.GetType() == PP_INPUTEVENT_TYPE_MOUSEMOVE &&
             engine_->IsSelecting()) {
    bool set_timer = false;
    pp::MouseInputEvent mouse_event(event);
    if (v_scrollbar_.get() &&
        (mouse_event.GetPosition().y() <= 0 ||
         mouse_event.GetPosition().y() >= (plugin_dip_size_.height() - 1))) {
      v_scrollbar_->ScrollBy(
          PP_SCROLLBY_LINE, mouse_event.GetPosition().y() >= 0 ? 1: -1);
      set_timer = true;
    }
    if (h_scrollbar_.get() &&
        (mouse_event.GetPosition().x() <= 0 ||
         mouse_event.GetPosition().x() >= (plugin_dip_size_.width() - 1))) {
      h_scrollbar_->ScrollBy(PP_SCROLLBY_LINE,
          mouse_event.GetPosition().x() >= 0 ? 1: -1);
      set_timer = true;
    }

    if (set_timer) {
      last_mouse_event_ = pp::MouseInputEvent(event);

      pp::CompletionCallback callback =
          timer_factory_.NewCallback(&Instance::OnTimerFired);
      pp::Module::Get()->core()->CallOnMainThread(kDragTimerMs, callback);
      timer_pending_ = true;
    }
  }

  if (event.GetType() == PP_INPUTEVENT_TYPE_KEYDOWN &&
      event.GetModifiers() & kDefaultKeyModifier) {
    pp::KeyboardInputEvent keyboard_event(event);
    switch (keyboard_event.GetKeyCode()) {
      case 'A':
        engine_->SelectAll();
        return true;
    }
  }

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

void Instance::DidChangeView(const pp::View& view) {
  pp::Rect view_rect(view.GetRect());
  float device_scale = 1.0f;
  float old_device_scale = device_scale_;
  if (hidpi_enabled_)
    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_)
    return;  // We don't care about the position, only the size.

  image_data_ = pp::ImageData();
  device_scale_ = device_scale;
  plugin_dip_size_ = view_rect.size();
  plugin_size_ = view_device_size;

  paint_manager_.SetSize(view_device_size, device_scale_);

  image_data_ = pp::ImageData(this,
                              PP_IMAGEDATAFORMAT_BGRA_PREMUL,
                              plugin_size_,
                              false);
  if (image_data_.is_null()) {
    DCHECK(plugin_size_.IsEmpty());
    return;
  }

  // View dimensions changed, disable autoscroll (if it was enabled).
  DisableAutoscroll();

  OnGeometryChanged(zoom_, old_device_scale);
}

pp::Var Instance::GetInstanceObject() {
  if (instance_object_.is_undefined()) {
    PDFScriptableObject* object = new PDFScriptableObject(this);
    // The pp::Var takes ownership of object here.
    instance_object_ = pp::VarPrivate(this, object);
  }

  return instance_object_;
}

pp::Var Instance::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);
}

pp::Var Instance::GetSelectedText(bool html) {
  if (html || !engine_->HasPermission(PDFEngine::PERMISSION_COPY))
    return pp::Var();
  return engine_->GetSelectedText();
}

void Instance::InvalidateWidget(pp::Widget_Dev widget,
                                const pp::Rect& dirty_rect) {
  if (v_scrollbar_.get() && *v_scrollbar_ == widget) {
    if (!image_data_.is_null())
      v_scrollbar_->Paint(dirty_rect.pp_rect(), &image_data_);
  } else if (h_scrollbar_.get() && *h_scrollbar_ == widget) {
    if (!image_data_.is_null())
      h_scrollbar_->Paint(dirty_rect.pp_rect(), &image_data_);
  } else {
    // Possible to hit this condition since sometimes the scrollbar codes posts
    // a task to do something later, and we could have deleted our reference in
    // the meantime.
    return;
  }

  pp::Rect dirty_rect_scaled = dirty_rect;
  ScaleRect(device_scale_, &dirty_rect_scaled);
  paint_manager_.InvalidateRect(dirty_rect_scaled);
}

void Instance::ScrollbarValueChanged(pp::Scrollbar_Dev scrollbar,
                                     uint32_t value) {
  value = GetScaled(value);
  if (v_scrollbar_.get() && *v_scrollbar_ == scrollbar) {
    engine_->ScrolledToYPosition(value);
    pp::Rect rc;
    v_scrollbar_->GetLocation(&rc);
    int32 doc_height = GetDocumentPixelHeight();
    doc_height -= GetScaled(rc.height());
#ifdef ENABLE_THUMBNAILS
    if (thumbnails_.visible()) {
      thumbnails_.SetPosition(value, doc_height, true);
    }
#endif
    pp::Point origin(
        plugin_size_.width() - page_indicator_.rect().width() -
            GetScaled(GetScrollbarReservedThickness()),
        page_indicator_.GetYPosition(value, doc_height, plugin_size_.height()));
    page_indicator_.MoveTo(origin, page_indicator_.visible());
  } else if (h_scrollbar_.get() && *h_scrollbar_ == scrollbar) {
    engine_->ScrolledToXPosition(value);
  }
}

void Instance::ScrollbarOverlayChanged(pp::Scrollbar_Dev scrollbar,
                                       bool overlay) {
  scrollbar_reserved_thickness_ = overlay ? 0 : scrollbar_thickness_;
  OnGeometryChanged(zoom_, device_scale_);
}

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

int32_t Instance::PrintBegin(const PP_PrintSettings_Dev& 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;
  engine_->PrintBegin();
  return ret;
}

pp::Resource Instance::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);
}

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

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

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

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

void Instance::StopFind() {
  engine_->StopFind();
}

void Instance::Zoom(double scale, bool text_only) {
  UserMetricsRecordAction("PDF.ZoomFromBrowser");
  SetZoom(ZOOM_SCALE, scale);
}

void Instance::ZoomChanged(double factor) {
  if (full_)
    Zoom_Dev::ZoomChanged(factor);
}

void Instance::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(), plugin_size_);
    unsigned int color = kBackgroundColorA << 24 |
                         kBackgroundColorR << 16 |
                         kBackgroundColorG << 8 |
                         kBackgroundColorB;
    FillRect(rect, color);
    ready->push_back(PaintManager::ReadyRect(rect, image_data_, true));
    *pending = paint_rects;
    return;
  }

  engine_->PrePaint();

  for (size_t i = 0; i < paint_rects.size(); i++) {
    // Intersect with plugin area since there could be pending invalidates from
    // when the plugin area was larger.
    pp::Rect rect =
        paint_rects[i].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 (size_t j = 0; j < pdf_ready.size(); ++j) {
        pdf_ready[j].Offset(available_area_.point());
        ready->push_back(
            PaintManager::ReadyRect(pdf_ready[j], image_data_, false));
      }
      for (size_t j = 0; j < pdf_pending.size(); ++j) {
        pdf_pending[j].Offset(available_area_.point());
        pending->push_back(pdf_pending[j]);
      }
    }

    for (size_t j = 0; j < background_parts_.size(); ++j) {
      pp::Rect intersection = background_parts_[j].location.Intersect(rect);
      if (!intersection.IsEmpty()) {
        FillRect(intersection, background_parts_[j].color);
        ready->push_back(
            PaintManager::ReadyRect(intersection, image_data_, false));
      }
    }

    if (document_load_state_ == LOAD_STATE_FAILED) {
      pp::Point top_center;
      top_center.set_x(plugin_size_.width() / 2);
      top_center.set_y(plugin_size_.height() / 2);
      DrawText(top_center, PP_RESOURCESTRING_PDFLOAD_FAILED);
    }

#ifdef ENABLE_THUMBNAILS
    thumbnails_.Paint(&image_data_, rect);
#endif
  }

  engine_->PostPaint();

  // Must paint scrollbars after the background parts, in case we have an
  // overlay scrollbar that's over the background. We also do this in a separate
  // loop because the scrollbar painting logic uses the signal of whether there
  // are pending paints or not to figure out if it should draw right away or
  // not.
  for (size_t i = 0; i < paint_rects.size(); i++) {
    PaintIfWidgetIntersects(h_scrollbar_.get(), paint_rects[i], ready, pending);
    PaintIfWidgetIntersects(v_scrollbar_.get(), paint_rects[i], ready, pending);
  }

  if (progress_bar_.visible())
    PaintOverlayControl(&progress_bar_, &image_data_, ready);

  if (page_indicator_.visible())
    PaintOverlayControl(&page_indicator_, &image_data_, ready);

  if (toolbar_->current_transparency() != kTransparentAlpha)
    PaintOverlayControl(toolbar_.get(), &image_data_, ready);

  // Paint autoscroll anchor if needed.
  if (is_autoscroll_) {
    size_t limit = ready->size();
    for (size_t i = 0; i < limit; i++) {
      pp::Rect anchor_rect = autoscroll_rect_.Intersect((*ready)[i].rect);
      if (!anchor_rect.IsEmpty()) {
        pp::Rect draw_rc = pp::Rect(
            pp::Point(anchor_rect.x() - autoscroll_rect_.x(),
                      anchor_rect.y() - autoscroll_rect_.y()),
            anchor_rect.size());
        // Paint autoscroll anchor.
        AlphaBlend(autoscroll_anchor_, draw_rc,
                   &image_data_, anchor_rect.point(), kOpaqueAlpha);
      }
    }
  }
}

void Instance::PaintOverlayControl(
    Control* ctrl,
    pp::ImageData* image_data,
    std::vector<PaintManager::ReadyRect>* ready) {
  // Make sure that we only paint overlay controls over an area that's ready,
  // i.e. not pending.  Otherwise we'll mark the control rect as ready and
  // it'll overwrite the pdf region.
  std::list<pp::Rect> ctrl_rects;
  for (size_t i = 0; i < ready->size(); i++) {
    pp::Rect rc = ctrl->rect().Intersect((*ready)[i].rect);
    if (!rc.IsEmpty())
      ctrl_rects.push_back(rc);
  }

  if (!ctrl_rects.empty()) {
    ctrl->PaintMultipleRects(image_data, ctrl_rects);

    std::list<pp::Rect>::iterator iter;
    for (iter = ctrl_rects.begin(); iter != ctrl_rects.end(); ++iter) {
      ready->push_back(PaintManager::ReadyRect(*iter, *image_data, false));
    }
  }
}

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

void Instance::DidOpenPreview(int32_t result) {
  if (result == PP_OK) {
    preview_engine_.reset(PDFEngine::Create(new PreviewModeClient(this)));
    preview_engine_->HandleDocumentLoad(embed_preview_loader_);
  } else {
    NOTREACHED();
  }
}

void Instance::PaintIfWidgetIntersects(
    pp::Widget_Dev* widget,
    const pp::Rect& rect,
    std::vector<PaintManager::ReadyRect>* ready,
    std::vector<pp::Rect>* pending) {
  if (!widget)
    return;

  pp::Rect location;
  if (!widget->GetLocation(&location))
    return;

  ScaleRect(device_scale_, &location);
  location = location.Intersect(rect);
  if (location.IsEmpty())
    return;

  if (IsOverlayScrollbar()) {
    // If we're using overlay scrollbars, and there are pending paints under the
    // scrollbar, don't update the scrollbar instantly. While it would be nice,
    // we would need to double buffer the plugin area in order to make this
    // work. This is because we'd need to always have a copy of what the pdf
    // under the scrollbar looks like, and additionally we couldn't paint the
    // pdf under the scrollbar if it's ready until we got the preceding flush.
    // So in practice, it would make painting slower and introduce extra buffer
    // copies for the general case.
    for (size_t i = 0; i < pending->size(); ++i) {
      if ((*pending)[i].Intersects(location))
        return;
    }

    // Even if none of the pending paints are under the scrollbar, we never want
    // to paint it if it's over the pdf if there are other pending paints.
    // Otherwise different parts of the pdf plugin would display at different
    // scroll offsets.
    if (!pending->empty() && available_area_.Intersects(rect)) {
      pending->push_back(location);
      return;
    }
  }

  pp::Rect location_dip = location;
  ScaleRect(1.0f / device_scale_, &location_dip);

  DCHECK(!image_data_.is_null());
  widget->Paint(location_dip, &image_data_);

  // Re-scale the rectangle from DIPs to device pixels, so we ensure that we
  // don't miss any pixels due to rounding outwards in ScaleRect.
  location = location_dip;
  ScaleRect(device_scale_, &location);

  ready->push_back(PaintManager::ReadyRect(location, image_data_, true));
}

void Instance::OnTimerFired(int32_t) {
  HandleInputEvent(last_mouse_event_);
}

void Instance::OnClientTimerFired(int32_t id) {
  engine_->OnCallback(id);
}

void Instance::OnControlTimerFired(int32_t,
                                   const uint32& control_id,
                                   const uint32& timer_id) {
  if (control_id == toolbar_->id()) {
    toolbar_->OnTimerFired(timer_id);
  } else if (control_id == progress_bar_.id()) {
    if (timer_id == delayed_progress_timer_id_) {
      if (document_load_state_ == LOAD_STATE_LOADING &&
          !progress_bar_.visible()) {
        progress_bar_.Fade(true, kProgressFadeTimeoutMs);
      }
      delayed_progress_timer_id_ = 0;
    } else {
      progress_bar_.OnTimerFired(timer_id);
    }
  } else if (control_id == kAutoScrollId) {
    if (is_autoscroll_) {
      if (autoscroll_x_ != 0 && h_scrollbar_.get()) {
        h_scrollbar_->ScrollBy(PP_SCROLLBY_PIXEL, autoscroll_x_);
      }
      if (autoscroll_y_ != 0 && v_scrollbar_.get()) {
        v_scrollbar_->ScrollBy(PP_SCROLLBY_PIXEL, autoscroll_y_);
      }

      // Reschedule timer.
      ScheduleTimer(kAutoScrollId, kAutoScrollTimeoutMs);
    }
  } else if (control_id == kPageIndicatorId) {
    page_indicator_.OnTimerFired(timer_id);
  }
#ifdef ENABLE_THUMBNAILS
  else if (control_id == thumbnails_.id()) {
    thumbnails_.OnTimerFired(timer_id);
  }
#endif
}

void Instance::CalculateBackgroundParts() {
  background_parts_.clear();
  int v_scrollbar_thickness =
      GetScaled(v_scrollbar_.get() ? GetScrollbarReservedThickness() : 0);
  int h_scrollbar_thickness =
      GetScaled(h_scrollbar_.get() ? GetScrollbarReservedThickness() : 0);
  int width_without_scrollbar = std::max(
      plugin_size_.width() - v_scrollbar_thickness, 0);
  int height_without_scrollbar = std::max(
      plugin_size_.height() - h_scrollbar_thickness, 0);
  int left_width = available_area_.x();
  int right_start = available_area_.right();
  int right_width = abs(width_without_scrollbar - available_area_.right());
  int bottom = std::min(available_area_.bottom(), height_without_scrollbar);

  // Add the left, right, and bottom rectangles.  Note: we assume only
  // horizontal centering.
  BackgroundPart part;
  part.color = kBackgroundColorA << 24 |
               kBackgroundColorR << 16 |
               kBackgroundColorG << 8 |
               kBackgroundColorB;
  part.location = pp::Rect(0, 0, left_width, bottom);
  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, width_without_scrollbar, height_without_scrollbar - bottom);
  if (!part.location.IsEmpty())
    background_parts_.push_back(part);

  if (h_scrollbar_thickness
#if defined(OS_MACOSX)
      ||
#else
      &&
#endif
      v_scrollbar_thickness) {
    part.color = 0xFFFFFFFF;
    part.location = pp::Rect(plugin_size_.width() - v_scrollbar_thickness,
                             plugin_size_.height() - h_scrollbar_thickness,
                             h_scrollbar_thickness,
                             v_scrollbar_thickness);
    background_parts_.push_back(part);
  }
}

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

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

void Instance::FillRect(const pp::Rect& rect, unsigned int color) {
  DCHECK(!image_data_.is_null() || rect.IsEmpty());
  unsigned int* buffer_start = static_cast<unsigned int*>(image_data_.data());
  int stride = image_data_.stride();
  unsigned int* 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 Instance::DocumentSizeUpdated(const pp::Size& size) {
  document_size_ = size;

  OnGeometryChanged(zoom_, device_scale_);
}

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

void Instance::Scroll(const pp::Point& point) {
  pp::Rect scroll_area = available_area_;
  if (IsOverlayScrollbar()) {
    pp::Rect rc;
    if (h_scrollbar_.get()) {
      h_scrollbar_->GetLocation(&rc);
      ScaleRect(device_scale_, &rc);
      if (scroll_area.bottom() > rc.y()) {
        scroll_area.set_height(rc.y() - scroll_area.y());
        paint_manager_.InvalidateRect(rc);
      }
    }
    if (v_scrollbar_.get()) {
      v_scrollbar_->GetLocation(&rc);
      ScaleRect(device_scale_, &rc);
      if (scroll_area.right() > rc.x()) {
        scroll_area.set_width(rc.x() - scroll_area.x());
        paint_manager_.InvalidateRect(rc);
      }
    }
  }
  paint_manager_.ScrollRect(scroll_area, point);

  if (toolbar_->current_transparency() != kTransparentAlpha)
    paint_manager_.InvalidateRect(toolbar_->GetControlsRect());

  if (progress_bar_.visible())
    paint_manager_.InvalidateRect(progress_bar_.rect());

  if (is_autoscroll_)
    paint_manager_.InvalidateRect(autoscroll_rect_);

  if (show_page_indicator_) {
    page_indicator_.set_current_page(GetPageNumberToDisplay());
    page_indicator_.Splash();
  }

  if (page_indicator_.visible())
    paint_manager_.InvalidateRect(page_indicator_.rect());

  if (on_scroll_callback_.is_string())
    ExecuteScript(on_scroll_callback_);
}

void Instance::ScrollToX(int position) {
  if (!h_scrollbar_.get()) {
    NOTREACHED();
    return;
  }
  int position_dip = static_cast<int>(position / device_scale_);
  h_scrollbar_->SetValue(position_dip);
}

void Instance::ScrollToY(int position) {
  if (!v_scrollbar_.get()) {
    NOTREACHED();
    return;
  }
  int position_dip = static_cast<int>(position / device_scale_);
  v_scrollbar_->SetValue(ClipToRange(position_dip, 0, valid_v_range_));
}

void Instance::ScrollToPage(int page) {
  if (!v_scrollbar_.get())
    return;

  if (engine_->GetNumberOfPages() == 0)
    return;

  int index = ClipToRange(page, 0, engine_->GetNumberOfPages() - 1);
  pp::Rect rect = engine_->GetPageRect(index);
  // If we are trying to scroll pass the last page,
  // scroll to the end of the last page.
  int position = index < page ? rect.bottom() : rect.y();
  ScrollToY(position * zoom_ * device_scale_);
}

void Instance::NavigateTo(const std::string& url, bool open_in_new_tab) {
  std::string url_copy(url);

  // Empty |url_copy| is ok, and will effectively be a reload.
  // Skip the code below so an empty URL does not turn into "http://", which
  // will cause GURL to fail a DCHECK.
  if (!url_copy.empty()) {
    // If there's no scheme, add http.
    if (url_copy.find("://") == std::string::npos &&
        url_copy.find("mailto:") == std::string::npos) {
      url_copy = std::string("http://") + url_copy;
    }
    // Make sure |url_copy| starts with a valid scheme.
    if (url_copy.find("http://") != 0 &&
        url_copy.find("https://") != 0 &&
        url_copy.find("ftp://") != 0 &&
        url_copy.find("mailto:") != 0) {
      return;
    }
    // Make sure |url_copy| is not only a scheme.
    if (url_copy == "http://" ||
        url_copy == "https://" ||
        url_copy == "ftp://" ||
        url_copy == "mailto:") {
      return;
    }
  }
  if (open_in_new_tab) {
    GetWindowObject().Call("open", url_copy);
  } else {
    GetWindowObject().GetProperty("top").GetProperty("location").
        SetProperty("href", url_copy);
  }
}

void Instance::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(), NULL);
}

void Instance::UpdateTickMarks(const std::vector<pp::Rect>& tickmarks) {
  if (!v_scrollbar_.get())
    return;

  float inverse_scale = 1.0f / device_scale_;
  std::vector<pp::Rect> scaled_tickmarks = tickmarks;
  for (size_t i = 0; i < scaled_tickmarks.size(); i++) {
    ScaleRect(inverse_scale, &scaled_tickmarks[i]);
  }

  v_scrollbar_->SetTickMarks(
      scaled_tickmarks.empty() ? NULL : &scaled_tickmarks[0], tickmarks.size());
}

void Instance::NotifyNumberOfFindResultsChanged(int total, bool final_result) {
  NumberOfFindResultsChanged(total, final_result);
}

void Instance::NotifySelectedFindResultChanged(int current_find_index) {
  SelectedFindResultChanged(current_find_index);
}

void Instance::OnEvent(uint32 control_id, uint32 event_id, void* data) {
  if (event_id == Button::EVENT_ID_BUTTON_CLICKED ||
      event_id == Button::EVENT_ID_BUTTON_STATE_CHANGED) {
    switch (control_id) {
      case kFitToPageButtonId:
        UserMetricsRecordAction("PDF.FitToPageButton");
        SetZoom(ZOOM_FIT_TO_PAGE, 0);
        ZoomChanged(zoom_);
        break;
      case kFitToWidthButtonId:
        UserMetricsRecordAction("PDF.FitToWidthButton");
        SetZoom(ZOOM_FIT_TO_WIDTH, 0);
        ZoomChanged(zoom_);
        break;
      case kZoomOutButtonId:
      case kZoomInButtonId:
        UserMetricsRecordAction(control_id == kZoomOutButtonId ?
            "PDF.ZoomOutButton" : "PDF.ZoomInButton");
        SetZoom(ZOOM_SCALE, CalculateZoom(control_id));
        ZoomChanged(zoom_);
        break;
      case kSaveButtonId:
        UserMetricsRecordAction("PDF.SaveButton");
        SaveAs();
        break;
      case kPrintButtonId:
        UserMetricsRecordAction("PDF.PrintButton");
        Print();
        break;
    }
  }
  if (control_id == kThumbnailsId &&
      event_id == ThumbnailControl::EVENT_ID_THUMBNAIL_SELECTED) {
    int page = *static_cast<int*>(data);
    pp::Rect page_rc(engine_->GetPageRect(page));
    ScrollToY(static_cast<int>(page_rc.y() * zoom_ * device_scale_));
  }
}

void Instance::Invalidate(uint32 control_id, const pp::Rect& rc) {
  paint_manager_.InvalidateRect(rc);
}

uint32 Instance::ScheduleTimer(uint32 control_id, uint32 timeout_ms) {
  current_timer_id_++;
  pp::CompletionCallback callback =
      timer_factory_.NewCallback(&Instance::OnControlTimerFired,
                                 control_id,
                                 current_timer_id_);
  pp::Module::Get()->core()->CallOnMainThread(timeout_ms, callback);
  return current_timer_id_;
}

void Instance::SetEventCapture(uint32 control_id, bool set_capture) {
  // TODO(gene): set event capture here.
}

void Instance::SetCursor(uint32 control_id, PP_CursorType_Dev cursor_type) {
  UpdateCursor(cursor_type);
}

pp::Instance* Instance::GetInstance() {
  return this;
}

void Instance::GetDocumentPassword(
    pp::CompletionCallbackWithOutput<pp::Var> callback) {
  std::string message(GetLocalizedString(PP_RESOURCESTRING_PDFGETPASSWORD));
  pp::Var result = pp::PDF::ModalPromptForPassword(this, message);
  *callback.output() = result.pp_var();
  callback.Run(PP_OK);
}

void Instance::Alert(const std::string& message) {
  GetWindowObject().Call("alert", message);
}

bool Instance::Confirm(const std::string& message) {
  pp::Var result = GetWindowObject().Call("confirm", message);
  return result.is_bool() ? result.AsBool() : false;
}

std::string Instance::Prompt(const std::string& question,
                             const std::string& default_answer) {
  pp::Var result = GetWindowObject().Call("prompt", question, default_answer);
  return result.is_string() ? result.AsString() : std::string();
}

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

void Instance::Email(const std::string& to,
                     const std::string& cc,
                     const std::string& bcc,
                     const std::string& subject,
                     const std::string& body) {
  std::string javascript =
      "var href = 'mailto:" + net::EscapeUrlEncodedData(to, false) +
      "?cc=" + net::EscapeUrlEncodedData(cc, false) +
      "&bcc=" + net::EscapeUrlEncodedData(bcc, false) +
      "&subject=" + net::EscapeUrlEncodedData(subject, false) +
      "&body=" + net::EscapeUrlEncodedData(body, false) +
      "';var temp = window.open(href, '_blank', " +
      "'width=1,height=1');if(temp) temp.close();";
  ExecuteScript(javascript);
}

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

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

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

void Instance::SaveAs() {
  pp::PDF::SaveAs(this);
}

void Instance::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 =
      form_factory_.NewCallback(&Instance::FormDidOpen);
  form_loader_ = CreateURLLoaderInternal();
  int rv = form_loader_.Open(request, callback);
  if (rv != PP_OK_COMPLETIONPENDING)
    callback.Run(rv);
}

void Instance::FormDidOpen(int32_t result) {
  // TODO: inform the user of success/failure.
  if (result != PP_OK) {
    NOTREACHED();
  }
}

std::string Instance::ShowFileSelectionDialog() {
  // Seems like very low priority to implement, since the pdf has no way to get
  // the file data anyways.  Javascript doesn't let you do this synchronously.
  NOTREACHED();
  return std::string();
}

pp::URLLoader Instance::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();
}

void Instance::ScheduleCallback(int id, int delay_in_ms) {
  pp::CompletionCallback callback =
      timer_factory_.NewCallback(&Instance::OnClientTimerFired);
  pp::Module::Get()->core()->CallOnMainThread(delay_in_ms, callback, id);
}

void Instance::SearchString(const base::char16* string,
                            const base::char16* term,
                            bool case_sensitive,
                            std::vector<SearchStringResult>* results) {
  if (!pp::PDF::IsAvailable()) {
    NOTREACHED();
    return;
  }

  PP_PrivateFindResult* pp_results;
  int count = 0;
  pp::PDF::SearchString(
      this,
      reinterpret_cast<const unsigned short*>(string),
      reinterpret_cast<const unsigned short*>(term),
      case_sensitive,
      &pp_results,
      &count);

  results->resize(count);
  for (int 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);
}

void Instance::DocumentPaintOccurred() {
  if (painted_first_page_)
    return;

  painted_first_page_ = true;
  UpdateToolbarPosition(false);
  toolbar_->Splash(kToolbarSplashTimeoutMs);

  if (engine_->GetNumberOfPages() > 1)
    show_page_indicator_ = true;
  else
    show_page_indicator_ = false;

  if (v_scrollbar_.get() && show_page_indicator_) {
    page_indicator_.set_current_page(GetPageNumberToDisplay());
    page_indicator_.Splash(kToolbarSplashTimeoutMs,
                           kPageIndicatorInitialFadeTimeoutMs);
  }
}

void Instance::DocumentLoadComplete(int page_count) {
  // Clear focus state for OSK.
  FormTextFieldFocusChange(false);

  // Update progress control.
  if (progress_bar_.visible())
    progress_bar_.Fade(false, kProgressFadeTimeoutMs);

  DCHECK(document_load_state_ == LOAD_STATE_LOADING);
  document_load_state_ = LOAD_STATE_COMPLETE;
  UserMetricsRecordAction("PDF.LoadSuccess");
  if (on_load_callback_.is_string())
    ExecuteScript(on_load_callback_);
  // Note: If we are in print preview mode on_load_callback_ might call
  // ScrollTo{X|Y}() and we don't want to scroll again and override it.
  // #page=N is not supported in Print Preview.
  if (!IsPrintPreview()) {
    int initial_page = GetInitialPage(url_);
    if (initial_page >= 0)
      ScrollToPage(initial_page);
  }

  if (!full_)
    return;
  if (!pp::PDF::IsAvailable())
    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)) {
    printing_enabled_ = false;
    if (current_tb_info_ == kPDFToolbarButtons) {
      // Remove Print button.
      CreateToolbar(kPDFNoPrintToolbarButtons,
                    arraysize(kPDFNoPrintToolbarButtons));
      UpdateToolbarPosition(false);
      Invalidate(pp::Rect(plugin_size_));
    }
  }

  pp::PDF::SetContentRestriction(this, content_restrictions);

  pp::PDF::HistogramPDFPageCount(this, page_count);
}

void Instance::RotateClockwise() {
  engine_->RotateClockwise();
}

void Instance::RotateCounterclockwise() {
  engine_->RotateCounterclockwise();
}

void Instance::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;
  int src_page_index =
      ExtractPrintPreviewPageIndex(preview_pages_info_.front().first);
  if (src_page_index > 0 &&  dest_page_index > -1 && preview_engine_.get())
    engine_->AppendPage(preview_engine_.get(), dest_page_index);

  preview_pages_info_.pop();
  // |print_preview_page_count_| is not updated yet. Do not load any
  // other preview pages till we get this information.
  if (print_preview_page_count_ == 0)
    return;

  if (preview_pages_info_.size())
    LoadAvailablePreviewPage();
}

void Instance::DocumentLoadFailed() {
  DCHECK(document_load_state_ == LOAD_STATE_LOADING);
  UserMetricsRecordAction("PDF.LoadFailure");

  // Hide progress control.
  progress_bar_.Fade(false, kProgressFadeTimeoutMs);

  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_));
}

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

  preview_document_load_state_ = LOAD_STATE_FAILED;
  preview_pages_info_.pop();

  if (preview_pages_info_.size())
    LoadAvailablePreviewPage();
}

pp::Instance* Instance::GetPluginInstance() {
  return GetInstance();
}

void Instance::DocumentHasUnsupportedFeature(const std::string& feature) {
  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 Instance::DocumentLoadProgress(uint32 available, uint32 doc_size) {
  double progress = 0.0;
  if (doc_size == 0) {
    // 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 = log(static_cast<double>(available)) / kFactor;
      if (progress > 100.0)
        progress = 100.0;
    }
  } else {
    progress = 100.0 * static_cast<double>(available) / doc_size;
  }
  progress_bar_.SetProgress(progress);
}

void Instance::FormTextFieldFocusChange(bool in_focus) {
  if (!text_input_.get())
    return;
  if (in_focus)
    text_input_->SetTextInputType(PP_TEXTINPUT_TYPE_DEV_TEXT);
  else
    text_input_->SetTextInputType(PP_TEXTINPUT_TYPE_DEV_NONE);
}

// Called by PDFScriptableObject.
bool Instance::HasScriptableMethod(const pp::Var& method, pp::Var* exception) {
  std::string method_str = method.AsString();
  return (method_str == kJSAccessibility ||
          method_str == kJSDocumentLoadComplete ||
          method_str == kJSGetHeight ||
          method_str == kJSGetHorizontalScrollbarThickness ||
          method_str == kJSGetPageLocationNormalized ||
          method_str == kJSGetVerticalScrollbarThickness ||
          method_str == kJSGetWidth ||
          method_str == kJSGetZoomLevel ||
          method_str == kJSGoToPage ||
          method_str == kJSGrayscale ||
          method_str == kJSLoadPreviewPage ||
          method_str == kJSOnLoad ||
          method_str == kJSOnPluginSizeChanged ||
          method_str == kJSOnScroll ||
          method_str == kJSPageXOffset ||
          method_str == kJSPageYOffset ||
          method_str == kJSPrintPreviewPageCount ||
          method_str == kJSReload ||
          method_str == kJSRemovePrintButton ||
          method_str == kJSResetPrintPreviewUrl ||
          method_str == kJSSendKeyEvent ||
          method_str == kJSSetPageNumbers ||
          method_str == kJSSetPageXOffset ||
          method_str == kJSSetPageYOffset ||
          method_str == kJSSetZoomLevel ||
          method_str == kJSZoomFitToHeight ||
          method_str == kJSZoomFitToWidth ||
          method_str == kJSZoomIn ||
          method_str == kJSZoomOut);
}

pp::Var Instance::CallScriptableMethod(const pp::Var& method,
                                       const std::vector<pp::Var>& args,
                                       pp::Var* exception) {
  std::string method_str = method.AsString();
  if (method_str == kJSGrayscale) {
    if (args.size() == 1 && args[0].is_bool()) {
      engine_->SetGrayscale(args[0].AsBool());
      // Redraw
      paint_manager_.InvalidateRect(pp::Rect(pp::Point(), plugin_size_));
#ifdef ENABLE_THUMBNAILS
      if (thumbnails_.visible())
        thumbnails_.Show(true, true);
#endif
      return pp::Var(true);
    }
    return pp::Var(false);
  }
  if (method_str == kJSOnLoad) {
    if (args.size() == 1 && args[0].is_string()) {
      on_load_callback_ = args[0];
      return pp::Var(true);
    }
    return pp::Var(false);
  }
  if (method_str == kJSOnScroll) {
    if (args.size() == 1 && args[0].is_string()) {
      on_scroll_callback_ = args[0];
      return pp::Var(true);
    }
    return pp::Var(false);
  }
  if (method_str == kJSOnPluginSizeChanged) {
    if (args.size() == 1 && args[0].is_string()) {
      on_plugin_size_changed_callback_ = args[0];
      return pp::Var(true);
    }
    return pp::Var(false);
  }
  if (method_str == kJSReload) {
    document_load_state_ = LOAD_STATE_LOADING;
    if (!full_)
      LoadUrl(url_);
    preview_engine_.reset();
    print_preview_page_count_ = 0;
    engine_.reset(PDFEngine::Create(this));
    engine_->New(url_.c_str());
#ifdef ENABLE_THUMBNAILS
    thumbnails_.ResetEngine(engine_.get());
#endif
    return pp::Var();
  }
  if (method_str == kJSResetPrintPreviewUrl) {
    if (args.size() == 1 && args[0].is_string()) {
      url_ = args[0].AsString();
      preview_pages_info_ = std::queue<PreviewPageInfo>();
      preview_document_load_state_ = LOAD_STATE_COMPLETE;
    }
    return pp::Var();
  }
  if (method_str == kJSZoomFitToHeight) {
    SetZoom(ZOOM_FIT_TO_PAGE, 0);
    return pp::Var();
  }
  if (method_str == kJSZoomFitToWidth) {
    SetZoom(ZOOM_FIT_TO_WIDTH, 0);
    return pp::Var();
  }
  if (method_str == kJSZoomIn) {
    SetZoom(ZOOM_SCALE, CalculateZoom(kZoomInButtonId));
    return pp::Var();
  }
  if (method_str == kJSZoomOut) {
    SetZoom(ZOOM_SCALE, CalculateZoom(kZoomOutButtonId));
    return pp::Var();
  }
  if (method_str == kJSSetZoomLevel) {
    if (args.size() == 1 && args[0].is_double())
      SetZoom(ZOOM_SCALE, args[0].AsDouble());
    return pp::Var();
  }
  if (method_str == kJSGetZoomLevel) {
    return pp::Var(zoom_);
  }
  if (method_str == kJSGetHeight) {
    return pp::Var(plugin_size_.height());
  }
  if (method_str == kJSGetWidth) {
    return pp::Var(plugin_size_.width());
  }
  if (method_str == kJSGetHorizontalScrollbarThickness) {
    return pp::Var(
          h_scrollbar_.get() ? GetScrollbarReservedThickness() : 0);
  }
  if (method_str == kJSGetVerticalScrollbarThickness) {
    return pp::Var(
          v_scrollbar_.get() ? GetScrollbarReservedThickness() : 0);
  }
  if (method_str == kJSDocumentLoadComplete) {
    return pp::Var((document_load_state_ != LOAD_STATE_LOADING));
  }
  if (method_str == kJSPageYOffset) {
    return pp::Var(static_cast<int32_t>(
        v_scrollbar_.get() ? v_scrollbar_->GetValue() : 0));
  }
  if (method_str == kJSSetPageYOffset) {
    if (args.size() == 1 && args[0].is_number() && v_scrollbar_.get())
      ScrollToY(GetScaled(args[0].AsInt()));
    return pp::Var();
  }
  if (method_str == kJSPageXOffset) {
    return pp::Var(static_cast<int32_t>(
        h_scrollbar_.get() ? h_scrollbar_->GetValue() : 0));
  }
  if (method_str == kJSSetPageXOffset) {
    if (args.size() == 1 && args[0].is_number() && h_scrollbar_.get())
      ScrollToX(GetScaled(args[0].AsInt()));
    return pp::Var();
  }
  if (method_str == kJSRemovePrintButton) {
    CreateToolbar(kPrintPreviewToolbarButtons,
                  arraysize(kPrintPreviewToolbarButtons));
    UpdateToolbarPosition(false);
    Invalidate(pp::Rect(plugin_size_));
    return pp::Var();
  }
  if (method_str == kJSGoToPage) {
    if (args.size() == 1 && args[0].is_string()) {
      ScrollToPage(atoi(args[0].AsString().c_str()));
    }
    return pp::Var();
  }
  if (method_str == kJSAccessibility) {
    if (args.size() == 0) {
      base::DictionaryValue node;
      node.SetInteger(kAccessibleNumberOfPages, engine_->GetNumberOfPages());
      node.SetBoolean(kAccessibleLoaded,
                      document_load_state_ != LOAD_STATE_LOADING);
      bool has_permissions =
          engine_->HasPermission(PDFEngine::PERMISSION_COPY) ||
          engine_->HasPermission(PDFEngine::PERMISSION_COPY_ACCESSIBLE);
      node.SetBoolean(kAccessibleCopyable, has_permissions);
      std::string json;
      base::JSONWriter::Write(&node, &json);
      return pp::Var(json);
    } else if (args[0].is_number()) {
      return pp::Var(engine_->GetPageAsJSON(args[0].AsInt()));
    }
  }
  if (method_str == kJSPrintPreviewPageCount) {
    if (args.size() == 1 && args[0].is_number())
      SetPrintPreviewMode(args[0].AsInt());
    return pp::Var();
  }
  if (method_str == kJSLoadPreviewPage) {
    if (args.size() == 2 && args[0].is_string() && args[1].is_number())
      ProcessPreviewPageInfo(args[0].AsString(), args[1].AsInt());
    return pp::Var();
  }
  if (method_str == kJSGetPageLocationNormalized) {
    const size_t kMaxLength = 30;
    char location_info[kMaxLength];
    int page_idx = engine_->GetMostVisiblePage();
    if (page_idx < 0)
      return pp::Var(std::string());
    pp::Rect rect = engine_->GetPageContentsRect(page_idx);
    int v_scrollbar_reserved_thickness =
        v_scrollbar_.get() ? GetScaled(GetScrollbarReservedThickness()) : 0;

    rect.set_x(rect.x() + ((plugin_size_.width() -
        v_scrollbar_reserved_thickness - available_area_.width()) / 2));
    base::snprintf(location_info,
                   kMaxLength,
                   "%0.4f;%0.4f;%0.4f;%0.4f;",
                   rect.x() / static_cast<float>(plugin_size_.width()),
                   rect.y() / static_cast<float>(plugin_size_.height()),
                   rect.width() / static_cast<float>(plugin_size_.width()),
                   rect.height()/ static_cast<float>(plugin_size_.height()));
    return pp::Var(std::string(location_info));
  }
  if (method_str == kJSSetPageNumbers) {
    if (args.size() != 1 || !args[0].is_string())
      return pp::Var();
    const int num_pages_signed = engine_->GetNumberOfPages();
    if (num_pages_signed <= 0)
      return pp::Var();
    scoped_ptr<base::ListValue> page_ranges(static_cast<base::ListValue*>(
        base::JSONReader::Read(args[0].AsString(), false)));
    const size_t num_pages = static_cast<size_t>(num_pages_signed);
    if (!page_ranges.get() || page_ranges->GetSize() != num_pages)
      return pp::Var();

    std::vector<int> print_preview_page_numbers;
    for (size_t index = 0; index < num_pages; ++index) {
      int page_number = 0;  // |page_number| is 1-based.
      if (!page_ranges->GetInteger(index, &page_number) || page_number < 1)
        return pp::Var();
      print_preview_page_numbers.push_back(page_number);
    }
    print_preview_page_numbers_ = print_preview_page_numbers;
    page_indicator_.set_current_page(GetPageNumberToDisplay());
    return pp::Var();
  }
  // This is here to work around https://bugs.webkit.org/show_bug.cgi?id=16735.
  // In JS, creating a synthetic keyboard event and dispatching it always
  // result in a keycode of 0.
  if (method_str == kJSSendKeyEvent) {
    if (args.size() == 1 && args[0].is_number()) {
      pp::KeyboardInputEvent event(
          this,                        // instance
          PP_INPUTEVENT_TYPE_KEYDOWN,  // HandleInputEvent only care about this.
          0,                           // timestamp, not used for kbd events.
          0,                           // no modifiers.
          args[0].AsInt(),             // keycode.
          pp::Var());                  // no char text needed.
      HandleInputEvent(event);
    }
  }
  return pp::Var();
}

void Instance::OnGeometryChanged(double old_zoom, float old_device_scale) {
  bool force_no_horizontal_scrollbar = false;
  int scrollbar_thickness = GetScrollbarThickness();

  if (old_device_scale != device_scale_) {
    // Change in device scale forces us to recreate resources
    ConfigureNumberImageGenerator();

    CreateToolbar(current_tb_info_, current_tb_info_size_);
    // Load autoscroll anchor image.
    autoscroll_anchor_ =
        CreateResourceImage(PP_RESOURCEIMAGE_PDF_PAN_SCROLL_ICON);

    ConfigurePageIndicator();
    ConfigureProgressBar();

    pp::Point scroll_position = engine_->GetScrollPosition();
    ScalePoint(device_scale_ / old_device_scale, &scroll_position);
    engine_->SetScrollPosition(scroll_position);
  }

  UpdateZoomScale();
  if (zoom_ != old_zoom || device_scale_ != old_device_scale)
    engine_->ZoomUpdated(zoom_ * device_scale_);
  if (zoom_ != old_zoom)
    ZoomChanged(zoom_);

  available_area_ = pp::Rect(plugin_size_);
  if (GetDocumentPixelHeight() > plugin_size_.height()) {
    CreateVerticalScrollbar();
  } else {
    DestroyVerticalScrollbar();
  }

  int v_scrollbar_reserved_thickness =
      v_scrollbar_.get() ? GetScaled(GetScrollbarReservedThickness()) : 0;

  if (!force_no_horizontal_scrollbar &&
      GetDocumentPixelWidth() >
      (plugin_size_.width() - v_scrollbar_reserved_thickness)) {
    CreateHorizontalScrollbar();

    // Adding the horizontal scrollbar now might cause us to need vertical
    // scrollbars.
    if (GetDocumentPixelHeight() >
        plugin_size_.height() - GetScaled(GetScrollbarReservedThickness())) {
      CreateVerticalScrollbar();
    }

  } else {
    DestroyHorizontalScrollbar();
  }

#ifdef ENABLE_THUMBNAILS
  int thumbnails_pos = 0, thumbnails_total = 0;
#endif
  if (v_scrollbar_.get()) {
    v_scrollbar_->SetScale(device_scale_);
    available_area_.set_width(
      std::max(0, plugin_size_.width() - v_scrollbar_reserved_thickness));

#ifdef ENABLE_THUMBNAILS
    int height = plugin_size_.height();
#endif
    int height_dip = plugin_dip_size_.height();

#if defined(OS_MACOSX)
    // Before Lion, Mac always had the resize at the bottom. After that, it
    // never did.
    if ((base::mac::IsOSSnowLeopard() && full_) ||
        (base::mac::IsOSLionOrLater() && h_scrollbar_.get())) {
#else
    if (h_scrollbar_.get()) {
#endif  // defined(OS_MACOSX)
#ifdef ENABLE_THUMBNAILS
      height -= GetScaled(GetScrollbarThickness());
#endif
      height_dip -= GetScrollbarThickness();
    }
#ifdef ENABLE_THUMBNAILS
    int32 doc_height = GetDocumentPixelHeight();
#endif
    int32 doc_height_dip =
        static_cast<int32>(GetDocumentPixelHeight() / device_scale_);
#if defined(OS_MACOSX)
    // On the Mac we always allow room for the resize button (whose width is
    // the same as that of the scrollbar) in full mode. However, if there is no
    // no horizontal scrollbar, the end of the scrollbar will scroll past the
    // end of the document. This is because the scrollbar assumes that its own
    // height (in the case of a vscroll bar) is the same as the height of the
    // viewport. Since the viewport is actually larger, we compensate by
    // adjusting the document height. Similar logic applies below for the
    // horizontal scrollbar.
    // For example, if the document size is 1000, and the viewport size is 200,
    // then the scrollbar position at the end will be 800. In this case the
    // viewport is actally 215 (assuming 15 as the scrollbar width) but the
    // scrollbar thinks it is 200. We want the scrollbar position at the end to
    // be 785. Making the document size 985 achieves this.
    if (full_ && !h_scrollbar_.get()) {
#ifdef ENABLE_THUMBNAILS
      doc_height -= GetScaled(GetScrollbarThickness());
#endif
      doc_height_dip -= GetScrollbarThickness();
    }
#endif  // defined(OS_MACOSX)

    int32 position;
    position = v_scrollbar_->GetValue();
    position = static_cast<int>(position * zoom_ / old_zoom);
    valid_v_range_ = doc_height_dip - height_dip;
    if (position > valid_v_range_)
      position = valid_v_range_;

    v_scrollbar_->SetValue(position);

    PP_Rect loc;
    loc.point.x = static_cast<int>(available_area_.right() / device_scale_);
    if (IsOverlayScrollbar())
      loc.point.x -= scrollbar_thickness;
    loc.point.y = 0;
    loc.size.width = scrollbar_thickness;
    loc.size.height = height_dip;
    v_scrollbar_->SetLocation(loc);
    v_scrollbar_->SetDocumentSize(doc_height_dip);

#ifdef ENABLE_THUMBNAILS
    thumbnails_pos = position;
    thumbnails_total = doc_height - height;
#endif
  }

  if (h_scrollbar_.get()) {
    h_scrollbar_->SetScale(device_scale_);
    available_area_.set_height(
        std::max(0, plugin_size_.height() -
                    GetScaled(GetScrollbarReservedThickness())));

    int width_dip = plugin_dip_size_.width();

    // See note above.
#if defined(OS_MACOSX)
    if ((base::mac::IsOSSnowLeopard() && full_) ||
        (base::mac::IsOSLionOrLater() && v_scrollbar_.get())) {
#else
    if (v_scrollbar_.get()) {
#endif
      width_dip -= GetScrollbarThickness();
    }
    int32 doc_width_dip =
        static_cast<int32>(GetDocumentPixelWidth() / device_scale_);
#if defined(OS_MACOSX)
    // See comment in the above if (v_scrollbar_.get()) block.
    if (full_ && !v_scrollbar_.get())
      doc_width_dip -= GetScrollbarThickness();
#endif  // defined(OS_MACOSX)

    int32 position;
    position = h_scrollbar_->GetValue();
    position = static_cast<int>(position * zoom_ / old_zoom);
    position = std::min(position, doc_width_dip - width_dip);

    h_scrollbar_->SetValue(position);

    PP_Rect loc;
    loc.point.x = 0;
    loc.point.y = static_cast<int>(available_area_.bottom() / device_scale_);
    if (IsOverlayScrollbar())
      loc.point.y -= scrollbar_thickness;
    loc.size.width = width_dip;
    loc.size.height = scrollbar_thickness;
    h_scrollbar_->SetLocation(loc);
    h_scrollbar_->SetDocumentSize(doc_width_dip);
  }

  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 doc_height = GetDocumentPixelHeight();
  if (doc_height < available_area_.height()) {
    available_area_.set_height(doc_height);
  }

  // We'll invalidate the entire plugin anyways.
  UpdateToolbarPosition(false);
  UpdateProgressBarPosition(false);
  UpdatePageIndicatorPosition(false);

#ifdef ENABLE_THUMBNAILS
  // Update thumbnail control position.
  thumbnails_.SetPosition(thumbnails_pos, thumbnails_total, false);
  pp::Rect thumbnails_rc(plugin_size_.width() - GetScaled(kThumbnailsWidth), 0,
    GetScaled(kThumbnailsWidth), plugin_size_.height());
  if (v_scrollbar_.get())
    thumbnails_rc.Offset(-v_scrollbar_reserved_thickness, 0);
  if (h_scrollbar_.get())
    thumbnails_rc.Inset(0, 0, 0, v_scrollbar_reserved_thickness);
  thumbnails_.SetRect(thumbnails_rc, false);
#endif

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

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

  if (on_plugin_size_changed_callback_.is_string())
    ExecuteScript(on_plugin_size_changed_callback_);
}

void Instance::CreateHorizontalScrollbar() {
  if (h_scrollbar_.get())
    return;

  h_scrollbar_.reset(new pp::Scrollbar_Dev(this, false));
}

void Instance::CreateVerticalScrollbar() {
  if (v_scrollbar_.get())
    return;

  v_scrollbar_.reset(new pp::Scrollbar_Dev(this, true));
}

void Instance::DestroyHorizontalScrollbar() {
  if (!h_scrollbar_.get())
    return;
  if (h_scrollbar_->GetValue())
    engine_->ScrolledToXPosition(0);
  h_scrollbar_.reset();
}

void Instance::DestroyVerticalScrollbar() {
  if (!v_scrollbar_.get())
    return;
  if (v_scrollbar_->GetValue())
    engine_->ScrolledToYPosition(0);
  v_scrollbar_.reset();
  page_indicator_.Show(false, true);
}

int Instance::GetScrollbarThickness() {
  if (scrollbar_thickness_ == -1) {
    pp::Scrollbar_Dev temp_scrollbar(this, false);
    scrollbar_thickness_ = temp_scrollbar.GetThickness();
    scrollbar_reserved_thickness_ =
      temp_scrollbar.IsOverlay() ? 0 : scrollbar_thickness_;
  }

  return scrollbar_thickness_;
}

int Instance::GetScrollbarReservedThickness() {
  GetScrollbarThickness();
  return scrollbar_reserved_thickness_;
}

bool Instance::IsOverlayScrollbar() {
  return GetScrollbarReservedThickness() == 0;
}

void Instance::CreateToolbar(const ToolbarButtonInfo* tb_info, size_t size) {
  toolbar_.reset(new FadingControls());

  DCHECK(tb_info);
  DCHECK(size >= 0);

  // Remember the current toolbar information in case we need to recreate the
  // images later.
  current_tb_info_ = tb_info;
  current_tb_info_size_ = size;

  int max_height = 0;
  pp::Point origin(kToolbarFadingOffsetLeft, kToolbarFadingOffsetTop);
  ScalePoint(device_scale_, &origin);

  std::list<Button*> buttons;
  for (size_t i = 0; i < size; i++) {
    Button* btn = new Button;
    pp::ImageData normal_face =
        CreateResourceImage(tb_info[i].normal);
    btn->CreateButton(tb_info[i].id,
                      origin,
                      true,
                      toolbar_.get(),
                      tb_info[i].style,
                      normal_face,
                      CreateResourceImage(tb_info[i].highlighted),
                      CreateResourceImage(tb_info[i].pressed));
    buttons.push_back(btn);

    origin += pp::Point(normal_face.size().width(), 0);
    max_height = std::max(max_height, normal_face.size().height());
  }

  pp::Rect rc_toolbar(0, 0,
      origin.x() + GetToolbarRightOffset(),
      origin.y() + max_height + GetToolbarBottomOffset());
  toolbar_->CreateFadingControls(
      kToolbarId, rc_toolbar, false, this, kTransparentAlpha);

  std::list<Button*>::iterator iter;
  for (iter = buttons.begin(); iter != buttons.end(); ++iter) {
    toolbar_->AddControl(*iter);
  }
}

int Instance::GetToolbarRightOffset() {
  int scrollbar_thickness = GetScrollbarThickness();
  return GetScaled(kToolbarFadingOffsetRight) + 2 * scrollbar_thickness;
}

int Instance::GetToolbarBottomOffset() {
  int scrollbar_thickness = GetScrollbarThickness();
  return GetScaled(kToolbarFadingOffsetBottom) + scrollbar_thickness;
}

std::vector<pp::ImageData> Instance::GetThumbnailResources() {
  std::vector<pp::ImageData> num_images(10);
  num_images[0] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_0);
  num_images[1] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_1);
  num_images[2] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_2);
  num_images[3] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_3);
  num_images[4] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_4);
  num_images[5] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_5);
  num_images[6] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_6);
  num_images[7] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_7);
  num_images[8] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_8);
  num_images[9] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_9);
  return num_images;
}

std::vector<pp::ImageData> Instance::GetProgressBarResources(
    pp::ImageData* background) {
  std::vector<pp::ImageData> result(9);
  result[0] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_0);
  result[1] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_1);
  result[2] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_2);
  result[3] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_3);
  result[4] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_4);
  result[5] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_5);
  result[6] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_6);
  result[7] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_7);
  result[8] = CreateResourceImage(PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_8);
  *background = CreateResourceImage(
      PP_RESOURCEIMAGE_PDF_PROGRESS_BAR_BACKGROUND);
  return result;
}

void Instance::CreatePageIndicator(bool always_visible) {
  page_indicator_.CreatePageIndicator(kPageIndicatorId, false, this,
      number_image_generator(), always_visible);
  ConfigurePageIndicator();
}

void Instance::ConfigurePageIndicator() {
  pp::ImageData background =
      CreateResourceImage(PP_RESOURCEIMAGE_PDF_PAGE_INDICATOR_BACKGROUND);
  page_indicator_.Configure(pp::Point(), background);
}

void Instance::CreateProgressBar() {
  pp::ImageData background;
  std::vector<pp::ImageData> images = GetProgressBarResources(&background);
  std::string text = GetLocalizedString(PP_RESOURCESTRING_PDFPROGRESSLOADING);
  progress_bar_.CreateProgressControl(kProgressBarId, false, this, 0.0,
      device_scale_, images, background, text);
}

void Instance::ConfigureProgressBar() {
  pp::ImageData background;
  std::vector<pp::ImageData> images = GetProgressBarResources(&background);
  progress_bar_.Reconfigure(background, images, device_scale_);
}

void Instance::CreateThumbnails() {
  thumbnails_.CreateThumbnailControl(
      kThumbnailsId, pp::Rect(), false, this, engine_.get(),
      number_image_generator());
}

void Instance::LoadUrl(const std::string& url) {
  LoadUrlInternal(url, &embed_loader_, &Instance::DidOpen);
}

void Instance::LoadPreviewUrl(const std::string& url) {
  LoadUrlInternal(url, &embed_preview_loader_, &Instance::DidOpenPreview);
}

void Instance::LoadUrlInternal(const std::string& url, pp::URLLoader* loader,
                               void (Instance::* method)(int32_t)) {
  pp::URLRequestInfo request(this);
  request.SetURL(url);
  request.SetMethod("GET");

  *loader = CreateURLLoaderInternal();
  pp::CompletionCallback callback = loader_factory_.NewCallback(method);
  int rv = loader->Open(request, callback);
  if (rv != PP_OK_COMPLETIONPENDING)
    callback.Run(rv);
}

pp::URLLoader Instance::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;
}

int Instance::GetInitialPage(const std::string& url) {
#if defined(OS_NACL)
  return -1;
#else
  size_t found_idx = url.find('#');
  if (found_idx == std::string::npos)
    return -1;

  const std::string& ref = url.substr(found_idx + 1);
  std::vector<std::string> fragments;
  Tokenize(ref, kDelimiters, &fragments);

  // Page number to return, zero-based.
  int page = -1;

  // Handle the case of http://foo.com/bar#NAMEDDEST. This is not explicitly
  // mentioned except by example in the Adobe "PDF Open Parameters" document.
  if ((fragments.size() == 1) && (fragments[0].find('=') == std::string::npos))
    return engine_->GetNamedDestinationPage(fragments[0]);

  for (size_t i = 0; i < fragments.size(); ++i) {
    std::vector<std::string> key_value;
    base::SplitString(fragments[i], '=', &key_value);
    if (key_value.size() != 2)
      continue;
    const std::string& key = key_value[0];
    const std::string& value = key_value[1];

    if (base::strcasecmp(kPage, key.c_str()) == 0) {
      // |page_value| is 1-based.
      int page_value = -1;
      if (base::StringToInt(value, &page_value) && page_value > 0)
        page = page_value - 1;
      continue;
    }
    if (base::strcasecmp(kNamedDest, key.c_str()) == 0) {
      // |page_value| is 0-based.
      int page_value = engine_->GetNamedDestinationPage(value);
      if (page_value >= 0)
        page = page_value;
      continue;
    }
  }
  return page;
#endif
}

void Instance::UpdateToolbarPosition(bool invalidate) {
  pp::Rect ctrl_rc = toolbar_->GetControlsRect();
  int min_toolbar_width = ctrl_rc.width() + GetToolbarRightOffset() +
      GetScaled(kToolbarFadingOffsetLeft);
  int min_toolbar_height = ctrl_rc.width() + GetToolbarBottomOffset() +
      GetScaled(kToolbarFadingOffsetBottom);

  // Update toolbar position
  if (plugin_size_.width() < min_toolbar_width ||
      plugin_size_.height() < min_toolbar_height) {
    // Disable toolbar if it does not fit on the screen.
    toolbar_->Show(false, invalidate);
  } else {
    pp::Point offset(
        plugin_size_.width() - GetToolbarRightOffset() - ctrl_rc.right(),
        plugin_size_.height() - GetToolbarBottomOffset() - ctrl_rc.bottom());
    toolbar_->MoveBy(offset, invalidate);

    int toolbar_width = std::max(plugin_size_.width() / 2, min_toolbar_width);
    toolbar_->ExpandLeft(toolbar_width - toolbar_->rect().width());
    toolbar_->Show(painted_first_page_, invalidate);
  }
}

void Instance::UpdateProgressBarPosition(bool invalidate) {
  // TODO(gene): verify we don't overlap with toolbar.
  int scrollbar_thickness = GetScrollbarThickness();
  pp::Point progress_origin(
      scrollbar_thickness + GetScaled(kProgressOffsetLeft),
      plugin_size_.height() - progress_bar_.rect().height() -
          scrollbar_thickness - GetScaled(kProgressOffsetBottom));
  progress_bar_.MoveTo(progress_origin, invalidate);
}

void Instance::UpdatePageIndicatorPosition(bool invalidate) {
  int32 doc_height = static_cast<int>(document_size_.height() * zoom_);
  pp::Point origin(
      plugin_size_.width() - page_indicator_.rect().width() -
          GetScaled(GetScrollbarReservedThickness()),
      page_indicator_.GetYPosition(engine_->GetVerticalScrollbarYPosition(),
                                   doc_height, plugin_size_.height()));
  page_indicator_.MoveTo(origin, invalidate);
}

void Instance::SetZoom(ZoomMode zoom_mode, double scale) {
  double old_zoom = zoom_;

  zoom_mode_ = zoom_mode;
  if (zoom_mode_ == ZOOM_SCALE)
    zoom_ = scale;
  UpdateZoomScale();

  engine_->ZoomUpdated(zoom_ * device_scale_);
  OnGeometryChanged(old_zoom, device_scale_);

  // If fit-to-height, snap to the beginning of the most visible page.
  if (zoom_mode_ == ZOOM_FIT_TO_PAGE) {
    ScrollToPage(engine_->GetMostVisiblePage());
  }

  // Update sticky buttons to the current zoom style.
  Button* ftp_btn = static_cast<Button*>(
      toolbar_->GetControl(kFitToPageButtonId));
  Button* ftw_btn = static_cast<Button*>(
      toolbar_->GetControl(kFitToWidthButtonId));
  switch (zoom_mode_) {
    case ZOOM_FIT_TO_PAGE:
      ftp_btn->SetPressedState(true);
      ftw_btn->SetPressedState(false);
      break;
    case ZOOM_FIT_TO_WIDTH:
      ftw_btn->SetPressedState(true);
      ftp_btn->SetPressedState(false);
      break;
    default:
      ftw_btn->SetPressedState(false);
      ftp_btn->SetPressedState(false);
  }
}

void Instance::UpdateZoomScale() {
  switch (zoom_mode_) {
    case ZOOM_SCALE:
      break;  // Keep current scale.
    case ZOOM_FIT_TO_PAGE: {
      int page_num = engine_->GetFirstVisiblePage();
      if (page_num == -1)
        break;
      pp::Rect rc = engine_->GetPageRect(page_num);
      if (!rc.height())
        break;
      // Calculate fit to width zoom level.
      double ftw_zoom = static_cast<double>(plugin_dip_size_.width() -
          GetScrollbarReservedThickness()) / document_size_.width();
      // Calculate fit to height zoom level. If document will not fit
      // horizontally, adjust zoom level to allow space for horizontal
      // scrollbar.
      double fth_zoom =
          static_cast<double>(plugin_dip_size_.height()) / rc.height();
      if (fth_zoom * document_size_.width() >
          plugin_dip_size_.width() - GetScrollbarReservedThickness())
        fth_zoom = static_cast<double>(plugin_dip_size_.height()
            - GetScrollbarReservedThickness()) / rc.height();
      zoom_ = std::min(ftw_zoom, fth_zoom);
    } break;
    case ZOOM_FIT_TO_WIDTH:
    case ZOOM_AUTO:
      if (!document_size_.width())
        break;
      zoom_ = static_cast<double>(plugin_dip_size_.width() -
          GetScrollbarReservedThickness()) / document_size_.width();
      if (zoom_mode_ == ZOOM_AUTO && zoom_ > 1.0)
        zoom_ = 1.0;
      break;
  }
  zoom_ = ClipToRange(zoom_, kMinZoom, kMaxZoom);
}

double Instance::CalculateZoom(uint32 control_id) const {
  if (control_id == kZoomInButtonId) {
    for (size_t i = 0; i < chrome_page_zoom::kPresetZoomFactorsSize; ++i) {
      double current_zoom = chrome_page_zoom::kPresetZoomFactors[i];
      if (current_zoom - content::kEpsilon > zoom_)
        return current_zoom;
    }
  } else {
    for (size_t i = chrome_page_zoom::kPresetZoomFactorsSize; i > 0; --i) {
      double current_zoom = chrome_page_zoom::kPresetZoomFactors[i - 1];
      if (current_zoom + content::kEpsilon < zoom_)
        return current_zoom;
    }
  }
  return zoom_;
}

pp::ImageData Instance::CreateResourceImage(PP_ResourceImage image_id) {
  if (hidpi_enabled_)
    return pp::PDF::GetResourceImageForScale(this, image_id, device_scale_);

  return pp::PDF::GetResourceImage(this, image_id);
}

std::string Instance::GetLocalizedString(PP_ResourceString id) {
  pp::Var rv(pp::PDF::GetLocalizedString(this, id));
  if (!rv.is_string())
    return std::string();

  return rv.AsString();
}

void Instance::DrawText(const pp::Point& top_center, PP_ResourceString id) {
  std::string str(GetLocalizedString(id));

  pp::FontDescription_Dev description;
  description.set_family(PP_FONTFAMILY_SANSSERIF);
  description.set_size(kMessageTextSize * device_scale_);
  pp::Font_Dev font(this, description);
  int length = font.MeasureSimpleText(str);
  pp::Point point(top_center);
  point.set_x(point.x() - length / 2);
  DCHECK(!image_data_.is_null());
  font.DrawSimpleText(&image_data_, str, point, kMessageTextColor);
}

void Instance::SetPrintPreviewMode(int page_count) {
  if (!IsPrintPreview() || page_count <= 0) {
    print_preview_page_count_ = 0;
    return;
  }

  print_preview_page_count_ = page_count;
  ScrollToPage(0);
  engine_->AppendBlankPages(print_preview_page_count_);
  if (preview_pages_info_.size() > 0)
    LoadAvailablePreviewPage();
}

bool Instance::IsPrintPreview() {
  return IsPrintPreviewUrl(url_);
}

int Instance::GetPageNumberToDisplay() {
  int page = engine_->GetMostVisiblePage();
  if (IsPrintPreview() && !print_preview_page_numbers_.empty()) {
    page = ClipToRange<int>(page, 0, print_preview_page_numbers_.size() - 1);
    return print_preview_page_numbers_[page];
  }
  return page + 1;
}

void Instance::ProcessPreviewPageInfo(const std::string& url,
                                      int dst_page_index) {
  if (!IsPrintPreview() || print_preview_page_count_ < 0)
    return;

  int src_page_index = ExtractPrintPreviewPageIndex(url);
  if (src_page_index < 1)
    return;

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

void Instance::LoadAvailablePreviewPage() {
  if (preview_pages_info_.size() <= 0)
    return;

  std::string url = preview_pages_info_.front().first;
  int dst_page_index = preview_pages_info_.front().second;
  int src_page_index = ExtractPrintPreviewPageIndex(url);
  if (src_page_index < 1 ||
      dst_page_index >= print_preview_page_count_ ||
      preview_document_load_state_ == LOAD_STATE_LOADING) {
    return;
  }

  preview_document_load_state_ = LOAD_STATE_LOADING;
  LoadPreviewUrl(url);
}

void Instance::EnableAutoscroll(const pp::Point& origin) {
  if (is_autoscroll_)
    return;

  pp::Size client_size = plugin_size_;
  if (v_scrollbar_.get())
    client_size.Enlarge(-GetScrollbarThickness(), 0);
  if (h_scrollbar_.get())
    client_size.Enlarge(0, -GetScrollbarThickness());

  // Do not allow autoscroll if client area is too small.
  if (autoscroll_anchor_.size().width() > client_size.width() ||
      autoscroll_anchor_.size().height() > client_size.height())
    return;

  autoscroll_rect_ = pp::Rect(
      pp::Point(origin.x() - autoscroll_anchor_.size().width() / 2,
                origin.y() - autoscroll_anchor_.size().height() / 2),
      autoscroll_anchor_.size());

  // Make sure autoscroll anchor is in the client area.
  if (autoscroll_rect_.right() > client_size.width()) {
    autoscroll_rect_.set_x(
        client_size.width() - autoscroll_anchor_.size().width());
  }
  if (autoscroll_rect_.bottom() > client_size.height()) {
    autoscroll_rect_.set_y(
        client_size.height() - autoscroll_anchor_.size().height());
  }

  if (autoscroll_rect_.x() < 0)
    autoscroll_rect_.set_x(0);
  if (autoscroll_rect_.y() < 0)
    autoscroll_rect_.set_y(0);

  is_autoscroll_ = true;
  Invalidate(kAutoScrollId, autoscroll_rect_);

  ScheduleTimer(kAutoScrollId, kAutoScrollTimeoutMs);
}

void Instance::DisableAutoscroll() {
  if (is_autoscroll_) {
    is_autoscroll_ = false;
    Invalidate(kAutoScrollId, autoscroll_rect_);
  }
}

PP_CursorType_Dev Instance::CalculateAutoscroll(const pp::Point& mouse_pos) {
  // Scroll only if mouse pointer is outside of the anchor area.
  if (autoscroll_rect_.Contains(mouse_pos)) {
    autoscroll_x_ = 0;
    autoscroll_y_ = 0;
    return PP_CURSORTYPE_MIDDLEPANNING;
  }

  // Relative position to the center of anchor area.
  pp::Point rel_pos = mouse_pos - autoscroll_rect_.CenterPoint();

  // Calculate angle from the X axis. Angle is in range from -pi to pi.
  double angle = atan2(static_cast<double>(rel_pos.y()),
                       static_cast<double>(rel_pos.x()));

  autoscroll_x_ = rel_pos.x() * kAutoScrollFactor;
  autoscroll_y_ = rel_pos.y() * kAutoScrollFactor;

  // Angle is from -pi to pi. Screen Y is increasing toward bottom,
  // so negative angle represent north direction.
  if (angle < - (M_PI * 7.0 / 8.0)) {
    // going west
    return PP_CURSORTYPE_WESTPANNING;
  } else if (angle < - (M_PI * 5.0 / 8.0)) {
    // going north-west
    return PP_CURSORTYPE_NORTHWESTPANNING;
  } else if (angle < - (M_PI * 3.0 / 8.0)) {
    // going north.
    return PP_CURSORTYPE_NORTHPANNING;
  } else if (angle < - (M_PI * 1.0 / 8.0)) {
    // going north-east
    return PP_CURSORTYPE_NORTHEASTPANNING;
  } else if (angle < M_PI * 1.0 / 8.0) {
    // going east.
    return PP_CURSORTYPE_EASTPANNING;
  } else if (angle < M_PI * 3.0 / 8.0) {
    // going south-east
    return PP_CURSORTYPE_SOUTHEASTPANNING;
  } else if (angle < M_PI * 5.0 / 8.0) {
    // going south.
    return PP_CURSORTYPE_SOUTHPANNING;
  } else if (angle < M_PI * 7.0 / 8.0) {
    // going south-west
    return PP_CURSORTYPE_SOUTHWESTPANNING;
  }

  // went around the circle, going west again
  return PP_CURSORTYPE_WESTPANNING;
}

void Instance::ConfigureNumberImageGenerator() {
  std::vector<pp::ImageData> num_images = GetThumbnailResources();
  pp::ImageData number_background = CreateResourceImage(
      PP_RESOURCEIMAGE_PDF_BUTTON_THUMBNAIL_NUM_BACKGROUND);
  number_image_generator_->Configure(number_background,
                                     num_images,
                                     device_scale_);
}

NumberImageGenerator* Instance::number_image_generator() {
  if (!number_image_generator_.get()) {
    number_image_generator_.reset(new NumberImageGenerator(this));
    ConfigureNumberImageGenerator();
  }
  return number_image_generator_.get();
}

int Instance::GetScaled(int x) const {
  return static_cast<int>(x * device_scale_);
}

void Instance::UserMetricsRecordAction(const std::string& action) {
  pp::PDF::UserMetricsRecordAction(this, pp::Var(action));
}

PDFScriptableObject::PDFScriptableObject(Instance* instance)
    : instance_(instance) {
}

PDFScriptableObject::~PDFScriptableObject() {
}

bool PDFScriptableObject::HasMethod(const pp::Var& name, pp::Var* exception) {
  return instance_->HasScriptableMethod(name, exception);
}

pp::Var PDFScriptableObject::Call(const pp::Var& method,
                                  const std::vector<pp::Var>& args,
                                  pp::Var* exception) {
  return instance_->CallScriptableMethod(method, args, exception);
}

}  // namespace chrome_pdf
