Home | History | Annotate | Download | only in pdf
      1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
      2 // Use of this source code is governed by a BSD-style license that can be
      3 // found in the LICENSE file.
      4 
      5 #ifndef PDF_INSTANCE_H_
      6 #define PDF_INSTANCE_H_
      7 
      8 #include <queue>
      9 #include <set>
     10 #include <string>
     11 #include <utility>
     12 #include <vector>
     13 
     14 #include "base/memory/scoped_ptr.h"
     15 #include "pdf/button.h"
     16 #include "pdf/fading_controls.h"
     17 #include "pdf/page_indicator.h"
     18 #include "pdf/paint_manager.h"
     19 #include "pdf/pdf_engine.h"
     20 #include "pdf/preview_mode_client.h"
     21 #include "pdf/progress_control.h"
     22 #include "pdf/thumbnail_control.h"
     23 
     24 #include "ppapi/c/private/ppb_pdf.h"
     25 #include "ppapi/cpp/dev/printing_dev.h"
     26 #include "ppapi/cpp/dev/scriptable_object_deprecated.h"
     27 #include "ppapi/cpp/dev/scrollbar_dev.h"
     28 #include "ppapi/cpp/dev/selection_dev.h"
     29 #include "ppapi/cpp/dev/widget_client_dev.h"
     30 #include "ppapi/cpp/dev/zoom_dev.h"
     31 #include "ppapi/cpp/graphics_2d.h"
     32 #include "ppapi/cpp/image_data.h"
     33 #include "ppapi/cpp/input_event.h"
     34 #include "ppapi/cpp/private/find_private.h"
     35 #include "ppapi/cpp/private/instance_private.h"
     36 #include "ppapi/cpp/private/var_private.h"
     37 #include "ppapi/cpp/url_loader.h"
     38 #include "ppapi/utility/completion_callback_factory.h"
     39 
     40 namespace pp {
     41 class TextInput_Dev;
     42 }
     43 
     44 namespace chrome_pdf {
     45 
     46 struct ToolbarButtonInfo;
     47 
     48 class Instance : public pp::InstancePrivate,
     49                  public pp::Find_Private,
     50                  public pp::Printing_Dev,
     51                  public pp::Selection_Dev,
     52                  public pp::WidgetClient_Dev,
     53                  public pp::Zoom_Dev,
     54                  public PaintManager::Client,
     55                  public PDFEngine::Client,
     56                  public PreviewModeClient::Client,
     57                  public ControlOwner {
     58  public:
     59   explicit Instance(PP_Instance instance);
     60   virtual ~Instance();
     61 
     62   // pp::Instance implementation.
     63   virtual bool Init(uint32_t argc,
     64                     const char* argn[],
     65                     const char* argv[]) OVERRIDE;
     66   virtual bool HandleDocumentLoad(const pp::URLLoader& loader) OVERRIDE;
     67   virtual bool HandleInputEvent(const pp::InputEvent& event) OVERRIDE;
     68   virtual void DidChangeView(const pp::View& view) OVERRIDE;
     69   virtual pp::Var GetInstanceObject() OVERRIDE;
     70 
     71   // pp::Find_Private implementation.
     72   virtual bool StartFind(const std::string& text, bool case_sensitive) OVERRIDE;
     73   virtual void SelectFindResult(bool forward) OVERRIDE;
     74   virtual void StopFind() OVERRIDE;
     75 
     76   // pp::PaintManager::Client implementation.
     77   virtual void OnPaint(const std::vector<pp::Rect>& paint_rects,
     78                        std::vector<PaintManager::ReadyRect>* ready,
     79                        std::vector<pp::Rect>* pending) OVERRIDE;
     80 
     81   // pp::Printing_Dev implementation.
     82   virtual uint32_t QuerySupportedPrintOutputFormats() OVERRIDE;
     83   virtual int32_t PrintBegin(
     84       const PP_PrintSettings_Dev& print_settings) OVERRIDE;
     85   virtual pp::Resource PrintPages(
     86       const PP_PrintPageNumberRange_Dev* page_ranges,
     87       uint32_t page_range_count) OVERRIDE;
     88   virtual void PrintEnd() OVERRIDE;
     89   virtual bool IsPrintScalingDisabled() OVERRIDE;
     90 
     91   // pp::Private implementation.
     92   virtual pp::Var GetLinkAtPosition(const pp::Point& point);
     93 
     94   // PPP_Selection_Dev implementation.
     95   virtual pp::Var GetSelectedText(bool html) OVERRIDE;
     96 
     97   // WidgetClient_Dev implementation.
     98   virtual void InvalidateWidget(pp::Widget_Dev widget,
     99                                 const pp::Rect& dirty_rect) OVERRIDE;
    100   virtual void ScrollbarValueChanged(pp::Scrollbar_Dev scrollbar,
    101                                      uint32_t value) OVERRIDE;
    102   virtual void ScrollbarOverlayChanged(pp::Scrollbar_Dev scrollbar,
    103                                        bool overlay) OVERRIDE;
    104 
    105   // pp::Zoom_Dev implementation.
    106   virtual void Zoom(double scale, bool text_only) OVERRIDE;
    107   void ZoomChanged(double factor);  // Override.
    108 
    109   void FlushCallback(int32_t result);
    110   void DidOpen(int32_t result);
    111   void DidOpenPreview(int32_t result);
    112   // If the given widget intersects the rectangle, paints it and adds the
    113   // rect to ready.
    114   void PaintIfWidgetIntersects(pp::Widget_Dev* widget,
    115                                const pp::Rect& rect,
    116                                std::vector<PaintManager::ReadyRect>* ready,
    117                                std::vector<pp::Rect>* pending);
    118 
    119   // Called when the timer is fired.
    120   void OnTimerFired(int32_t);
    121   void OnClientTimerFired(int32_t id);
    122 
    123   // Called when the control timer is fired.
    124   void OnControlTimerFired(int32_t,
    125                            const uint32& control_id,
    126                            const uint32& timer_id);
    127 
    128   // Called to print without re-entrancy issues.
    129   void OnPrint(int32_t);
    130 
    131   // PDFEngine::Client implementation.
    132   virtual void DocumentSizeUpdated(const pp::Size& size);
    133   virtual void Invalidate(const pp::Rect& rect);
    134   virtual void Scroll(const pp::Point& point);
    135   virtual void ScrollToX(int position);
    136   virtual void ScrollToY(int position);
    137   virtual void ScrollToPage(int page);
    138   virtual void NavigateTo(const std::string& url, bool open_in_new_tab);
    139   virtual void UpdateCursor(PP_CursorType_Dev cursor);
    140   virtual void UpdateTickMarks(const std::vector<pp::Rect>& tickmarks);
    141   virtual void NotifyNumberOfFindResultsChanged(int total, bool final_result);
    142   virtual void NotifySelectedFindResultChanged(int current_find_index);
    143   virtual void GetDocumentPassword(
    144       pp::CompletionCallbackWithOutput<pp::Var> callback);
    145   virtual void Alert(const std::string& message);
    146   virtual bool Confirm(const std::string& message);
    147   virtual std::string Prompt(const std::string& question,
    148                              const std::string& default_answer);
    149   virtual std::string GetURL();
    150   virtual void Email(const std::string& to,
    151                      const std::string& cc,
    152                      const std::string& bcc,
    153                      const std::string& subject,
    154                      const std::string& body);
    155   virtual void Print();
    156   virtual void SubmitForm(const std::string& url,
    157                           const void* data,
    158                           int length);
    159   virtual std::string ShowFileSelectionDialog();
    160   virtual pp::URLLoader CreateURLLoader();
    161   virtual void ScheduleCallback(int id, int delay_in_ms);
    162   virtual void SearchString(const base::char16* string,
    163                             const base::char16* term,
    164                             bool case_sensitive,
    165                             std::vector<SearchStringResult>* results);
    166   virtual void DocumentPaintOccurred();
    167   virtual void DocumentLoadComplete(int page_count);
    168   virtual void DocumentLoadFailed();
    169   virtual pp::Instance* GetPluginInstance();
    170   virtual void DocumentHasUnsupportedFeature(const std::string& feature);
    171   virtual void DocumentLoadProgress(uint32 available, uint32 doc_size);
    172   virtual void FormTextFieldFocusChange(bool in_focus);
    173   virtual bool IsPrintPreview();
    174 
    175   // ControlOwner implementation.
    176   virtual void OnEvent(uint32 control_id, uint32 event_id, void* data);
    177   virtual void Invalidate(uint32 control_id, const pp::Rect& rc);
    178   virtual uint32 ScheduleTimer(uint32 control_id, uint32 timeout_ms);
    179   virtual void SetEventCapture(uint32 control_id, bool set_capture);
    180   virtual void SetCursor(uint32 control_id, PP_CursorType_Dev cursor_type);
    181   virtual pp::Instance* GetInstance();
    182 
    183   bool dont_paint() const { return dont_paint_; }
    184   void set_dont_paint(bool dont_paint) { dont_paint_ = dont_paint; }
    185 
    186   // Called by PDFScriptableObject.
    187   bool HasScriptableMethod(const pp::Var& method, pp::Var* exception);
    188   pp::Var CallScriptableMethod(const pp::Var& method,
    189                                const std::vector<pp::Var>& args,
    190                                pp::Var* exception);
    191 
    192   // PreviewModeClient::Client implementation.
    193   virtual void PreviewDocumentLoadComplete() OVERRIDE;
    194   virtual void PreviewDocumentLoadFailed() OVERRIDE;
    195 
    196   // Helper functions for implementing PPP_PDF.
    197   void RotateClockwise();
    198   void RotateCounterclockwise();
    199 
    200  private:
    201   // Called whenever the plugin geometry changes to update the location of the
    202   // scrollbars, background parts, and notifies the pdf engine.
    203   void OnGeometryChanged(double old_zoom, float old_device_scale);
    204 
    205   void CreateHorizontalScrollbar();
    206   void CreateVerticalScrollbar();
    207   void DestroyHorizontalScrollbar();
    208   void DestroyVerticalScrollbar();
    209 
    210   // Returns the thickness of a scrollbar. This returns the thickness when it's
    211   // shown, so for overlay scrollbars it'll still be non-zero.
    212   int GetScrollbarThickness();
    213 
    214   // Returns the space we need to reserve for the scrollbar in the plugin area.
    215   // If overlay scrollbars are used, this will be 0.
    216   int GetScrollbarReservedThickness();
    217 
    218   // Returns true if overlay scrollbars are in use.
    219   bool IsOverlayScrollbar();
    220 
    221   // Figures out the location of any background rectangles (i.e. those that
    222   // aren't painted by the PDF engine).
    223   void CalculateBackgroundParts();
    224 
    225   // Computes document width/height in device pixels, based on current zoom and
    226   // device scale
    227   int GetDocumentPixelWidth() const;
    228   int GetDocumentPixelHeight() const;
    229 
    230   // Draws a rectangle with the specified dimensions and color in our buffer.
    231   void FillRect(const pp::Rect& rect, unsigned int color);
    232 
    233   std::vector<pp::ImageData> GetThumbnailResources();
    234   std::vector<pp::ImageData> GetProgressBarResources(pp::ImageData* background);
    235 
    236   void CreateToolbar(const ToolbarButtonInfo* tb_info, size_t size);
    237   int GetToolbarRightOffset();
    238   int GetToolbarBottomOffset();
    239   void CreateProgressBar();
    240   void ConfigureProgressBar();
    241   void CreateThumbnails();
    242   void CreatePageIndicator(bool always_visible);
    243   void ConfigurePageIndicator();
    244 
    245   void PaintOverlayControl(Control* ctrl,
    246                            pp::ImageData* image_data,
    247                            std::vector<PaintManager::ReadyRect>* ready);
    248 
    249   void LoadUrl(const std::string& url);
    250   void LoadPreviewUrl(const std::string& url);
    251   void LoadUrlInternal(const std::string& url, pp::URLLoader* loader,
    252                        void (Instance::* method)(int32_t));
    253 
    254   // Creates a URL loader and allows it to access all urls, i.e. not just the
    255   // frame's origin.
    256   pp::URLLoader CreateURLLoaderInternal();
    257 
    258   // Figure out the initial page to display based on #page=N and #nameddest=foo
    259   // in the |url_|.
    260   // Returns -1 if there is no valid fragment. The returned value is 0-based,
    261   // whereas page=N is 1-based.
    262   int GetInitialPage(const std::string& url);
    263 
    264   void UpdateToolbarPosition(bool invalidate);
    265   void UpdateProgressBarPosition(bool invalidate);
    266   void UpdatePageIndicatorPosition(bool invalidate);
    267 
    268   void FormDidOpen(int32_t result);
    269 
    270   std::string GetLocalizedString(PP_ResourceString id);
    271 
    272   void UserMetricsRecordAction(const std::string& action);
    273 
    274   void SaveAs();
    275 
    276   enum ZoomMode {
    277     ZOOM_SCALE,  // Standard zooming mode, resize will not affect it.
    278     ZOOM_FIT_TO_WIDTH,  // Maintain fit to width on resize.
    279     ZOOM_FIT_TO_PAGE,  // Maintain fit to page on resize.
    280     ZOOM_AUTO  // Maintain the default auto fitting mode on resize.
    281   };
    282 
    283   enum DocumentLoadState {
    284     LOAD_STATE_LOADING,
    285     LOAD_STATE_COMPLETE,
    286     LOAD_STATE_FAILED,
    287   };
    288 
    289   // Set new zoom mode and scale. Scale will be ignored if mode != ZOOM_SCALE.
    290   void SetZoom(ZoomMode zoom_mode, double scale);
    291 
    292   // Updates internal zoom scale based on the plugin/document geometry and
    293   // current mode.
    294   void UpdateZoomScale();
    295 
    296   // Simulates how Chrome "snaps" zooming up/down to the next nearest zoom level
    297   // when the previous zoom level wasn't an integer.  We do this so that
    298   // pressing the zoom buttons has the same effect as the menu buttons, even if
    299   // we start from a non-standard zoom level because of fit-width or fit-height.
    300   double CalculateZoom(uint32 control_id) const;
    301 
    302   pp::ImageData CreateResourceImage(PP_ResourceImage image_id);
    303 
    304   void DrawText(const pp::Point& top_center, PP_ResourceString id);
    305 
    306   // Set print preview mode, where the current PDF document is reduced to
    307   // only one page, and then extended to |page_count| pages with
    308   // |page_count| - 1 blank pages.
    309   void SetPrintPreviewMode(int page_count);
    310 
    311   // Returns the page number to be displayed in the page indicator. If the
    312   // plugin is running within print preview, the displayed number might be
    313   // different from the index of the displayed page.
    314   int GetPageNumberToDisplay();
    315 
    316   // Process the preview page data information. |src_url| specifies the preview
    317   // page data location. The |src_url| is in the format:
    318   // chrome://print/id/page_number/print.pdf
    319   // |dst_page_index| specifies the blank page index that needs to be replaced
    320   // with the new page data.
    321   void ProcessPreviewPageInfo(const std::string& src_url, int dst_page_index);
    322   // Load the next available preview page into the blank page.
    323   void LoadAvailablePreviewPage();
    324 
    325   // Enables autoscroll using origin as a neutral (center) point.
    326   void EnableAutoscroll(const pp::Point& origin);
    327   // Disables autoscroll and returns to normal functionality.
    328   void DisableAutoscroll();
    329   // Calculate autoscroll info and return proper mouse pointer and scroll
    330   // andjustments.
    331   PP_CursorType_Dev CalculateAutoscroll(const pp::Point& mouse_pos);
    332 
    333   void ConfigureNumberImageGenerator();
    334 
    335   NumberImageGenerator* number_image_generator();
    336 
    337   int GetScaled(int x) const;
    338 
    339   pp::ImageData image_data_;
    340   // Used when the plugin is embedded in a page and we have to create the loader
    341   // ourself.
    342   pp::CompletionCallbackFactory<Instance> loader_factory_;
    343   pp::URLLoader embed_loader_;
    344   pp::URLLoader embed_preview_loader_;
    345 
    346   scoped_ptr<pp::Scrollbar_Dev> h_scrollbar_;
    347   scoped_ptr<pp::Scrollbar_Dev> v_scrollbar_;
    348   int32 valid_v_range_;
    349 
    350   PP_CursorType_Dev cursor_;  // The current cursor.
    351 
    352   // Used when selecting and dragging beyond the visible portion, in which case
    353   // we want to scroll the document.
    354   bool timer_pending_;
    355   pp::MouseInputEvent last_mouse_event_;
    356   pp::CompletionCallbackFactory<Instance> timer_factory_;
    357   uint32 current_timer_id_;
    358 
    359   // Size, in pixels, of plugin rectangle.
    360   pp::Size plugin_size_;
    361   // Size, in DIPs, of plugin rectangle.
    362   pp::Size plugin_dip_size_;
    363   // Remaining area, in pixels, to render the pdf in after accounting for
    364   // scrollbars/toolbars and horizontal centering.
    365   pp::Rect available_area_;
    366   // Size of entire document in pixels (i.e. if each page is 800 pixels high and
    367   // there are 10 pages, the height will be 8000).
    368   pp::Size document_size_;
    369 
    370   double zoom_;  // Current zoom factor.
    371 
    372   float device_scale_;  // Current device scale factor.
    373   bool printing_enabled_;
    374   bool hidpi_enabled_;
    375   // True if the plugin is full-page.
    376   bool full_;
    377   // Zooming mode (none, fit to width, fit to height)
    378   ZoomMode zoom_mode_;
    379 
    380   // If true, this means we told the RenderView that we're starting a network
    381   // request so that it can start the throbber. We will tell it again once the
    382   // document finishes loading.
    383   bool did_call_start_loading_;
    384 
    385   // Hold off on painting invalidated requests while this flag is true.
    386   bool dont_paint_;
    387 
    388   // Indicates if plugin is in autoscroll mode.
    389   bool is_autoscroll_;
    390   // Rect for autoscroll anchor.
    391   pp::Rect autoscroll_rect_;
    392   // Image of the autoscroll anchor and its background.
    393   pp::ImageData autoscroll_anchor_;
    394   // Autoscrolling deltas in pixels.
    395   int autoscroll_x_;
    396   int autoscroll_y_;
    397 
    398   // Thickness of a scrollbar.
    399   int scrollbar_thickness_;
    400 
    401   // Reserved thickness of a scrollbar. This is how much space the scrollbar
    402   // takes from the available area. 0 for overlay.
    403   int scrollbar_reserved_thickness_;
    404 
    405   // Used to remember which toolbar is in use
    406   const ToolbarButtonInfo* current_tb_info_;
    407   size_t current_tb_info_size_;
    408 
    409   PaintManager paint_manager_;
    410 
    411   struct BackgroundPart {
    412     pp::Rect location;
    413     unsigned int color;
    414   };
    415   std::vector<BackgroundPart> background_parts_;
    416 
    417   struct PrintSettings {
    418     PrintSettings() {
    419       Clear();
    420     }
    421     void Clear() {
    422       is_printing = false;
    423       print_pages_called_ = false;
    424       memset(&pepper_print_settings, 0, sizeof(pepper_print_settings));
    425     }
    426     // This is set to true when PrintBegin is called and false when PrintEnd is
    427     // called.
    428     bool is_printing;
    429     // To know whether this was an actual print operation, so we don't double
    430     // count UMA logging.
    431     bool print_pages_called_;
    432     PP_PrintSettings_Dev pepper_print_settings;
    433   };
    434 
    435   PrintSettings print_settings_;
    436 
    437   scoped_ptr<PDFEngine> engine_;
    438 
    439   // This engine is used to render the individual preview page data. This is
    440   // used only in print preview mode. This will use |PreviewModeClient|
    441   // interface which has very limited access to the pp::Instance.
    442   scoped_ptr<PDFEngine> preview_engine_;
    443 
    444   std::string url_;
    445 
    446   scoped_ptr<FadingControls> toolbar_;
    447   ThumbnailControl thumbnails_;
    448   ProgressControl progress_bar_;
    449   uint32 delayed_progress_timer_id_;
    450   PageIndicator page_indicator_;
    451 
    452   // Used for creating images from numbers.
    453   scoped_ptr<NumberImageGenerator> number_image_generator_;
    454 
    455   // Used for submitting forms.
    456   pp::CompletionCallbackFactory<Instance> form_factory_;
    457   pp::URLLoader form_loader_;
    458 
    459   // Used for printing without re-entrancy issues.
    460   pp::CompletionCallbackFactory<Instance> print_callback_factory_;
    461 
    462   // True if we haven't painted the plugin viewport yet.
    463   bool first_paint_;
    464 
    465   // True when we've painted at least one page from the document.
    466   bool painted_first_page_;
    467 
    468   // True if we should display page indicator, false otherwise
    469   bool show_page_indicator_;
    470 
    471   // Callback when the document load completes.
    472   pp::Var on_load_callback_;
    473   pp::Var on_scroll_callback_;
    474   pp::Var on_plugin_size_changed_callback_;
    475 
    476   DocumentLoadState document_load_state_;
    477   DocumentLoadState preview_document_load_state_;
    478 
    479   // JavaScript interface to control this instance.
    480   // This wraps a PDFScriptableObject in a pp::Var.
    481   pp::VarPrivate instance_object_;
    482 
    483   // Used so that we only tell the browser once about an unsupported feature, to
    484   // avoid the infobar going up more than once.
    485   bool told_browser_about_unsupported_feature_;
    486 
    487   // Keeps track of which unsupported features we reported, so we avoid spamming
    488   // the stats if a feature shows up many times per document.
    489   std::set<std::string> unsupported_features_reported_;
    490 
    491   // Number of pages in print preview mode, 0 if not in print preview mode.
    492   int print_preview_page_count_;
    493   std::vector<int> print_preview_page_numbers_;
    494 
    495   // Used to manage loaded print preview page information. A |PreviewPageInfo|
    496   // consists of data source url string and the page index in the destination
    497   // document.
    498   typedef std::pair<std::string, int> PreviewPageInfo;
    499   std::queue<PreviewPageInfo> preview_pages_info_;
    500 
    501   // Used to signal the browser about focus changes to trigger the OSK.
    502   // TODO(abodenha (at) chromium.org) Implement full IME support in the plugin.
    503   // http://crbug.com/132565
    504   scoped_ptr<pp::TextInput_Dev> text_input_;
    505 };
    506 
    507 // This implements the JavaScript class entrypoint for the plugin instance.
    508 // This class is just a thin wrapper. It delegates relevant methods to Instance.
    509 class PDFScriptableObject : public pp::deprecated::ScriptableObject {
    510  public:
    511   explicit PDFScriptableObject(Instance* instance);
    512   virtual ~PDFScriptableObject();
    513 
    514   // pp::deprecated::ScriptableObject implementation.
    515   virtual bool HasMethod(const pp::Var& method, pp::Var* exception);
    516   virtual pp::Var Call(const pp::Var& method,
    517                        const std::vector<pp::Var>& args,
    518                        pp::Var* exception);
    519 
    520  private:
    521   Instance* instance_;
    522 };
    523 
    524 }  // namespace chrome_pdf
    525 
    526 #endif  // PDF_INSTANCE_H_
    527