PageRenderTime 31ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 0ms

/prebuilt/extension/components/PDFService.js

http://firefox-mac-pdf.googlecode.com/
JavaScript | 295 lines | 210 code | 39 blank | 46 comment | 47 complexity | 0bea677eeeb29508f024b5ffb2b5dbd2 MD5 | raw file
  1. /*
  2. * Copyright (c) 2008 Samuel Gross.
  3. *
  4. * Permission is hereby granted, free of charge, to any person obtaining a copy
  5. * of this software and associated documentation files (the "Software"), to deal
  6. * in the Software without restriction, including without limitation the rights
  7. * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  8. * copies of the Software, and to permit persons to whom the Software is
  9. * furnished to do so, subject to the following conditions:
  10. *
  11. * The above copyright notice and this permission notice shall be included in
  12. * all copies or substantial portions of the Software.
  13. *
  14. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  15. * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  16. * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  17. * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  18. * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  19. * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  20. * THE SOFTWARE.
  21. */
  22. Components.utils.import("resource://gre/modules/XPCOMUtils.jsm");
  23. var consoleservice = Components.classes["@mozilla.org/consoleservice;1"].
  24. getService(Components.interfaces.nsIConsoleService);
  25. function log(message) {
  26. consoleservice.logStringMessage(message);
  27. }
  28. function findPluginWithId(window, plugin_id) {
  29. var embeds = window.document.embeds;
  30. if (embeds.length == 1) {
  31. if (embeds[0].wrappedJSObject.plugin_id == plugin_id) {
  32. return window;
  33. }
  34. }
  35. var frames = window.frames;
  36. for (var i = 0; i < frames.length; ++i) {
  37. var found = findPluginWithId(frames[i], plugin_id);
  38. if (found) {
  39. return found;
  40. }
  41. }
  42. return null;
  43. }
  44. function getWindowForPluginId(plugin_id) {
  45. var console = Components.classes["@mozilla.org/consoleservice;1"].
  46. getService(Components.interfaces.nsIConsoleService);
  47. var wm = Components.classes["@mozilla.org/appshell/window-mediator;1"].
  48. getService(Components.interfaces.nsIWindowMediator);
  49. var enumerator = wm.getEnumerator("navigator:browser");
  50. while(enumerator.hasMoreElements()) {
  51. var chromeWindow = enumerator.getNext();
  52. var browsers = chromeWindow.gBrowser.browsers;
  53. for (var i = 0; i < browsers.length; ++i) {
  54. var window = browsers[i].contentWindow;
  55. var found = findPluginWithId(window, plugin_id);
  56. if (found) {
  57. return {window:found, chromeWindow:chromeWindow};
  58. }
  59. }
  60. }
  61. return null;
  62. }
  63. function getChromeWindowForPluginId(plugin_id) {
  64. for (var i = 0; i < plugins.length; i++) {
  65. if (plugins[i].plugin_id == plugin_id) {
  66. return plugins[i].chromeWindow;
  67. }
  68. }
  69. return null;
  70. }
  71. function getTabBrowserForWindow(plugin_id) {
  72. var chromeWindow = getChromeWindowForPluginId(plugin_id);
  73. return chromeWindow && chromeWindow.gBrowser;
  74. }
  75. function getPluginShim(chromeWindow) {
  76. var window = chromeWindow.gBrowser.contentWindow;
  77. for (var i = 0; i < plugins.length; i++) {
  78. if (plugins[i].window == chromeWindow.gBrowser.contentWindow) {
  79. return plugins[i].plugin;
  80. }
  81. }
  82. return null;
  83. }
  84. var plugins = [];
  85. function PDFService() {
  86. };
  87. PDFService.prototype = {
  88. classDescription: "Firefox PDF Plugin Service",
  89. classID: Components.ID("{862827b0-98ac-4b68-a0c9-4ccd8ff35a02}"),
  90. contractID: "@sgross.mit.edu/pdfservice;1",
  91. QueryInterface: XPCOMUtils.generateQI([Components.interfaces.PDFService]),
  92. Init: function(plugin_id, plugin) {
  93. var obj = getWindowForPluginId(plugin_id);
  94. if (obj == null) {
  95. return;
  96. }
  97. var window = obj.window;
  98. var chromeWindow = obj.chromeWindow;
  99. plugins.push({plugin_id:plugin_id, plugin:plugin, window:window, chromeWindow:chromeWindow});
  100. if (!chromeWindow.edu_mit_sgross_pdfplugin_swizzled) {
  101. var browser = chromeWindow.gBrowser;
  102. browser._fastFind = new FastFindShim(chromeWindow, browser._fastFind);
  103. // also 'swizzle' the close function on the find bar to cause the elem to regain focus
  104. var findBar = chromeWindow.gFindBar;
  105. findBar.toggleHighlight = createFindbarToggleHighlight(chromeWindow, findBar.toggleHighlight);
  106. findBar._setHighlightTimeout = createSetHighlightTimeout(chromeWindow, findBar._setHighlightTimeout);
  107. // route zoom commands to the plugin
  108. var FullZoom = chromeWindow.FullZoom;
  109. FullZoom.reduce = createZoom(chromeWindow, FullZoom.reduce, -1);
  110. FullZoom.reset = createZoom(chromeWindow, FullZoom.reset, 0);
  111. FullZoom.enlarge = createZoom(chromeWindow, FullZoom.enlarge, 1);
  112. chromeWindow.goDoCommand = createGoDoCommand(chromeWindow, chromeWindow.goDoCommand);
  113. chromeWindow.edu_mit_sgross_pdfplugin_swizzled = true;
  114. }
  115. return;
  116. },
  117. CleanUp: function(plugin_id) {
  118. for (var i = 0; i < plugins.length; i++) {
  119. var obj = plugins[i];
  120. if (obj.plugin_id == plugin_id) {
  121. plugins = plugins.slice(0, i).concat(plugins.slice(i+1, plugins.length));
  122. return;
  123. }
  124. }
  125. },
  126. FindPrevious: function(plugin_id) {
  127. var chromeWindow = getChromeWindowForPluginId(plugin_id);
  128. chromeWindow.gFindBar.onFindAgainCommand(true);
  129. },
  130. Save: function(plugin_id, url) {
  131. var chromeWindow = getChromeWindowForPluginId(plugin_id);
  132. chromeWindow.internalSave(url, null, null, null, "application/pdf", false,
  133. null, null, null, null);
  134. }
  135. }
  136. /**
  137. * Wraps a nsITypeAheadFind object to route find queries to the plugin when appropriate
  138. */
  139. function FastFindShim(chromeWindow, fastfind) {
  140. this.fastfind = fastfind;
  141. this.chromeWindow = chromeWindow;
  142. for (let prop in fastfind) {
  143. if (fastfind.__lookupGetter__(prop)) {
  144. this.__defineGetter__(prop, createDelegateGetter(chromeWindow, this.fastfind, prop));
  145. }
  146. if (fastfind.__lookupSetter__(prop)) {
  147. this.__defineSetter__(prop, createDelegateSetter(chromeWindow, this.fastfind, prop));
  148. }
  149. }
  150. }
  151. /**
  152. * Delegates gets to underlying fastfind.
  153. */
  154. function createDelegateGetter(chromeWindow, fastfind, prop) {
  155. if (prop == 'searchString') {
  156. return function() {
  157. // TODO: improve condition based on last search type (PDF versus HTML)
  158. return getPluginShim(chromeWindow) ? this.lastSearchString : fastfind[prop];
  159. }
  160. }
  161. return function() {
  162. return fastfind[prop];
  163. }
  164. }
  165. function createDelegateSetter(chromeWindow, fastfind, prop) {
  166. return function(val) {
  167. return fastfind[prop] = val;
  168. }
  169. }
  170. /**
  171. * Delegate all other methods to wrapped fastfind object.
  172. */
  173. FastFindShim.prototype.__noSuchMethod__ = function(id, args) {
  174. if (id == 'find' || id == 'findAgain') {
  175. var plugin = getPluginShim(this.chromeWindow);
  176. if (plugin) {
  177. var str, reverse;
  178. if (id == 'find') {
  179. str = args[0];
  180. reverse = false;
  181. } else { // findAgain
  182. str = this.lastSearchString;
  183. reverse = args[0];
  184. }
  185. this.lastSearchString = str;
  186. // find must take place before findAll because find cancels any current searches
  187. var ret = plugin.Find(str, this.fastfind.caseSensitive, !reverse);
  188. var findBar = this.chromeWindow.gFindBar;
  189. if (findBar.getElement("highlight").checked) {
  190. plugin.FindAll(str, this.fastfind.caseSensitive);
  191. }
  192. return ret;
  193. }
  194. }
  195. return this.fastfind[id].apply(this.fastfind, args);
  196. }
  197. /**
  198. * Creates a function that calls toggleHighlight on the plugin.
  199. */
  200. function createFindbarToggleHighlight(chromeWindow, orig) {
  201. return function(shouldHighlight) {
  202. var plugin = getPluginShim(chromeWindow);
  203. if (plugin) {
  204. if (shouldHighlight) {
  205. var word = this._findField.value;
  206. // TODO: better choice for determining case sensitivity?
  207. var caseSensitive = this._shouldBeCaseSensitive(word);
  208. plugin.FindAll(word, caseSensitive);
  209. } else {
  210. plugin.RemoveHighlights();
  211. }
  212. } else {
  213. orig.call(this, shouldHighlight);
  214. }
  215. };
  216. }
  217. /**
  218. * Creates a function that only sets the highlight timeout when
  219. * the plugin is not present.
  220. */
  221. function createSetHighlightTimeout(chromeWindow, orig) {
  222. return function() {
  223. if (!getPluginShim(chromeWindow)) {
  224. orig.call(this);
  225. }
  226. };
  227. }
  228. function createZoom(chromeWindow, orig, arg) {
  229. return function() {
  230. var plugin = getPluginShim(chromeWindow);
  231. if (plugin) {
  232. plugin.Zoom(arg);
  233. } else {
  234. orig.call(this);
  235. }
  236. }
  237. }
  238. function createGoDoCommand(chromeWindow, orig) {
  239. return function(cmd) {
  240. var plugin;
  241. if (cmd == 'cmd_copy' && (plugin = getPluginShim(chromeWindow))) {
  242. plugin.Copy();
  243. } else {
  244. return orig.call(this, cmd);
  245. }
  246. }
  247. }
  248. var components = [PDFService];
  249. /**
  250. * XPCOMUtils.generateNSGetFactory was introduced in Mozilla 2 (Firefox 4).
  251. * XPCOMUtils.generateNSGetModule is for Mozilla 1.9.2 (Firefox 3.6).
  252. */
  253. if (XPCOMUtils.generateNSGetFactory)
  254. var NSGetFactory = XPCOMUtils.generateNSGetFactory(components);
  255. else
  256. var NSGetModule = XPCOMUtils.generateNSGetModule(components);