PageRenderTime 36ms CodeModel.GetById 18ms RepoModel.GetById 0ms app.codeStats 0ms

/src/pdfplugin.mm

http://firefox-mac-pdf.googlecode.com/
Objective C++ | 230 lines | 149 code | 38 blank | 43 comment | 27 complexity | 766f44cfafda9ab096dea74560042b80 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. #import "PluginInstance.h"
  23. #include "npapi.h"
  24. #include "npruntime.h"
  25. #include "PDFService.h"
  26. #include "nsCOMPtr.h"
  27. #include "nsServiceManagerUtils.h"
  28. NPError NPP_Initialize() {
  29. return NPERR_NO_ERROR;
  30. }
  31. void NPP_Shutdown() {
  32. }
  33. NPError NPP_New(NPMIMEType pluginType, NPP npp, uint16 mode, int16 argc, char* argn[], char* argv[], NPSavedData* saved) {
  34. NSLog(@"NPP_New(npp=%8p,mode=%d,argc=%d)\n", npp, mode, argc);
  35. if (npp == NULL) {
  36. return NPERR_INVALID_INSTANCE_ERROR;
  37. }
  38. // Check if the browser supports the CoreGraphics drawing model
  39. NPBool supportsCoreGraphics = FALSE;
  40. NPError err = NPN_GetValue(npp, NPNVsupportsCoreGraphicsBool, &supportsCoreGraphics);
  41. if (err != NPERR_NO_ERROR || !supportsCoreGraphics) {
  42. NSLog(@"firefox-mac-pdf: does not support core graphics");
  43. return NPERR_INCOMPATIBLE_VERSION_ERROR;
  44. }
  45. // Set the drawing model
  46. err = NPN_SetValue(npp, NPPVpluginDrawingModel, (void*) NPDrawingModelCoreGraphics);
  47. if (err != NPERR_NO_ERROR) {
  48. NSLog(@"firefox-mac-pdf: does not support drawing model");
  49. return NPERR_INCOMPATIBLE_VERSION_ERROR;
  50. }
  51. // select the Carbon event model
  52. // I'm not absolutely sure that this is necessary, but the documentation
  53. // suggests that the Cocoa event model is used by default in 64-bit plugins,
  54. // which will definitely not work for this plugin.
  55. // The problem with the Cocoa event model is that there is no way to get the
  56. // browser's NSWindow or NSView, which we need to attach the PDFView
  57. NPBool supportsCarbonEvents = false;
  58. if (NPN_GetValue(npp, NPNVsupportsCarbonBool, &supportsCarbonEvents) == NPERR_NO_ERROR && supportsCarbonEvents) {
  59. NPN_SetValue(npp, NPPVpluginEventModel, (void*)NPEventModelCarbon);
  60. } else {
  61. printf("Carbon event model not supported, can't create a plugin instance.\n");
  62. return NPERR_INCOMPATIBLE_VERSION_ERROR;
  63. }
  64. nsCOMPtr<PDFService> pdfService(do_GetService("@sgross.mit.edu/pdfservice;1"));
  65. if (!pdfService) {
  66. NSLog(@"firefox-mac-pdf: could not get PDF service");
  67. return NPERR_GENERIC_ERROR;
  68. }
  69. NPObject* pluginElement;
  70. err = NPN_GetValue(npp, NPNVPluginElementNPObject, &pluginElement);
  71. if (err != NPERR_NO_ERROR) {
  72. NSLog(@"firefox-mac-pdf: could not get PluginElement object");
  73. return NPERR_GENERIC_ERROR;
  74. }
  75. NPIdentifier idName = NPN_GetStringIdentifier("plugin_id");
  76. NPVariant idValue;
  77. NSString* pluginId = [NSString stringWithFormat:@"%x%x%x%x", arc4random(),
  78. arc4random(), arc4random(), arc4random()];
  79. STRINGZ_TO_NPVARIANT([pluginId cStringUsingEncoding:NSASCIIStringEncoding], idValue);
  80. if (!NPN_SetProperty(npp, pluginElement, idName, &idValue)) {
  81. NSLog(@"firefox-mac-pdf: could not set plugin_id");
  82. return NPERR_GENERIC_ERROR;
  83. }
  84. NSString* mimeType = [NSString stringWithUTF8String:pluginType];
  85. // allocate the plugin
  86. npp->pdata = [[PluginInstance alloc] initWithService:pdfService.get()
  87. plugin_id:pluginId
  88. npp:npp
  89. mimeType:mimeType];
  90. return NPERR_NO_ERROR;
  91. }
  92. NPError NPP_Destroy(NPP instance, NPSavedData** save) {
  93. if (instance == NULL) {
  94. return NPERR_INVALID_INSTANCE_ERROR;
  95. }
  96. // NSLog(@"NPP_Destroy: %d", (int) instance->pdata);
  97. PluginInstance* plugin = (PluginInstance*) instance->pdata;
  98. if (plugin) {
  99. [plugin updatePreferences];
  100. [plugin release];
  101. instance->pdata = NULL;
  102. }
  103. return NPERR_NO_ERROR;
  104. }
  105. bool getVisible(NPWindow*) __attribute ((__noinline__));
  106. bool getVisible(NPWindow* window) {
  107. NPRect clipRect = window->clipRect;
  108. return (clipRect.top != clipRect.bottom && clipRect.left != clipRect.right);
  109. }
  110. void maybeAttach(PluginInstance*, NPWindow*) __attribute ((__noinline__));
  111. void maybeAttach(PluginInstance* plugin, NPWindow* window) {
  112. // attach the plugin if it's not attached and is visible
  113. NPRect clipRect = window->clipRect;
  114. if (![plugin attached]) {
  115. NP_CGContext* npContext = (NP_CGContext*) window->window;
  116. NSWindow* browserWindow = [[[NSWindow alloc] initWithWindowRef:npContext->window] autorelease];
  117. int y = [browserWindow frame].size.height - (clipRect.bottom - clipRect.top) - window->y;
  118. [plugin attachToWindow:browserWindow at:NSMakePoint(window->x, y)];
  119. }
  120. }
  121. void maybeSetVisible(PluginInstance*, bool) __attribute ((__noinline__));
  122. void maybeSetVisible(PluginInstance* plugin, bool visible) {
  123. if ([plugin attached]) {
  124. [plugin setVisible:visible];
  125. }
  126. }
  127. NPError NPP_SetWindow(NPP instance, NPWindow* window) {
  128. PluginInstance* plugin = (PluginInstance*)instance->pdata;
  129. bool visible = getVisible(window);
  130. if (visible) {
  131. maybeAttach(plugin, window);
  132. }
  133. maybeSetVisible(plugin, visible);
  134. return NPERR_NO_ERROR;
  135. }
  136. NPError NPP_NewStream(NPP instance, NPMIMEType type, NPStream* stream, NPBool seekable, uint16* stype) {
  137. // NSLog(@"NPP_NewStream end=%d", (int) stream->end);
  138. NSMutableData* data = [NSMutableData dataWithCapacity:stream->end];
  139. stream->pdata = [data retain];
  140. PluginInstance* plugin = (PluginInstance*)instance->pdata;
  141. [plugin setUrl:[NSString stringWithUTF8String:stream->url]];
  142. *stype = NP_NORMAL;
  143. return NPERR_NO_ERROR;
  144. }
  145. NPError NPP_DestroyStream(NPP instance, NPStream* stream, NPReason reason) {
  146. // NSLog(@"NPP_DestroyStream reason: %d", (int) reason);
  147. NSMutableData* data = (NSMutableData*) stream->pdata;
  148. PluginInstance* plugin = (PluginInstance*)instance->pdata;
  149. if (reason == 0) {
  150. [plugin setData:data];
  151. } else {
  152. [plugin downloadFailed];
  153. }
  154. [data release];
  155. return NPERR_NO_ERROR;
  156. }
  157. int32 NPP_WriteReady(NPP instance, NPStream* stream) {
  158. //NSLog(@"NPP_WriteReady");
  159. return 2147483647;
  160. }
  161. int32 NPP_Write(NPP instance, NPStream* stream, int32 offset, int32 len, void* buffer) {
  162. NSMutableData* data = (NSMutableData*) stream->pdata;
  163. [data appendBytes:buffer length:len];
  164. PluginInstance* plugin = (PluginInstance*)instance->pdata;
  165. [plugin setProgress:offset total:stream->end];
  166. return len;
  167. }
  168. void NPP_StreamAsFile(NPP instance, NPStream* stream, const char* fname) {
  169. }
  170. void NPP_Print(NPP instance, NPPrint* platformPrint) {
  171. PluginInstance* plugin = (PluginInstance*)instance->pdata;
  172. [plugin print];
  173. }
  174. int16 NPP_HandleEvent(NPP instance, void* _event) {
  175. // NPEvent* event = (NPEvent*) _event;
  176. // PluginInstance* plugin = (PluginInstance*)instance->pdata;
  177. // // seems to be called after plugin is created. use it to give plugin focus
  178. // const int updateEvt = 6;
  179. // if (event->what == NPEventType_GetFocusEvent || event->what == updateEvt) {
  180. // [plugin requestFocus];
  181. // return 1;
  182. // }
  183. return 0;
  184. }
  185. void NPP_URLNotify(NPP instance, const char* url, NPReason reason, void* notifyData) {
  186. }
  187. NPError NPP_GetValue(NPP npp, NPPVariable variable, void *value) {
  188. return NPERR_GENERIC_ERROR;
  189. }
  190. NPError NPP_SetValue(NPP instance, NPNVariable variable, void *value) {
  191. return NPERR_GENERIC_ERROR;
  192. }