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   // Runs the given JS callback given in |callback|.
    206   void RunCallback(int32_t, pp::Var callback);
    207 
    208   void CreateHorizontalScrollbar();
    209   void CreateVerticalScrollbar();
    210   void DestroyHorizontalScrollbar();
    211   void DestroyVerticalScrollbar();
    212 
    213   // Returns the thickness of a scrollbar. This returns the thickness when it's
    214   // shown, so for overlay scrollbars it'll still be non-zero.
    215   int GetScrollbarThickness();
    216 
    217   // Returns the space we need to reserve for the scrollbar in the plugin area.
    218   // If overlay scrollbars are used, this will be 0.
    219   int GetScrollbarReservedThickness();
    220 
    221   // Returns true if overlay scrollbars are in use.
    222   bool IsOverlayScrollbar();
    223 
    224   // Figures out the location of any background rectangles (i.e. those that
    225   // aren't painted by the PDF engine).
    226   void CalculateBackgroundParts();
    227 
    228   // Computes document width/height in device pixels, based on current zoom and
    229   // device scale
    230   int GetDocumentPixelWidth() const;
    231   int GetDocumentPixelHeight() const;
    232 
    233   // Draws a rectangle with the specified dimensions and color in our buffer.
    234   void FillRect(const pp::Rect& rect, uint32 color);
    235 
    236   std::vector<pp::ImageData> GetThumbnailResources();
    237   std::vector<pp::ImageData> GetProgressBarResources(pp::ImageData* background);
    238 
    239   void CreateToolbar(const ToolbarButtonInfo* tb_info, size_t size);
    240   int GetToolbarRightOffset();
    241   int GetToolbarBottomOffset();
    242   void CreateProgressBar();
    243   void ConfigureProgressBar();
    244   void CreateThumbnails();
    245   void CreatePageIndicator(bool always_visible);
    246   void ConfigurePageIndicator();
    247 
    248   void PaintOverlayControl(Control* ctrl,
    249                            pp::ImageData* image_data,
    250                            std::vector<PaintManager::ReadyRect>* ready);
    251 
    252   void LoadUrl(const std::string& url);
    253   void LoadPreviewUrl(const std::string& url);
    254   void LoadUrlInternal(const std::string& url, pp::URLLoader* loader,
    255                        void (Instance::* method)(int32_t));
    256 
    257   // Creates a URL loader and allows it to access all urls, i.e. not just the
    258   // frame's origin.
    259   pp::URLLoader CreateURLLoaderInternal();
    260 
    261   // Figure out the initial page to display based on #page=N and #nameddest=foo
    262   // in the |url_|.
    263   // Returns -1 if there is no valid fragment. The returned value is 0-based,
    264   // whereas page=N is 1-based.
    265   int GetInitialPage(const std::string& url);
    266 
    267   void UpdateToolbarPosition(bool invalidate);
    268   void UpdateProgressBarPosition(bool invalidate);
    269   void UpdatePageIndicatorPosition(bool invalidate);
    270 
    271   void FormDidOpen(int32_t result);
    272 
    273   std::string GetLocalizedString(PP_ResourceString id);
    274 
    275   void UserMetricsRecordAction(const std::string& action);
    276 
    277   void SaveAs();
    278 
    279   enum ZoomMode {
    280     ZOOM_SCALE,  // Standard zooming mode, resize will not affect it.
    281     ZOOM_FIT_TO_WIDTH,  // Maintain fit to width on resize.
    282     ZOOM_FIT_TO_PAGE,  // Maintain fit to page on resize.
    283     ZOOM_AUTO  // Maintain the default auto fitting mode on resize.
    284   };
    285 
    286   enum DocumentLoadState {
    287     LOAD_STATE_LOADING,
    288     LOAD_STATE_COMPLETE,
    289     LOAD_STATE_FAILED,
    290   };
    291 
    292   // Set new zoom mode and scale. Scale will be ignored if mode != ZOOM_SCALE.
    293   void SetZoom(ZoomMode zoom_mode, double scale);
    294 
    295   // Updates internal zoom scale based on the plugin/document geometry and
    296   // current mode.
    297   void UpdateZoomScale();
    298 
    299   // Simulates how Chrome "snaps" zooming up/down to the next nearest zoom level
    300   // when the previous zoom level wasn't an integer.  We do this so that
    301   // pressing the zoom buttons has the same effect as the menu buttons, even if
    302   // we start from a non-standard zoom level because of fit-width or fit-height.
    303   double CalculateZoom(uint32 control_id) const;
    304 
    305   pp::ImageData CreateResourceImage(PP_ResourceImage image_id);
    306 
    307   void DrawText(const pp::Point& top_center, PP_ResourceString id);
    308 
    309   // Set print preview mode, where the current PDF document is reduced to
    310   // only one page, and then extended to |page_count| pages with
    311   // |page_count| - 1 blank pages.
    312   void SetPrintPreviewMode(int page_count);
    313 
    314   // Returns the page number to be displayed in the page indicator. If the
    315   // plugin is running within print preview, the displayed number might be
    316   // different from the index of the displayed page.
    317   int GetPageNumberToDisplay();
    318 
    319   // Process the preview page data information. |src_url| specifies the preview
    320   // page data location. The |src_url| is in the format:
    321   // chrome://print/id/page_number/print.pdf
    322   // |dst_page_index| specifies the blank page index that needs to be replaced
    323   // with the new page data.
    324   void ProcessPreviewPageInfo(const std::string& src_url, int dst_page_index);
    325   // Load the next available preview page into the blank page.
    326   void LoadAvailablePreviewPage();
    327 
    328   // Enables autoscroll using origin as a neutral (center) point.
    329   void EnableAutoscroll(const pp::Point& origin);
    330   // Disables autoscroll and returns to normal functionality.
    331   void DisableAutoscroll();
    332   // Calculate autoscroll info and return proper mouse pointer and scroll
    333   // andjustments.
    334   PP_CursorType_Dev CalculateAutoscroll(const pp::Point& mouse_pos);
    335 
    336   void ConfigureNumberImageGenerator();
    337 
    338   NumberImageGenerator* number_image_generator();
    339 
    340   int GetScaled(int x) const;
    341 
    342   pp::ImageData image_data_;
    343   // Used when the plugin is embedded in a page and we have to create the loader
    344   // ourself.
    345   pp::CompletionCallbackFactory<Instance> loader_factory_;
    346   pp::URLLoader embed_loader_;
    347   pp::URLLoader embed_preview_loader_;
    348 
    349   scoped_ptr<pp::Scrollbar_Dev> h_scrollbar_;
    350   scoped_ptr<pp::Scrollbar_Dev> v_scrollbar_;
    351   int32 valid_v_range_;
    352 
    353   PP_CursorType_Dev cursor_;  // The current cursor.
    354 
    355   // Used when selecting and dragging beyond the visible portion, in which case
    356   // we want to scroll the document.
    357   bool timer_pending_;
    358   pp::MouseInputEvent last_mouse_event_;
    359   pp::CompletionCallbackFactory<Instance> timer_factory_;
    360   uint32 current_timer_id_;
    361 
    362   // Size, in pixels, of plugin rectangle.
    363   pp::Size plugin_size_;
    364   // Size, in DIPs, of plugin rectangle.
    365   pp::Size plugin_dip_size_;
    366   // Remaining area, in pixels, to render the pdf in after accounting for
    367   // scrollbars/toolbars and horizontal centering.
    368   pp::Rect available_area_;
    369   // Size of entire document in pixels (i.e. if each page is 800 pixels high and
    370   // there are 10 pages, the height will be 8000).
    371   pp::Size document_size_;
    372 
    373   double zoom_;  // Current zoom factor.
    374 
    375   float device_scale_;  // Current device scale factor.
    376   bool printing_enabled_;
    377   bool hidpi_enabled_;
    378   // True if the plugin is full-page.
    379   bool full_;
    380   // Zooming mode (none, fit to width, fit to height)
    381   ZoomMode zoom_mode_;
    382 
    383   // If true, this means we told the RenderView that we're starting a network
    384   // request so that it can start the throbber. We will tell it again once the
    385   // document finishes loading.
    386   bool did_call_start_loading_;
    387 
    388   // Hold off on painting invalidated requests while this flag is true.
    389   bool dont_paint_;
    390 
    391   // Indicates if plugin is in autoscroll mode.
    392   bool is_autoscroll_;
    393   // Rect for autoscroll anchor.
    394   pp::Rect autoscroll_rect_;
    395   // Image of the autoscroll anchor and its background.
    396   pp::ImageData autoscroll_anchor_;
    397   // Autoscrolling deltas in pixels.
    398   int autoscroll_x_;
    399   int autoscroll_y_;
    400 
    401   // Thickness of a scrollbar.
    402   int scrollbar_thickness_;
    403 
    404   // Reserved thickness of a scrollbar. This is how much space the scrollbar
    405   // takes from the available area. 0 for overlay.
    406   int scrollbar_reserved_thickness_;
    407 
    408   // Used to remember which toolbar is in use
    409   const ToolbarButtonInfo* current_tb_info_;
    410   size_t current_tb_info_size_;
    411 
    412   PaintManager paint_manager_;
    413 
    414   struct BackgroundPart {
    415     pp::Rect location;
    416     uint32 color;
    417   };
    418   std::vector<BackgroundPart> background_parts_;
    419 
    420   struct PrintSettings {
    421     PrintSettings() {
    422       Clear();
    423     }
    424     void Clear() {
    425       is_printing = false;
    426       print_pages_called_ = false;
    427       memset(&pepper_print_settings, 0, sizeof(pepper_print_settings));
    428     }
    429     // This is set to true when PrintBegin is called and false when PrintEnd is
    430     // called.
    431     bool is_printing;
    432     // To know whether this was an actual print operation, so we don't double
    433     // count UMA logging.
    434     bool print_pages_called_;
    435     PP_PrintSettings_Dev pepper_print_settings;
    436   };
    437 
    438   PrintSettings print_settings_;
    439 
    440   scoped_ptr<PDFEngine> engine_;
    441 
    442   // This engine is used to render the individual preview page data. This is
    443   // used only in print preview mode. This will use |PreviewModeClient|
    444   // interface which has very limited access to the pp::Instance.
    445   scoped_ptr<PDFEngine> preview_engine_;
    446 
    447   std::string url_;
    448 
    449   scoped_ptr<FadingControls> toolbar_;
    450   ThumbnailControl thumbnails_;
    451   ProgressControl progress_bar_;
    452   uint32 delayed_progress_timer_id_;
    453   PageIndicator page_indicator_;
    454 
    455   // Used for creating images from numbers.
    456   scoped_ptr<NumberImageGenerator> number_image_generator_;
    457 
    458   // Used for submitting forms.
    459   pp::CompletionCallbackFactory<Instance> form_factory_;
    460   pp::URLLoader form_loader_;
    461 
    462   // Used for generating callbacks.
    463   // TODO(raymes): We don't really need other callback factories we can just
    464   // fold them into this one.
    465   pp::CompletionCallbackFactory<Instance> callback_factory_;
    466 
    467   // True if we haven't painted the plugin viewport yet.
    468   bool first_paint_;
    469 
    470   // True when we've painted at least one page from the document.
    471   bool painted_first_page_;
    472 
    473   // True if we should display page indicator, false otherwise
    474   bool show_page_indicator_;
    475 
    476   // Callback when the document load completes.
    477   pp::Var on_load_callback_;
    478   pp::Var on_scroll_callback_;
    479   pp::Var on_plugin_size_changed_callback_;
    480 
    481   DocumentLoadState document_load_state_;
    482   DocumentLoadState preview_document_load_state_;
    483 
    484   // JavaScript interface to control this instance.
    485   // This wraps a PDFScriptableObject in a pp::Var.
    486   pp::VarPrivate instance_object_;
    487 
    488   // Used so that we only tell the browser once about an unsupported feature, to
    489   // avoid the infobar going up more than once.
    490   bool told_browser_about_unsupported_feature_;
    491 
    492   // Keeps track of which unsupported features we reported, so we avoid spamming
    493   // the stats if a feature shows up many times per document.
    494   std::set<std::string> unsupported_features_reported_;
    495 
    496   // Number of pages in print preview mode, 0 if not in print preview mode.
    497   int print_preview_page_count_;
    498   std::vector<int> print_preview_page_numbers_;
    499 
    500   // Used to manage loaded print preview page information. A |PreviewPageInfo|
    501   // consists of data source url string and the page index in the destination
    502   // document.
    503   typedef std::pair<std::string, int> PreviewPageInfo;
    504   std::queue<PreviewPageInfo> preview_pages_info_;
    505 
    506   // Used to signal the browser about focus changes to trigger the OSK.
    507   // TODO(abodenha (at) chromium.org) Implement full IME support in the plugin.
    508   // http://crbug.com/132565
    509   scoped_ptr<pp::TextInput_Dev> text_input_;
    510 };
    511 
    512 // This implements the JavaScript class entrypoint for the plugin instance.
    513 // This class is just a thin wrapper. It delegates relevant methods to Instance.
    514 class PDFScriptableObject : public pp::deprecated::ScriptableObject {
    515  public:
    516   explicit PDFScriptableObject(Instance* instance);
    517   virtual ~PDFScriptableObject();
    518 
    519   // pp::deprecated::ScriptableObject implementation.
    520   virtual bool HasMethod(const pp::Var& method, pp::Var* exception);
    521   virtual pp::Var Call(const pp::Var& method,
    522                        const std::vector<pp::Var>& args,
    523                        pp::Var* exception);
    524 
    525  private:
    526   Instance* instance_;
    527 };
    528 
    529 }  // namespace chrome_pdf
    530 
    531 #endif  // PDF_INSTANCE_H_
    532