// 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 kJSGetSelectedText[] = "getSelectedText";
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);
  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() {
  if (timer_pending_) {
    timer_factory_.CancelAll();
    timer_pending_ = false;
  }
  // The engine may try to access this instance during its destruction.
  // Make sure this happens early while the instance is still intact.
  engine_.reset();
  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. Spacebar / shift+spacebar should do the same.
  if (v_scrollbar_.get() && event.GetType() == PP_INPUTEVENT_TYPE_KEYDOWN) {
    pp::KeyboardInputEvent keyboard_event(event);
    bool no_h_scrollbar = !h_scrollbar_.get();
    uint32_t key_code = keyboard_event.GetKeyCode();
    bool page_down = no_h_scrollbar && key_code == ui::VKEY_RIGHT;
    bool page_up = no_h_scrollbar && key_code == ui::VKEY_LEFT;
    if (zoom_mode_ == ZOOM_FIT_TO_PAGE) {
      bool has_shift =
          keyboard_event.GetModifiers() & PP_INPUTEVENT_MODIFIER_SHIFTKEY;
      bool key_is_space = key_code == ui::VKEY_SPACE;
      page_down |= key_is_space || key_code == ui::VKEY_NEXT;
      page_up |= (key_is_space && has_shift) || (key_code == ui::VKEY_PRIOR);
    }
    if (page_down) {
      int page = engine_->GetFirstVisiblePage();
      if (page == -1)
        return true;
      // 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 (page == -1)
        return true;
      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) {
    pp::KeyboardInputEvent keyboard_event(event);
    const uint32 modifier = event.GetModifiers();
    if (modifier & kDefaultKeyModifier) {
      switch (keyboard_event.GetKeyCode()) {
        case 'A':
          engine_->SelectAll();
          return true;
      }
    }
    if (modifier & PP_INPUTEVENT_MODIFIER_CONTROLKEY) {
      switch (keyboard_event.GetKeyCode()) {
        case ui::VKEY_OEM_4:
          // Left bracket.
          engine_->RotateCounterclockwise();
          return true;
        case ui::VKEY_OEM_6:
          // Right bracket.
          engine_->RotateClockwise();
          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");

  // If the zoom level doesn't change it means that this zoom change might have
  // been initiated by the plugin. In that case, we don't want to change the
  // zoom mode to ZOOM_SCALE as it may have been intentionally set to
  // ZOOM_FIT_TO_PAGE or some other value when the zoom was last changed.
  if (scale == zoom_)
    return;

  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_);
    FillRect(rect, kBackgroundColor);
    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 = {
    pp::Rect(0, 0, left_width, bottom),
    kBackgroundColor
  };
  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, uint32 color) {
  DCHECK(!image_data_.is_null() || rect.IsEmpty());
  uint32* buffer_start = static_cast<uint32*>(image_data_.data());
  int stride = image_data_.stride();
  uint32* 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());

  // Run the scroll callback asynchronously. This function can be invoked by a
  // layout change which should not re-enter into JS synchronously.
  pp::CompletionCallback callback =
      callback_factory_.NewCallback(&Instance::RunCallback,
                                    on_scroll_callback_);
  pp::Module::Get()->core()->CallOnMainThread(0, 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 |url_copy| starts with '#', then it's for the same URL with a
    // different URL fragment.
    if (url_copy[0] == '#') {
      url_copy = url_ + url_copy;
      // Changing the href does not actually do anything when navigating in the
      // same tab, so do the actual page scroll here. Then fall through so the
      // href gets updated.
      if (!open_in_new_tab) {
        int page_number = GetInitialPage(url_copy);
        if (page_number >= 0)
          ScrollToPage(page_number);
      }
    }
    // If there's no scheme, add http.
    if (url_copy.find("://") == std::string::npos &&
        url_copy.find("mailto:") == std::string::npos) {
      url_copy = "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("file://") != 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 == "file://" ||
        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) {
  DCHECK_GE(current_find_index, 0);
  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 =
      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 (did_call_start_loading_) {
    pp::PDF::DidStopLoading(this);
    did_call_start_loading_ = false;
  }

  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;

  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 == kJSGetSelectedText ||
          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_number())
      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 == kJSGetSelectedText) {
    return GetSelectedText(false);
  }
  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_));

  // Run the plugin size change callback asynchronously. This function can be
  // invoked by a layout change which should not re-enter into JS synchronously.
  pp::CompletionCallback callback =
      callback_factory_.NewCallback(&Instance::RunCallback,
                                    on_plugin_size_changed_callback_);
  pp::Module::Get()->core()->CallOnMainThread(0, callback);
}

void Instance::RunCallback(int32_t, pp::Var callback) {
  if (callback.is_string())
    ExecuteScript(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) {
  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;
}

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) {
  pp::ImageData resource_data;
  if (hidpi_enabled_) {
    resource_data =
        pp::PDF::GetResourceImageForScale(this, image_id, device_scale_);
  }

  return resource_data.data() ? resource_data
                              : 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
