// 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);
  } else {
    DCHECK(!did_call_start_loading_);
    pp::PDF::DidStartLoading(this);
    did_call_start_loading_ = true;
  }

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

  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
