Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / chrome / browser / resources / pdf / pdf_scripting_api.js
1 // Copyright 2014 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 /**
6  * Create a new PDFMessagingClient. This provides a scripting interface to
7  * the PDF viewer so that it can be customized by things like print preview.
8  * @param {HTMLIFrameElement} iframe an iframe containing the PDF viewer.
9  * @param {Window} window the window of the page containing the iframe.
10  * @param {string} extensionUrl the url of the PDF extension.
11  */
12 function PDFMessagingClient(iframe, window, extensionUrl) {
13   this.iframe_ = iframe;
14   this.extensionUrl_ = extensionUrl;
15   this.readyToReceive_ = false;
16   this.messageQueue_ = [];
17   window.addEventListener('message', function(event) {
18     switch (event.data.type) {
19       case 'readyToReceive':
20         this.flushPendingMessages_();
21         break;
22       case 'viewportChanged':
23         this.viewportChangedCallback_(event.data.pageX,
24                                       event.data.pageY,
25                                       event.data.pageWidth,
26                                       event.data.viewportWidth,
27                                       event.data.viewportHeight);
28         break;
29       case 'documentLoaded':
30         this.loadCallback_();
31         break;
32     }
33   }.bind(this), false);
34 }
35
36 PDFMessagingClient.prototype = {
37   /**
38    * @private
39    * Send a message to the extension. If we try to send messages prior to the
40    * extension being ready to receive messages (i.e. before it has finished
41    * loading) we queue up the messages and flush them later.
42    * @param {MessageObject} the message to send.
43    */
44   sendMessage_: function(message) {
45     if (!this.readyToReceive_) {
46       this.messageQueue_.push(message);
47       return;
48     }
49
50     this.iframe_.contentWindow.postMessage(message, this.extensionUrl_);
51   },
52
53   /**
54    * @private
55    * Flushes all pending messages to the extension.
56    */
57   flushPendingMessages_: function() {
58     this.readyToReceive_ = true;
59     while (this.messageQueue_.length != 0) {
60       this.iframe_.contentWindow.postMessage(this.messageQueue_.shift(),
61                                              this.extensionUrl_);
62     }
63   },
64
65   /**
66    * Sets the callback which will be run when the PDF viewport changes.
67    * @param {Function} callback the callback to be called.
68    */
69   setViewportChangedCallback: function(callback) {
70     this.viewportChangedCallback_ = callback;
71   },
72
73   /**
74    * Sets the callback which will be run when the PDF document has finished
75    * loading.
76    * @param {Function} callback the callback to be called.
77    */
78   setLoadCallback: function(callback) {
79     this.loadCallback_ = callback;
80   },
81
82   /**
83    * Resets the PDF viewer into print preview mode.
84    * @param {string} url the url of the PDF to load.
85    * @param {boolean} grayscale whether or not to display the PDF in grayscale.
86    * @param {Array.<number>} pageNumbers an array of the page numbers.
87    * @param {boolean} modifiable whether or not the document is modifiable.
88    */
89   resetPrintPreviewMode: function(url, grayscale, pageNumbers, modifiable) {
90     this.sendMessage_({
91       type: 'resetPrintPreviewMode',
92       url: url,
93       grayscale: grayscale,
94       pageNumbers: pageNumbers,
95       modifiable: modifiable
96     });
97   },
98
99   /**
100    * Load a page into the document while in print preview mode.
101    * @param {string} url the url of the pdf page to load.
102    * @param {number} index the index of the page to load.
103    */
104   loadPreviewPage: function(url, index) {
105     this.sendMessage_({
106       type: 'loadPreviewPage',
107       url: url,
108       index: index
109     });
110   },
111
112   /**
113    * Send a key event to the extension.
114    * @param {number} keyCode the key code to send to the extension.
115    */
116   sendKeyEvent: function(keyCode) {
117     // TODO(raymes): Figure out a way to do this. It's only used to do scrolling
118     // the viewport, so probably just expose viewport controls instead.
119   },
120 };
121
122 /**
123  * Creates a PDF viewer with a scripting interface. This is basically 1) an
124  * iframe which is navigated to the PDF viewer extension and 2) a scripting
125  * interface which provides access to various features of the viewer for use
126  * by print preview and accessbility.
127  * @param {string} src the source URL of the PDF to load initially.
128  * @return {HTMLIFrameElement} the iframe element containing the PDF viewer.
129  */
130 function PDFCreateOutOfProcessPlugin(src) {
131   var EXTENSION_URL = 'chrome-extension://mhjfbmdgcfjbbpaeojofohoefgiehjai';
132   var iframe = window.document.createElement('iframe');
133   iframe.setAttribute('src', EXTENSION_URL + '/index.html?' + src);
134   var client = new PDFMessagingClient(iframe, window, EXTENSION_URL);
135
136   // Add the functions to the iframe so that they can be called directly.
137   iframe.setViewportChangedCallback =
138       client.setViewportChangedCallback.bind(client);
139   iframe.setLoadCallback = client.setLoadCallback.bind(client);
140   iframe.resetPrintPreviewMode = client.resetPrintPreviewMode.bind(client);
141   iframe.loadPreviewPage = client.loadPreviewPage.bind(client);
142   iframe.sendKeyEvent = client.sendKeyEvent.bind(client);
143   return iframe;
144 }
145
146 /**
147  * Create a new PDFMessagingHost. This is the extension-side of the scripting
148  * interface to the PDF viewer. It handles requests from a page which contains
149  * a PDF viewer extension and translates them into actions on the viewer.
150  * @param {Window} window the window containing the PDF extension.
151  * @param {PDFViewer} pdfViewer the object which provides access to the viewer.
152  */
153 function PDFMessagingHost(window, pdfViewer) {
154   this.window_ = window;
155   this.pdfViewer_ = pdfViewer;
156   this.viewport_ = pdfViewer.viewport;
157
158   window.addEventListener('message', function(event) {
159     switch (event.data.type) {
160       case 'resetPrintPreviewMode':
161         this.pdfViewer_.resetPrintPreviewMode(
162             event.data.url,
163             event.data.grayscale,
164             event.data.pageNumbers,
165             event.data.modifiable);
166
167         break;
168       case 'loadPreviewPage':
169         this.pdfViewer_.loadPreviewPage(event.data.url, event.data.index);
170         break;
171     }
172   }.bind(this), false);
173
174   if (this.window_.parent != this.window_)
175     this.sendMessage_({type: 'readyToReceive'});
176 }
177
178 PDFMessagingHost.prototype = {
179   sendMessage_: function(message) {
180     if (this.window_.parent == this.window_)
181       return;
182     this.window_.parent.postMessage(message, '*');
183   },
184
185   viewportChanged: function() {
186     var visiblePage = this.viewport_.getMostVisiblePage();
187     var pageDimensions = this.viewport_.getPageScreenRect(visiblePage);
188     var size = this.viewport_.size;
189
190     this.sendMessage_({
191       type: 'viewportChanged',
192       pageX: pageDimensions.x,
193       pageY: pageDimensions.y,
194       pageWidth: pageDimensions.width,
195       viewportWidth: size.width,
196       viewportHeight: size.height,
197     });
198   },
199
200   documentLoaded: function() {
201     if (this.window_.parent == this.window_)
202       return;
203     this.sendMessage_({ type: 'documentLoaded' });
204   }
205 };